diff --git a/millions/src/main/java/no/ntnu/gruppe53/view/MarketView.java b/millions/src/main/java/no/ntnu/gruppe53/view/MarketView.java index bab3197..9dc83fe 100644 --- a/millions/src/main/java/no/ntnu/gruppe53/view/MarketView.java +++ b/millions/src/main/java/no/ntnu/gruppe53/view/MarketView.java @@ -3,15 +3,13 @@ import java.math.RoundingMode; import java.util.function.Consumer; +import javafx.collections.transformation.FilteredList; import javafx.collections.transformation.SortedList; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.*; import javafx.scene.chart.XYChart; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; +import javafx.scene.layout.*; import javafx.scene.chart.LineChart; import javafx.util.Subscription; import no.ntnu.gruppe53.model.*; @@ -42,9 +40,11 @@ public class MarketView extends BorderPane { public TextField gross; public TextField commission; public TextField total; + private TextField searchField; //StockListView private ListView stocksListView; + private FilteredList filteredStocksList; //Input private Spinner quantitySpinner; @@ -154,6 +154,21 @@ protected void updateItem(Stock stock, boolean empty) { } }); + HBox searchBox = new HBox(); + searchField = new TextField(); + searchField.promptTextProperty().bind(lm.bindString("search")); + searchBox.setStyle("-fx-background-color: #ffe556;" + + "-fx-text-fill: #303539;" + + "-fx-background-radius: 8;" + + "-fx-border-color: #303539;" + + "-fx-border-radius: 8;" + ); + + searchBox.setPadding(new Insets(8, 14, 8, 14)); + searchBox.setAlignment(Pos.CENTER_LEFT); + searchBox.setMaxWidth(Region.USE_PREF_SIZE); + searchBox.getChildren().addAll(searchField); + // Container for list of stocks HBox stockListBox = new HBox(stocksListView); @@ -254,7 +269,7 @@ protected void updateItem(Stock stock, boolean empty) { - vBox.getChildren().addAll(titleBox, + vBox.getChildren().addAll(titleBox, searchBox, stockBox, purchaseBox); @@ -326,18 +341,34 @@ public void onQuantitySelect(Runnable action) { /** * Sets the exchange to use for the view. - *

Uses a {@link SortedList} to sort the stocks in the exchange alphabetically + *

Uses first a {@link FilteredList} to account for what the user has searched for.

+ *

Then utilises a {@link SortedList} to sort the stocks in the exchange alphabetically * on their symbol/ticker.

* * @param exchange the exchange to be used for the view */ public void setExchange(Exchange exchange) { this.exchange = exchange; + + if (exchange != null) { - SortedList sortedStocks = new SortedList<>(exchange.getObservableStocks()); + filteredStocksList = new FilteredList<>(exchange.getObservableStocks()); + + SortedList sortedStocks = new SortedList<>(filteredStocksList); sortedStocks.setComparator((s1, s2) -> s1.getSymbol().compareToIgnoreCase(s2.getSymbol())); + stocksListView.setItems(sortedStocks); + + searchField.textProperty().addListener((observable, oldText, newText) -> { + String search = newText == null ? "" : newText.toLowerCase(); + + filteredStocksList.setPredicate(stock -> search.isBlank() + || stock.getSymbol().toLowerCase().contains(search) + || stock.getCompany().toLowerCase().contains(search) + ); + }); } + } /** diff --git a/millions/src/main/java/no/ntnu/gruppe53/view/PortfolioView.java b/millions/src/main/java/no/ntnu/gruppe53/view/PortfolioView.java index 1d05348..4c55fe5 100644 --- a/millions/src/main/java/no/ntnu/gruppe53/view/PortfolioView.java +++ b/millions/src/main/java/no/ntnu/gruppe53/view/PortfolioView.java @@ -5,6 +5,7 @@ import java.util.function.Consumer; import javafx.collections.ObservableList; +import javafx.collections.transformation.FilteredList; import javafx.geometry.Insets; import javafx.scene.control.Button; import javafx.scene.control.Label; @@ -12,10 +13,7 @@ import javafx.scene.control.ListView; import javafx.geometry.Pos; import javafx.scene.control.*; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; +import javafx.scene.layout.*; import javafx.scene.text.Text; import javafx.scene.text.TextFlow; import javafx.util.Subscription; @@ -56,9 +54,11 @@ public class PortfolioView extends BorderPane { private TextField tax; private TextField total; private TextField profit; + private TextField searchField; //PortfolioListView private ListView portfolioListView; + private FilteredList filteredPortfolioList; private Player player; private SaleCalculator saleCalculator; @@ -152,6 +152,21 @@ protected void updateItem(Share item, boolean empty) { } }); + HBox searchBox = new HBox(); + searchField = new TextField(); + searchField.promptTextProperty().bind(lm.bindString("search")); + searchBox.setStyle("-fx-background-color: #ffe556;" + + "-fx-text-fill: #303539;" + + "-fx-background-radius: 8;" + + "-fx-border-color: #303539;" + + "-fx-border-radius: 8;" + ); + + searchBox.setPadding(new Insets(8, 14, 8, 14)); + searchBox.setAlignment(Pos.CENTER_LEFT); + searchBox.setMaxWidth(Region.USE_PREF_SIZE); + searchBox.getChildren().addAll(searchField); + VBox portfolioListBox = new VBox(portfolioListView); portfolioListBox.setStyle("-fx-background-color: #ffe556;" + "-fx-text-fill: #303539;" + @@ -231,7 +246,7 @@ protected void updateItem(Share item, boolean empty) { saleBox.getChildren().addAll(selectedShareBox, calculationBox, totalBox, sellButton); - vBox.getChildren().addAll(titleBox, + vBox.getChildren().addAll(titleBox, searchBox, portfolioListBox, saleBox); return vBox; @@ -265,7 +280,7 @@ public Share getSelectedShare() { /** * Sets the player to be observed. *

The values observed are the players portfolio and name.

- *

Uses an {@link ObservableList} to observe the shares and + *

Uses a {@link FilteredList} to get and filter the shares and * binds it to the portfolioListView.

* * @param player the player to be observed @@ -274,10 +289,19 @@ public void setPlayer(Player player) { this.player = player; if (player != null && player.getPortfolio() != null) { - ObservableList observableShares = player.getPortfolio().getShares(); - portfolioListView.setItems(observableShares); + filteredPortfolioList = new FilteredList<>(player.getPortfolio().getShares()); + + portfolioListView.setItems(filteredPortfolioList); + + searchField.textProperty().addListener((observable, oldText, newText) -> { + String search = newText == null ? "" : newText.toLowerCase(); + filteredPortfolioList.setPredicate(share -> search.isBlank() + || share.getStock().getSymbol().toLowerCase().contains(search) + || share.getStock().getCompany().toLowerCase().contains(search) + ); + }); } else { diff --git a/millions/src/main/java/no/ntnu/gruppe53/view/TransactionArchiveView.java b/millions/src/main/java/no/ntnu/gruppe53/view/TransactionArchiveView.java index 91e64b4..4c949a5 100644 --- a/millions/src/main/java/no/ntnu/gruppe53/view/TransactionArchiveView.java +++ b/millions/src/main/java/no/ntnu/gruppe53/view/TransactionArchiveView.java @@ -1,13 +1,14 @@ package no.ntnu.gruppe53.view; +import javafx.collections.transformation.FilteredList; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; -import javafx.scene.layout.BorderPane; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; +import javafx.scene.control.TextField; +import javafx.scene.layout.*; + import java.math.BigDecimal; import java.math.RoundingMode; @@ -31,8 +32,12 @@ public class TransactionArchiveView extends BorderPane { private final LanguageManager lm = LanguageManager.getInstance(); private ListView historyListView; + private FilteredList filteredTransactionList; + private Label titleLabel; + private TextField searchField; + /** * Builds the view components and places them in the center pane. */ @@ -146,6 +151,20 @@ protected void updateItem(Transaction item, boolean empty) { } }); + HBox searchBox = new HBox(); + searchField = new TextField(); + searchField.promptTextProperty().bind(lm.bindString("search")); + searchBox.setStyle("-fx-background-color: #ffe556;" + + "-fx-text-fill: #303539;" + + "-fx-background-radius: 8;" + + "-fx-border-color: #303539;" + + "-fx-border-radius: 8;" + ); + + searchBox.setPadding(new Insets(8, 14, 8, 14)); + searchBox.setAlignment(Pos.CENTER_LEFT); + searchBox.setMaxWidth(Region.USE_PREF_SIZE); + searchBox.getChildren().addAll(searchField); VBox historyListBox = new VBox(historyListView); historyListBox.setStyle("-fx-background-color: #ffe556;" + @@ -162,18 +181,33 @@ protected void updateItem(Transaction item, boolean empty) { VBox.setVgrow(historyListView, Priority.ALWAYS); VBox.setVgrow(historyListBox, Priority.ALWAYS); - vBox.getChildren().addAll(titleBox, historyListBox); + vBox.getChildren().addAll(titleBox, searchBox, historyListBox); return vBox; } /** * Sets the player to be observed. + *

And puts the {@link TransactionArchive} into a {@link FilteredList} for searching.

* * @param player the player to be observed */ public void setPlayer(Player player) { - if (player != null && player.getTransactionArchive() != null) { - historyListView.setItems(player.getTransactionArchive().getObservableTransactions()); + if (player != null && player.getTransactionArchive().getObservableTransactions() != null) { + + + filteredTransactionList = new FilteredList<>(player.getTransactionArchive().getObservableTransactions()); + + historyListView.setItems(filteredTransactionList); + + searchField.textProperty().addListener((observable, oldText, newText) -> { + String search = newText == null ? "" : newText.toLowerCase(); + + filteredTransactionList.setPredicate( transaction -> search.isBlank() + || transaction.getShare().getStock().getSymbol().toLowerCase().contains(search) + || transaction.getShare().getStock().getCompany().toLowerCase().contains(search) + ); + }); + } else { historyListView.setItems(null); } diff --git a/millions/src/main/resources/i18n/lang.properties b/millions/src/main/resources/i18n/lang.properties index 64cdd1f..87c134e 100644 --- a/millions/src/main/resources/i18n/lang.properties +++ b/millions/src/main/resources/i18n/lang.properties @@ -3,6 +3,7 @@ # General yes = Yes no = No +search = Search: # StartView newGame = New Game diff --git a/millions/src/main/resources/i18n/lang_en.properties b/millions/src/main/resources/i18n/lang_en.properties index 7ed958b..1c8ef53 100644 --- a/millions/src/main/resources/i18n/lang_en.properties +++ b/millions/src/main/resources/i18n/lang_en.properties @@ -3,6 +3,7 @@ # General yes = Yes no = No +search = Search: # StartView newGame = New Game diff --git a/millions/src/main/resources/i18n/lang_no.properties b/millions/src/main/resources/i18n/lang_no.properties index 00735e7..b5deee0 100644 --- a/millions/src/main/resources/i18n/lang_no.properties +++ b/millions/src/main/resources/i18n/lang_no.properties @@ -3,6 +3,7 @@ # General yes = Ja no = Nei +search = Søk: # StartView newGame = Nytt Spill diff --git a/millions/target/classes/i18n/lang.properties b/millions/target/classes/i18n/lang.properties index 01a4ec3..87c134e 100644 --- a/millions/target/classes/i18n/lang.properties +++ b/millions/target/classes/i18n/lang.properties @@ -1,8 +1,9 @@ -# Default file to use if there is an error with language locale +# File for the english language # General yes = Yes no = No +search = Search: # StartView newGame = New Game @@ -58,6 +59,7 @@ portfolioGross = Gross: portfolioCommission = Commission: portfolioTax = Tax: portfolioTotal = Total: +portfolioProfit = Profit: sellButton = Sell portfolioShareQuantity = Qty: portfolioBuyPrice = Buy price: @@ -67,7 +69,7 @@ portfolioCurrentPrice = Current Price: historyTitle=Transaction History historyTypePurchase=Purchase historyTypeSale=Sale -historyCellFormat=Week %d | %s | %s | Qty: %s | Total: $%s +historyCellFormat=Week %d | %s | %s | Price: %s | Qty: %s | Gross: %s | Commission: %s | Tax: %s | Total: $%s | Profit: %s # EndView congratsLabel = Thank you for playing Millions!\nBelow you can see what level you reached and the amount of\nmoney you ended up with!\nYou can also choose to start a new game. diff --git a/millions/target/classes/i18n/lang_en.properties b/millions/target/classes/i18n/lang_en.properties index 3cd4ac9..1c8ef53 100644 --- a/millions/target/classes/i18n/lang_en.properties +++ b/millions/target/classes/i18n/lang_en.properties @@ -3,6 +3,7 @@ # General yes = Yes no = No +search = Search: # StartView newGame = New Game @@ -58,6 +59,7 @@ portfolioGross = Gross: portfolioCommission = Commission: portfolioTax = Tax: portfolioTotal = Total: +portfolioProfit = Profit: sellButton = Sell portfolioShareQuantity = Qty: portfolioBuyPrice = Buy price: @@ -67,7 +69,7 @@ portfolioCurrentPrice = Current Price: historyTitle=Transaction History historyTypePurchase=Purchase historyTypeSale=Sale -historyCellFormat=Week %d | %s | %s | Qty: %s | Total: $%s +historyCellFormat=Week %d | %s | %s | Price: %s | Qty: %s | Gross: %s | Commission: %s | Tax: %s | Total: $%s | Profit: %s # EndView congratsLabel = Thank you for playing Millions!\nBelow you can see what level you reachedand the amount of\nmoney you ended up with!\nYou can also choose to start a new game. diff --git a/millions/target/classes/i18n/lang_no.properties b/millions/target/classes/i18n/lang_no.properties index c8bdec5..b5deee0 100644 --- a/millions/target/classes/i18n/lang_no.properties +++ b/millions/target/classes/i18n/lang_no.properties @@ -3,6 +3,7 @@ # General yes = Ja no = Nei +search = Søk: # StartView newGame = Nytt Spill @@ -58,6 +59,7 @@ portfolioGross = Brutto: portfolioCommission = Kurtasje: portfolioTax = Skatt: portfolioTotal = Total: +portfolioProfit = Profitt: sellButton = Selg portfolioShareQuantity = Ant: portfolioBuyPrice = Kjøpspris: @@ -67,7 +69,8 @@ portfolioCurrentPrice = Gjeldende pris: historyTitle=Transaksjonshistorikk historyTypePurchase=Kjøp historyTypeSale=Salg -historyCellFormat=Uke %d | %s | %s | Ant: %s | Total: $%s +historyCellFormat=Uke %d | %s | %s | Pris: %s | Ant: %s | Brutto: %s | Kurtasje: %s | Skatt: %s | Total: $%s | Profit: %s + # EndView congratsLabel = Takk for at du spilte Millions!\nNedenfor kan du se hvilket nivå du nådde opp til\nog din endelige saldo!\nDu kan også velge å starte et nytt spill.