shareList) {
model.getShareList().clear();
for (Share share : shareList) {
ShareComponent shareComponent = new ShareComponent(share);
+
+ if (share.getStock().getNewspaper().hasNewNews()) {
+ applyNewspaperGlow(shareComponent);
+ }
+
shareComponent.onShareSellButton((sellShare) -> holdingSale(sellShare));
shareComponent.onShareClick((stockSymbol) -> SceneManager.switchTo(SceneFactory.createStockView(stockSymbol)));
model.getShareList().add(shareComponent);
}
}
+ /**
+ * Method that applies glow effect to ShareComponent with new stock news.
+ *
+ * @param component - The chosen ShareComponent.
+ */
+ public void applyNewspaperGlow(ShareComponent component) {
+ DropShadow glow = new DropShadow(7, Color.WHITE);
+
+ Timeline timeline = new Timeline(
+ new KeyFrame(Duration.ZERO,
+ new KeyValue(glow.radiusProperty(), 10)),
+ new KeyFrame(Duration.seconds(0.5),
+ new KeyValue(glow.radiusProperty(), 50)));
+
+ timeline.setAutoReverse(true);
+ timeline.setCycleCount(Animation.INDEFINITE);
+
+ component.setEffect(glow);
+ timeline.play();
+ }
+
/**
* Method for initializing controller dependencies.
*
@@ -249,6 +283,13 @@ public void sortSharesBy(SortAction action) {
switch (action) {
+ case NEWS: {
+ sharesSorted.clear();
+ sharesSorted.addAll(session.getPlayer().getPortfolio().getShares()
+ .stream().filter(share -> share.getStock().getNewspaper().hasNewNews()).toList());
+ break;
+ }
+
case OLDEST: {
break;
}
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java
index 132dc30..b10d3a7 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioView.java
@@ -73,10 +73,12 @@ public Parent createHeader() {
return UIFactory.createHeader("Search after holdings..",
queryProperty -> searchQueryProperty = queryProperty,
List.of(
+ "New News",
"Oldest first",
"Newest first",
"Highest profit",
"Highest loss"),
+ () -> sortHandle.accept(SortAction.NEWS),
() -> sortHandle.accept(SortAction.OLDEST),
() -> sortHandle.accept(SortAction.NEWEST),
() -> sortHandle.accept(SortAction.PROFIT),
From 1ae529659575eb7097a1d97b4c1d99fb52fdb2b8 Mon Sep 17 00:00:00 2001
From: pawelsa
Date: Tue, 26 May 2026 18:26:37 +0200
Subject: [PATCH 5/8] feat: Add animation to menu
---
.../idatt/view/components/AbstractViewUI.java | 29 +++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java
index 93a9574..028b77c 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java
@@ -1,5 +1,8 @@
package edu.ntnu.idi.idatt.view.components;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Pos;
import javafx.scene.Parent;
@@ -9,6 +12,7 @@
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
+import javafx.util.Duration;
/**
* Abstract View UI class.
@@ -59,12 +63,12 @@ public AbstractViewUI() {
disableMenu.setVisible(false);
disableMenu.setOnMouseClicked(e -> {
- menu.setVisible(false);
+ animationMenu(false);
disableMenu.setVisible(false);
});
isMenuVisible.addListener((observer, oldVal, newVal) -> {
- menu.setVisible(true);
+ animationMenu(true);
disableMenu.setVisible(true);
});
@@ -165,4 +169,25 @@ public void toggleMenu() {
isMenuVisible.set(!isMenuVisible.get());
}
+ /**
+ * Method for animating the menu.
+ *
+ * @param val - in = true, out = false
+ */
+ private void animationMenu(boolean val) {
+ Timeline animation;
+ if (val) {
+ menu.setVisible(true);
+ menu.setTranslateX(menu.getWidth()); // Fix issue from menu initialization
+ // (hide before starting to appear no matter what)
+ animation = new Timeline(new KeyFrame(Duration.millis(200),
+ new KeyValue(menu.translateXProperty(), 0)));
+ } else {
+ animation = new Timeline(new KeyFrame(Duration.millis(200),
+ new KeyValue(menu.translateXProperty(), menu.getWidth())));
+ animation.setOnFinished((e) -> menu.setVisible(false));
+ }
+ animation.play();
+ }
+
}
From 2314fa1152dd5ac62c28e26623dc9109a1ab4a5b Mon Sep 17 00:00:00 2001
From: pawelsa
Date: Tue, 26 May 2026 18:26:56 +0200
Subject: [PATCH 6/8] feat: Add animation methods to CssUtils
---
.../ntnu/idi/idatt/view/util/CssUtils.java | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java b/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java
index 737d34f..c718c4c 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/util/CssUtils.java
@@ -2,7 +2,16 @@
import java.math.BigDecimal;
+import javafx.animation.Animation;
+import javafx.animation.FadeTransition;
+import javafx.animation.KeyFrame;
+import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
+import javafx.scene.Node;
import javafx.scene.Parent;
+import javafx.scene.effect.DropShadow;
+import javafx.scene.paint.Color;
+import javafx.util.Duration;
/**
* Utility CSS class.
@@ -69,4 +78,43 @@ public static String generateValueColors(double value) {
return value >= 0 ? GREEN : RED;
}
+ /**
+ * Method that applies glow effect of new news in newspaper.
+ *
+ * @param node - The node to animate.
+ */
+ public static void applyNewspaperGlow(Node node) {
+ DropShadow glow = new DropShadow(7, Color.WHITE);
+
+ Timeline timeline = new Timeline(
+ new KeyFrame(Duration.ZERO,
+ new KeyValue(glow.radiusProperty(), 10)),
+ new KeyFrame(Duration.seconds(0.5),
+ new KeyValue(glow.radiusProperty(), 50)));
+
+ timeline.setAutoReverse(true);
+ timeline.setCycleCount(Animation.INDEFINITE);
+
+ node.setEffect(glow);
+ timeline.play();
+ }
+
+ /**
+ * Method for creating a fade in animation.
+ *
+ * @param node - The node to animate
+ *
+ */
+ public static void fadeInAnimation(Node node) {
+ node.setOpacity(0.0);
+
+ FadeTransition fadeIn = new FadeTransition(Duration.seconds(0.5), node);
+ fadeIn.setFromValue(0.0);
+ fadeIn.setToValue(1.0);
+ fadeIn.setCycleCount(1);
+ fadeIn.setAutoReverse(false);
+
+ fadeIn.play();
+ }
+
}
From 00fe9109d2c9ceece2603cd0527143fb64c329e9 Mon Sep 17 00:00:00 2001
From: pawelsa
Date: Tue, 26 May 2026 18:27:22 +0200
Subject: [PATCH 7/8] chore: Unbind navigation to itself from menu
---
.../idi/idatt/view/primary/transactions/TransactionView.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java
index 07a7d8c..0aef86f 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionView.java
@@ -108,7 +108,8 @@ public Parent createMenu() {
return UIFactory.createMenu("Account",
List.of("Portfolio", "Transactions"),
() -> SceneManager.switchTo(SceneFactory.createPortfolioView()),
- () -> SceneManager.switchTo(SceneFactory.createTransactionView()));
+ () -> {
+ });
}
From ed191643435835bb82763d9de51e0f0ca20225e2 Mon Sep 17 00:00:00 2001
From: pawelsa
Date: Tue, 26 May 2026 18:27:56 +0200
Subject: [PATCH 8/8] feat: Add fade in animations for asthetics
---
.../idatt/view/components/ui/UIFactory.java | 5 +++-
.../ntnu/idi/idatt/view/entry/StartView.java | 3 +++
.../primary/exchange/ExchangeController.java | 24 ++---------------
.../portfolio/PortfolioController.java | 26 +++----------------
.../view/primary/stock/StockController.java | 1 +
.../transactions/TransactionController.java | 7 ++++-
6 files changed, 20 insertions(+), 46 deletions(-)
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java b/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java
index 97e9120..25ed060 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/components/ui/UIFactory.java
@@ -192,7 +192,10 @@ private static Parent createDefaultNavigation(Label titleLabel, List but
.properties(nav -> nav.setPadding(new Insets(40)))
.addContent(titleLabel);
- buttons.forEach(b -> navigationBuilder.addContent(b));
+ buttons.forEach(b -> {
+ navigationBuilder.addContent(b);
+ CssUtils.fadeInAnimation(b);
+ });
navigationBuilder
.filler();
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java
index 3f05ecf..7b51f10 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java
@@ -3,6 +3,7 @@
import java.util.List;
import edu.ntnu.idi.idatt.view.components.AbstractView;
+import edu.ntnu.idi.idatt.view.util.CssUtils;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
@@ -145,6 +146,8 @@ public void setModel(StartModel model) {
this.errorLabel.textProperty().bind(model.getError());
this.fileLabel.textProperty().bind(model.getFileName());
this.newGameWrapper.visibleProperty().bind(model.isNewGame());
+ this.newGameWrapper.visibleProperty()
+ .addListener((obs) -> this.newGameWrapper.getChildren().forEach(c -> CssUtils.fadeInAnimation(c)));
this.csvPredefinedCheckBox.selectedProperty().bindBidirectional(model.isPredefinedCSV());
// Binding importCsvWrapper visibleProperty here for convenience
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java
index cd317d1..af9df1b 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/exchange/ExchangeController.java
@@ -9,6 +9,7 @@
import edu.ntnu.idi.idatt.view.SceneManager;
import edu.ntnu.idi.idatt.view.components.AbstractController;
import edu.ntnu.idi.idatt.view.components.elements.StockComponent;
+import edu.ntnu.idi.idatt.view.util.CssUtils;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
@@ -80,7 +81,7 @@ public void setStocksModel(List stockList) {
StockComponent stockComponent = new StockComponent(stock);
if (stock.getNewspaper().hasNewNews()) {
- applyNewspaperGlow(stockComponent);
+ CssUtils.applyNewspaperGlow(stockComponent);
}
stockComponent.onStockClick((symbol) -> redirectView(symbol));
@@ -88,27 +89,6 @@ public void setStocksModel(List stockList) {
}
}
- /**
- * Method that applies glow effect to StockComponent with new news.
- *
- * @param component - The chosen StockComponent.
- */
- public void applyNewspaperGlow(StockComponent component) {
- DropShadow glow = new DropShadow(7, Color.WHITE);
-
- Timeline timeline = new Timeline(
- new KeyFrame(Duration.ZERO,
- new KeyValue(glow.radiusProperty(), 10)),
- new KeyFrame(Duration.seconds(0.5),
- new KeyValue(glow.radiusProperty(), 50)));
-
- timeline.setAutoReverse(true);
- timeline.setCycleCount(Animation.INDEFINITE);
-
- component.setEffect(glow);
- timeline.play();
- }
-
/**
* Method to handle searchbar query.
*
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java
index fe39f99..3279774 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/portfolio/PortfolioController.java
@@ -81,36 +81,17 @@ public void setShareModel(List shareList) {
ShareComponent shareComponent = new ShareComponent(share);
if (share.getStock().getNewspaper().hasNewNews()) {
- applyNewspaperGlow(shareComponent);
+ CssUtils.applyNewspaperGlow(shareComponent);
}
+ CssUtils.fadeInAnimation(shareComponent);
+
shareComponent.onShareSellButton((sellShare) -> holdingSale(sellShare));
shareComponent.onShareClick((stockSymbol) -> SceneManager.switchTo(SceneFactory.createStockView(stockSymbol)));
model.getShareList().add(shareComponent);
}
}
- /**
- * Method that applies glow effect to ShareComponent with new stock news.
- *
- * @param component - The chosen ShareComponent.
- */
- public void applyNewspaperGlow(ShareComponent component) {
- DropShadow glow = new DropShadow(7, Color.WHITE);
-
- Timeline timeline = new Timeline(
- new KeyFrame(Duration.ZERO,
- new KeyValue(glow.radiusProperty(), 10)),
- new KeyFrame(Duration.seconds(0.5),
- new KeyValue(glow.radiusProperty(), 50)));
-
- timeline.setAutoReverse(true);
- timeline.setCycleCount(Animation.INDEFINITE);
-
- component.setEffect(glow);
- timeline.play();
- }
-
/**
* Method for initializing controller dependencies.
*
@@ -169,6 +150,7 @@ public void showReciept(Sale sale) {
});
model.instanceChildren().add(reciept);
+ CssUtils.fadeInAnimation(reciept);
}
/**
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java
index cfd7b42..fbb5a22 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/stock/StockController.java
@@ -197,6 +197,7 @@ public void showReciept(Purchase purchase) {
});
model.instanceChildren().add(reciept);
+ CssUtils.fadeInAnimation(reciept);
}
/**
diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java
index 1fa4867..4e23523 100644
--- a/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java
+++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/transactions/TransactionController.java
@@ -11,6 +11,7 @@
import edu.ntnu.idi.idatt.session.UserSession;
import edu.ntnu.idi.idatt.view.components.AbstractController;
import edu.ntnu.idi.idatt.view.components.elements.TransactionComponent;
+import edu.ntnu.idi.idatt.view.util.CssUtils;
/**
* Controller class of the Transaction MVC.
@@ -74,7 +75,11 @@ public void initController() {
public void setTransactionModel(List list) {
model.getTransactionList().clear();
for (Transaction transaction : list) {
- model.getTransactionList().add(new TransactionComponent(transaction));
+ TransactionComponent transactionComponent = new TransactionComponent(transaction);
+
+ CssUtils.fadeInAnimation(transactionComponent);
+
+ model.getTransactionList().add(transactionComponent);
}
}