diff --git a/Workspace/client/src/main/java/com/pqt/client/Main.java b/Workspace/client/src/main/java/com/pqt/client/Main.java index 4eed78eb..a15ac623 100644 --- a/Workspace/client/src/main/java/com/pqt/client/Main.java +++ b/Workspace/client/src/main/java/com/pqt/client/Main.java @@ -1,12 +1,18 @@ package com.pqt.client; +import com.pqt.client.gui.main_frame.MainFrame; import com.pqt.client.gui.modules.sale_screen.SaleScreen; +import com.pqt.client.gui.ressources.components.generics.others.SideBar; +import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener; import com.pqt.client.gui.ressources.css.GUICssTool; +import com.pqt.client.gui.ressources.strings.GUIStringTool; import com.pqt.client.module.account.AccountService; import com.pqt.client.module.sale.SaleService; import com.pqt.client.module.stock.StockService; import javafx.application.Application; import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.layout.BorderPane; import javafx.stage.Stage; public class Main extends Application{ @@ -21,11 +27,14 @@ public class Main extends Application{ StockService stockService = new StockService(); AccountService accountService = new AccountService(); - SaleScreen saleScreen = new SaleScreen(accountService, stockService, saleService); - Scene scene = new Scene(saleScreen.getPane(), 800, 600); + MainFrame mainFrame = new MainFrame(accountService); + mainFrame.addModule(new SaleScreen(accountService, stockService, saleService)); + + Scene scene = new Scene(mainFrame.getPane(), 800, 600); scene.getStylesheets().clear(); scene.getStylesheets().addAll(getClass().getResource(GUICssTool.getCssFilePath()).toExternalForm()); + primaryStage.setTitle(GUIStringTool.getAppTitle()); primaryStage.setScene(scene); primaryStage.show(); } diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrame.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrame.java new file mode 100644 index 00000000..ea60287c --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrame.java @@ -0,0 +1,30 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.module.account.AccountService; +import javafx.scene.layout.Pane; + +public class MainFrame implements IFXComponent { + + private MainFrameView view; + private MainFrameController ctrl; + + public MainFrame(AccountService accountService) { + MainFrameModel model = new MainFrameModel(accountService); + ctrl = new MainFrameController(model); + model.addListener(ctrl); + + view = new MainFrameView(ctrl); + ctrl.setView(view); + } + + public void addModule(IGuiModule module){ + ctrl.addModule(module); + } + + @Override + public Pane getPane() { + return view.getPane(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameController.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameController.java new file mode 100644 index 00000000..c432978e --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameController.java @@ -0,0 +1,81 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener; +import com.pqt.client.gui.modules.IGuiModule; +import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener; +import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener; +import com.pqt.core.entities.user_account.Account; +import javafx.event.Event; + +class MainFrameController implements IMainFrameModelListener { + + private MainFrameModel model; + private MainFrameView view; + private IValidatorComponentListener accountManagerAccountListener; + + MainFrameController(MainFrameModel model) { + this.model = model; + } + + void setView(MainFrameView view) { + this.view = view; + } + + void addModule(IGuiModule module) { + this.view.addGuiModule(module.getModuleName(),module.getPane()); + } + + IValidatorComponentListener getAccountManagerValidatorListener() { + return new IValidatorComponentListener() { + @Override + public void onValidationEvent() { + if(view.isAccountCreationPossible()) + model.connectAccount(view.create()); + } + + @Override + public void onCancelEvent() { + model.disconnectCurrentAccount(); + } + }; + } + + IAccountComponentListener getAccountManagerAccountListener() { + return new IAccountComponentListener() { + @Override + public void onRefreshContentRequestEvent() { + + } + + @Override + public void onContentClickEvent(Event event, Account eventTarget) { + + } + + @Override + public void onAddContentRequestEvent() { + + } + + @Override + public void onRemoveContentRequestEvent(Account content) { + + } + + @Override + public void onDetailContentRequestEvent(Account content) { + + } + }; + } + + @Override + public void onAccountStatusChangedEvent(boolean status) { + view.setCurrentAccount(model.getCurrentAccount()); + } + + @Override + public void onAccountCollectionChangedEvent() { + view.feedAccountCollectionToManager(model.getAccounts()); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameModel.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameModel.java new file mode 100644 index 00000000..c8cb5fc7 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameModel.java @@ -0,0 +1,65 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.main_frame.listeners.IMainFrameModelListener; +import com.pqt.client.module.account.AccountService; +import com.pqt.client.module.account.listeners.IAccountListener; +import com.pqt.core.entities.user_account.Account; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.Collection; + +class MainFrameModel { + + private EventListenerList listenerList; + private AccountService accountService; + + MainFrameModel(AccountService accountService) { + listenerList = new EventListenerList(); + this.accountService = accountService; + this.accountService.addListener(new IAccountListener() { + @Override + public void onAccountStatusChangedEvent(boolean status) { + MainFrameModel.this.fireAccountStatusChangedEvent(status); + } + + @Override + public void onAccountListChangedEvent() { + MainFrameModel.this.fireAccountCollectionChangedEvent(); + } + }); + } + + private void fireAccountCollectionChangedEvent() { + Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(IMainFrameModelListener::onAccountCollectionChangedEvent); + } + + private void fireAccountStatusChangedEvent(boolean status) { + Arrays.stream(listenerList.getListeners(IMainFrameModelListener.class)).forEach(l->l.onAccountStatusChangedEvent(status)); + } + + void connectAccount(Account account) { + accountService.setCurrentAccount(account); + accountService.logInCurrentAccount(account.getPassword()); + } + + void disconnectCurrentAccount() { + accountService.logOutCurrentAccount(); + } + + Collection getAccounts(){ + return accountService.getAllAccounts(); + } + + void addListener(IMainFrameModelListener listener){ + listenerList.add(IMainFrameModelListener.class, listener); + } + + void removeListener(IMainFrameModelListener listener){ + listenerList.remove(IMainFrameModelListener.class, listener); + } + + Account getCurrentAccount() { + return accountService.getCurrentAccount(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameView.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameView.java new file mode 100644 index 00000000..12464cab --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/MainFrameView.java @@ -0,0 +1,102 @@ +package com.pqt.client.gui.main_frame; + +import com.pqt.client.gui.ressources.components.AccountManager; +import com.pqt.client.gui.ressources.components.generics.IFXComponent; +import com.pqt.client.gui.ressources.components.generics.others.SideBar; +import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener; +import com.pqt.client.gui.ressources.strings.GUIStringTool; +import com.pqt.core.entities.user_account.Account; +import javafx.geometry.Orientation; +import javafx.scene.control.Button; +import javafx.scene.control.ToolBar; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; + +import java.util.Collection; + +class MainFrameView implements IFXComponent{ + + private final MainFrameController ctrl; + + private BorderPane mainPane; + private ToolBar moduleListToolbar; + private AccountManager accountManager; + + MainFrameView(MainFrameController ctrl) { + + this.ctrl = ctrl; + initGui(); + } + + private void initGui(){ + mainPane = new BorderPane(); + mainPane.getStyleClass().addAll("main-module-pane", "main-frame"); + + moduleListToolbar = new ToolBar(); + moduleListToolbar.setOrientation(Orientation.VERTICAL); + + SideBar sidebar = new SideBar(); + sidebar.setFillWidth(true); + SideBar.setVgrow(moduleListToolbar, Priority.ALWAYS); + sidebar.getChildren().add(moduleListToolbar); + + accountManager = new AccountManager(); + accountManager.addListener(ctrl.getAccountManagerValidatorListener()); + accountManager.addListener(ctrl.getAccountManagerAccountListener()); + sidebar.getChildren().add(accountManager.getPane()); + + mainPane.setLeft(sidebar); + + Button sidebarCtrl = new Button(); + if(sidebar.isExpanded()) + sidebarCtrl.setText(GUIStringTool.getSideBarCollapseButtonLabel()); + else + sidebarCtrl.setText(GUIStringTool.getSideBarExpandButtonLabel()); + sidebarCtrl.setOnMouseClicked(event -> { + if(sidebar.isExpanded()) + sidebar.collapse(); + else if(sidebar.isCollapsed()) + sidebar.expand(); + }); + sidebar.addListener(new ISideBarListener() { + @Override + public void onCollapsedFinished() { + sidebarCtrl.setText(GUIStringTool.getSideBarExpandButtonLabel()); + } + + @Override + public void onExpandFinished() { + sidebarCtrl.setText(GUIStringTool.getSideBarCollapseButtonLabel()); + } + }); + mainPane.setTop(sidebarCtrl); + } + + @Override + public Pane getPane() { + return mainPane; + } + + void addGuiModule(String moduleName, Pane moduleContent){ + Button button = new Button(moduleName); + button.setOnMouseClicked(event->mainPane.setCenter(moduleContent)); + moduleListToolbar.getItems().add(button); + } + + boolean isAccountCreationPossible(){ + return accountManager.isCreationPossible(); + } + + Account create(){ + return accountManager.create(); + } + + void setCurrentAccount(Account account){ + accountManager.setCurrentAccount(account); + } + + void feedAccountCollectionToManager(Collection accounts){ + accountManager.display(accounts); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/listeners/IMainFrameModelListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/listeners/IMainFrameModelListener.java new file mode 100644 index 00000000..5c876e26 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/main_frame/listeners/IMainFrameModelListener.java @@ -0,0 +1,8 @@ +package com.pqt.client.gui.main_frame.listeners; + +import java.util.EventListener; + +public interface IMainFrameModelListener extends EventListener{ + void onAccountStatusChangedEvent(boolean status); + void onAccountCollectionChangedEvent(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/SideBar.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/SideBar.java new file mode 100644 index 00000000..94807320 --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/SideBar.java @@ -0,0 +1,118 @@ +package com.pqt.client.gui.ressources.components.generics.others; + +import com.pqt.client.gui.ressources.components.generics.others.listeners.ISideBarListener; +import javafx.animation.Animation; +import javafx.animation.Transition; +import javafx.beans.value.ObservableValue; +import javafx.css.*; +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.layout.VBox; +import javafx.util.Duration; + +import javax.swing.event.EventListenerList; +import java.util.Arrays; +import java.util.List; + +public class SideBar extends VBox { + + private static final StyleablePropertyFactory FACTORY = new StyleablePropertyFactory<>(VBox.getClassCssMetaData()); + + private static final CssMetaData EXPANDED_WIDTH = + FACTORY.createSizeCssMetaData("-pqt-expanded-width",p->p.expandedWidth, 100, false); + + private StyleableProperty expandedWidth; + private EventListenerList listenerList; + private Animation collapseSideBar, expandSideBar; + + /** creates a sidebar containing a vertical alignment of the given nodes */ + public SideBar(Node... children) { + listenerList = new EventListenerList(); + getStyleClass().add("sidebar"); + this.setMinWidth(0); + this.expandedWidth = new SimpleStyleableDoubleProperty(EXPANDED_WIDTH, this, "expanded-width"); + this.setPrefWidth(expandedWidth.getValue().doubleValue()); + + setAlignment(Pos.CENTER); + getChildren().addAll(children); + + // create an animation to show a sidebar. + expandSideBar = new Transition() { + { + setCycleDuration(Duration.millis(250)); + } + protected void interpolate(double frac) { + final double curWidth = expandedWidth.getValue().doubleValue() * frac; + setPrefWidth(curWidth); + setTranslateX(-expandedWidth.getValue().doubleValue() + curWidth); + } + }; + expandSideBar.onFinishedProperty().set(actionEvent -> + Arrays.stream(listenerList.getListeners(ISideBarListener.class)) + .forEach(ISideBarListener::onExpandFinished) + ); + + + // create an animation to hide sidebar. + collapseSideBar = new Transition() { + { + setCycleDuration(Duration.millis(250)); + } + protected void interpolate(double frac) { + final double curWidth = expandedWidth.getValue().doubleValue() * (1.0 - frac); + setPrefWidth(curWidth); + setTranslateX(-expandedWidth.getValue().doubleValue() + curWidth); + } + }; + collapseSideBar.onFinishedProperty().set(actionEvent -> + Arrays.stream(listenerList.getListeners(ISideBarListener.class)) + .forEach(ISideBarListener::onCollapsedFinished)); + collapse(); + } + + public void expand(){ + if (expandSideBar.statusProperty().get() == Animation.Status.STOPPED + && collapseSideBar.statusProperty().get() == Animation.Status.STOPPED) { + if (!isVisible()) { + setVisible(true); + expandSideBar.play(); + } + } + } + + public void collapse(){ + if (expandSideBar.statusProperty().get() == Animation.Status.STOPPED + && collapseSideBar.statusProperty().get() == Animation.Status.STOPPED) { + if (isVisible()) { + collapseSideBar.play(); + setVisible(false); + } + } + } + + public boolean isExpanded(){ + return isVisible() && expandSideBar.statusProperty().get().equals(Animation.Status.STOPPED); + } + + public boolean isCollapsed() { + return !isVisible() && collapseSideBar.statusProperty().get().equals(Animation.Status.STOPPED); + } + + public void addListener(ISideBarListener listener){ + listenerList.add(ISideBarListener.class, listener); + } + + public void removeListener(ISideBarListener listener){ + listenerList.remove(ISideBarListener.class, listener); + } + + + public static List> getClassCssMetaData() { + return FACTORY.getCssMetaData(); + } + + @Override + public List> getCssMetaData() { + return FACTORY.getCssMetaData(); + } +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/listeners/ISideBarListener.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/listeners/ISideBarListener.java new file mode 100644 index 00000000..2a1314ff --- /dev/null +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/components/generics/others/listeners/ISideBarListener.java @@ -0,0 +1,9 @@ +package com.pqt.client.gui.ressources.components.generics.others.listeners; + +import java.util.EventListener; + +public interface ISideBarListener extends EventListener { + + void onCollapsedFinished(); + void onExpandFinished(); +} diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java index 3beba068..7c85140a 100644 --- a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/css/GUICssTool.java @@ -4,4 +4,12 @@ public class GUICssTool { public static String getCssFilePath(){ return "/dark-theme.css"; } + + public static String getCollapsedSideBarCssStyle() { + return "sidebar-collapsed"; + } + + public static String getExpandedSideBarCssStyle() { + return "sidebar-expanded"; + } } diff --git a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java index c4d5818a..0e58801d 100644 --- a/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java +++ b/Workspace/client/src/main/java/com/pqt/client/gui/ressources/strings/GUIStringTool.java @@ -56,7 +56,7 @@ public class GUIStringTool { @Override public String toString(Account object) { if(object!=null) - return String.format("%s - %s)", object.getUsername(), object.getPermissionLevel()); + return String.format("%s - (%s)", object.getUsername(), object.getPermissionLevel()); return "null"; } @@ -151,6 +151,22 @@ public class GUIStringTool { public static String getOkButtonLabel() { return "OK"; } + + public static String getAppTitle() { + return "Client PQT - Gargotte"; + } + + public static String getSideBarCollapseButtonLabel() { + return "Hide"; + } + + public static String getSideBarExpandButtonLabel() { + return "Show"; + } + + public static String getSaleGuiModuleName() { + return "Vente"; + } } diff --git a/Workspace/client/src/main/resources/dark-theme.css b/Workspace/client/src/main/resources/dark-theme.css index 5789bca8..7ba8b06a 100644 --- a/Workspace/client/src/main/resources/dark-theme.css +++ b/Workspace/client/src/main/resources/dark-theme.css @@ -114,7 +114,7 @@ -fx-background-color: black; } -.text-field { +.text-field, .password-field, .choice-box { -fx-font-size: 12pt; -fx-font-family: "Segoe UI Semibold"; -fx-pref-width: 125; @@ -173,17 +173,6 @@ -fx-background-color: derive(-fx-focus-color,30%); } -.choice-box { - -fx-pref-width: 150; - -fx-pref-height: 30; - -fx-background-radius: 0; - -fx-background-color: #1d1d1d; - -fx-background-insets: 0 0 0 0, 0, 1, 2; - -fx-border-color: #e2e2e2; - -fx-border-width: 2; - -fx-text-fill: #d8d8d8; -} - .progress-indicator { -fx-pref-width: 50; -fx-pref-height: 50; @@ -206,4 +195,21 @@ .validator .button{ -fx-pref-width: 150; -fx-pref-height: 50; - } \ No newline at end of file + } + +.sidebar { + -fx-background-color: #2e2e2e; + -fx-padding: 5 22 5 22; + -fx-border-color: #e2e2e2; + -fx-border-width: 2; + -fx-background-radius: 0; + -fx-background-insets: 0 0 0 0, 0, 1, 2; + -pqt-expanded-width : 200px; +} + +.tool-bar { + -fx-background-color: #2e2e2e; + -fx-padding: 5 5 5 5; + -fx-background-radius: 0; + -fx-background-insets: 0 0 0 0, 0, 1, 2; +} \ No newline at end of file