From e1bc41a958e9cf55d80dff06cd9f6b0f1ae53a48 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sat, 25 Apr 2026 19:11:45 +0200 Subject: [PATCH 01/13] refactor: Primary package -> Entry Package. Primary*.java -> Entry*.java --- src/main/java/edu/ntnu/idi/idatt/Launcher.java | 12 ++++++------ .../StartController.java} | 6 +++--- .../PrimaryModel.java => entry/StartModel.java} | 4 ++-- .../PrimaryView.java => entry/StartView.java} | 10 +++++----- 4 files changed, 16 insertions(+), 16 deletions(-) rename src/main/java/edu/ntnu/idi/idatt/view/{primary/PrimaryController.java => entry/StartController.java} (87%) rename src/main/java/edu/ntnu/idi/idatt/view/{primary/PrimaryModel.java => entry/StartModel.java} (88%) rename src/main/java/edu/ntnu/idi/idatt/view/{primary/PrimaryView.java => entry/StartView.java} (94%) diff --git a/src/main/java/edu/ntnu/idi/idatt/Launcher.java b/src/main/java/edu/ntnu/idi/idatt/Launcher.java index 18a6b15..f13f7fd 100644 --- a/src/main/java/edu/ntnu/idi/idatt/Launcher.java +++ b/src/main/java/edu/ntnu/idi/idatt/Launcher.java @@ -2,9 +2,9 @@ import edu.ntnu.idi.idatt.storage.CSVtoJSON; import edu.ntnu.idi.idatt.view.SceneManager; -import edu.ntnu.idi.idatt.view.primary.PrimaryController; -import edu.ntnu.idi.idatt.view.primary.PrimaryModel; -import edu.ntnu.idi.idatt.view.primary.PrimaryView; +import edu.ntnu.idi.idatt.view.entry.StartController; +import edu.ntnu.idi.idatt.view.entry.StartModel; +import edu.ntnu.idi.idatt.view.entry.StartView; import javafx.application.Application; import javafx.stage.Stage; @@ -25,9 +25,9 @@ public void start(Stage stage) { stage.setHeight(700); stage.setTitle("Stock Game"); - PrimaryModel model = new PrimaryModel(); - PrimaryView view = new PrimaryView(); - PrimaryController controller = new PrimaryController(model); + StartModel model = new StartModel(); + StartView view = new StartView(); + StartController controller = new StartController(model); view.setModel(model); view.setController(controller); diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryController.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java similarity index 87% rename from src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryController.java rename to src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java index 2fe27fa..a57215c 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryController.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java @@ -1,4 +1,4 @@ -package edu.ntnu.idi.idatt.view.primary; +package edu.ntnu.idi.idatt.view.entry; import java.io.File; import java.math.BigDecimal; @@ -6,11 +6,11 @@ import edu.ntnu.idi.idatt.view.components.AbstractController; import javafx.stage.FileChooser; -public class PrimaryController extends AbstractController { +public class StartController extends AbstractController { private File csv; - public PrimaryController(PrimaryModel model) { + public StartController(StartModel model) { super(model); } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryModel.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java similarity index 88% rename from src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryModel.java rename to src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java index 440ea91..e1b0f92 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryModel.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartModel.java @@ -1,10 +1,10 @@ -package edu.ntnu.idi.idatt.view.primary; +package edu.ntnu.idi.idatt.view.entry; import edu.ntnu.idi.idatt.view.components.Model; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -public class PrimaryModel implements Model { +public class StartModel implements Model { private final StringProperty name = new SimpleStringProperty(); private final StringProperty balance = new SimpleStringProperty(); diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java similarity index 94% rename from src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java rename to src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java index c107572..60180b1 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/PrimaryView.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartView.java @@ -1,4 +1,4 @@ -package edu.ntnu.idi.idatt.view.primary; +package edu.ntnu.idi.idatt.view.entry; import java.util.List; @@ -15,7 +15,7 @@ import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; -public class PrimaryView extends AbstractView { +public class StartView extends AbstractView { // Globlal variables for model implementation private TextField nameField; @@ -27,7 +27,7 @@ public class PrimaryView extends AbstractView { private Button csvButton; private Button startButton; - public PrimaryView() { + public StartView() { super(new StackPane()); this.getInstance().getStyleClass().add("dark"); } @@ -106,14 +106,14 @@ public Parent createContent() { return root; } - public void setModel(PrimaryModel model) { + public void setModel(StartModel model) { this.nameField.textProperty().bindBidirectional(model.getName()); this.balanceField.textProperty().bindBidirectional(model.getBalance()); this.errorLabel.textProperty().bind(model.getError()); this.fileLabel.textProperty().bind(model.getFileName()); } - public void setController(PrimaryController controller) { + public void setController(StartController controller) { this.csvButton.setOnAction(e -> controller.obtainCSVFile()); this.startButton.setOnAction(e -> controller.initializeGame()); } From af1390625010fb21727a9b6792d1e6f3f635241f Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sat, 25 Apr 2026 21:20:14 +0200 Subject: [PATCH 02/13] feat: Add singleton class for holding user session. --- .../ntnu/idi/idatt/session/UserSession.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/edu/ntnu/idi/idatt/session/UserSession.java diff --git a/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java b/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java new file mode 100644 index 0000000..c8a2863 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/session/UserSession.java @@ -0,0 +1,31 @@ +package edu.ntnu.idi.idatt.session; + +import edu.ntnu.idi.idatt.model.player.Player; + +public class UserSession { + + // Singleton instance + private static UserSession INSTANCE; + + // Disable constructor initialization. + private UserSession() { + } + + public static UserSession getInstance() { + if (INSTANCE == null) { + INSTANCE = new UserSession(); + } + return INSTANCE; + } + + private Player player; + + public Player getPlayer() { + return player; + } + + public void setPlayer(Player player) { + this.player = player; + } + +} From 9a919229b037a95b39f127338e19c500d826aeda Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sat, 25 Apr 2026 21:25:23 +0200 Subject: [PATCH 03/13] feat: Add abstract class for main UI creation --- .../idatt/view/components/AbstractViewUI.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java 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 new file mode 100644 index 0000000..76a5375 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractViewUI.java @@ -0,0 +1,72 @@ +package edu.ntnu.idi.idatt.view.components; + +import javafx.scene.Parent; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; + +public abstract class AbstractViewUI extends AbstractView { + + private VBox navigation; + private HBox header; + private HBox toolbar; + + public AbstractViewUI() { + HBox wrapper = new HBox(); + BorderPane layout = new BorderPane(); + + createUIComponents(); + navigation.getChildren().add(createNavigation()); + header.getChildren().add(createHeader()); + toolbar.getChildren().add(createToolbar()); + + layout.setTop(header); + layout.setBottom(toolbar); + layout.setCenter(createContent()); + + HBox.setHgrow(layout, Priority.ALWAYS); + wrapper.getChildren().addAll(navigation, layout); + + this.setInstance(new StackPane()); + this.getInstance().getChildren().add(wrapper); + } + + public void createUIComponents() { + navigation = new VBox(); + navigation.setMaxHeight(Double.MAX_VALUE); + navigation.getStyleClass().add("dark"); + navigation.setPrefWidth(150); + + header = new HBox(); + header.getStyleClass().add("light"); + header.setPrefHeight(80); + + toolbar = new HBox(); + toolbar.getStyleClass().add("light"); + HBox.setHgrow(toolbar, Priority.ALWAYS); + toolbar.setPrefHeight(80); + } + + public abstract Parent createContent(); + + public abstract Parent createNavigation(); + + public abstract Parent createHeader(); + + public abstract Parent createToolbar(); + + public VBox getNavigation() { + return navigation; + } + + public HBox getHeader() { + return header; + } + + public HBox getToolbar() { + return toolbar; + } + +} From dcde2c651d3ce3b6340122c127c19adcfc9c252b Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sat, 25 Apr 2026 21:27:17 +0200 Subject: [PATCH 04/13] refactor(AbstractView): Modify instance initialization methods --- .../idi/idatt/view/components/AbstractView.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractView.java b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractView.java index 18d51a2..b4f96ec 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractView.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/AbstractView.java @@ -36,11 +36,18 @@ public abstract class AbstractView { /** * Constructor for AbstractView. */ - public AbstractView(T type) { + protected AbstractView(T type) { instance = type; instance.getChildren().add(this.createContent()); } + /** + * Constructor for AbstractView without initialization. + */ + protected AbstractView() { + + } + /** * Getter for current view instance. * @@ -50,6 +57,13 @@ public T getInstance() { return instance; } + /** + * Setter for current view instance. + */ + public void setInstance(T instance) { + this.instance = instance; + } + /** * Abstract method for creating view content. */ From e7da7e24cccfd7f629c353ef559a36f36d0f60d7 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sat, 25 Apr 2026 21:28:50 +0200 Subject: [PATCH 05/13] refactor: Create example of MainView --- .../idi/idatt/view/entry/StartController.java | 11 ++++++- .../ntnu/idi/idatt/view/primary/MainView.java | 31 ++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java index a57215c..52f7eeb 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/entry/StartController.java @@ -3,7 +3,11 @@ import java.io.File; import java.math.BigDecimal; +import edu.ntnu.idi.idatt.model.player.Player; +import edu.ntnu.idi.idatt.session.UserSession; +import edu.ntnu.idi.idatt.view.SceneManager; import edu.ntnu.idi.idatt.view.components.AbstractController; +import edu.ntnu.idi.idatt.view.primary.MainView; import javafx.stage.FileChooser; public class StartController extends AbstractController { @@ -35,8 +39,9 @@ public void initializeGame() { return; } + BigDecimal balance = null; try { - BigDecimal balance = new BigDecimal(model.getBalance().get()); + balance = new BigDecimal(model.getBalance().get()); } catch (NumberFormatException e) { model.getError().set("The balance must be a number format!"); return; @@ -46,6 +51,10 @@ public void initializeGame() { model.getError().set("Specify the stocks .csv file!"); return; } + + UserSession.getInstance().setPlayer(new Player(model.getName().get(), balance)); + SceneManager.switchTo(new MainView().getInstance()); + } } diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java index cede902..cb0869b 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java @@ -1,12 +1,15 @@ package edu.ntnu.idi.idatt.view.primary; +import edu.ntnu.idi.idatt.session.UserSession; import edu.ntnu.idi.idatt.view.components.AbstractView; +import edu.ntnu.idi.idatt.view.components.AbstractViewUI; import javafx.geometry.Pos; import javafx.scene.Parent; +import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.scene.transform.Scale; - +/* public class MainView extends AbstractView { public MainView() { @@ -32,3 +35,29 @@ public Parent createContent() { return main; } } +*/ + +public class MainView extends AbstractViewUI { + + @Override + public Parent createContent() { + return new Label("Hello " + UserSession.getInstance().getPlayer().getName() + " " + + UserSession.getInstance().getPlayer().getNetWorth()); + } + + @Override + public Parent createNavigation() { + return new Label("Hello from nav"); + } + + @Override + public Parent createHeader() { + return new Label("Header"); + } + + @Override + public Parent createToolbar() { + return new Label("Toolbar"); + } + +} From 9643c68005c04935ff095e0304cf185a5818d47a Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 11:33:51 +0200 Subject: [PATCH 06/13] feat: Add basic icon package --- src/main/resources/icons/portfolio.png | Bin 0 -> 2809 bytes src/main/resources/icons/quit.png | Bin 0 -> 1893 bytes src/main/resources/icons/search.png | Bin 0 -> 1691 bytes src/main/resources/icons/user.png | Bin 0 -> 3189 bytes src/main/resources/logo.png | Bin 8691 -> 0 bytes src/main/resources/stonks.png | Bin 20446 -> 0 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/icons/portfolio.png create mode 100644 src/main/resources/icons/quit.png create mode 100644 src/main/resources/icons/search.png create mode 100644 src/main/resources/icons/user.png delete mode 100644 src/main/resources/logo.png delete mode 100644 src/main/resources/stonks.png diff --git a/src/main/resources/icons/portfolio.png b/src/main/resources/icons/portfolio.png new file mode 100644 index 0000000000000000000000000000000000000000..2f33093aad300d1e6b43aa2303d113e3902b64ce GIT binary patch literal 2809 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/icons/search.png b/src/main/resources/icons/search.png new file mode 100644 index 0000000000000000000000000000000000000000..a206015495c28cbc96d86ea7ad0323873a632c6b GIT binary patch literal 1691 zcmV;M24wk(P)Px*MM*?KRCt{2ol9&LRUC)E3fz)_MNCX|BjFY*CW7?V zM;}y)8)Fqy3&glFAw~_p663-cBe<6~ihxG=^@P#12*YLr4ZxWGqU83mOn&_W{g z_FZ387iSE2&Y9^wmpf<9nS0NdOw!X%@A>`bH*?-|E_gg1kH_Qjc#@~Vwty1W0`0&$ zpe0CO4y**01?S8FMPLf}2{;b?02~d{o+?-hYy;i}P67W`d7KPBYb(&0VjP*L0PF?E zsNRIQV+?o`XiX`mOwt7$0Om1gMAUHvxFd!55+RK`q#1YvxU0;0(};^V3>*uN-w}1j zOmNOJM4fUK7weh=(9OkqCXNB%Dd0rK5!47dU^g&F{M|bWyn=XomQ<0~lHfC54L&n2 zzgb{cpslXR178z=VGbdlm_-KiUIg?6dBo-a6|mYs-cHg7j1zq!J_l}1QA-DKFh)xe z=uJ_J6`lYtpawqzJZMqZ7T~uCUGu;*7Ihh;0eFe%J8>VPgJ+v2U_a3s`*Ew2Ts2W< z%mNSD6cxiGL^m}0ZHh{g$A~VUyKRapLpyK|Rrk|2MI}KWYMpTg*kDtXCL0i1OSNAh z!xjB1;5^}g#(|ACMODZRs6#kKGT0=}q4qOoal4p`<95_KI!>+&dS zJTF*PQ~}MXchm<~6(z%as84*}sv=E3B`o|DZuB#%r3pAqIJN^;6=~3c`e<*pswi3R zM~$z`s-iM{hB`J?YYY;Oalo#ecnYX@PrFq`X6Qs6?{aeHaW7$^gLdT@Wr%RBd+f?l zS&G_$DmMd|WqJt5dLG9XPHZPEa1=9>ORlgOby%e@jf^kTJa3DX-iH|Xsa5^~-j{xN zj}0Ml$m^y$?aE1oZo)DDYE?}MErf+lQQd-stdK*jgei@^*>t8lMV34Vegyd2fEL&I z3;0s{o$+SAjv?!$^tUF2ILfe;zRq-pI)=z1j+qeRC~~Y$7$TRO$4v-v6xon9rZdzr zWTlioYeI;l$g#@TB5`yKk%!i&ObBrlIaVj88U7^P^vl%LW|cG&j{OhQ8S3`bJp$v4 z>2wU4meR{j2yv9ui)$T2oGeFEqDe~2H)rDL7*dqd*O(CEC|67AbEY%YG2|C1-C{zB zqsSdW`C257jv+rvY2&?Bhj7vmxwqP8LWrXjr1bYzR7k8P+!mjqKKde2!|$uCDk|Y5 z8Ct895VsMIc_fWYbvuSbQu@B6g*b>Dqf@JFwo!kJ9L^Gs`ChAvBpOkd0rgl_WR|-L z$2y5v3gr~?Lb*eBZoWIS%K(ll*ab4RYjWQ5wCld3g2&4Q8IjpIy-p1 zRYeuB3-!@{*s7xH*ohj?^HvpANDi^ZQE32kh~b8;u^I6+l*Tel2A9iTi@I^Z1dhIK z6vKMd4(}uxDyn39$?nz~H=@1+GLK_JB$vXIsO4`Fw~MdML~pV-3v99{D>?d6gPTKa zh2$DLQR@u3$a22#QH}_R_f1!~i_rcD8Ooain7MzO!epFGJ{?wCdtZJDPR zQHMkYIY_#%!*!vKO;vJCrmWW(s}Wlq#RYm8F`r^$l4~(yK4WNs{J%pi0IVxha)>RC z`sCq|=MbiCLR@SeQzodPsfIjaSDkV}&mi_rc^TM& zxBz+JO2h@v1wZG5zwHRl{UZ3^a-aVZ>I*k@YYK?Ret>j0*C8b+R*<> zrg75!#)rDao8lne6bJF9I7l1%{U&cpN))Kflw0h`tS`JN4&qI55O0cucvBpt6@62R zz|D4K))(Fs2l1vj$W7??=%2NuvF>Ok`uh<}kKNYP)hQc^H^rM_i6~RN8I~zE#hc*> l1$+hW@pwEQkH_Nx{{hHo(253myc+-j002ovPDHLkV1j910vG@Q literal 0 HcmV?d00001 diff --git a/src/main/resources/icons/user.png b/src/main/resources/icons/user.png new file mode 100644 index 0000000000000000000000000000000000000000..0534bddc47d6b3efb3ba3cacfcc6191f2e2ec3f4 GIT binary patch literal 3189 zcmV-*42tuKP)Px>A4x<(RCt{2oqLp3RT;p4cV?U!UOI_Ah{y0yz#c|v zSb;p`QPDEV%1l8N7iFsltK}k1D_9FHEDVK}E0!w_h$tocr$2g_R*q?3d+t4ZpF2bMx7JygGu-=q-#Po7y}$kKZ|@BiDpaUYp+ae7 z%56XlYJt(f7~kgzpg+*yefIOd+YYn=E#AL(13Q5K_&z&Qw7qD0Vu4fxs1RMdnQ#uX84TPB>><5E2s`!wOFf&) zM!BAfk-)9MJfJSd_xA!@f$f}b3l4in8`55Yv?aN=rGe9J&RF1Gz_1v)P69s#?nc_6 zGn(PRIv`8*)4C5>3*6}a#-{%Ho(=m7*pLO*5U&t>9cKXxfmXtAz%k%q;0mB71)HjX ziNI>$XoOwuz!KuU$-RQhfo+6e@OI>>?H48>1^Rh5>>%9Et%&2%YpFq=tWJV2@L$07 zh@0C}s6yV*e-LbQ7jPf)#`h|Q0e>aSl5id2 z1=5Ygu|AMc$85~Ex`}jRa{K`EqP~()W({V%>mX7{Nyz}`BX7$J;0;Xsn}Hz-^#nOL z%M!{g$TZ9<V7buyXo-P;kK?+7+$1f7f&0zLZx`3$(<%Uv+L}qp4n6%TE@#OgB zu1Y8~4&T9iqLW4w8ZdkGTM?(jI(H~VS;U1*%0wmi81N1Yato2cYzrT-Aoo(t_T)AT za`PC0+$g`2do9UcuH;ulWBwIhFpSC174%L{A z{QE7)ZNLoOudyH(5D!Jaf}gh}y9(3Q9b`#%Tz;+e-(*SdTqQS)rSQ!IO7Ldv4K58< zvfr>Iw-}Zx87_=SEZsZbx|mF(v%%8tv;%7!0Xl>Ip+`ve8@ zzN!ic{1W*t+cscR0s}QVEPlwM?6`EP^FsHe7&an_6FKUTdm2iV@+x4C`rG$0FCYop zKR;zrc3gDzYqLN)k$dK6PLz%)0*O>iiL;FJhB6b^dnC^5dX&zGhi|J7zUMw^$*ynAv<&l3EtPP^IIb1098UNZIgZ z2Rf!H9Y-iKw@ZgJUdC?SnxmThJl`(TueKg1|5}p{BLq=}nM?eUurCI2xjO$Nb{q2? zok(VTjtuF>?o$C6qU!9Ue`(jnktXe9puXho(vxZrVh z9=ky5fe#fBW|L>td724zTGwXW)C6F@ArlA~(+?_;G3txEkv7B?o7MSvhq^S{{cLim z>m~2VQIAY0$|I~m{A{skR1nXo^GirC5&Prn{P&La{ac-vR3NVE)ErqPYa_?GNP3TJ z#v+mI9NkE0$R*lg&<;hc0&(GW__+%+rj<0&E)G|y^9+)*>Joh~W2GQ9k?${0wrrH2 zdd!i?JH5ZVrXG11{JPt5J9TZU()UE1AL*p#_qehS$%pdma$RKvp%XW3j2MP-k<#_N z{z6cdH9(!W+PCXXbRt=M;J4hO<7qCZtLb~G?{y$LMf6M?GYHzPG`zS?BQyr7w55?2v8=(fKilIzjHGU*CZ^KiaK+)ac4O zj|}i<%$su*H$Cq_>=-6=jv}uuroER2ALD$XFchzxmZ#peH@xLZSBY|k z&{GAnCCJcK)y>wdi%%8i8$Y2K0kxQ~`4p=r#-oq2p_J@+-TO~tG*S~gl{DaEN3hIrA&v=BZ9GpO)WBC>EBC&_V{ikY+DjxB``?of4u}5dfIcE$=p?# zNfh5pBGC1u&qAE9be9q}(7oeP)~qYc)k=2<7RHwzR6?I6y;RQ|lq9k$i6K^=1#;5vh515 zRC?O6yX^*Gt}m5EmLf{Zg~%#(uMvFHx{+blB<)rP_+fnSCNY9KP(Rj&l3kE6&FY>S(S-YcXVnXj@Ccv}hb--5Y)({>ytaL>f-`NmyL zpbq#H5|Yubv_4J(_v2<9W(e>j%r;6NS>QLwdL?lq6dRR{F5E3u_$DhbjgMMVd@xca z1?`xij~1lJZcBIt?eUVYds13vXjd%FCH)+xSAuz`1!(zeE zbeGJq&83(FO}PfV>}^INW?_cSbA6Q+ly^tZV(E``9)tQPhbW^rRV*WbzY|>7?nV}3 zE=QhMT&j@moc0iW4Nv1Bdh41Rr1KQ!7HN%$B?H?n}) z0_^TNSS@_k4eYZ}#AH8M|qCBbc8?l^{QGIqvn z-|c4<;yQ-yAe}p!k#*9qrohtNMKaivxtiz!v78gKo|I!!<*L6&1K&h8?1~c+-HSA& zFCv3tyO1QlHe_7mu=l+NBx2kT39pazjth`w3*+qJkwwP8mwEdBuNaOj#jP{L%W=Gd zBnCFRyx`tKHPZO6!_HQ#agSCcO=t!^#0~FhE+>e){656}oQ^c|wi?t^h$r=^cRWGN z^+wX7Cl-jNFS0h_Xzz0j($Ee-deQ?pooI0wdFtD|&s~VSx&ukj*hc>Pjuk3Ys8FH8 b8N>eo8=(qLl)QVr00000NkvXXu0mjfYrX

cJR;2{X)$ovejy5oJrZvWMbPAxo%G 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 B=uiLv From ff7e3c34b8bf215b916c1b94cfdc91bb27c4f9a6 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 13:28:28 +0200 Subject: [PATCH 07/13] feat: Implement SearchBarComponent --- .../elements/SearchBarComponent.java | 49 +++++++++++++++++++ .../ntnu/idi/idatt/view/primary/MainView.java | 6 ++- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java new file mode 100644 index 0000000..0493b21 --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java @@ -0,0 +1,49 @@ +package edu.ntnu.idi.idatt.view.components.elements; + +import javafx.beans.property.SimpleStringProperty; +import javafx.beans.property.StringProperty; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.HBox; + +public class SearchBarComponent extends HBox { + + private final StringProperty query = new SimpleStringProperty(); + private final Button searchButton; + + public SearchBarComponent(String placeholder) { + TextField searchBar = new TextField(); + searchBar.setPromptText(placeholder); + searchBar.getStyleClass().add("button"); + searchBar.textProperty().bindBidirectional(query); + searchBar.setFocusTraversable(false); + + Image image = new Image(this.getClass().getResource("/icons/search.png/").toExternalForm()); + ImageView iv = new ImageView(); + iv.setImage(image); + + iv.setFitHeight(40); + iv.setFitWidth(40); + + searchButton = new Button("", iv); + searchButton.getStyleClass().clear(); // TODO: Make icon component or fix + + this.getChildren().addAll(searchBar, searchButton); + } + + public String getQuery() { + return query.get(); + } + + public void onSearchQuery(ActionEventHandler handler) { + this.searchButton.setOnAction(e -> handler.handle()); + } + + @FunctionalInterface + public interface ActionEventHandler { + void handle(); + } + +} diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java index cb0869b..09e1e17 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java @@ -3,6 +3,7 @@ import edu.ntnu.idi.idatt.session.UserSession; import edu.ntnu.idi.idatt.view.components.AbstractView; import edu.ntnu.idi.idatt.view.components.AbstractViewUI; +import edu.ntnu.idi.idatt.view.components.elements.SearchBarComponent; import javafx.geometry.Pos; import javafx.scene.Parent; import javafx.scene.control.Label; @@ -52,7 +53,10 @@ public Parent createNavigation() { @Override public Parent createHeader() { - return new Label("Header"); + this.getHeader().setAlignment(Pos.BASELINE_CENTER); + SearchBarComponent bar = new SearchBarComponent("Search after stocks.."); + bar.onSearchQuery(() -> System.out.println(bar.getQuery())); + return bar; } @Override From a3d28017af83b272c31240454eb036db795fea06 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 23:02:41 +0200 Subject: [PATCH 08/13] feat(AbstractViewUI): Implement togglable menu solution --- .../idatt/view/components/AbstractViewUI.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) 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 76a5375..1b7b889 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,9 +1,12 @@ package edu.ntnu.idi.idatt.view.components; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.geometry.Pos; import javafx.scene.Parent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; @@ -12,6 +15,7 @@ public abstract class AbstractViewUI extends AbstractView { private VBox navigation; private HBox header; private HBox toolbar; + private SimpleBooleanProperty isMenuVisible = new SimpleBooleanProperty(false); public AbstractViewUI() { HBox wrapper = new HBox(); @@ -30,7 +34,25 @@ public AbstractViewUI() { wrapper.getChildren().addAll(navigation, layout); this.setInstance(new StackPane()); - this.getInstance().getChildren().add(wrapper); + + Parent menu = createMenu(); + StackPane.setAlignment(menu, Pos.CENTER_RIGHT); + menu.setVisible(false); + + Region disableMenu = new Region(); + disableMenu.setVisible(false); + + disableMenu.setOnMouseClicked(e -> { + menu.setVisible(false); + disableMenu.setVisible(false); + }); + + isMenuVisible.addListener((observer, oldVal, newVal) -> { + menu.setVisible(true); + disableMenu.setVisible(true); + }); + + this.getInstance().getChildren().addAll(wrapper, disableMenu, menu); } public void createUIComponents() { @@ -57,6 +79,8 @@ public void createUIComponents() { public abstract Parent createToolbar(); + public abstract Parent createMenu(); + public VBox getNavigation() { return navigation; } @@ -69,4 +93,8 @@ public HBox getToolbar() { return toolbar; } + public void toggleMenu() { + isMenuVisible.set(!isMenuVisible.get()); + } + } From e86dd10fd18f5951e3b748732c51a4e061b51327 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 23:02:58 +0200 Subject: [PATCH 09/13] chore: Update .css stylesheet --- src/main/resources/themes/default.css | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/resources/themes/default.css b/src/main/resources/themes/default.css index 2e79159..a372c2b 100644 --- a/src/main/resources/themes/default.css +++ b/src/main/resources/themes/default.css @@ -30,7 +30,6 @@ -fx-font-size: 16px; -fx-font-weight: 700; -fx-text-fill: #EEEEEE; - -fx-padding: 30px; } /* ======================= @@ -51,3 +50,26 @@ -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.4), 8, 0.4, 0, 4); -fx-translate-y: 1; } + +.icon { + -fx-border-radius: 20; + -fx-padding: 5; + -fx-cursor: hand; +} + +.searchbar { + -fx-background-color: #FFFFFF; + -fx-background-radius: 20; + -fx-border-radius: 20; + -fx-effect: dropshadow(gaussian, rgba(0,0,0,0.3), 6, 0.3, 0, 2); +} + +.searchbar-field { + -fx-font-size: 16px; + -fx-text-fill: black; + -fx-background-color: #FFFFFF; + -fx-background-radius: 20; + -fx-border-radius: 20; + -fx-cursor: hand; +} + From 3c60893d1de4fd5df59a37ff5b30493e92faef20 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 23:03:31 +0200 Subject: [PATCH 10/13] feat: Add functional interface for event handeling --- .../view/components/primitives/ActionEventHandler.java | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/java/edu/ntnu/idi/idatt/view/components/primitives/ActionEventHandler.java diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/primitives/ActionEventHandler.java b/src/main/java/edu/ntnu/idi/idatt/view/components/primitives/ActionEventHandler.java new file mode 100644 index 0000000..a42993d --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/primitives/ActionEventHandler.java @@ -0,0 +1,6 @@ +package edu.ntnu.idi.idatt.view.components.primitives; + +@FunctionalInterface +public interface ActionEventHandler { + void handle(); +} From 3f8b74e95e569d8b2e8c1ea20a9ca26d1a7504f6 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 23:04:05 +0200 Subject: [PATCH 11/13] feat: Implement IconComponent class --- .../components/elements/IconComponent.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java new file mode 100644 index 0000000..a3ef67a --- /dev/null +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/IconComponent.java @@ -0,0 +1,32 @@ +package edu.ntnu.idi.idatt.view.components.elements; + +import edu.ntnu.idi.idatt.view.components.primitives.ActionEventHandler; +import javafx.scene.control.Button; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.StackPane; + +public class IconComponent extends StackPane { + + private Button icon; + + public IconComponent(Image image, String description, int size) { + + ImageView iv = new ImageView(); + iv.setImage(image); + iv.setFitHeight(size); // TODO: Fix? + iv.setFitWidth(size); + + icon = new Button(description, iv); + icon.getStyleClass().clear(); // Remove parent buffers in case. + icon.getStyleClass().add("icon"); + icon.setMaxHeight(Double.MAX_VALUE); + + this.getChildren().add(icon); + } + + public void onIconClick(ActionEventHandler handler) { + this.icon.setOnAction(e -> handler.handle()); + } + +} From ff5e1bf12b5d8df0315e80441f6c08d9fa24de4c Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 23:04:52 +0200 Subject: [PATCH 12/13] refactor: Update SearchBarComponent class --- .../elements/SearchBarComponent.java | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java index 0493b21..0e56051 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/components/elements/SearchBarComponent.java @@ -1,36 +1,37 @@ package edu.ntnu.idi.idatt.view.components.elements; +import edu.ntnu.idi.idatt.view.components.primitives.ActionEventHandler; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; -import javafx.scene.control.Button; +import javafx.geometry.Pos; import javafx.scene.control.TextField; import javafx.scene.image.Image; -import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; public class SearchBarComponent extends HBox { private final StringProperty query = new SimpleStringProperty(); - private final Button searchButton; + private final IconComponent searchIcon; public SearchBarComponent(String placeholder) { + + HBox wrapper = new HBox(); + wrapper.getStyleClass().add("searchbar"); + wrapper.setAlignment(Pos.CENTER); + TextField searchBar = new TextField(); + searchBar.getStyleClass().add("searchbar-field"); searchBar.setPromptText(placeholder); - searchBar.getStyleClass().add("button"); + searchBar.setMaxHeight(Double.MAX_VALUE); searchBar.textProperty().bindBidirectional(query); searchBar.setFocusTraversable(false); Image image = new Image(this.getClass().getResource("/icons/search.png/").toExternalForm()); - ImageView iv = new ImageView(); - iv.setImage(image); - - iv.setFitHeight(40); - iv.setFitWidth(40); + searchIcon = new IconComponent(image, null, 32); - searchButton = new Button("", iv); - searchButton.getStyleClass().clear(); // TODO: Make icon component or fix + wrapper.getChildren().addAll(searchBar, searchIcon); - this.getChildren().addAll(searchBar, searchButton); + this.getChildren().addAll(wrapper); } public String getQuery() { @@ -38,12 +39,7 @@ public String getQuery() { } public void onSearchQuery(ActionEventHandler handler) { - this.searchButton.setOnAction(e -> handler.handle()); - } - - @FunctionalInterface - public interface ActionEventHandler { - void handle(); + this.searchIcon.onIconClick(() -> handler.handle()); } } From 78971a36a11c2c0b0e9b8b8ff5391de536addee9 Mon Sep 17 00:00:00 2001 From: pawelsa Date: Sun, 26 Apr 2026 23:05:16 +0200 Subject: [PATCH 13/13] feat: Implement initial MainView --- .../ntnu/idi/idatt/view/primary/MainView.java | 117 ++++++++++++------ 1 file changed, 82 insertions(+), 35 deletions(-) diff --git a/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java b/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java index 09e1e17..d3a151d 100644 --- a/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java +++ b/src/main/java/edu/ntnu/idi/idatt/view/primary/MainView.java @@ -1,67 +1,114 @@ package edu.ntnu.idi.idatt.view.primary; import edu.ntnu.idi.idatt.session.UserSession; -import edu.ntnu.idi.idatt.view.components.AbstractView; import edu.ntnu.idi.idatt.view.components.AbstractViewUI; +import edu.ntnu.idi.idatt.view.components.elements.IconComponent; import edu.ntnu.idi.idatt.view.components.elements.SearchBarComponent; +import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Parent; import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; -import javafx.scene.transform.Scale; - -/* -public class MainView extends AbstractView { - - public MainView() { - super(new StackPane()); - this.getInstance().getStyleClass().add("light"); - } - - @Override - public Parent createContent() { - StackPane menu = new StackPane(); - menu.getStyleClass().add("dark"); - menu.setScaleX(menu.getScaleX()*0.75); - Scale scale = new Scale(-2.0, 1.0, 0, 0); - menu.getTransforms().add(scale); - - StackPane background = new StackPane(); - background.getStyleClass().add("primary"); - StackPane.setAlignment(background, Pos.CENTER); - background.setScaleY(background.getScaleY()*0.80); - StackPane main = new StackPane(background, menu); - - - return main; - } -} -*/ +import javafx.scene.layout.VBox; public class MainView extends AbstractViewUI { @Override public Parent createContent() { - return new Label("Hello " + UserSession.getInstance().getPlayer().getName() + " " - + UserSession.getInstance().getPlayer().getNetWorth()); + StackPane root = new StackPane(); + root.getStyleClass().add("primary"); + return root; } @Override public Parent createNavigation() { - return new Label("Hello from nav"); + VBox navigation = new VBox(); + Label title = new Label("Title"); + title.getStyleClass().add("big-text-32"); + + Label newspaper = new Label(" • Newspaper"); + newspaper.getStyleClass().add("med-text-16"); + + navigation.getChildren().addAll(title, newspaper); + return navigation; } @Override public Parent createHeader() { - this.getHeader().setAlignment(Pos.BASELINE_CENTER); + this.getHeader().setAlignment(Pos.CENTER); SearchBarComponent bar = new SearchBarComponent("Search after stocks.."); bar.onSearchQuery(() -> System.out.println(bar.getQuery())); + HBox.setMargin(bar, new Insets(20)); return bar; } @Override public Parent createToolbar() { - return new Label("Toolbar"); + HBox bar = new HBox(); + bar.setAlignment(Pos.CENTER); + bar.setMaxWidth(Double.MAX_VALUE); + HBox.setHgrow(bar, Priority.ALWAYS); + + Label balance = new Label(" Money: " + UserSession.getInstance().getPlayer().getMoney().toString() + " USD"); + balance.getStyleClass().add("med-text-16"); + + Region filler = new Region(); + HBox.setHgrow(filler, Priority.ALWAYS); + + VBox infoWrapper = new VBox(); + infoWrapper.setAlignment(Pos.CENTER); + + Label playerStatus = new Label(); + playerStatus.setText("Status:" + UserSession.getInstance().getPlayer().getStatus()); + playerStatus.getStyleClass().add("med-text-16"); + + Label playerNetWorth = new Label(); + playerNetWorth.setText("Net Worth: " + UserSession.getInstance().getPlayer().getNetWorth().toString() + " USD"); + playerNetWorth.getStyleClass().add("med-text-16"); + + infoWrapper.getChildren().addAll(playerStatus, playerNetWorth); + + HBox iconWrapper = new HBox(); + iconWrapper.setAlignment(Pos.CENTER); + + Image userImg = new Image(this.getClass().getResource("/icons/user.png").toExternalForm()); + Image quitImg = new Image(this.getClass().getResource("/icons/quit.png").toExternalForm()); + + IconComponent userIcon = new IconComponent(userImg, null, 44); + IconComponent quitIcon = new IconComponent(quitImg, null, 44); + + userIcon.onIconClick(() -> toggleMenu()); + + iconWrapper.getChildren().addAll(userIcon, quitIcon); + + bar.getChildren().addAll(balance, filler, infoWrapper, iconWrapper); + return bar; + } + + @Override + public Parent createMenu() { + VBox menu = new VBox(); + menu.setMaxSize(300, Double.MAX_VALUE); + menu.getStyleClass().add("dark"); + menu.setAlignment(Pos.TOP_CENTER); + + Image menuImg = new Image(this.getClass().getResource("/icons/user.png").toExternalForm()); + IconComponent menuIcon = new IconComponent(menuImg, "Account", 60); + menuIcon.getStyleClass().add("big-text-32"); + + Label portfolio = new Label(" • Portfolio"); + portfolio.getStyleClass().add("med-text-16"); + + Label transactions = new Label(" • Transactions"); + transactions.getStyleClass().add("med-text-16"); + + menu.getChildren().addAll(menuIcon, portfolio, transactions); + + return menu; } }