Skip to content

added search functionality to market, portfolio, and history #65

Merged
merged 1 commit into from
May 26, 2026
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 38 additions & 7 deletions millions/src/main/java/no/ntnu/gruppe53/view/MarketView.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.*;
Expand Down Expand Up @@ -42,9 +40,11 @@ public class MarketView extends BorderPane {
public TextField gross;
public TextField commission;
public TextField total;
private TextField searchField;

//StockListView
private ListView<Stock> stocksListView;
private FilteredList<Stock> filteredStocksList;

//Input
private Spinner<Integer> quantitySpinner;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -254,7 +269,7 @@ protected void updateItem(Stock stock, boolean empty) {



vBox.getChildren().addAll(titleBox,
vBox.getChildren().addAll(titleBox, searchBox,
stockBox,
purchaseBox);

Expand Down Expand Up @@ -326,18 +341,34 @@ public void onQuantitySelect(Runnable action) {

/**
* Sets the exchange to use for the view.
* <p>Uses a {@link SortedList} to sort the stocks in the exchange alphabetically
* <p>Uses first a {@link FilteredList} to account for what the user has searched for. </p>
* <p>Then utilises a {@link SortedList} to sort the stocks in the exchange alphabetically
* on their symbol/ticker.</p>
*
* @param exchange the exchange to be used for the view
*/
public void setExchange(Exchange exchange) {
this.exchange = exchange;


if (exchange != null) {
SortedList<Stock> sortedStocks = new SortedList<>(exchange.getObservableStocks());
filteredStocksList = new FilteredList<>(exchange.getObservableStocks());

SortedList<Stock> 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)
);
});
}

}

/**
Expand Down
40 changes: 32 additions & 8 deletions millions/src/main/java/no/ntnu/gruppe53/view/PortfolioView.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
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;
import javafx.scene.control.ListCell;
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;
Expand Down Expand Up @@ -56,9 +54,11 @@ public class PortfolioView extends BorderPane {
private TextField tax;
private TextField total;
private TextField profit;
private TextField searchField;

//PortfolioListView
private ListView<Share> portfolioListView;
private FilteredList<Share> filteredPortfolioList;

private Player player;
private SaleCalculator saleCalculator;
Expand Down Expand Up @@ -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;" +
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -265,7 +280,7 @@ public Share getSelectedShare() {
/**
* Sets the player to be observed.
* <p>The values observed are the players portfolio and name.</p>
* <p>Uses an {@link ObservableList} to observe the shares and
* <p>Uses a {@link FilteredList} to get and filter the shares and
* binds it to the portfolioListView.</p>
*
* @param player the player to be observed
Expand All @@ -274,10 +289,19 @@ public void setPlayer(Player player) {
this.player = player;

if (player != null && player.getPortfolio() != null) {
ObservableList<Share> 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 {

Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -31,8 +32,12 @@ public class TransactionArchiveView extends BorderPane {
private final LanguageManager lm = LanguageManager.getInstance();

private ListView<Transaction> historyListView;
private FilteredList<Transaction> filteredTransactionList;

private Label titleLabel;

private TextField searchField;

/**
* Builds the view components and places them in the center pane.
*/
Expand Down Expand Up @@ -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;" +
Expand All @@ -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.
* <p>And puts the {@link TransactionArchive} into a {@link FilteredList} for searching.</p>
*
* @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);
}
Expand Down
1 change: 1 addition & 0 deletions millions/src/main/resources/i18n/lang.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# General
yes = Yes
no = No
search = Search:

# StartView
newGame = New Game
Expand Down
1 change: 1 addition & 0 deletions millions/src/main/resources/i18n/lang_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# General
yes = Yes
no = No
search = Search:

# StartView
newGame = New Game
Expand Down
1 change: 1 addition & 0 deletions millions/src/main/resources/i18n/lang_no.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# General
yes = Ja
no = Nei
search = Søk:

# StartView
newGame = Nytt Spill
Expand Down
6 changes: 4 additions & 2 deletions millions/target/classes/i18n/lang.properties
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -58,6 +59,7 @@ portfolioGross = Gross:
portfolioCommission = Commission:
portfolioTax = Tax:
portfolioTotal = Total:
portfolioProfit = Profit:
sellButton = Sell
portfolioShareQuantity = Qty:
portfolioBuyPrice = Buy price:
Expand All @@ -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.
Expand Down
4 changes: 3 additions & 1 deletion millions/target/classes/i18n/lang_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# General
yes = Yes
no = No
search = Search:

# StartView
newGame = New Game
Expand Down Expand Up @@ -58,6 +59,7 @@ portfolioGross = Gross:
portfolioCommission = Commission:
portfolioTax = Tax:
portfolioTotal = Total:
portfolioProfit = Profit:
sellButton = Sell
portfolioShareQuantity = Qty:
portfolioBuyPrice = Buy price:
Expand All @@ -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.
Expand Down
5 changes: 4 additions & 1 deletion millions/target/classes/i18n/lang_no.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# General
yes = Ja
no = Nei
search = Søk:

# StartView
newGame = Nytt Spill
Expand Down Expand Up @@ -58,6 +59,7 @@ portfolioGross = Brutto:
portfolioCommission = Kurtasje:
portfolioTax = Skatt:
portfolioTotal = Total:
portfolioProfit = Profitt:
sellButton = Selg
portfolioShareQuantity = Ant:
portfolioBuyPrice = Kjøpspris:
Expand All @@ -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.
Expand Down