Merge branch 'develop' into feature/#1_développement_code_métier_partie_client

This commit is contained in:
Notmoo-PC\Notmoo 2017-08-23 13:23:57 +02:00
commit df5837f79a
152 changed files with 7715 additions and 1443 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
#Ignoring Intellij workspace specific folders and files
/**/.idea/workspace.xml
/**/tasks.xml
/**/.idea/libraries
#Ignoring target folders
**/target/

View File

@ -0,0 +1,8 @@
<component name="ArtifactManager">
<artifact type="war" name="server:war">
<output-path>$PROJECT_DIR$/server/target</output-path>
<root id="archive" name="server-1.0-SNAPSHOT.war">
<element id="artifact" artifact-name="server:war exploded" />
</root>
</artifact>
</component>

View File

@ -0,0 +1,23 @@
<component name="ArtifactManager">
<artifact type="exploded-war" name="server:war exploded">
<output-path>$PROJECT_DIR$/server/target/server-1.0-SNAPSHOT</output-path>
<root id="root">
<element id="directory" name="WEB-INF">
<element id="directory" name="classes">
<element id="module-output" name="server" />
</element>
<element id="directory" name="lib">
<element id="archive" name="core-1.0-SNAPSHOT.jar">
<element id="module-output" name="core" />
</element>
<element id="library" level="project" name="Maven: com.google.code.gson:gson:2.8.1" />
<element id="library" level="project" name="Maven: commons-io:commons-io:2.4" />
</element>
</element>
<element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/server/target/server-1.0-SNAPSHOT/META-INF/MANIFEST.MF" />
</element>
<element id="javaee-facet-resources" facet="server/web/Web" />
</root>
</artifact>
</component>

9
Workspace/.idea/codeStyleSettings.xml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value />
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</component>
</project>

View File

@ -8,12 +8,13 @@
<outputRelativeToContentRoot value="true" />
<module name="client" />
<module name="core" />
<module name="server" />
</profile>
</annotationProcessing>
<bytecodeTargetLevel>
<module name="client" target="1.8" />
<module name="core" target="1.8" />
<module name="server" target="1.5" />
<module name="server" target="1.8" />
<module name="Workspace" target="1.8" />
</bytecodeTargetLevel>
</component>

View File

@ -1,15 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$/server" />
</component>
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
<option name="ignoredFiles">
<set>
<option value="$PROJECT_DIR$/server/pom.xml" />
</set>
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">

View File

@ -5,6 +5,7 @@
<module fileurl="file://$PROJECT_DIR$/Workspace.iml" filepath="$PROJECT_DIR$/Workspace.iml" />
<module fileurl="file://$PROJECT_DIR$/client/client.iml" filepath="$PROJECT_DIR$/client/client.iml" />
<module fileurl="file://$PROJECT_DIR$/core/core.iml" filepath="$PROJECT_DIR$/core/core.iml" />
<module fileurl="file://$PROJECT_DIR$/server/server.iml" filepath="$PROJECT_DIR$/server/server.iml" />
</modules>
</component>
</project>

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -11,6 +11,8 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
<orderEntry type="module" module-name="core" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
</component>
</module>

View File

@ -0,0 +1,50 @@
package com.pqt.client;
import com.pqt.client.gui.main_frame.MainFrame;
import com.pqt.client.gui.modules.account_screen.AccountScreen;
import com.pqt.client.gui.modules.sale_screen.SaleScreen;
import com.pqt.client.gui.modules.stat_screen.StatScreen;
import com.pqt.client.gui.modules.stock_screen.StockScreen;
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.components.generics.toast.ToastFactory;
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.stat.StatService;
import com.pqt.client.module.stock.StockService;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application{
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
SaleService saleService = new SaleService();
StockService stockService = new StockService();
AccountService accountService = new AccountService();
StatService statService = new StatService();
MainFrame mainFrame = new MainFrame(accountService);
mainFrame.addModule(new SaleScreen(accountService, stockService, saleService), true);
mainFrame.addModule(new StockScreen(stockService, accountService));
mainFrame.addModule(new StatScreen(statService));
mainFrame.addModule(new AccountScreen(accountService));
Scene scene = new Scene(mainFrame.getPane(), 800, 600);
scene.getStylesheets().clear();
scene.getStylesheets().addAll(getClass().getResource(GUICssTool.getCssFilePath()).toExternalForm());
ToastFactory.init(primaryStage);
primaryStage.setTitle(GUIStringTool.getAppTitle());
primaryStage.setScene(scene);
primaryStage.show();
}
}

View File

@ -0,0 +1,35 @@
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);
ctrl.updateView();
}
public void addModule(IGuiModule module, boolean setActive){
ctrl.addModule(module, setActive);
}
public void addModule(IGuiModule module){
ctrl.addModule(module, false);
}
@Override
public Pane getPane() {
return view.getPane();
}
}

View File

@ -0,0 +1,94 @@
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 com.pqt.core.entities.user_account.AccountLevel;
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 updateView(){
view.feedAccountCollectionToManager(model.getAccounts());
view.setCurrentAccount(model.getCurrentAccount());
if(model.getCurrentAccount()!=null)
view.updateModuleButtonLock(model.getCurrentAccount().getPermissionLevel());
else
view.updateModuleButtonLock(AccountLevel.getLowest());
}
void addModule(IGuiModule module, boolean activationRequired) {
boolean activate = activationRequired
&& model.getCurrentAccount()!=null
&& model.getCurrentAccount().getPermissionLevel().compareTo(module.getLowestRequiredAccountLevel())>=0;
this.view.addGuiModule(module.getModuleName(),module.getPane(), module.getLowestRequiredAccountLevel(), activate);
}
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) {
updateView();
}
@Override
public void onAccountCollectionChangedEvent() {
updateView();
}
}

View File

@ -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<Account> 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();
}
}

View File

@ -0,0 +1,142 @@
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 com.pqt.core.entities.user_account.AccountLevel;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ToolBar;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import java.util.Collection;
class MainFrameView implements IFXComponent{
private final MainFrameController ctrl;
private BorderPane mainPane;
private AccountManager accountManager;
private VBox buttonHolder;
private ObjectProperty<AccountLevel> currentAccountLevel;
MainFrameView(MainFrameController ctrl) {
this.ctrl = ctrl;
currentAccountLevel = new SimpleObjectProperty<>(AccountLevel.getLowest());
initGui();
}
private void initGui(){
mainPane = new BorderPane();
mainPane.getStyleClass().addAll("main-module-pane", "main-frame");
buttonHolder = new VBox();
SideBar sidebar = new SideBar();
sidebar.setFillWidth(true);
SideBar.setVgrow(buttonHolder, Priority.ALWAYS);
buttonHolder.prefWidthProperty().bind(sidebar.widthProperty());
sidebar.getChildren().add(buttonHolder);
accountManager = new AccountManager();
accountManager.addListener(ctrl.getAccountManagerValidatorListener());
accountManager.addListener(ctrl.getAccountManagerAccountListener());
accountManager.getPane().prefWidthProperty().bind(sidebar.widthProperty());
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, AccountLevel requiredLevel, boolean setActive){
Button button = new Button(moduleName);
button.getStyleClass().add("menu-button");
Runnable buttonActivationCode = ()->{
buttonHolder.getChildren()
.stream()
.filter(Button.class::isInstance)
.map(Button.class::cast)
.forEach(b-> b.getStyleClass().remove("menu-button-selected"));
button.getStyleClass().add("menu-button-selected");
Platform.runLater(()->{
buttonHolder.getChildren().forEach(Node::applyCss);
mainPane.setCenter(moduleContent);
});
};
button.setOnMouseClicked(event-> {
if(event.getButton().equals(MouseButton.PRIMARY))
buttonActivationCode.run();
});
button.setOnKeyTyped(event->{
if (event.getCode().equals(KeyCode.ENTER))
buttonActivationCode.run();
});
currentAccountLevel.addListener((obs, oldVal, newVal)->button.setDisable(requiredLevel.compareTo(newVal)>0));
button.setDisable(requiredLevel.compareTo(currentAccountLevel.get())>0);
if(setActive)
buttonActivationCode.run();
buttonHolder.getChildren().add(button);
}
boolean isAccountCreationPossible(){
return accountManager.isCreationPossible();
}
Account create(){
return accountManager.create();
}
void setCurrentAccount(Account account){
accountManager.setCurrentAccount(account);
}
void feedAccountCollectionToManager(Collection<Account> accounts){
accountManager.display(accounts);
}
void updateModuleButtonLock(AccountLevel level) {
currentAccountLevel.setValue(level);
}
}

View File

@ -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();
}

View File

@ -0,0 +1,9 @@
package com.pqt.client.gui.modules;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.core.entities.user_account.AccountLevel;
public interface IGuiModule extends IFXComponent{
String getModuleName();
AccountLevel getLowestRequiredAccountLevel();
}

View File

@ -0,0 +1,36 @@
package com.pqt.client.gui.modules.account_screen;
import com.pqt.client.gui.modules.IGuiModule;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.module.account.AccountService;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.scene.layout.Pane;
public class AccountScreen implements IGuiModule {
private AccountScreenView view;
public AccountScreen(AccountService accountService) {
AccountScreenModel model = new AccountScreenModel(accountService);
AccountScreenController ctrl = new AccountScreenController(model);
view = new AccountScreenView(ctrl);
ctrl.setView(view);
ctrl.updateView();
}
@Override
public String getModuleName() {
return GUIStringTool.getAccountGuiModuleName();
}
@Override
public AccountLevel getLowestRequiredAccountLevel() {
return AccountLevel.WAITER;
}
@Override
public Pane getPane() {
return view.getPane();
}
}

View File

@ -0,0 +1,83 @@
package com.pqt.client.gui.modules.account_screen;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
class AccountScreenController {
private AccountScreenModel model;
private AccountScreenView view;
AccountScreenController(AccountScreenModel model) {
this.model = model;
}
void setView(AccountScreenView view) {
this.view = view;
}
void updateView() {
updateViewAccountCollection();
updateViewActionLock();
}
private void updateViewAccountCollection(){
view.setAccountCollection(model.getAccountCollection());
}
private void updateViewActionLock() {
if (model.getCurrentAccount() != null) {
view.setAddAccountActionLocked(AccountLevel.MASTER.compareTo(model.getCurrentAccount().getPermissionLevel()) > 0);
view.setDetailAccountActionLocked(!view.isItemSelected() || AccountLevel.MASTER.compareTo(model.getCurrentAccount().getPermissionLevel()) > 0);
view.setRemoveAccountActionLocked(!view.isItemSelected() || AccountLevel.MASTER.compareTo(model.getCurrentAccount().getPermissionLevel()) > 0);
}else{
view.setAddAccountActionLocked(true);
view.setDetailAccountActionLocked(true);
view.setRemoveAccountActionLocked(true);
}
}
IValidatorComponentListener getDetailScreenValidationListener(){
return new IValidatorComponentListener() {
@Override
public void onValidationEvent() {
if(view.isDetailCreationPossible()){
if(view.getDetailScreenInitialValue()!=null){
model.modifyAccount(view.getDetailScreenInitialValue(), view.getDetailScreenCreatedValue());
}else{
model.addAccount(view.getDetailScreenCreatedValue());
}
view.hideDetailScreen();
}
}
@Override
public void onCancelEvent() {
view.hideDetailScreen();
}
};
}
void onAddAccountRequested() {
view.showDetailScreen(null, model.getLevels());
}
void onDetailAccountRequested() {
if(view.isItemSelected())
view.showDetailScreen(view.getSelectedItem(), model.getLevels());
}
void onRemoveAccountRequested() {
if(view.isItemSelected())
model.removeAccount(view.getSelectedItem());
}
void onRefreshAccountRequested() {
this.updateView();
}
void onSelectedAccountChanged(Account oldVal, Account newVal) {
updateViewActionLock();
}
}

View File

@ -0,0 +1,44 @@
package com.pqt.client.gui.modules.account_screen;
import com.pqt.client.module.account.AccountService;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import java.util.Collection;
import java.util.EnumSet;
//TODO MAJ les méthds modif, add et remove une fois que l'accountService prend en compte les modifs
class AccountScreenModel {
private AccountService accountService;
AccountScreenModel(AccountService accountService) {
this.accountService = accountService;
}
void modifyAccount(Account oldVal, Account newVal) {
//accountService.submitAccountUpdate(oldVal, newVal);
}
void addAccount(Account newVal) {
//accountService.submitAccountUpdate(null, newVal);
}
void removeAccount(Account oldVal) {
//accountService.submitAccountUpdate(oldVal, null);
}
Collection<Account> getAccountCollection() {
return accountService.getAllAccounts();
}
Account getCurrentAccount() {
return accountService.getCurrentAccount();
}
Collection<AccountLevel> getLevels() {
//TODO régler ça aussi
//return accountService.getAvailableLevels();
return EnumSet.allOf(AccountLevel.class);
}
}

View File

@ -0,0 +1,178 @@
package com.pqt.client.gui.modules.account_screen;
import com.pqt.client.gui.modules.account_screen.account_manager_screen.AccountManagerScreen;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.*;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
class AccountScreenView implements IFXComponent{
private AccountScreenController ctrl;
private StackPane mainPane;
private BorderPane mainPaneContent;
private TableView<Account> tableView;
private AccountManagerScreen accountManagerScreen;
private Button addAccountButton, detailAccountButton, removeAccountButton;
AccountScreenView(AccountScreenController ctrl) {
this.ctrl = ctrl;
initGui();
}
private void initGui() {
mainPane = new StackPane();
mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass());
mainPaneContent = new BorderPane();
tableView = new TableView<>();
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tableView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal)-> ctrl.onSelectedAccountChanged(oldVal, newVal));
TableColumn<Account, String> nameColumn = new TableColumn<>(GUIStringTool.getAccountNameColumnHeaderLabel());
nameColumn.setCellValueFactory(param -> new SimpleStringProperty(param.getValue().getUsername()));
tableView.getColumns().add(nameColumn);
TableColumn<Account, String> levelColumn = new TableColumn<>(GUIStringTool.getAccountLevelColumnHeaderLabel());
levelColumn.setCellValueFactory(param -> new SimpleStringProperty(
GUIStringTool.getAccountLevelStringRenderer().render(param.getValue().getPermissionLevel())
));
tableView.getColumns().add(levelColumn);
mainPaneContent.setCenter(tableView);
HBox mainPaneTopContent = new HBox();
mainPaneTopContent.setFillHeight(true);
Label label = new Label(GUIStringTool.getAccountListTitleLabel());
label.getStyleClass().add(GUICssTool.getTitleTextStyleClass());
mainPaneTopContent.getChildren().add(label);
HBox separator = new HBox();
ToolBar buttonToolbar = new ToolBar();
addAccountButton = new Button(GUIStringTool.getAddButtonLabel());
addAccountButton.setOnMouseClicked(event->{
if (event.getButton().equals(MouseButton.PRIMARY))
ctrl.onAddAccountRequested();
});
buttonToolbar.getItems().add(addAccountButton);
detailAccountButton = new Button(GUIStringTool.getDetailButtonLabel());
detailAccountButton.setOnMouseClicked(event->{
if (event.getButton().equals(MouseButton.PRIMARY))
ctrl.onDetailAccountRequested();
});
buttonToolbar.getItems().add(detailAccountButton);
removeAccountButton = new Button(GUIStringTool.getRemoveButtonLabel());
removeAccountButton.setOnMouseClicked(event->{
if (event.getButton().equals(MouseButton.PRIMARY))
ctrl.onRemoveAccountRequested();
});
buttonToolbar.getItems().add(removeAccountButton);
Button refreshAccountButton = new Button(GUIStringTool.getRefreshButtonLabel());
refreshAccountButton.setOnMouseClicked(event->{
if (event.getButton().equals(MouseButton.PRIMARY))
ctrl.onRefreshAccountRequested();
});
buttonToolbar.getItems().add(refreshAccountButton);
mainPaneTopContent.getChildren().addAll(separator, buttonToolbar);
HBox.setHgrow(separator, Priority.ALWAYS);
mainPaneContent.setTop(mainPaneTopContent);
mainPane.getChildren().add(mainPaneContent);
}
boolean isItemSelected(){
return tableView.getSelectionModel().getSelectedItem()!=null;
}
Account getSelectedItem(){
return tableView.getSelectionModel().getSelectedItem();
}
@Override
public Pane getPane() {
return mainPane;
}
boolean isDetailCreationPossible() {
return accountManagerScreen!=null && accountManagerScreen.isCreationPossible();
}
Account getDetailScreenInitialValue() {
if(accountManagerScreen!=null)
return accountManagerScreen.getInitialValue();
return null;
}
Account getDetailScreenCreatedValue() {
if(accountManagerScreen!=null)
return accountManagerScreen.create();
return null;
}
boolean isDetailScreenShown(){
return accountManagerScreen!=null;
}
void showDetailScreen(Account initialValue, Collection<AccountLevel> availableLevels){
if(!isDetailScreenShown()){
Pane separator = new Pane();
separator.getStyleClass().add(GUICssTool.getIntermediaryPaneStyleClass());
accountManagerScreen = new AccountManagerScreen(initialValue, availableLevels);
accountManagerScreen.addListener(ctrl.getDetailScreenValidationListener());
Platform.runLater(()->{
mainPane.getChildren().addAll(separator, accountManagerScreen.getPane());
});
}
}
void hideDetailScreen(){
if(isDetailScreenShown()){
List<Node> toRemove = mainPane.getChildren()
.stream()
.filter(node->!node.equals(mainPaneContent))
.collect(Collectors.toList());
Platform.runLater(()->{
mainPane.getChildren().removeAll(toRemove);
accountManagerScreen = null;
});
}
}
void setAccountCollection(Collection<Account> accountCollection) {
Platform.runLater(()->{
tableView.getItems().clear();
if(accountCollection!=null)
tableView.getItems().addAll(accountCollection);
});
}
void setAddAccountActionLocked(boolean locked) {
addAccountButton.setDisable(locked);
}
void setDetailAccountActionLocked(boolean locked) {
detailAccountButton.setDisable(locked);
}
void setRemoveAccountActionLocked(boolean locked) {
removeAccountButton.setDisable(locked);
}
}

View File

@ -0,0 +1,56 @@
package com.pqt.client.gui.modules.account_screen.account_manager_screen;
import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.scene.layout.Pane;
import java.util.Collection;
//TODO à faire
public class AccountManagerScreen implements IFXValidatorComponent, IFXCreatorComponent<Account>{
private AccountManagerScreenModel model;
private AccountManagerScreenView view;
private AccountManagerScreenController ctrl;
public AccountManagerScreen(Account initialValue, Collection<AccountLevel> availableLevels) {
model = new AccountManagerScreenModel(initialValue, availableLevels);
ctrl = new AccountManagerScreenController(model);
view = new AccountManagerScreenView(ctrl);
ctrl.setView(view);
ctrl.updateView();
}
public Account getInitialValue(){
return model.getInitialValue();
}
@Override
public Account create() {
return model.getCurrentValue();
}
@Override
public boolean isCreationPossible() {
return model.isCurrentValueValid();
}
@Override
public void addListener(IValidatorComponentListener l) {
ctrl.addListener(l);
}
@Override
public void removeListener(IValidatorComponentListener l) {
ctrl.removeListener(l);
}
@Override
public Pane getPane() {
return view.getPane();
}
}

View File

@ -0,0 +1,58 @@
package com.pqt.client.gui.modules.account_screen.account_manager_screen;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.core.entities.user_account.AccountLevel;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
class AccountManagerScreenController {
private EventListenerList listenerList;
private AccountManagerScreenView view;
private AccountManagerScreenModel model;
AccountManagerScreenController(AccountManagerScreenModel model) {
listenerList = new EventListenerList();
this.model = model;
}
void setView(AccountManagerScreenView view) {
this.view = view;
}
void updateView() {
view.setLevelCollection(model.getAccountLevelCollection());
view.setData(model.getCurrentValue());
}
void addListener(IValidatorComponentListener l) {
listenerList.add(IValidatorComponentListener.class, l);
}
void removeListener(IValidatorComponentListener l) {
listenerList.remove(IValidatorComponentListener.class, l);
}
void onNameChanged(String oldVal, String newVal) {
model.changeName(newVal);
}
void onPasswordChanged(String oldVal, String newVal) {
model.changePassword(newVal);
}
void onLevelChanged(AccountLevel oldVal, AccountLevel newVal) {
model.changeLevel(newVal);
}
void onValidationEvent() {
Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class))
.forEach(IValidatorComponentListener::onValidationEvent);
}
void onCancelEvent() {
Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class))
.forEach(IValidatorComponentListener::onCancelEvent);
}
}

View File

@ -0,0 +1,61 @@
package com.pqt.client.gui.modules.account_screen.account_manager_screen;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
class AccountManagerScreenModel {
private Account currentValue;
private Account initialValue;
private Set<AccountLevel> levels;
AccountManagerScreenModel(Account initialValue, Collection<AccountLevel> availableLevels) {
levels = new HashSet<>();
if(availableLevels!=null)
levels.addAll(availableLevels);
this.initialValue = initialValue;
this.currentValue = (initialValue!=null?new Account(initialValue):getNewAccount());
}
Account getCurrentValue() {
return currentValue;
}
Account getInitialValue() {
return initialValue;
}
boolean isCurrentValueValid() {
return !currentValue.equals(initialValue)
&& currentValue.getUsername()!=null
&& !currentValue.getUsername().isEmpty()
&& currentValue.getPermissionLevel()!=null;
}
Collection<AccountLevel> getAccountLevelCollection(){
return levels;
}
void changeName(String username) {
currentValue.setUsername(username);
}
void changePassword(String password) {
currentValue.setPassword(password);
}
void changeLevel(AccountLevel level) {
currentValue.setPermissionLevel(level);
}
private Account getNewAccount() {
Account account = new Account();
account.setUsername("");
account.setPassword("");
account.setPermissionLevel(levels.stream().min(Enum::compareTo).orElse(AccountLevel.getLowest()));
return account;
}
}

View File

@ -0,0 +1,107 @@
package com.pqt.client.gui.modules.account_screen.account_manager_screen;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.*;
import java.util.Collection;
class AccountManagerScreenView implements IFXComponent{
private StackPane mainPane;
private AccountManagerScreenController ctrl;
private ChoiceBox<AccountLevel> levelChoiceBox;
private TextField nameTextField;
private PasswordField passwordField;
AccountManagerScreenView(AccountManagerScreenController ctrl) {
this.ctrl = ctrl;
initGui();
}
private void initGui() {
mainPane = new StackPane();
BorderPane mainPaneContent = new BorderPane();
GridPane mainPaneCenterContent = new GridPane();
mainPaneCenterContent.setAlignment(Pos.CENTER);
Label nameLabel = new Label(GUIStringTool.getUsernameLabel());
nameTextField = new TextField();
nameTextField.textProperty().addListener((obs, oldVal, newVal)->ctrl.onNameChanged(oldVal, newVal));
mainPaneCenterContent.add(nameLabel, 0, 0);
mainPaneCenterContent.add(nameTextField, 1,0);
Label passwordLabel = new Label(GUIStringTool.getPasswordLabel());
passwordField = new PasswordField();
passwordField.textProperty().addListener((obs, oldVal, newVal)->ctrl.onPasswordChanged(oldVal, newVal));
mainPaneCenterContent.add(passwordLabel, 0, 1);
mainPaneCenterContent.add(passwordField, 1,1);
Label levelLabel = new Label(GUIStringTool.getUserLevelLabel());
levelChoiceBox = new ChoiceBox<>();
levelChoiceBox.valueProperty().addListener((obs, oldVal, newVal)->ctrl.onLevelChanged(oldVal, newVal));
mainPaneCenterContent.add(levelLabel, 0, 2);
mainPaneCenterContent.add(levelChoiceBox, 1,2);
mainPaneContent.setCenter(mainPaneCenterContent);
HBox mainPaneBottomContent = new HBox();
mainPaneBottomContent.setFillHeight(true);
Button validationButton = new Button(GUIStringTool.getValidationButtonLabel());
validationButton.setOnMouseClicked(event -> {
if (event.getButton().equals(MouseButton.PRIMARY))
ctrl.onValidationEvent();
});
Button cancelButton = new Button(GUIStringTool.getCancelButtonLabel());
cancelButton.setOnMouseClicked(event -> {
if (event.getButton().equals(MouseButton.PRIMARY))
ctrl.onCancelEvent();
});
HBox separator = new HBox();
mainPaneBottomContent.getChildren().addAll(separator, validationButton, cancelButton);
HBox.setHgrow(separator, Priority.ALWAYS);
mainPaneContent.setBottom(mainPaneBottomContent);
mainPane.getChildren().add(mainPaneContent);
}
@Override
public Pane getPane() {
return mainPane;
}
void setLevelCollection(Collection<AccountLevel> levelCollection) {
Platform.runLater(()->{
levelChoiceBox.getItems().clear();
levelChoiceBox.getItems().addAll(levelCollection);
});
}
void setData(Account data) {
Platform.runLater(()->{
if(data!=null){
nameTextField.setText(data.getUsername());
passwordField.setText(data.getPassword());
levelChoiceBox.setValue(data.getPermissionLevel());
}else{
nameTextField.setText("");
passwordField.setText("");
levelChoiceBox.setValue(levelChoiceBox.getItems()
.stream()
.min(Enum::compareTo)
.orElse(AccountLevel.getLowest()));
}
});
}
}

View File

@ -0,0 +1,39 @@
package com.pqt.client.gui.modules.sale_screen;
import com.pqt.client.gui.modules.IGuiModule;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
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 com.pqt.core.entities.user_account.AccountLevel;
import javafx.scene.layout.Pane;
public class SaleScreen implements IGuiModule {
private SaleScreenView view;
public SaleScreen(AccountService accountService, StockService stockService, SaleService saleService) {
SaleScreenModel model = new SaleScreenModel(accountService, stockService, saleService);
SaleScreenController ctrl = new SaleScreenController(model);
view = new SaleScreenView(ctrl);
ctrl.setView(view);
ctrl.updateView();
}
@Override
public Pane getPane() {
return view.getPane();
}
@Override
public String getModuleName() {
return GUIStringTool.getSaleGuiModuleName();
}
@Override
public AccountLevel getLowestRequiredAccountLevel() {
return AccountLevel.WAITER;
}
}

View File

@ -0,0 +1,191 @@
package com.pqt.client.gui.modules.sale_screen;
import com.pqt.client.gui.modules.sale_screen.listeners.ISaleScreenModelListener;
import com.pqt.client.gui.modules.sale_screen.sale_validation_screen.listeners.ISaleValidationScreenListener;
import com.pqt.client.gui.ressources.components.specifics.products.listeners.IStockComponentListener;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.gui.ressources.components.specifics.sale.listeners.ISaleComponentListener;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.sale.SaleStatus;
import com.pqt.core.entities.sale.SaleType;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.event.Event;
import java.util.List;
class SaleScreenController {
private SaleScreenModel model;
private SaleScreenView view;
SaleScreenController(SaleScreenModel model) {
this.model = model;
this.model.addListener(new ISaleScreenModelListener() {
@Override
public void onSaleValidatedEvent() {
SaleScreenController.this.onSaleValidationSuccess();
}
@Override
public void onSaleNotValidatedEvent(SaleStatus status, Throwable cause) {
onSaleValidationError(status, cause);
}
@Override
public void onStockUpdatedEvent() {
view.setProducts(model.getProductList());
}
@Override
public void onAccountConnectedStateUpdatedEvent() {
updateActionLock();
}
@Override
public void onAccountListUpdatedEvent() {
view.setAccounts(model.getAccountList());
}
});
}
private void onSaleValidationSuccess() {
view.setSaleStatus(SaleStatus.ACCEPTED);
}
private void onSaleValidationError(SaleStatus status, Throwable cause) {
view.setSaleStatus(status);
}
void setView(SaleScreenView view) {
this.view = view;
}
void onAccountSelectedAsBeneficiary(Account account){
model.setSaleBeneficiary(account);
}
private Sale getCurrentSale(){
return model.getCurrentSale();
}
private void updateSale(){
view.setSale(getCurrentSale());
updateActionLock();
}
private void updateActionLock() {
boolean validationButtonEnabled = model.checkValidity(getCurrentSale())
&& model.isCurrentAccountConnected()
&& model.getCurrentAccountLevel().compareTo(AccountLevel.WAITER)>=0;
view.setValidationButtonEnabled(validationButtonEnabled);
}
private void updateData(){
view.setProducts(fetchProductList());
view.setSaleTypes(fetchSaleTypeList());
view.setAccounts(fetchAccountList());
}
void updateView(){
updateData();
updateSale();
}
private List<Product> fetchProductList(){
return model.getProductList();
}
private List<Account> fetchAccountList(){
return model.getAccountList();
}
private List<SaleType> fetchSaleTypeList(){
return model.getSaleTypeList();
}
ISaleComponentListener getSaleDisplayerListener() {
return new ISaleComponentListener() {
@Override
public void onComponentClickEvent(Event event, Product product) {
model.removeProductFromSale(product);
SaleScreenController.this.updateSale();
}
@Override
public void onRefreshContentRequestEvent() {}
@Override
public void onContentClickEvent(Event event, Sale eventTarget) {}
@Override
public void onAddContentRequestEvent() {}
@Override
public void onRemoveContentRequestEvent(Sale content) {}
@Override
public void onDetailContentRequestEvent(Sale content) {}
};
}
IStockComponentListener getStockDisplayerListener() {
return new IStockComponentListener() {
@Override
public void onRefreshContentRequestEvent() {}
@Override
public void onContentClickEvent(Event event, Product eventTarget) {
if(eventTarget!=null) {
model.addProductToSale(eventTarget);
SaleScreenController.this.updateSale();
}
}
@Override
public void onAddContentRequestEvent() {}
@Override
public void onRemoveContentRequestEvent(Product content) {}
@Override
public void onDetailContentRequestEvent(Product content) {}
};
}
Account getDefaultAccount() {
return new Account(null, null, AccountLevel.getLowest());
}
IValidatorComponentListener getValidatorListener() {
return new IValidatorComponentListener() {
@Override
public void onValidationEvent() {
if(model.commitSale())
view.switchToSaleValidationWaitingMode(model.getTempSaleId(), model.getCurrentSale());
}
@Override
public void onCancelEvent() {
model.clearSale();
SaleScreenController.this.updateView();
}
};
}
void onSaleTypeSelected(SaleType saleType) {
model.setSaleType(saleType);
}
ISaleValidationScreenListener getSaleValidationScreenListener() {
return saleValidatedSuccessfully -> {
view.switchToSaleCompositionMode();
if(saleValidatedSuccessfully){
model.clearSale();
}
updateView();
};
}
}

View File

@ -0,0 +1,225 @@
package com.pqt.client.gui.modules.sale_screen;
import com.pqt.client.gui.modules.sale_screen.listeners.ISaleScreenModelListener;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.account.listeners.IAccountListener;
import com.pqt.client.module.sale.SaleBuilder;
import com.pqt.client.module.sale.SaleService;
import com.pqt.client.module.sale.listeners.ISaleListener;
import com.pqt.client.module.stock.Listeners.IStockListener;
import com.pqt.client.module.stock.StockService;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.sale.SaleStatus;
import com.pqt.core.entities.sale.SaleType;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
class SaleScreenModel {
private EventListenerList listeners;
private AccountService accountService;
private StockService stockService;
private SaleService saleService;
private SaleBuilder currentSaleBuilder;
private long tempSaleId;
SaleScreenModel(AccountService accountService, StockService stockService, SaleService saleService) {
if(accountService==null || stockService==null || saleService==null)
throw new NullPointerException("At least one of the following services is null : account, stock, sale");
listeners = new EventListenerList();
this.accountService = accountService;
this.stockService = stockService;
this.saleService = saleService;
saleService.addListener(new ISaleListener() {
@Override
public void onSaleValidationSuccess(long saleId) {
if(saleId == SaleScreenModel.this.tempSaleId){
SaleScreenModel.this.fireSaleValidatedEvent();
}
}
@Override
public void onSaleValidationError(long saleId, Throwable cause) {
if(saleId == SaleScreenModel.this.tempSaleId){
SaleScreenModel.this.fireSaleNotValidatedEvent(SaleStatus.ABORTED, cause);
}
}
@Override
public void onSaleValidationRefused(long saleId, Throwable cause) {
if(saleId == SaleScreenModel.this.tempSaleId){
SaleScreenModel.this.fireSaleNotValidatedEvent(SaleStatus.REFUSED, cause);
}
}
});
stockService.addListener(new IStockListener() {
@Override
public void onGetProductListSuccessEvent() {
}
@Override
public void onGetProductListErrorEvent(Throwable cause) {
}
@Override
public void onGetProductListRefusedEvent(Throwable cause) {
}
@Override
public void onProductListUpdateSuccessEvent(long id) {
}
@Override
public void onProductListUpdateErrorEvent(long id, Throwable cause) {
}
@Override
public void onProductListUpdateRefusedEvent(long id, Throwable cause) {
}
@Override
public void onProductListChangedEvent() {
fireStockUpdatedEvent();
}
});
accountService.addListener(new IAccountListener() {
@Override
public void onAccountStatusChangedEvent(boolean status) {
fireAccountConnectedStatusUpdateEvent();
}
@Override
public void onAccountListChangedEvent() {
fireAccountListUpdatedEvent();
}
});
clearSale();
}
private void fireSaleValidatedEvent() {
Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class))
.forEach(ISaleScreenModelListener::onSaleValidatedEvent);
}
private void fireSaleNotValidatedEvent(SaleStatus status, Throwable cause) {
Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class))
.forEach(l->l.onSaleNotValidatedEvent(status, cause));
}
private void fireStockUpdatedEvent(){
Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class))
.forEach(ISaleScreenModelListener::onStockUpdatedEvent);
}
private void fireAccountListUpdatedEvent(){
Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class))
.forEach(ISaleScreenModelListener::onAccountListUpdatedEvent);
}
private void fireAccountConnectedStatusUpdateEvent() {
Arrays.stream(listeners.getListeners(ISaleScreenModelListener.class))
.forEach(ISaleScreenModelListener::onAccountConnectedStateUpdatedEvent);
}
List<Account> getAccountList() {
return accountService.getAllAccounts();
}
List<SaleType> getSaleTypeList() {
return saleService.getSaleTypes();
}
Sale getCurrentSale() {
return currentSaleBuilder!=null?currentSaleBuilder.build():null;
}
List<Product> getProductList() {
return stockService.getProducts().stream().filter(Product::isSellable).collect(Collectors.toList());
}
void clearSale() {
currentSaleBuilder = getNewSaleBuilder();
tempSaleId = -1;
}
private SaleBuilder getNewSaleBuilder(){
SaleBuilder saleBuilder = saleService.getNewSaleBuilder();
saleBuilder.orderedBy(accountService.getCurrentAccount());
saleBuilder.saleType(SaleType.CASH);
return saleBuilder;
}
boolean commitSale() {
if(!checkValidity(currentSaleBuilder.build()))
return false;
tempSaleId = saleService.commitSale(currentSaleBuilder);
return tempSaleId!=-1;
}
boolean checkValidity(Sale sale) {
return sale.getProducts().size()>0
&& sale.getOrderedBy()!=null
&& sale.getType()!=null;
}
long getTempSaleId(){
return tempSaleId;
}
void addProductToSale(Product product) {
if(currentSaleBuilder!=null)
currentSaleBuilder.addProduct(product);
}
void removeProductFromSale(Product product) {
if(currentSaleBuilder!=null)
currentSaleBuilder.removeProduct(product);
}
void setSaleType(SaleType saleType) {
if(currentSaleBuilder!=null)
currentSaleBuilder.saleType(saleType);
}
void setSaleBeneficiary(Account saleBeneficiary) {
if(currentSaleBuilder!=null)
currentSaleBuilder.orderedFor(saleBeneficiary);
}
void addListener(ISaleScreenModelListener listener){
listeners.add(ISaleScreenModelListener.class, listener);
}
void removeListener(ISaleScreenModelListener listener){
listeners.remove(ISaleScreenModelListener.class, listener);
}
boolean isCurrentAccountConnected() {
return accountService.isCurrentAccountLoggedIn();
}
AccountLevel getCurrentAccountLevel() {
if(accountService.getCurrentAccount()!=null)
return accountService.getCurrentAccount().getPermissionLevel();
else
return AccountLevel.getLowest();
}
}

View File

@ -0,0 +1,224 @@
package com.pqt.client.gui.modules.sale_screen;
import com.pqt.client.gui.modules.sale_screen.sale_validation_screen.SaleValidationScreen;
import com.pqt.client.gui.ressources.components.CommandComposerSaleDisplayer;
import com.pqt.client.gui.ressources.components.SimpleValidator;
import com.pqt.client.gui.ressources.components.generics.javafx_override.CssEnabledGridPane;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.gui.ressources.components.CategoryTabStockDisplayer;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.sale.SaleStatus;
import com.pqt.core.entities.sale.SaleType;
import com.pqt.core.entities.user_account.Account;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import java.util.List;
import java.util.stream.Collectors;
class SaleScreenView implements IFXComponent {
private SaleScreenController ctrl;
private SaleValidationScreen saleValidationScreen;
private StackPane mainPane;
private BorderPane mainPaneContent;
private CategoryTabStockDisplayer stockDisplayer;
private CommandComposerSaleDisplayer saleDisplayer;
private TextField saleMakerAccountDisplayer;
private ChoiceBox<Account> saleBeneficiaryAccountDisplayer;
private ChoiceBox<SaleType> saleTypeDisplayer;
private TextField salePriceDisplayer;
private SimpleValidator validator;
SaleScreenView(SaleScreenController ctrl) {
this.ctrl = ctrl;
initGui();
}
private void initGui() {
mainPane = new StackPane();
mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass());
mainPaneContent = new BorderPane();
/*
-----------------------CENTER PANE-----------------------
*/
{
mainPaneContent.prefWidthProperty().bind(mainPane.widthProperty());
mainPaneContent.prefHeightProperty().bind(mainPane.heightProperty());
stockDisplayer = new CategoryTabStockDisplayer();
stockDisplayer.addListener(ctrl.getStockDisplayerListener());
saleDisplayer = new CommandComposerSaleDisplayer();
saleDisplayer.addListener(ctrl.getSaleDisplayerListener());
HBox mainContentCenterPane = new HBox();
mainContentCenterPane.getChildren().addAll(stockDisplayer.getPane(), saleDisplayer.getPane());
mainContentCenterPane.setFillHeight(true);
stockDisplayer.getPane().prefWidthProperty().bind(mainContentCenterPane.widthProperty().divide(2));
saleDisplayer.getPane().prefWidthProperty().bind(mainContentCenterPane.widthProperty().divide(2));
mainPaneContent.setCenter(mainContentCenterPane);
}
/*
-----------------------BOTTOM PANE-----------------------
*/
{
HBox mainContentBottomPane = new HBox();
mainContentBottomPane.setFillHeight(true);
mainContentBottomPane.setAlignment(Pos.CENTER);
// Sale secondary data configuration (author, beneficiary, payment type, etc...
{
saleMakerAccountDisplayer = new TextField();
saleMakerAccountDisplayer.setEditable(false);
saleMakerAccountDisplayer.setPromptText(GUIStringTool.getSaleMakerTextFieldPromptText());
saleBeneficiaryAccountDisplayer = new ChoiceBox<>();
saleBeneficiaryAccountDisplayer.setConverter(GUIStringTool.getAccountStringConverter());
saleBeneficiaryAccountDisplayer.getSelectionModel()
.selectedItemProperty()
.addListener((observable, oldElem, newElem) -> ctrl.onAccountSelectedAsBeneficiary(newElem));
saleTypeDisplayer = new ChoiceBox<>();
saleTypeDisplayer.setConverter(GUIStringTool.getSaleTypeStringConverter());
saleTypeDisplayer.getSelectionModel()
.selectedItemProperty()
.addListener((observable, oldElem, newElem) -> ctrl.onSaleTypeSelected(newElem));
salePriceDisplayer = new TextField();
salePriceDisplayer.setEditable(false);
salePriceDisplayer.setPromptText(GUIStringTool.getSalePriceTextFieldPromptText());
GridPane mainContentBottomCenterPane = new CssEnabledGridPane();
mainContentBottomCenterPane.add(new Label(GUIStringTool.getSaleMakerTextFieldLabel()), 0, 0);
mainContentBottomCenterPane.add(saleMakerAccountDisplayer, 1, 0);
mainContentBottomCenterPane.add(new Label(GUIStringTool.getSaleBeneficiaryTextFieldLabel()), 0, 1);
mainContentBottomCenterPane.add(saleBeneficiaryAccountDisplayer, 1, 1);
mainContentBottomCenterPane.add(new Label(GUIStringTool.getSaleTypeTextFieldLabel()), 0, 2);
mainContentBottomCenterPane.add(saleTypeDisplayer, 1, 2);
mainContentBottomCenterPane.add(new Label(GUIStringTool.getSalePriceTextFieldLabel()), 0, 3);
mainContentBottomCenterPane.add(salePriceDisplayer, 1, 3);
mainContentBottomPane.getChildren().add(mainContentBottomCenterPane);
}
//Sale Validator
{
AnchorPane anchorPane = new AnchorPane();
validator = new SimpleValidator(true);
validator.addListener(ctrl.getValidatorListener());
anchorPane.getChildren().add(validator.getPane());
AnchorPane.setRightAnchor(validator.getPane(), 0d);
AnchorPane.setBottomAnchor(validator.getPane(), 0d);
mainContentBottomPane.getChildren().add(anchorPane);
HBox.setHgrow(anchorPane, Priority.ALWAYS);
}
mainPaneContent.setBottom(mainContentBottomPane);
}
/*
------------------------MAIN PANE------------------------
*/
mainPane.getChildren().add(mainPaneContent);
}
@Override
public Pane getPane() {
return mainPane;
}
void switchToSaleValidationWaitingMode(long saleId, Sale sale){
boolean clearChildren = mainPane.getChildren().size()>1;
Pane greyIntermediaryPane = new Pane();
greyIntermediaryPane.getStyleClass().clear();
greyIntermediaryPane.getStyleClass().add(GUICssTool.getIntermediaryPaneStyleClass());
saleValidationScreen = new SaleValidationScreen(saleId, sale);
saleValidationScreen.addListener(ctrl.getSaleValidationScreenListener());
Platform.runLater(()->{
if(clearChildren){
mainPane.getChildren().clear();
mainPane.getChildren().add(mainPaneContent);
}
StackPane.setAlignment(saleValidationScreen.getPane(), Pos.CENTER);
mainPane.getChildren().addAll(greyIntermediaryPane, saleValidationScreen.getPane());
});
}
void switchToSaleCompositionMode(){
Node[] childrenToRemove = mainPane.getChildren()
.stream()
.filter(child->!child.equals(mainPaneContent))
.collect(Collectors.toList())
.toArray(new Node[]{});
Platform.runLater(()->mainPane.getChildren().removeAll(childrenToRemove));
}
void setProducts(List<Product> products) {
stockDisplayer.display(products);
}
void setSaleTypes(List<SaleType> saleTypes) {
Platform.runLater(()->{
saleTypeDisplayer.getItems().clear();
if(saleTypes!=null)
saleTypeDisplayer.getItems().addAll(saleTypes);
});
}
void setAccounts(List<Account> accounts) {
Platform.runLater(()->{
saleBeneficiaryAccountDisplayer.getItems().clear();
saleBeneficiaryAccountDisplayer.getItems().add(ctrl.getDefaultAccount());
if(accounts!=null)
saleBeneficiaryAccountDisplayer.getItems().addAll(accounts);
});
}
void setSale(Sale sale) {
if(sale!=null) {
saleDisplayer.display(sale);
String price = GUIStringTool.getPriceRenderer().render(sale.getTotalPrice());
String currentAccount = GUIStringTool.getAccountStringConverter().toString(sale.getOrderedBy());
Platform.runLater(() -> {
salePriceDisplayer.setText(price);
saleMakerAccountDisplayer.setText(currentAccount);
selectElement(saleTypeDisplayer, sale.getType());
selectElement(saleBeneficiaryAccountDisplayer, sale.getOrderedFor());
});
}
}
private <T> void selectElement(ChoiceBox<T> choiceBox, T element){
if(element!=null){
if(!choiceBox.getItems().contains(element))
choiceBox.getItems().add(element);
choiceBox.getSelectionModel().select(element);
}else
choiceBox.getSelectionModel().clearSelection();
}
void setSaleStatus(SaleStatus status){
this.saleValidationScreen.setSaleStatus(status);
}
void setValidationButtonEnabled(boolean validationButtonEnabled) {
validator.setValidationButtonEnable(validationButtonEnabled);
}
}

View File

@ -0,0 +1,13 @@
package com.pqt.client.gui.modules.sale_screen.listeners;
import com.pqt.core.entities.sale.SaleStatus;
import java.util.EventListener;
public interface ISaleScreenModelListener extends EventListener {
void onSaleValidatedEvent();
void onSaleNotValidatedEvent(SaleStatus status, Throwable cause);
void onStockUpdatedEvent();
void onAccountConnectedStateUpdatedEvent();
void onAccountListUpdatedEvent();
}

View File

@ -0,0 +1,97 @@
package com.pqt.client.gui.modules.sale_screen.sale_validation_screen;
import com.pqt.client.gui.modules.sale_screen.sale_validation_screen.listeners.ISaleValidationScreenListener;
import com.pqt.client.gui.ressources.components.generics.javafx_override.CssEnabledGridPane;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.sale.SaleStatus;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
public class SaleValidationScreen {
private Pane mainPane;
private TextField saleStatusTextField;
private SaleStatus saleStatus;
private ProgressIndicator progressIndicator;
private Button validationButton;
private EventListenerList listeners;
public SaleValidationScreen(long saleId, Sale sale) {
listeners = new EventListenerList();
mainPane = new Pane();
mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass());
saleStatus = sale.getStatus();
BorderPane mainPaneContent = new BorderPane();
GridPane centerPane = new CssEnabledGridPane();
centerPane.setAlignment(Pos.CENTER);
Label saleIdLabel = new Label(GUIStringTool.getSaleIdLabel());
centerPane.add(saleIdLabel, 0, 0);
TextField saleIdTextField = new TextField(Long.toString(saleId));
saleIdTextField.setEditable(false);
centerPane.add(saleIdTextField, 1, 0);
Label saleStatusLabel = new Label(GUIStringTool.getSaleStatusLabel());
centerPane.add(saleStatusLabel, 0, 1);
saleStatusTextField = new TextField(GUIStringTool.getSaleStatusRenderer().render(saleStatus));
saleStatusTextField.setEditable(false);
centerPane.add(saleStatusTextField, 1, 1);
validationButton = new Button(GUIStringTool.getOkButtonLabel());
validationButton.setDisable(saleStatus.equals(SaleStatus.PENDING));
validationButton.setOnMouseClicked(event->fireScreenClose(saleStatus.equals(SaleStatus.ACCEPTED)));
centerPane.add(validationButton, 1,2);
mainPaneContent.setCenter(centerPane);
progressIndicator = new ProgressIndicator();
mainPaneContent.setLeft(progressIndicator);
mainPaneContent.prefHeightProperty().bind(mainPane.heightProperty());
mainPaneContent.prefWidthProperty().bind(mainPane.widthProperty());
mainPane.getChildren().add(mainPaneContent);
}
private void fireScreenClose(boolean saleValidatedSuccessFully) {
if(!validationButton.isDisable()){
Arrays.stream(listeners.getListeners(ISaleValidationScreenListener.class))
.forEach(listener->listener.onScreenClose(saleValidatedSuccessFully));
}
}
public void addListener(ISaleValidationScreenListener listener){
listeners.add(ISaleValidationScreenListener.class, listener);
}
public void setSaleStatus(SaleStatus status){
saleStatus = status;
Platform.runLater(()->{
validationButton.setDisable(saleStatus.equals(SaleStatus.PENDING));
saleStatusTextField.setText(GUIStringTool.getSaleStatusRenderer().render(status));
progressIndicator.setProgress((status.equals(SaleStatus.PENDING)?ProgressIndicator.INDETERMINATE_PROGRESS:1F));
});
}
public Pane getPane(){
return mainPane;
}
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.modules.sale_screen.sale_validation_screen.listeners;
import java.util.EventListener;
public interface ISaleValidationScreenListener extends EventListener {
void onScreenClose(boolean saleValidatedSuccessfully);
}

View File

@ -0,0 +1,35 @@
package com.pqt.client.gui.modules.stat_screen;
import com.pqt.client.gui.modules.IGuiModule;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.module.stat.StatService;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.scene.layout.Pane;
public class StatScreen implements IGuiModule {
private StatScreenView view;
public StatScreen(StatService statService) {
StatScreenModel model = new StatScreenModel(statService);
StatScreenController ctrl = new StatScreenController(model);
view = new StatScreenView();
ctrl.setView(view);
}
@Override
public String getModuleName() {
return GUIStringTool.getStatGuiModuleName();
}
@Override
public AccountLevel getLowestRequiredAccountLevel() {
return AccountLevel.STAFF;
}
@Override
public Pane getPane() {
return view.getPane();
}
}

View File

@ -0,0 +1,22 @@
package com.pqt.client.gui.modules.stat_screen;
import com.pqt.client.gui.modules.stat_screen.listeners.IStatScreenModelListener;
class StatScreenController implements IStatScreenModelListener{
private StatScreenModel model;
private StatScreenView view;
StatScreenController(StatScreenModel model) {
this.model = model;
}
void setView(StatScreenView view) {
this.view = view;
}
@Override
public void onStatisticsChangedEvent() {
view.display(model.getStatistics());
}
}

View File

@ -0,0 +1,38 @@
package com.pqt.client.gui.modules.stat_screen;
import com.pqt.client.gui.modules.stat_screen.listeners.IStatScreenModelListener;
import com.pqt.client.module.stat.StatService;
import com.pqt.client.module.stat.listeners.IStatListener;
import com.pqt.client.module.stat.listeners.StatListenerAdapter;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
import java.util.Map;
class StatScreenModel {
private EventListenerList listenerList;
private StatService statService;
StatScreenModel(StatService statService) {
this.statService = statService;
listenerList = new EventListenerList();
this.statService.addListener(new StatListenerAdapter() {
@Override
public void onGetStatSuccess() {
Arrays.stream(listenerList.getListeners(IStatScreenModelListener.class)).forEach(IStatScreenModelListener::onStatisticsChangedEvent);
}
});
}
Map<String, String> getStatistics() {
return statService.getStats();
}
void addListener(IStatScreenModelListener l){
listenerList.add(IStatScreenModelListener.class, l);
}
void removeListener(IStatScreenModelListener l){
listenerList.remove(IStatScreenModelListener.class, l);
}
}

View File

@ -0,0 +1,52 @@
package com.pqt.client.gui.modules.stat_screen;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.css.GUICssTool;
import javafx.application.Platform;
import javafx.scene.control.TextArea;
import javafx.scene.layout.Pane;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class StatScreenView implements IFXComponent {
private TextArea statTextArea;
private Pane mainPane;
StatScreenView() {
initGui();
}
private void initGui() {
mainPane = new Pane();
mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass());
statTextArea = new TextArea();
mainPane.getChildren().add(statTextArea);
statTextArea.setId("stat-screen-text-area");
statTextArea.setWrapText(true);
statTextArea.setEditable(false);
statTextArea.prefWidthProperty().bind(mainPane.widthProperty());
statTextArea.prefHeightProperty().bind(mainPane.heightProperty());
}
void display(Map<String, String> statistics){
List<String> lines = new ArrayList<>();
if(statistics!=null)
lines.addAll(statistics.keySet()
.stream()
.map(key->String.format(" * %s : %s", key, statistics.get(key)))
.collect(Collectors.toList()));
Platform.runLater(()->lines.forEach(line -> statTextArea.appendText(line+"\n")));
}
@Override
public Pane getPane() {
return mainPane;
}
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.modules.stat_screen.listeners;
import java.util.EventListener;
public interface IStatScreenModelListener extends EventListener {
void onStatisticsChangedEvent();
}

View File

@ -0,0 +1,39 @@
package com.pqt.client.gui.modules.stock_screen;
import com.pqt.client.gui.modules.IGuiModule;
import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreen;
import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreenFactory;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.stock.StockService;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.scene.layout.Pane;
public class StockScreen implements IGuiModule {
private StockScreenView view;
public StockScreen(StockService stockService, AccountService accountService) {
StockScreenModel model = new StockScreenModel(stockService, accountService);
StockScreenController ctrl = new StockScreenController(model);
view = new StockScreenView(ctrl, new ProductManagerScreenFactory(stockService));
model.addListener(ctrl);
ctrl.setView(view);
ctrl.refreshView();
}
@Override
public String getModuleName() {
return "Stock";
}
@Override
public AccountLevel getLowestRequiredAccountLevel() {
return AccountLevel.WAITER;
}
@Override
public Pane getPane() {
return view.getPane();
}
}

View File

@ -0,0 +1,112 @@
package com.pqt.client.gui.modules.stock_screen;
import com.pqt.client.gui.modules.stock_screen.listeners.IStockItemEventListener;
import com.pqt.client.gui.modules.stock_screen.listeners.IStockScreenModelListener;
import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreen;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.user_account.AccountLevel;
class StockScreenController implements IStockScreenModelListener{
private StockScreenModel model;
private StockScreenView view;
StockScreenController(StockScreenModel model) {
this.model = model;
}
void setView(StockScreenView view) {
this.view = view;
}
void onAddProductRequest() {
detailProduct(null);
}
void onDetailProductRequest() {
if(view.getSelectedProduct()!=null)
detailProduct(view.getSelectedProduct());
}
private void detailProduct(Product product){
view.switchToDetailMode(product);
}
IValidatorComponentListener getDetailScreenValidationListener(){
return new IValidatorComponentListener() {
@Override
public void onValidationEvent() {
if(view.isDetailScreenCreationPossible()) {
if (view.hasDetailScreenInitialValue()){
modifyProduct(view.getDetailScreenInitialValue(), view.getDetailScreenCreation());
}else{
addProduct(view.getDetailScreenCreation());
}
view.switchToGeneralMode();
}
}
@Override
public void onCancelEvent() {
view.switchToGeneralMode();
}
};
}
void onDeleteProductRequest() {
deleteProduct(view.getSelectedProduct());
}
private void addProduct(Product product){
model.commitProductAddition(product);
}
private void modifyProduct(Product oldProduct, Product newProduct){
model.commitProductModification(oldProduct, newProduct);
}
private void deleteProduct(Product product){
model.commitProductDeletion(product);;
}
void onRefreshProductsRequest() {
refreshView();
}
IStockItemEventListener getProductActivationListener() {
return this::detailProduct;
}
void refreshView(){
view.display(model.getProductCollection());
}
@Override
public void onStockUpdatedEvent() {
refreshView();
}
@Override
public void onAcccountConnectedStatusUpdatedEvent() {
updateViewActionLock();
}
void updateViewActionLock(){
if(model.isAccountConnected() && model.getConnectedAccountLevel().compareTo(AccountLevel.MASTER)>=0){
view.setAddProductActionLocked(false);
view.setEditProductActionLocked(view.getSelectedProduct()==null);
view.setRemoveProductActionLocked(view.getSelectedProduct()==null);
}else{
view.setAddProductActionLocked(true);
view.setEditProductActionLocked(true);
view.setRemoveProductActionLocked(true);
}
}
void onProductSelectedChange(){
updateViewActionLock();
}
}

View File

@ -0,0 +1,88 @@
package com.pqt.client.gui.modules.stock_screen;
import com.pqt.client.gui.modules.stock_screen.listeners.IStockScreenModelListener;
import com.pqt.client.module.account.AccountService;
import com.pqt.client.module.account.listeners.IAccountListener;
import com.pqt.client.module.stock.Listeners.StockListenerAdapter;
import com.pqt.client.module.stock.StockService;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.user_account.AccountLevel;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
import java.util.Collection;
class StockScreenModel {
private StockService stockService;
private AccountService accountService;
private EventListenerList listenerList;
StockScreenModel(StockService stockService, AccountService accountService) {
listenerList = new EventListenerList();
this.stockService = stockService;
this.stockService.addListener(new StockListenerAdapter(){
@Override
public void onProductListChangedEvent() {
StockScreenModel.this.fireProductCollectionChanged();
}
});
this.accountService = accountService;
this.accountService.addListener(new IAccountListener() {
@Override
public void onAccountStatusChangedEvent(boolean status) {
StockScreenModel.this.fireConnectedStatusChanged();
}
@Override
public void onAccountListChangedEvent() {
}
});
}
private void fireConnectedStatusChanged() {
Arrays.stream(listenerList.getListeners(IStockScreenModelListener.class))
.forEach(IStockScreenModelListener::onAcccountConnectedStatusUpdatedEvent);
}
private void fireProductCollectionChanged() {
Arrays.stream(listenerList.getListeners(IStockScreenModelListener.class))
.forEach(IStockScreenModelListener::onStockUpdatedEvent);
}
Collection<Product> getProductCollection() {
return stockService.getProducts();
}
void commitProductDeletion(Product product) {
stockService.commitUpdate(stockService.getNewUpdateBuilder().removeProduct(product));
}
void commitProductModification(Product oldProduct, Product newProduct) {
stockService.commitUpdate(stockService.getNewUpdateBuilder().modifyProduct(oldProduct, newProduct));
}
void commitProductAddition(Product product) {
stockService.commitUpdate(stockService.getNewUpdateBuilder().addProduct(product));
}
void addListener(IStockScreenModelListener l){
listenerList.add(IStockScreenModelListener.class, l);
}
void removeListener(IStockScreenModelListener l){
listenerList.remove(IStockScreenModelListener.class, l);
}
boolean isAccountConnected() {
return accountService.isCurrentAccountLoggedIn();
}
AccountLevel getConnectedAccountLevel() {
if(accountService.getCurrentAccount()!=null)
return accountService.getCurrentAccount().getPermissionLevel();
else
return AccountLevel.getLowest();
}
}

View File

@ -0,0 +1,242 @@
package com.pqt.client.gui.modules.stock_screen;
import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreen;
import com.pqt.client.gui.modules.stock_screen.product_manager_screen.ProductManagerScreenFactory;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.gui.ressources.strings.IObjectStringRenderer;
import com.pqt.core.entities.product.Product;
import javafx.application.Platform;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.css.PseudoClass;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.*;
import javafx.util.Callback;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
class StockScreenView implements IFXComponent {
private StockScreenController ctrl;
private StackPane mainPane;
private BorderPane mainPaneContent;
private TableView<Product> stockTableView;
private ProductManagerScreenFactory productManagerScreenFactory;
private ProductManagerScreen currentDetailScreen;
private Button addProductButton;
private Button detailProductButton;
private Button removeProductButton;
StockScreenView(StockScreenController ctrl, ProductManagerScreenFactory productManagerScreenFactory) {
this.ctrl = ctrl;
this.productManagerScreenFactory = productManagerScreenFactory;
initGui();
}
private void initGui() {
mainPane = new StackPane();
mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass());
mainPaneContent = new BorderPane();
mainPane.getChildren().add(mainPaneContent);
mainPaneContent.prefWidthProperty().bind(mainPane.widthProperty());
mainPaneContent.prefHeightProperty().bind(mainPane.heightProperty());
addProductButton = new Button(GUIStringTool.getAddButtonLabel());
addProductButton.setOnMouseClicked(event -> ctrl.onAddProductRequest());
detailProductButton = new Button(GUIStringTool.getDetailButtonLabel());
detailProductButton.setOnMouseClicked(event -> ctrl.onDetailProductRequest());
detailProductButton.setDisable(true);
removeProductButton = new Button(GUIStringTool.getRemoveButtonLabel());
removeProductButton.setDisable(true);
removeProductButton.setOnMouseClicked(event -> ctrl.onDeleteProductRequest());
Button refreshProductButton = new Button(GUIStringTool.getRefreshButtonLabel());
refreshProductButton.setOnMouseClicked(event -> ctrl.onRefreshProductsRequest());
ToolBar actionToolbar = new ToolBar();
actionToolbar.getItems().addAll(addProductButton, detailProductButton, removeProductButton, refreshProductButton);
HBox mainPaneTopContent = new HBox();
HBox separator = new HBox();
mainPaneTopContent.getChildren().addAll(separator, actionToolbar);
HBox.setHgrow(separator, Priority.ALWAYS);
mainPaneContent.setTop(mainPaneTopContent);
PseudoClass outOfStockPseudoClass = PseudoClass.getPseudoClass("stock-out");
PseudoClass lowStockPseudoClass = PseudoClass.getPseudoClass("stock-low");
PseudoClass highStockPseudoClass = PseudoClass.getPseudoClass("stock-high");
stockTableView = new TableView<>();
stockTableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
stockTableView.setRowFactory(tableView->{
TableRow<Product> row = new TableRow<>();
row.itemProperty().addListener((obs, oldVal, newVal)->{
if(newVal!=null){
row.pseudoClassStateChanged(outOfStockPseudoClass, newVal.getAmountRemaining()<=0);
row.pseudoClassStateChanged(lowStockPseudoClass, newVal.getAmountRemaining()>0 && newVal.getAmountRemaining()<30);
row.pseudoClassStateChanged(highStockPseudoClass, newVal.getAmountRemaining()>=30);
}else{
row.pseudoClassStateChanged(outOfStockPseudoClass, false);
row.pseudoClassStateChanged(lowStockPseudoClass, false);
row.pseudoClassStateChanged(highStockPseudoClass, false);
}
});
row.setOnMouseClicked(event -> {
if (event.getButton().equals(MouseButton.PRIMARY) && event.getClickCount() == 2)
ctrl.getProductActivationListener().onProductActivated(row.getItem());
});
row.setOnKeyTyped(event -> {
if (event.getCode().equals(KeyCode.ENTER))
ctrl.getProductActivationListener().onProductActivated(row.getItem());
});
return row;
});
stockTableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
stockTableView.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal)->ctrl.onProductSelectedChange());
List<TableColumn<Product, ?>> columns = new ArrayList<>();
columns.add(createNewTableColumn(String.class,
GUIStringTool.getProductNameColumnHeader(),
param -> new SimpleStringProperty(param.getValue().getName()),
null
));
columns.add(createNewTableColumn(String.class,
GUIStringTool.getProductCategoryColumnHeader(),
param -> new SimpleStringProperty(param.getValue().getCategory().getName()),
null
));
columns.add(createNewTableColumn(Integer.class,
GUIStringTool.getProductAmountRemainingColumnHeader(),
param -> new SimpleIntegerProperty(param.getValue().getAmountRemaining()).asObject(),
null
));
columns.add(createNewTableColumn(Integer.class,
GUIStringTool.getProductAmountSoldColumnHeader(),
param -> new SimpleIntegerProperty(param.getValue().getAmountSold()).asObject(),
null
));
columns.add(createNewTableColumn(Double.class,
GUIStringTool.getProductPriceColumnHeader(),
param -> new SimpleDoubleProperty(param.getValue().getPrice()).asObject(),
GUIStringTool.getPriceRenderer()
));
columns.add(createNewTableColumn(Boolean.class,
GUIStringTool.getProductIsSellableColumnHeader(),
param -> new SimpleBooleanProperty(param.getValue().isSellable()),
GUIStringTool.getBooleanRenderer()
));
stockTableView.getColumns().addAll(columns);
mainPaneContent.setCenter(stockTableView);
}
private <T> TableColumn<Product, T> createNewTableColumn(Class<T> clazz,
String header,
Callback<TableColumn.CellDataFeatures<Product, T>, ObservableValue<T>> cellValueFactory,
IObjectStringRenderer<T> renderer){
TableColumn<Product, T> column = new TableColumn<>();
if(header!=null)
column.setText(header);
if(cellValueFactory!=null)
column.setCellValueFactory(cellValueFactory);
if(renderer!=null)
column.setCellFactory(table -> new TableCell<Product, T>() {
@Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item == null || empty) {
setText(null);
setStyle("");
} else {
setText(renderer.render(item));
}
}
}
);
return column;
}
void display(Collection<Product> productCollection){
Platform.runLater(()->{
this.stockTableView.getItems().clear();
this.stockTableView.getItems().addAll(productCollection);
});
}
@Override
public Pane getPane() {
return mainPane;
}
Product getSelectedProduct() {
return stockTableView.getSelectionModel().getSelectedItem();
}
void switchToDetailMode(Product product) {
if(currentDetailScreen==null){
currentDetailScreen = productManagerScreenFactory.create(product);
currentDetailScreen.addListener(ctrl.getDetailScreenValidationListener());
Pane separator = new Pane();
separator.getStyleClass().add(GUICssTool.getIntermediaryPaneStyleClass());
Platform.runLater(()->mainPane.getChildren().addAll(separator, currentDetailScreen.getPane()));
}
}
void switchToGeneralMode() {
if(currentDetailScreen!=null){
List<Node> toRemove = mainPane.getChildren()
.stream()
.filter(node->!node.equals(mainPaneContent))
.collect(Collectors.toList());
Platform.runLater(()->{
mainPane.getChildren().removeAll(toRemove);
currentDetailScreen = null;
});
}
}
boolean isDetailScreenCreationPossible() {
System.out.println("test creation possible : ");
return currentDetailScreen!=null && currentDetailScreen.isCreationPossible();
}
boolean hasDetailScreenInitialValue() {
return currentDetailScreen!=null && currentDetailScreen.hasInitialValue();
}
Product getDetailScreenInitialValue() {
if(currentDetailScreen!=null)
return currentDetailScreen.getInitialValueSnapshot();
else
return null;
}
Product getDetailScreenCreation() {
if(currentDetailScreen!=null)
return currentDetailScreen.create();
else
return null;
}
void setAddProductActionLocked(boolean locked){
addProductButton.setDisable(locked);
}
void setRemoveProductActionLocked(boolean locked){
removeProductButton.setDisable(locked);
}
void setEditProductActionLocked(boolean locked){
detailProductButton.setDisable(locked);
}
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.modules.stock_screen.listeners;
import com.pqt.core.entities.product.Product;
public interface IStockItemEventListener {
void onProductActivated(Product product);
}

View File

@ -0,0 +1,8 @@
package com.pqt.client.gui.modules.stock_screen.listeners;
import java.util.EventListener;
public interface IStockScreenModelListener extends EventListener {
void onStockUpdatedEvent();
void onAcccountConnectedStatusUpdatedEvent();
}

View File

@ -0,0 +1,56 @@
package com.pqt.client.gui.modules.stock_screen.product_manager_screen;
import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.module.stock.StockService;
import com.pqt.core.entities.product.Product;
import javafx.scene.layout.Pane;
public class ProductManagerScreen implements IFXCreatorComponent<Product>, IFXValidatorComponent {
private ProductManagerScreenView view;
private ProductManagerScreenModel model;
private ProductManagerScreenController ctrl;
public ProductManagerScreen(Product initialData, StockService stockService){
model = new ProductManagerScreenModel(initialData, stockService);
ctrl = new ProductManagerScreenController(model);
view = new ProductManagerScreenView(ctrl);
ctrl.setView(view);
ctrl.updateView();
}
@Override
public Product create() {
return model.create();
}
@Override
public boolean isCreationPossible() {
return model.isProductCreationPossible();
}
@Override
public Pane getPane() {
return view.getPane();
}
@Override
public void addListener(IValidatorComponentListener l) {
ctrl.addListener(l);
}
@Override
public void removeListener(IValidatorComponentListener l) {
ctrl.removeListener(l);
}
public boolean hasInitialValue(){
return model.hasInitialData();
}
public Product getInitialValueSnapshot(){
return new Product(model.getInitialData());
}
}

View File

@ -0,0 +1,93 @@
package com.pqt.client.gui.modules.stock_screen.product_manager_screen;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.core.entities.product.Category;
import com.pqt.core.entities.product.Product;
import javafx.beans.value.ChangeListener;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
class ProductManagerScreenController {
private EventListenerList listenerList;
private ProductManagerScreenModel model;
private ProductManagerScreenView view;
ProductManagerScreenController(ProductManagerScreenModel model) {
listenerList = new EventListenerList();
this.model = model;
}
void setView(ProductManagerScreenView view){
this.view = view;
}
ChangeListener<? super Product> getProductComponentSelectionListener() {
return (obs, oldValue, newValue)->{
if(newValue!=null) {
if (model.isComponent(newValue))
model.removeComponent(newValue);
else
model.addComponent(newValue);
updateView();
}
};
}
void updateView() {
view.setProduct(model.getActualProductState());
view.setCategoryCollection(model.getCategoryCollection());
view.setProductCollection(model.getEligibleComponentList());
}
IValidatorComponentListener getValidatorListener() {
return new IValidatorComponentListener() {
@Override
public void onValidationEvent() {
Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onValidationEvent);
}
@Override
public void onCancelEvent() {
Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onCancelEvent);
}
};
}
public void addListener(IValidatorComponentListener l) {
listenerList.add(IValidatorComponentListener.class, l);
}
public void removeListener(IValidatorComponentListener l) {
listenerList.remove(IValidatorComponentListener.class, l);
}
boolean isProductHighlighted(Product product) {
return model.getActualProductState().getComponents().contains(product);
}
void onNameChanged(String oldVal, String newVal) {
model.changeName(newVal);
}
void onPriceChanged(double oldVal, double newVal) {
model.changePrice(newVal);
}
void onCategoryChanged(Category oldVal, Category newVal) {
model.changeCategory(newVal);
}
void onAmountRemainingChanged(int oldVal, int newVal) {
model.changeAmountRemaining(newVal);
}
void onAmountSoldChanged(int oldVal, int newVal) {
model.changeAmountSold(newVal);
}
void onSellableStateChanged(boolean oldVal, boolean newVal) {
model.setSellable(newVal);
}
}

View File

@ -0,0 +1,17 @@
package com.pqt.client.gui.modules.stock_screen.product_manager_screen;
import com.pqt.client.module.stock.StockService;
import com.pqt.core.entities.product.Product;
public final class ProductManagerScreenFactory {
private StockService stockService;
public ProductManagerScreenFactory(StockService stockService) {
this.stockService = stockService;
}
public ProductManagerScreen create(Product product){
return new ProductManagerScreen(product, stockService);
}
}

View File

@ -0,0 +1,100 @@
package com.pqt.client.gui.modules.stock_screen.product_manager_screen;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.module.stock.StockService;
import com.pqt.core.entities.product.Category;
import com.pqt.core.entities.product.LightweightProduct;
import com.pqt.core.entities.product.Product;
import java.util.*;
import java.util.stream.Collectors;
class ProductManagerScreenModel {
private StockService stockService;
private Product initialData;
private Product currentData;
ProductManagerScreenModel(Product initialData, StockService stockService) {
this.stockService = stockService;
this.initialData = initialData;
if(initialData==null)
currentData = new Product();
else
currentData = new Product(initialData);
}
List<Product> getEligibleComponentList() {
return stockService.getProductsExcluding(currentData);
}
Product getActualProductState(){
return currentData;
}
Product create() {
if(isProductCreationPossible())
return currentData;
else
return null;
}
boolean isProductCreationPossible() {
return (initialData!=null && !currentData.equals(initialData))
&& !currentData.getName().isEmpty()
&& currentData.getCategory()!=null
&& currentData.getPrice()>=0;
}
void addComponent(Product product) {
currentData.getComponents().add(product);
}
void removeComponent(Product product) {
currentData.getComponents().remove(product);
}
void changeCategory(Category category){
this.currentData.setCategory(category);
}
void changePrice(double price){
this.currentData.setPrice(price);
}
void changeName(String name){
this.currentData.setName(name);
}
void changeAmountRemaining(int amount){
this.currentData.setAmountRemaining(amount);
}
void changeAmountSold(int amount){
this.currentData.setAmountSold(amount);
}
void setSellable(boolean sellable){
this.currentData.setSellable(sellable);
}
Collection<Category> getCategoryCollection() {
return stockService.getProducts()
.stream()
.map(Product::getCategory)
.distinct()
.collect(Collectors.toList());
}
boolean isComponent(Product product) {
return currentData.getComponents().contains(product);
}
boolean hasInitialData(){
return initialData!=null;
}
Product getInitialData(){
return initialData;
}
}

View File

@ -0,0 +1,212 @@
package com.pqt.client.gui.modules.stock_screen.product_manager_screen;
import com.pqt.client.gui.ressources.components.SimpleValidator;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.components.generics.javafx_override.CssEnabledGridPane;
import com.pqt.client.gui.ressources.components.generics.javafx_override.HighlightListCell;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.product.Category;
import com.pqt.core.entities.product.Product;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Collection;
class ProductManagerScreenView implements IFXComponent {
private ProductManagerScreenController ctrl;
private int gridLines;
private StackPane mainPane;
private BorderPane mainPaneContent;
private TextField productNameTextField,
productAmountRemainingTextField,
productAmountSoldTextField,
productPriceTextField;
private ComboBox<Category> productCategoryComboBox;
private CheckBox productSellableCheckBox;
private ListView<Product> productComponentsListView;
ProductManagerScreenView(ProductManagerScreenController ctrl) {
this.ctrl = ctrl;
initGui();
}
private void initGui() {
mainPane = new StackPane();
mainPane.getStyleClass().add(GUICssTool.getMainModulePaneCssClass());
mainPaneContent = new BorderPane();
GridPane mainPaneCenterContent = new CssEnabledGridPane();
mainPaneCenterContent.setAlignment(Pos.CENTER);
gridLines = 0;
NumberFormat priceFormat = NumberFormat.getNumberInstance();
NumberFormat intFormat = NumberFormat.getIntegerInstance();
Label productNameLabel = new Label(GUIStringTool.getProductNameLabel());
productNameTextField = new TextField();
productNameTextField.textProperty().addListener((obs, oldVal, newVal)->ctrl.onNameChanged(oldVal,newVal));
addLineToGrid(mainPaneCenterContent, productNameLabel, productNameTextField);
Label productCategoryLabel = new Label(GUIStringTool.getProductCategoryLabel());
productCategoryComboBox = new ComboBox<>();
productCategoryComboBox.setEditable(true);
productCategoryComboBox.setConverter(GUIStringTool.getCategoryStringConverter());
productCategoryComboBox.valueProperty().addListener((obs, oldVal, newVal)->ctrl.onCategoryChanged(oldVal, newVal));
addLineToGrid(mainPaneCenterContent, productCategoryLabel, productCategoryComboBox);
Label productAmountRemainingLabel = new Label(GUIStringTool.getProductAmountRemainingLabel());
productAmountRemainingTextField = getNumberOnlyTextField(intFormat);
productAmountRemainingTextField.textProperty().addListener((obs, oldVal, newVal)->{
try{
int oldInt = oldVal.isEmpty()?0:Integer.parseInt(oldVal);
int newInt = newVal.isEmpty()?0:Integer.parseInt(newVal);
ctrl.onAmountRemainingChanged(oldInt, newInt);
}catch(NumberFormatException e){
e.printStackTrace();
}
});
addLineToGrid(mainPaneCenterContent, productAmountRemainingLabel, productAmountRemainingTextField);
Label productAmountSoldLabel = new Label(GUIStringTool.getProductAmountSoldLabel());
productAmountSoldTextField = getNumberOnlyTextField(intFormat);
productAmountSoldTextField.textProperty().addListener((obs, oldVal, newVal)->{
try{
int oldInt = oldVal.isEmpty()?0:Integer.parseInt(oldVal);
int newInt = newVal.isEmpty()?0:Integer.parseInt(newVal);
ctrl.onAmountSoldChanged(oldInt, newInt);
}catch(NumberFormatException e){
e.printStackTrace();
}
});
addLineToGrid(mainPaneCenterContent, productAmountSoldLabel, productAmountSoldTextField);
Label productSellableLabel = new Label(GUIStringTool.getProductSellableLabel());
productSellableCheckBox = new CheckBox();
productSellableCheckBox.selectedProperty().addListener((obs, oldVal, newVal)->ctrl.onSellableStateChanged(oldVal,newVal));
addLineToGrid(mainPaneCenterContent, productSellableLabel, productSellableCheckBox);
Label productPriceLabel = new Label(GUIStringTool.getProductPriceLabel());
productPriceTextField = getNumberOnlyTextField(priceFormat);
productPriceTextField.textProperty().addListener((obs, oldVal, newVal)->{
try{
ctrl.onPriceChanged((oldVal.isEmpty()?-1:Double.parseDouble(oldVal)), (newVal.isEmpty()?-1:Double.parseDouble(newVal)));
}catch(NumberFormatException e){
e.printStackTrace();
}
});
addLineToGrid(mainPaneCenterContent, productPriceLabel, productPriceTextField);
mainPaneContent.setCenter(mainPaneCenterContent);
VBox mainPaneRightContent = new VBox();
mainPaneRightContent.setAlignment(Pos.CENTER);
Label title = new Label(GUIStringTool.getComponentListTitleLabel());
title.setAlignment(Pos.CENTER);
title.getStyleClass().add(GUICssTool.getTitleTextStyleClass());
productComponentsListView = new ListView<>();
productComponentsListView.setCellFactory(listView->new HighlightListCell<Product>(){
@Override
protected void updateItem(Product item, boolean empty) {
super.updateItem(item, empty);
if(item==null || empty){
setText(null);
setGraphic(null);
}else{
setText(GUIStringTool.getSimpleProductStringRenderer().render(item));
if(ctrl.isProductHighlighted(item)){
if(!isHightlighted()) {
setHighLight(true);
applyCss();
}
}else {
if (isHightlighted()) {
setHighLight(false);
applyCss();
}
}
}
}
});
productComponentsListView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
productComponentsListView.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue)->{
this.ctrl.getProductComponentSelectionListener().changed(obs, oldValue, newValue);
if(newValue!=null)
Platform.runLater(()->productComponentsListView.getSelectionModel().clearSelection(productComponentsListView.getSelectionModel().getSelectedIndex()));
});
mainPaneRightContent.getChildren().addAll(title, productComponentsListView);
mainPaneContent.setRight(mainPaneRightContent);
HBox mainPaneBottomContent = new HBox();
HBox separator = new HBox();
SimpleValidator validator = new SimpleValidator();
validator.addListener(ctrl.getValidatorListener());
mainPaneBottomContent.getChildren().addAll(separator, validator.getPane());
HBox.setHgrow(separator, Priority.ALWAYS);
mainPaneContent.setBottom(mainPaneBottomContent);
mainPane.getChildren().add(mainPaneContent);
}
private void addLineToGrid(GridPane grid, Node... nodes){
gridLines++;
int columnIndex = 0;
for(Node node : nodes){
grid.add(node, columnIndex, gridLines);
columnIndex++;
}
}
private TextField getNumberOnlyTextField(NumberFormat format){
TextField textField = new TextField();
textField.textProperty().addListener((obs, oldValue, newValue)->{
if(!newValue.matches("^[-+]?[0-9]+[.,]?[0-9]*$"))
Platform.runLater(()->textField.setText(oldValue));
});
return textField;
}
@Override
public Pane getPane() {
return mainPane;
}
void setProduct(Product product){
if(product!=null){
Platform.runLater(()->{
productNameTextField.setText(product.getName());
productCategoryComboBox.setValue(product.getCategory());
productAmountRemainingTextField.setText(Integer.toString(product.getAmountRemaining()));
productAmountRemainingTextField.setEditable(product.getComponents().isEmpty());
productAmountSoldTextField.setText(Integer.toString(product.getAmountSold()));
productComponentsListView.getItems().clear();
productComponentsListView.getItems().addAll(product.getComponents());
productSellableCheckBox.setSelected(product.isSellable());
productPriceTextField.setText(Double.toString(product.getPrice()));
});
}
}
void setCategoryCollection(Collection<Category> categoryCollection){
Platform.runLater(()->{
productCategoryComboBox.getItems().clear();
productCategoryComboBox.getItems().addAll(categoryCollection);
});
}
void setProductCollection(Collection<Product> productCollection){
Platform.runLater(()->{
productComponentsListView.getItems().clear();
productComponentsListView.getItems().addAll(productCollection);
});
}
}

View File

@ -0,0 +1,162 @@
package com.pqt.client.gui.ressources.components;
import com.pqt.client.gui.ressources.components.generics.creators.IFXCreatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.SimpleValidatorComponentFirerer;
import com.pqt.client.gui.ressources.components.specifics.account.IFXAccountsDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.SimpleAccountComponentFirerer;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import java.util.Collection;
public class AccountManager implements IFXAccountsDisplayerComponent, IFXValidatorComponent, IFXCreatorComponent<Account> {
private Pane mainPane;
private VBox mainDisconnectedPane, mainConnectedPane;
private TextField connectedUsernameField;
private ChoiceBox<Account> disconnectedUsernameField;
private PasswordField passwordField;
private SimpleAccountComponentFirerer accountEventFirerer;
private SimpleValidatorComponentFirerer validatorEventFirerer;
private Account currentAccount;
public AccountManager() {
accountEventFirerer = new SimpleAccountComponentFirerer();
validatorEventFirerer = new SimpleValidatorComponentFirerer();
currentAccount = null;
init();
}
private void init() {
mainPane = new Pane();
mainConnectedPane = new VBox();
mainDisconnectedPane = new VBox();
connectedUsernameField = new TextField();
connectedUsernameField.setEditable(false);
Button disconnectButton = new Button(GUIStringTool.getLogoutButtonLabel());
disconnectButton.setOnMouseClicked(event->validatorEventFirerer.fireCancelEvent());
disconnectButton.setOnKeyTyped(event->{if(event.getCode().equals(KeyCode.ENTER)) validatorEventFirerer.fireCancelEvent();});
mainConnectedPane.getChildren().addAll(connectedUsernameField, disconnectButton);
disconnectedUsernameField = new ChoiceBox<>();
disconnectedUsernameField.setConverter(GUIStringTool.getAccountStringConverter());
passwordField = new PasswordField();
passwordField.setPromptText(GUIStringTool.getPasswordFieldPromptText());
Button validationButton = new Button(GUIStringTool.getLoginButtonLabel());
validationButton.setOnMouseClicked(event-> validatorEventFirerer.fireValidationEvent());
validationButton.setOnKeyTyped(event->{if(event.getCode().equals(KeyCode.ENTER)) validatorEventFirerer.fireValidationEvent();});
mainDisconnectedPane.getChildren().addAll(disconnectedUsernameField, passwordField, validationButton);
refreshMainPane();
display(null);
}
@Override
public void display(Collection<Account> content) {
Platform.runLater(()->{
if(content!=null && content.size()>0)
disconnectedUsernameField.setItems(FXCollections.observableArrayList(content));
else{
disconnectedUsernameField.getItems().clear();
disconnectedUsernameField.getItems().add(new Account("null", "", AccountLevel.getLowest()));
}
});
}
public void setCurrentAccount(Account account){
currentAccount = account;
Platform.runLater(()->connectedUsernameField.setText(GUIStringTool.getAccountStringConverter().toString(currentAccount)));
refreshMainPane();
}
private void refreshMainPane() {
if(currentAccount!=null)
Platform.runLater(
()->{
mainPane.getChildren().clear();
mainPane.getChildren().add(mainConnectedPane);
}
);
else
Platform.runLater(
()->{
mainPane.getChildren().clear();
mainPane.getChildren().add(mainDisconnectedPane);
}
);
}
public Account getCurrentAccount() {
return currentAccount;
}
@Override
public void addListener(IAccountComponentListener l) {
accountEventFirerer.addListener(l);
}
@Override
public void removeListener(IAccountComponentListener l) {
accountEventFirerer.removeListener(l);
}
@Override
public Pane getPane() {
return mainPane;
}
@Override
public void addListener(IValidatorComponentListener l) {
validatorEventFirerer.addListener(l);
}
@Override
public void removeListener(IValidatorComponentListener l) {
validatorEventFirerer.removeListener(l);
}
@Override
public Account create() {
if(!isCreationPossible())
return null;
return new Account(disconnectedUsernameField.getValue().getUsername(), passwordField.getText(), disconnectedUsernameField.getValue().getPermissionLevel());
}
@Override
public boolean isCreationPossible() {
return currentAccount==null
&& disconnectedUsernameField.getAccessibleText()!=null
&& !disconnectedUsernameField.getAccessibleText().isEmpty()
&& passwordField.getText()!=null
&& !passwordField.getText().isEmpty();
}
}

View File

@ -0,0 +1,129 @@
package com.pqt.client.gui.ressources.components;
import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.products.listeners.IStockComponentListener;
import com.pqt.client.gui.ressources.components.specifics.products.listeners.SimpleStockComponentFirerer;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.gui.ressources.strings.IObjectStringRenderer;
import com.pqt.core.entities.product.Product;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
public class CategoryTabStockDisplayer implements IFXDisplayerComponent<Collection<Product>, IStockComponentListener> {
private SimpleStockComponentFirerer firerer;
private BorderPane mainPane;
private TabPane tabPane;
public CategoryTabStockDisplayer() {
init();
firerer = new SimpleStockComponentFirerer();
}
@Override
public void display(Collection<Product> content) {
final ObservableList<Tab> tabs = FXCollections.observableArrayList();
if(content!=null){
List<String> categories = content.stream().map(product->product.getCategory().getName()).distinct().collect(Collectors.toList());
for(String cat : categories){
tabs.add(createCategoryTab(cat, content.stream().filter(p->p.getCategory().getName().equals(cat)).collect(Collectors.toList())));
}
}
Platform.runLater(()->{
tabPane.getTabs().clear();
tabPane.getTabs().addAll(tabs);
});
}
@Override
public void addListener(IStockComponentListener l) {
firerer.addListener(l);
}
@Override
public void removeListener(IStockComponentListener l) {
firerer.removeListener(l);
}
@Override
public Pane getPane() {
return mainPane;
}
private void init(){
mainPane = new BorderPane();
Label title = new Label(GUIStringTool.getCategorytabStockDisplayerTitle());
title.setAlignment(Pos.CENTER);
title.getStyleClass().add(GUICssTool.getTitleTextStyleClass());
HBox topPane = new HBox();
topPane.setFillHeight(true);
topPane.setAlignment(Pos.CENTER);
topPane.getChildren().add(title);
mainPane.setTop(topPane);
tabPane = new TabPane();
mainPane.setCenter(tabPane);
}
private Tab createCategoryTab(String categoryName, Collection<Product> products){
Tab tab = new Tab(categoryName);
tab.closableProperty().setValue(false);
ListView<Product> listView = new ListView<>();
listView.setCellFactory(list->new ListCell<Product>(){
@Override
protected void updateItem(Product item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
setText(CategoryTabStockDisplayer.getProductRenderer().render(item));
}
}
});
listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
listView.setEditable(false);
listView.setOnMouseClicked(event->{
firerer.fireContentClickEvent(event, listView.getSelectionModel().getSelectedItem());
Platform.runLater(()->listView.getSelectionModel().clearSelection(listView.getSelectionModel().getSelectedIndex()));
});
listView.setOnKeyTyped(event -> {
if(event.getCode().equals(KeyCode.ENTER)){
firerer.fireContentClickEvent(event, listView.getSelectionModel().getSelectedItem());
Platform.runLater(()->listView.getSelectionModel().clearSelection(listView.getSelectionModel().getSelectedIndex()));
event.consume();
}
});
listView.setItems(FXCollections.observableArrayList(products));
tab.setContent(listView);
return tab;
}
private static IObjectStringRenderer<Product> getProductRenderer(){
return GUIStringTool.getDetailledProductStringRenderer();
}
}

View File

@ -0,0 +1,96 @@
package com.pqt.client.gui.ressources.components;
import com.pqt.client.gui.ressources.components.specifics.sale.IFXSaleDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.sale.listeners.ISaleComponentListener;
import com.pqt.client.gui.ressources.components.specifics.sale.listeners.SimpleSaleComponentFirerer;
import com.pqt.client.gui.ressources.css.GUICssTool;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
public class CommandComposerSaleDisplayer implements IFXSaleDisplayerComponent {
private SimpleSaleComponentFirerer firerer;
private BorderPane mainPane;
private ListView<Product> listView;
private Sale sale;
public CommandComposerSaleDisplayer() {
firerer = new SimpleSaleComponentFirerer();
init();
}
private void init() {
mainPane = new BorderPane();
Label title = new Label(GUIStringTool.getCommandComposerTitleLabel());
title.setAlignment(Pos.CENTER);
title.getStyleClass().add(GUICssTool.getTitleTextStyleClass());
HBox topPane = new HBox();
topPane.setFillHeight(true);
topPane.setAlignment(Pos.CENTER);
topPane.getChildren().add(title);
mainPane.setTop(topPane);
listView = new ListView<>();
listView.setCellFactory(list->new ListCell<Product>(){
@Override
protected void updateItem(Product item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
setGraphic(null);
} else {
setText(GUIStringTool.getSaleItemStringRenderer().render(item, sale.getProducts().get(item)));
}
}
});
listView.setEditable(false);
listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
listView.setOnMouseClicked(event->firerer.fireComponentClickEvent(event, listView.getSelectionModel().getSelectedItem()));
listView.setOnKeyTyped(event -> {
if(event.getCode().equals(KeyCode.ENTER)){
firerer.fireComponentClickEvent(event, listView.getSelectionModel().getSelectedItem());
}
});
mainPane.setCenter(listView);
}
@Override
public void display(Sale content) {
if(content ==null)
return;
this.sale = content;
Platform.runLater(()->{
this.listView.getItems().clear();
this.listView.getItems().addAll(this.sale.getProducts().keySet());
});
}
@Override
public void addListener(ISaleComponentListener l) {
firerer.addListener(l);
}
@Override
public void removeListener(ISaleComponentListener l) {
firerer.removeListener(l);
}
@Override
public Pane getPane() {
return mainPane;
}
}

View File

@ -0,0 +1,108 @@
package com.pqt.client.gui.ressources.components;
import com.pqt.client.gui.ressources.components.generics.validators.IFXValidatorComponent;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentFirerer;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
import com.pqt.client.gui.ressources.strings.GUIStringTool;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.SimpleValidatorComponentFirerer;
import javafx.application.Platform;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
public class SimpleValidator implements IFXValidatorComponent {
private final IValidatorComponentFirerer firerer;
private Pane pane;
private boolean askConfirmation;
private Button validationButton, cancelButton;
public SimpleValidator() {
this(false);
}
public SimpleValidator(boolean askConfirmation) {
firerer = new SimpleValidatorComponentFirerer();
this.askConfirmation = askConfirmation;
}
@Override
public void addListener(IValidatorComponentListener l) {
firerer.addListener(l);
}
@Override
public void removeListener(IValidatorComponentListener l) {
firerer.removeListener(l);
}
@Override
public Pane getPane() {
if(pane == null)
pane = createPane();
return pane;
}
private Pane createPane(){
GridPane grid = new GridPane();
grid.getStyleClass().add("validator");
validationButton = new Button(GUIStringTool.getValidationButtonLabel());
validationButton.setOnMouseClicked(event->{
getValidationButtonProcess().process();
});
grid.add(validationButton, 0,0);
cancelButton = new Button(GUIStringTool.getCancelButtonLabel());
cancelButton.setOnMouseClicked(event->{
getCancelButtonProcess().process();
});
grid.add(cancelButton, 1, 0);
return grid;
}
private IButtonProcess getValidationButtonProcess(){
return ()->{
if(validationButton.getText().equals(GUIStringTool.getValidationButtonLabel())){
if(askConfirmation)
Platform.runLater(()->validationButton.setText(GUIStringTool.getConfirmationValidationButtonLabel()));
else
firerer.fireValidationEvent();
}else{
if(validationButton.getText().equals(GUIStringTool.getConfirmationValidationButtonLabel()))
firerer.fireValidationEvent();
Platform.runLater(()->validationButton.setText(GUIStringTool.getValidationButtonLabel()));
}
};
}
private IButtonProcess getCancelButtonProcess(){
return ()->{
if(cancelButton.getText().equals(GUIStringTool.getCancelButtonLabel())){
if(askConfirmation)
Platform.runLater(()->cancelButton.setText(GUIStringTool.getConfirmationCancelButtonLabel()));
else
firerer.fireCancelEvent();
}else{
Platform.runLater(()->cancelButton.setText(GUIStringTool.getCancelButtonLabel()));
firerer.fireCancelEvent();
}
};
}
private interface IButtonProcess{
void process();
}
public void setValidationButtonEnable(boolean enable){
this.validationButton.setDisable(!enable);
}
public void setCancelationButtonEnable(boolean enable){
this.cancelButton.setDisable(!enable);
}
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.ressources.components.generics;
import javafx.scene.layout.Pane;
public interface IFXComponent {
Pane getPane();
}

View File

@ -0,0 +1,8 @@
package com.pqt.client.gui.ressources.components.generics.creators;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
public interface IFXCreatorComponent<T> extends IFXComponent{
T create();
boolean isCreationPossible();
}

View File

@ -0,0 +1,10 @@
package com.pqt.client.gui.ressources.components.generics.displayers;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener;
public interface IFXDisplayerComponent<T, U extends IDisplayerComponentListener> extends IFXComponent{
void display(T content);
void addListener(U l);
void removeListener(U l);
}

View File

@ -0,0 +1,13 @@
package com.pqt.client.gui.ressources.components.generics.displayers.listeners;
import javafx.event.Event;
public interface IDisplayerComponentFirerer<T> {
void fireRefreshContentRequestEvent();
void fireContentClickEvent(Event event, T eventTarget);
void fireAddContentRequestEvent();
void fireRemoveContentRequestEvent(T content);
void fireDetailContentRequestEvent(T content);
void addListener(IDisplayerComponentListener<T> l);
void removeListener(IDisplayerComponentListener<T> l);
}

View File

@ -0,0 +1,13 @@
package com.pqt.client.gui.ressources.components.generics.displayers.listeners;
import javafx.event.Event;
import java.util.EventListener;
public interface IDisplayerComponentListener<T> extends EventListener {
void onRefreshContentRequestEvent();
void onContentClickEvent(Event event, T eventTarget);
void onAddContentRequestEvent();
void onRemoveContentRequestEvent(T content);
void onDetailContentRequestEvent(T content);
}

View File

@ -0,0 +1,58 @@
package com.pqt.client.gui.ressources.components.generics.displayers.listeners;
import javafx.event.Event;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
public class SimpleDisplayerComponentFirerer<T, U extends IDisplayerComponentListener<T>> implements IDisplayerComponentFirerer<T> {
protected EventListenerList listenerList;
protected Class<U> clazz;
public SimpleDisplayerComponentFirerer(Class<U> clazz) {
listenerList = new EventListenerList();
this.clazz = clazz;
}
@Override
public void fireRefreshContentRequestEvent() {
Arrays.stream(listenerList.getListeners(clazz)).forEach(IDisplayerComponentListener::onRefreshContentRequestEvent);
}
@Override
public void fireContentClickEvent(Event event, T eventTarget) {
Arrays.stream(listenerList.getListeners(clazz)).forEach(l->l.onContentClickEvent(event, eventTarget));
}
@Override
public void fireAddContentRequestEvent() {
Arrays.stream(listenerList.getListeners(clazz)).forEach(IDisplayerComponentListener::onAddContentRequestEvent);
}
@Override
public void fireRemoveContentRequestEvent(T content) {
Arrays.stream(listenerList.getListeners(clazz)).forEach(l->l.onRemoveContentRequestEvent(content));
}
@Override
public void fireDetailContentRequestEvent(T content) {
Arrays.stream(listenerList.getListeners(clazz)).forEach(l->l.onDetailContentRequestEvent(content));
}
@Override
public void addListener(IDisplayerComponentListener<T> l) throws IllegalArgumentException {
if(clazz.isInstance(l)){
listenerList.add(clazz, clazz.cast(l));
}else{
throw new IllegalArgumentException("Listener must implement the following interface : "+clazz.getName());
}
}
@Override
public void removeListener(IDisplayerComponentListener<T> l) {
if (clazz.isInstance(l)) {
listenerList.remove(clazz, clazz.cast(l));
}
}
}

View File

@ -0,0 +1,11 @@
package com.pqt.client.gui.ressources.components.generics.javafx_override;
import javafx.scene.layout.GridPane;
public class CssEnabledGridPane extends GridPane {
public CssEnabledGridPane() {
super();
this.getStyleClass().add("grid-pane");
}
}

View File

@ -0,0 +1,25 @@
package com.pqt.client.gui.ressources.components.generics.javafx_override;
import javafx.css.PseudoClass;
import javafx.scene.control.ListCell;
public class HighlightListCell<T> extends ListCell<T> {
private PseudoClass highlightPC;
private boolean highlighted;
public HighlightListCell() {
super();
highlighted = false;
highlightPC = PseudoClass.getPseudoClass("highlighted");
}
public void setHighLight(boolean highLight){
highlighted = highLight;
this.pseudoClassStateChanged(highlightPC, highLight);
}
public boolean isHightlighted(){
return highlighted;
}
}

View File

@ -0,0 +1,119 @@
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<SideBar> FACTORY = new StyleablePropertyFactory<>(VBox.getClassCssMetaData());
private static final CssMetaData<SideBar, Number> EXPANDED_WIDTH =
FACTORY.createSizeCssMetaData("-pqt-expanded-width",p->p.expandedWidth, 100, false);
private StyleableProperty<Number> 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) {
SideBar.this.setVisible(true);
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 ->{
setVisible(false);
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()) {
expandSideBar.play();
}
}
}
public void collapse(){
if (expandSideBar.statusProperty().get() == Animation.Status.STOPPED
&& collapseSideBar.statusProperty().get() == Animation.Status.STOPPED) {
if (isVisible()) {
collapseSideBar.play();
}
}
}
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<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
return FACTORY.getCssMetaData();
}
@Override
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
return FACTORY.getCssMetaData();
}
}

View File

@ -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();
}

View File

@ -0,0 +1,54 @@
package com.pqt.client.gui.ressources.components.generics.toast;
import com.pqt.client.gui.ressources.css.GUICssTool;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Duration;
final class Toast {
static void toast(Stage ownerStage, String toastMsg, int toastDelay, int fadeInDelay, int fadeOutDelay) {
Stage toastStage = new Stage();
toastStage.initOwner(ownerStage);
toastStage.setResizable(false);
toastStage.initStyle(StageStyle.TRANSPARENT);
Text text = new Text(toastMsg);
text.getStyleClass().add("toast-text");
StackPane root = new StackPane(text);
root.getStyleClass().add("toast-pane");
root.setOpacity(0);
Scene scene = new Scene(root);
scene.setFill(Color.TRANSPARENT);
scene.getStylesheets().addAll(Toast.class.getResource(GUICssTool.getCssFilePath()).toExternalForm());
toastStage.setScene(scene);
toastStage.show();
Timeline fadeInTimeline = new Timeline();
KeyFrame fadeInKey1 = new KeyFrame(Duration.millis(fadeInDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 1));
fadeInTimeline.getKeyFrames().add(fadeInKey1);
fadeInTimeline.setOnFinished((ae) ->
new Thread(() -> {
try {
Thread.sleep(toastDelay);
}
catch (InterruptedException e) {
e.printStackTrace();
}
Timeline fadeOutTimeline = new Timeline();
KeyFrame fadeOutKey1 = new KeyFrame(Duration.millis(fadeOutDelay), new KeyValue (toastStage.getScene().getRoot().opacityProperty(), 0));
fadeOutTimeline.getKeyFrames().add(fadeOutKey1);
fadeOutTimeline.setOnFinished((aeb) -> toastStage.close());
fadeOutTimeline.play();
}).start());
fadeInTimeline.play();
}
}

View File

@ -0,0 +1,46 @@
package com.pqt.client.gui.ressources.components.generics.toast;
import javafx.stage.Stage;
public class ToastFactory {
private static ToastFactory INSTANCE = null;
private Stage stage;
private int delay, fadeInDelay, fadeOutDelay;
private ToastFactory(Stage stage){
this.stage = stage;
delay = 3000;
fadeInDelay = 250;
fadeOutDelay = 250;
}
public void setToastDelay(int msDelay){
this.delay = msDelay;
}
public void setToastFadeInDelay(int msDelay){
this.fadeInDelay = msDelay;
}
public void setToastFadeOutDelay(int msDelay){
this.fadeOutDelay = msDelay;
}
public void toast(String message){
Toast.toast(stage, message, delay, fadeInDelay, fadeOutDelay);
}
public static void init(Stage stage){
INSTANCE = new ToastFactory(stage);
}
public static boolean isInitialized(){
return INSTANCE!=null;
}
public static ToastFactory getINSTANCE(){
return INSTANCE;
}
}

View File

@ -0,0 +1,9 @@
package com.pqt.client.gui.ressources.components.generics.validators;
import com.pqt.client.gui.ressources.components.generics.IFXComponent;
import com.pqt.client.gui.ressources.components.generics.validators.listeners.IValidatorComponentListener;
public interface IFXValidatorComponent extends IFXComponent{
void addListener(IValidatorComponentListener l);
void removeListener(IValidatorComponentListener l);
}

View File

@ -0,0 +1,9 @@
package com.pqt.client.gui.ressources.components.generics.validators.listeners;
public interface IValidatorComponentFirerer {
void addListener(IValidatorComponentListener l);
void removeListener(IValidatorComponentListener l);
void fireValidationEvent();
void fireCancelEvent();
}

View File

@ -0,0 +1,8 @@
package com.pqt.client.gui.ressources.components.generics.validators.listeners;
import java.util.EventListener;
public interface IValidatorComponentListener extends EventListener {
void onValidationEvent();
void onCancelEvent();
}

View File

@ -0,0 +1,33 @@
package com.pqt.client.gui.ressources.components.generics.validators.listeners;
import javax.swing.event.EventListenerList;
import java.util.Arrays;
public class SimpleValidatorComponentFirerer implements IValidatorComponentFirerer {
private EventListenerList listenerList;
public SimpleValidatorComponentFirerer() {
listenerList = new EventListenerList();
}
@Override
public void addListener(IValidatorComponentListener l) {
listenerList.add(IValidatorComponentListener.class, l);
}
@Override
public void removeListener(IValidatorComponentListener l) {
listenerList.remove(IValidatorComponentListener.class, l);
}
@Override
public void fireValidationEvent() {
Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onValidationEvent);
}
@Override
public void fireCancelEvent() {
Arrays.stream(listenerList.getListeners(IValidatorComponentListener.class)).forEach(IValidatorComponentListener::onCancelEvent);
}
}

View File

@ -0,0 +1,11 @@
package com.pqt.client.gui.ressources.components.specifics.account;
import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.account.listeners.IAccountComponentListener;
import com.pqt.core.entities.user_account.Account;
import java.util.Collection;
public interface IFXAccountsDisplayerComponent extends IFXDisplayerComponent<Collection<Account>, IAccountComponentListener> {
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.ressources.components.specifics.account.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener;
import com.pqt.core.entities.user_account.Account;
public interface IAccountComponentListener extends IDisplayerComponentListener<Account>{
}

View File

@ -0,0 +1,10 @@
package com.pqt.client.gui.ressources.components.specifics.account.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer;
import com.pqt.core.entities.user_account.Account;
public class SimpleAccountComponentFirerer extends SimpleDisplayerComponentFirerer<Account, IAccountComponentListener> {
public SimpleAccountComponentFirerer() {
super(IAccountComponentListener.class);
}
}

View File

@ -0,0 +1,10 @@
package com.pqt.client.gui.ressources.components.specifics.products;
import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.products.listeners.IStockComponentListener;
import com.pqt.core.entities.product.Product;
import java.util.Collection;
public interface IFXProductsDisplayerComponent extends IFXDisplayerComponent<Collection<Product>, IStockComponentListener> {
}

View File

@ -0,0 +1,7 @@
package com.pqt.client.gui.ressources.components.specifics.products.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener;
import com.pqt.core.entities.product.Product;
public interface IStockComponentListener extends IDisplayerComponentListener<Product> {
}

View File

@ -0,0 +1,11 @@
package com.pqt.client.gui.ressources.components.specifics.products.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer;
import com.pqt.core.entities.product.Product;
public class SimpleStockComponentFirerer extends SimpleDisplayerComponentFirerer<Product, IStockComponentListener> {
public SimpleStockComponentFirerer() {
super(IStockComponentListener.class);
}
}

View File

@ -0,0 +1,8 @@
package com.pqt.client.gui.ressources.components.specifics.sale;
import com.pqt.client.gui.ressources.components.generics.displayers.IFXDisplayerComponent;
import com.pqt.client.gui.ressources.components.specifics.sale.listeners.ISaleComponentListener;
import com.pqt.core.entities.sale.Sale;
public interface IFXSaleDisplayerComponent extends IFXDisplayerComponent<Sale, ISaleComponentListener> {
}

View File

@ -0,0 +1,10 @@
package com.pqt.client.gui.ressources.components.specifics.sale.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.IDisplayerComponentListener;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import javafx.event.Event;
public interface ISaleComponentListener extends IDisplayerComponentListener<Sale> {
void onComponentClickEvent(Event event, Product product);
}

View File

@ -0,0 +1,19 @@
package com.pqt.client.gui.ressources.components.specifics.sale.listeners;
import com.pqt.client.gui.ressources.components.generics.displayers.listeners.SimpleDisplayerComponentFirerer;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import javafx.event.Event;
import java.util.Arrays;
public class SimpleSaleComponentFirerer extends SimpleDisplayerComponentFirerer<Sale, ISaleComponentListener> {
public SimpleSaleComponentFirerer() {
super(ISaleComponentListener.class);
}
public void fireComponentClickEvent(Event event, Product product) {
Arrays.stream(listenerList.getListeners(ISaleComponentListener.class)).forEach(l->l.onComponentClickEvent(event, product));
}
}

View File

@ -0,0 +1,20 @@
package com.pqt.client.gui.ressources.css;
public class GUICssTool {
public static String getCssFilePath(){
//return "/daymode-blue.css";
return "/nightmode.css";
}
public static String getMainModulePaneCssClass() {
return "main-module-pane";
}
public static String getIntermediaryPaneStyleClass() {
return "grey-intermediary-pane";
}
public static String getTitleTextStyleClass() {
return "label-header";
}
}

View File

@ -0,0 +1,336 @@
package com.pqt.client.gui.ressources.strings;
import com.pqt.core.entities.product.Category;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.SaleStatus;
import com.pqt.core.entities.sale.SaleType;
import com.pqt.core.entities.user_account.Account;
import com.pqt.core.entities.user_account.AccountLevel;
import javafx.util.StringConverter;
import java.text.NumberFormat;
import java.util.EnumSet;
//TODO faire ça un peu mieux
public class GUIStringTool {
public static String getValidationButtonLabel() {
return "Valider";
}
public static String getConfirmationValidationButtonLabel() {
return "Confirmer";
}
public static String getCancelButtonLabel() {
return "Annuler";
}
public static String getConfirmationCancelButtonLabel() {
return "Confirmer";
}
public static String getCategorytabStockDisplayerTitle() {
return "Produits";
}
public static IObjectStringRenderer<Product> getDetailledProductStringRenderer(){
return product->{
if(product!=null){
String amountStr;
if(product.getAmountRemaining()<=0){
amountStr = "OUT OF STOCK";
}else if(product.getAmountRemaining()>=30){
amountStr = "30+";
}else{
amountStr = Integer.toString(product.getAmountRemaining());
}
return String.format("%s - %.2f€ (%s)", product.getName(), product.getPrice(), amountStr);
}else
return "null";
};
}
public static IObjectStringRenderer<Product> getSimpleProductStringRenderer(){
return product->{
if(product!=null)
return String.format("%s - %.2f€", product.getName(), product.getPrice());
else
return "null";
};
}
public static String getCommandComposerTitleLabel() {
return "Commande";
}
public static IObjectWithQuantityStringRenderer<Product> getSaleItemStringRenderer(){
return (product, qte)->String.format("%dx %s", qte, product.getName());
}
public static String getPasswordFieldPromptText() {
return "mot de passe";
}
public static StringConverter<Account> getAccountStringConverter() {
return new StringConverter<Account>() {
@Override
public String toString(Account object) {
if(object!=null)
return String.format("%s - (%s)", object.getUsername(), object.getPermissionLevel());
return "null";
}
@Override
public Account fromString(String string) {
Account reply = new Account();
String[] pieces = string.split(" - ");
reply.setUsername(pieces[0]);
if(pieces.length>1)
for(AccountLevel al : EnumSet.allOf(AccountLevel.class)){
if(al.name().equals(pieces[1]))
reply.setPermissionLevel(al);
}
return reply;
}
};
}
public static String getLogoutButtonLabel() {
return "Déconnexion";
}
public static String getLoginButtonLabel() {
return "Connexion";
}
public static IObjectStringRenderer<Double> getPriceRenderer() {
return price -> NumberFormat.getCurrencyInstance().format(price);
}
public static String getSaleMakerTextFieldPromptText() {
return "Auteur";
}
public static String getSaleMakerTextFieldLabel() {
return "Fait par : ";
}
public static String getSaleBeneficiaryTextFieldLabel() {
return "Fait pour : ";
}
public static String getSaleTypeTextFieldLabel() {
return "Type de paiement : ";
}
public static String getSalePriceTextFieldLabel() {
return "Prix de la commande : ";
}
public static StringConverter<SaleType> getSaleTypeStringConverter() {
return new StringConverter<SaleType>() {
@Override
public String toString(SaleType object) {
return object.name();
}
@Override
public SaleType fromString(String string) {
return EnumSet.allOf(SaleType.class).stream().filter(type->type.name().equals(string)).findFirst().orElse(null);
}
};
}
public static String getSalePriceTextFieldPromptText() {
return getPriceRenderer().render(0d);
}
public static String getCommandValidationErrorMessage() {
return "La commande n'a pas pu être validée";
}
public static String getCommandValidationErrorMessage(Throwable cause) {
return "La commande n'a pas pu être validée : "+cause.getMessage();
}
public static String getSaleIdLabel() {
return "Numéro de commande : ";
}
public static String getSaleStatusLabel() {
return "Etat actuel";
}
public static IObjectStringRenderer<SaleStatus> getSaleStatusRenderer() {
return Enum::name;
}
public static String getOkButtonLabel() {
return "OK";
}
public static String getAppTitle() {
return "Client PQT - Gargotte";
}
public static String getSideBarCollapseButtonLabel() {
return "Réduire";
}
public static String getSideBarExpandButtonLabel() {
return "Menu";
}
public static String getSaleGuiModuleName() {
return "Vente";
}
public static String getAddButtonLabel() {
return "Ajouter";
}
public static String getDetailButtonLabel() {
return "Détail";
}
public static String getRemoveButtonLabel() {
return "Supprimer";
}
public static String getRefreshButtonLabel() {
return "Rafraichir";
}
public static String getProductNameColumnHeader() {
return "Nom";
}
public static String getProductCategoryColumnHeader() {
return "Catégorie";
}
public static String getProductAmountRemainingColumnHeader() {
return "Stock";
}
public static String getProductAmountSoldColumnHeader() {
return "Vendu";
}
public static String getProductPriceColumnHeader() {
return "Prix";
}
public static String getProductIsSellableColumnHeader() {
return "Vendable";
}
public static IObjectStringRenderer<Boolean> getBooleanRenderer() {
return bool->bool?"Oui":"Non";
}
public static String getStatGuiModuleName() {
return "Statistiques";
}
public static String getProductNameLabel() {
return "Nom : ";
}
public static String getProductCategoryLabel() {
return "Catégorie : ";
}
public static String getProductAmountRemainingLabel() {
return "En stock : ";
}
public static String getProductAmountSoldLabel() {
return "Vendu : ";
}
public static String getProductSellableLabel() {
return "Vendable : ";
}
public static String getProductPriceLabel() {
return "Prix : ";
}
public static StringConverter<Category> getCategoryStringConverter() {
return new StringConverter<Category>() {
@Override
public String toString(Category object) {
if(object!=null)
return object.getName();
else
return "";
}
@Override
public Category fromString(String string) {
if(string!=null)
return new Category(-1, string);
else
return null;
}
};
}
public static String getComponentListTitleLabel() {
return "Composants";
}
public static String getAccountGuiModuleName() {
return "Utilisateurs";
}
public static IObjectStringRenderer<AccountLevel> getAccountLevelStringRenderer() {
return level->{
switch (level){
case LOWEST:
return "autre";
case GUEST:
return "Invité";
case STAFF:
return "Staff";
case WAITER:
return "Caissier";
case MASTER:
return "Chef";
default:
return "unknown";
}
};
}
public static String getAccountListTitleLabel() {
return "Utilisateurs";
}
public static String getUsernameLabel() {
return "Nom :";
}
public static String getPasswordLabel() {
return "Mot de passe : ";
}
public static String getUserLevelLabel() {
return "Niveau d'accréditation : ";
}
public static String getAccountNameColumnHeaderLabel() {
return "Nom d'utilisateur";
}
public static String getAccountLevelColumnHeaderLabel() {
return "Niveau d'accréditation";
}
}

View File

@ -0,0 +1,5 @@
package com.pqt.client.gui.ressources.strings;
public interface IObjectStringRenderer<T> {
String render(T obj);
}

View File

@ -0,0 +1,5 @@
package com.pqt.client.gui.ressources.strings;
public interface IObjectWithQuantityStringRenderer<T> {
String render(T obj, int quantity);
}

View File

@ -18,7 +18,7 @@ public class AccountService {
}
public boolean isAccountLoggedIn(Account account) {
public boolean isCurrentAccountLoggedIn() {
return false;
}
@ -26,7 +26,7 @@ public class AccountService {
}
public void logOutCurrentAccount(String password) {
public void logOutCurrentAccount() {
}
@ -42,4 +42,7 @@ public class AccountService {
}
public List<Account> getAllAccounts() {
return null;
}
}

View File

@ -6,9 +6,16 @@ public class AccountListenerAdapter implements IAccountListener {
/**
* @see com.pqt.client.module.account.listeners.IAccountListener#onAccountStatusChanged(boolean)
* @see com.pqt.client.module.account.listeners.IAccountListener#onAccountStatusChangedEvent(boolean)
*/
public void onAccountStatusChanged(boolean status) {
public void onAccountStatusChangedEvent(boolean status) {
}
/**
* @see com.pqt.client.module.account.listeners.IAccountListener#onAccountListChangedEvent()
*/
public void onAccountListChangedEvent() {
}

View File

@ -4,6 +4,6 @@ import java.util.EventListener;
public interface IAccountListener extends EventListener {
public void onAccountStatusChanged(boolean status);
void onAccountStatusChangedEvent(boolean status);
void onAccountListChangedEvent();
}

View File

@ -1,15 +1,14 @@
package com.pqt.client.module.sale;
import com.pqt.core.entities.client.Client;
import com.pqt.client.module.stock.StockDao;
import com.pqt.core.entities.members.Client;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.sale.Sale;
import com.pqt.core.entities.sale.SaleStatus;
import com.pqt.core.entities.sale.SaleType;
import com.pqt.core.entities.user_account.Account;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
//TODO écrire javadoc
public class SaleBuilder {
@ -26,18 +25,40 @@ public class SaleBuilder {
}
public SaleBuilder addProduct(Product product) {
if(products.containsKey(product)){
//Check for sufficient stock
if(product.getAmountRemaining()<products.get(product)) {
products.replace(product, products.get(product) + 1);
//Check for sufficient stock
if(isAmountRemainingSufficient(product, 1)) {
if(products.containsKey(product)){
products.replace(product, products.get(product) + 1);
}else{
products.put(product, 1);
}
}else{
products.put(product, 1);
}
return this;
}
private boolean isAmountRemainingSufficient(Product newProduct, int requiredAmount){
Map<Product, Integer> rank0Products = new HashMap<>();
collectRank0Products(newProduct, requiredAmount, rank0Products);
products.keySet().forEach(oldProduct->collectRank0Products(oldProduct, products.get(oldProduct), rank0Products));
return rank0Products.keySet()
.stream()
.filter(rank0Product->rank0Product.getAmountRemaining()<rank0Products.get(rank0Product))
.count()==0;
}
private void collectRank0Products(Product rootProduct, Integer rootProductAmount, Map<Product, Integer> collector){
if(rootProduct.getComponents().isEmpty()){
if(collector.containsKey(rootProduct))
collector.replace(rootProduct, collector.get(rootProduct)+rootProductAmount);
else
collector.put(rootProduct, rootProductAmount);
}else{
rootProduct.getComponents().forEach(product->collectRank0Products(product, rootProductAmount, collector));
}
}
public SaleBuilder removeProduct(Product product) {
if(products.containsKey(product)) {
if (products.get(product) == 1)

View File

@ -6,6 +6,9 @@ import com.pqt.client.module.query.query_callback.IIdQueryCallback;
import com.pqt.client.module.sale.listeners.ISaleFirerer;
import com.pqt.client.module.sale.listeners.ISaleListener;
import com.pqt.client.module.sale.listeners.SimpleSaleFirerer;
import com.pqt.core.entities.sale.SaleType;
import java.util.List;
//TODO écrire javadoc
//TODO add log lines
@ -55,4 +58,8 @@ public class SaleService {
eventFirerer.removeListener(listener);
}
public List<SaleType> getSaleTypes() {
//TODO
return null;
}
}

View File

@ -1,15 +1,13 @@
package com.pqt.client.module.sale.listeners;
import com.pqt.core.entities.sale.Sale;
import java.util.EventListener;
public interface ISaleListener extends EventListener {
public abstract void onSaleValidationSuccess(long saleId);
void onSaleValidationSuccess(long saleId);
public abstract void onSaleValidationError(long saleId, Throwable cause);
void onSaleValidationError(long saleId, Throwable cause);
public abstract void onSaleValidationRefused(long saleId, Throwable cause);
void onSaleValidationRefused(long saleId, Throwable cause);
}

View File

@ -33,12 +33,8 @@ public class StockDao {
}
public synchronized Product getProduct(final int id) {
Optional<Product> match = products.stream().filter((product->product.getId()==id)).findFirst();
if(match.isPresent())
return match.get();
return null;
}
return products.stream().filter((product->product.getId()==id)).findFirst().orElse(null);
}
public void refreshProductList() {
QueryExecutor.INSTANCE.execute(QueryFactory.newStockQuery(), new IStockQueryCallback() {

View File

@ -13,7 +13,7 @@ public class StockService {
private StockDao dao;
private StockService() {
public StockService() {
dao = new StockDao();
}
@ -39,7 +39,8 @@ public class StockService {
/**
* Accesseur de la liste des produits actuellement en vente.
* <p/>
* La liste peut être obsolète, voir {@link #getLastRefreshTimestamp()} pour la date du dernier refresh et {@link #refreshProductList()} pour la mettre à jour.
* La liste peut être obsolète, voir {@link #getLastRefreshTimestamp()} pour la date du dernier refresh et
* {@link #refreshProductList()} pour la mettre à jour.
*
* @return Liste des produits en vente.
*/
@ -47,6 +48,35 @@ public class StockService {
return dao.getProducts();
}
/**
* Récupère la liste des produits n'étant pas {@code product} et n'étant pas composé de {@code product}.
* Les composants sont récursivements vérifiés pour que ces derniers valident aussi ces deux conditions.
* <p/>
* La liste peut être obsolète, voir {@link #getLastRefreshTimestamp()} pour la date du dernier refresh et
* {@link #refreshProductList()} pour la mettre à jour.
*
* @param product produit à exclure des résultats.
* @return Liste de produit n'étant pas et ne contenant pas {@code product}.
*/
public List<Product> getProductsExcluding(Product product) {
return dao.getProducts();
}
private boolean contains(Product container, Product contained){
if(container==null || contained==null)
return false;
if(container.equals(contained))
return true;
if(container.getComponents()!=null)
return container.getComponents()
.stream()
.filter(component->contains(component, contained))
.count()>0;
return false;
}
/**
* Accesseur récupérant un unique produit présent dans les stocks en se basant sur son id.
*
@ -100,5 +130,4 @@ public class StockService {
public void removeListener(IStockListener listener) {
dao.removeListener(listener);
}
}

View File

@ -16,20 +16,23 @@ public class UpdateBuilder {
toModify = new HashMap<>();
}
public void addProduct(Product product) {
public UpdateBuilder addProduct(Product product) {
if(!toAdd.contains(product)){
toAdd.add(product);
}
return this;
}
public void removeProduct(Product product) {
public UpdateBuilder removeProduct(Product product) {
if(toRemove.contains(product)){
toRemove.remove(product);
}
return this;
}
public void modifyProduct(Product oldVersion, Product newVersion) {
public UpdateBuilder modifyProduct(Product oldVersion, Product newVersion) {
toModify.put(oldVersion, newVersion);
return this;
}
public List<ProductUpdate> build() {

View File

@ -0,0 +1,235 @@
.root {
-fx-background-color: #1d1d1d;
}
.label {
-fx-font-size: 11pt;
-fx-font-family: "Segoe UI Semibold";
-fx-text-fill: white;
-fx-opacity: 0.8;
}
.label-bright {
-fx-font-size: 11pt;
-fx-font-family: "Segoe UI Semibold";
-fx-text-fill: white;
-fx-opacity: 1;
}
.label-header {
-fx-font-size: 25pt;
-fx-font-family: "Segoe UI";
-fx-text-fill: white;
-fx-opacity: 1;
}
.tab {
-fx-background-color: #3a3a3a;
}
.tab-label {
-fx-text-fill: white;
}
.tab:selected {
-fx-background-color: #4d4d4d;
}
.tab-pane *.tab-header-background {
-fx-background-color: #1d1d1d;
}
.list-view {
-fx-control-inner-background: #1d1d1d;
-fx-control-inner-background-alt: #333333;
-fx-padding: 5;
-fx-border-width: 0px;
}
.list-view .list-cell .label{
-fx-font-size: 20pt;
-fx-font-family: "Segoe UI Light";
-fx-text-fill: white;
-fx-alignment: center-left;
}
.list-view:focused .list-cell:filled:focused:selected {
-fx-background-color: -fx-focus-color;
}
.list-cell:highlighted{
-fx-text-fill: #cc7a00;
-fx-border-width: 1px;
-fx-border-color: white;
}
.table-view {
-fx-base: #1d1d1d;
-fx-control-inner-background: #1d1d1d;
-fx-control-inner-background-alt: #333333;
-fx-table-cell-border-color: transparent;
-fx-table-header-border-color: transparent;
-fx-padding: 5;
}
.table-view .column-header-background {
-fx-background-color: transparent;
}
.table-view .column-header, .table-view .filler {
-fx-size: 35px;
-fx-border-width: 0 0 1 0;
-fx-background-color: transparent;
-fx-border-color:
transparent
transparent
derive(-fx-base, 80%)
transparent;
-fx-border-insets: 0 10 1 0;
}
.table-view .column-header .label {
-fx-font-size: 20pt;
-fx-font-family: "Segoe UI Light";
-fx-text-fill: white;
-fx-alignment: center-left;
-fx-opacity: 1;
}
.table-view .table-row-cell {
-fx-control-inner-background: #1d1d1d;
-fx-control-inner-background-alt: #333333;
}
.table-view .table-row-cell:stock-out {
-fx-control-inner-background: #4d0000;
-fx-control-inner-background-alt: #4d0000;
}
.table-view .table-row-cell:stock-low {
-fx-control-inner-background: #4d2e00;
-fx-control-inner-background-alt: #4d2e00;
}
.table-view .table-row-cell:stock-high {
-fx-control-inner-background: #1a3300;
-fx-control-inner-background-alt: #1a3300;
}
.table-view:focused .table-row-cell:filled:focused:selected {
-fx-background-color: -fx-focus-color;
}
.grid-pane {
-fx-hgap: 10;
-fx-vgap: 10;
}
.context-menu {
-fx-background-color: derive(#1d1d1d,5%);
}
.text-field, .password-field, .choice-box, .text-area, .combo-box, .button {
-fx-font-size: 12pt;
-fx-font-family: "Segoe UI Semibold";
-fx-pref-width: 150;
-fx-pref-height: 30;
-fx-background-color: #1d1d1d;
-fx-border-color: #e2e2e2;
-fx-border-width: 2;
-fx-text-fill: #d8d8d8;
}
.button:hover {
-fx-background-color: #3a3a3a;
}
.button:pressed, .button:default:hover:pressed {
-fx-background-color: white;
-fx-text-fill: #1d1d1d;
}
.button:focused {
-fx-border-color: white, white;
-fx-border-width: 1, 1;
-fx-border-style: solid;
-fx-border-radius: 0, 0;
-fx-border-insets: 1 1 1 1, 0;
}
.button:disabled, .button:default:disabled {
-fx-opacity: 0.4;
-fx-background-color: #1d1d1d;
-fx-text-fill: white;
}
.button:default {
-fx-background-color: -fx-focus-color;
-fx-text-fill: #ffffff;
}
.button:default:hover {
-fx-background-color: derive(-fx-focus-color,30%);
}
.text-area .content {
-fx-background-color: #1d1d1d;
-fx-padding: 15 15 15 15;
}
#stat-screen-text-area {
-fx-border-width: 0;
}
.progress-indicator {
-fx-pref-width: 50;
-fx-pref-height: 50;
}
.grey-intermediary-pane {
-fx-background-color: #1d1d1d;
-fx-opacity: 85%;
}
.main-module-pane {
-fx-padding: 10 10 10 10;
}
.validator {
-fx-padding: 10 10 10 10;
-fx-hgap: 10;
-fx-vgap: 10;
}
.validator .button{
-fx-pref-width: 150;
-fx-pref-height: 50;
}
.sidebar {
-fx-background-color: #2e2e2e;
-fx-padding: 5 22 5 22;
-fx-border-color: whitesmoke;
-fx-border-width: 2;
-fx-background-radius: 0;
-fx-background-insets: 0 0 0 0, 0, 1, 2;
-pqt-expanded-width : 195px;
}
.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;
}
.toast-text{
-fx-font: 50px "Impact";
-fx-fill: whitesmoke;
}
.toast-pane {
-fx-background-radius: 10px;
-fx-background-color: rgba(0, 0, 0, 0.4);
-fx-border-width: 2px;
-fx-border-color: whitesmoke;
-fx-border-radius: 6px;
-fx-padding: 25px;
}

View File

@ -1,5 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
<component name="FacetManager">
<facet type="hibernate" name="Hibernate">
<configuration>
<datasource-map />
<naming-strategy-map />
<deploymentDescriptor name="hibernate.cfg.xml" url="file://$MODULE_DIR$/src/main/resources/hibernate.cfg.xml" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
@ -11,5 +20,7 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
<orderEntry type="library" name="Maven: com.google.code.gson:gson:2.8.1" level="project" />
</component>
</module>

View File

@ -12,4 +12,14 @@
<artifactId>core</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,32 @@
package com.pqt.core.communication;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
//TODO écrire Javadoc
public class GSonMessageToolFactory implements IMessageToolFactory {
private Gson gson;
public GSonMessageToolFactory() {
gson = new GsonBuilder().create();
}
public <T> IObjectFormatter<T> getObjectFormatter(Class<T> clazz){
return (obj)->gson.toJson(obj);
}
public <T> IObjectParser<T> getObjectParser(Class<T> clazz){
return (str)->gson.fromJson(str, clazz);
}
public <T> IObjectFormatter<List<T>> getListFormatter(Class<T> clazz){
return (obj)->gson.toJson(obj);
}
public <T> IObjectParser<List<T>> getListParser(Class<T> clazz){
Type listType = new TypeToken<ArrayList<T>>(){}.getType();
return (str)->gson.fromJson(str, listType);
}
}

View File

@ -0,0 +1,25 @@
package com.pqt.core.communication;
import com.google.gson.reflect.TypeToken;
import com.pqt.core.entities.members.PqtMember;
import com.pqt.core.entities.members.PqtMemberType;
import com.pqt.core.entities.messages.Message;
import com.pqt.core.entities.messages.MessageType;
import com.pqt.core.entities.product.Product;
import com.pqt.core.entities.product.ProductUpdate;
import com.pqt.core.entities.sale.Sale;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public interface IMessageToolFactory {
<T> IObjectFormatter<T> getObjectFormatter(Class<T> clazz);
<T> IObjectParser<T> getObjectParser(Class<T> clazz);
<T> IObjectFormatter<List<T>> getListFormatter(Class<T> clazz);
<T> IObjectParser<List<T>> getListParser(Class<T> clazz);
}

View File

@ -0,0 +1,7 @@
package com.pqt.core.communication;
public interface IObjectFormatter<T> {
String format(T obj);
}

View File

@ -0,0 +1,6 @@
package com.pqt.core.communication;
public interface IObjectParser<T> {
T parse(String str);
}

View File

@ -1,49 +0,0 @@
package com.pqt.core.entities.client;
import com.pqt.core.entities.log.ILoggable;
import java.io.Serializable;
import java.util.Date;
/**
* Created by Notmoo on 18/07/2017.
*/
public class Client implements ILoggable, Serializable {
private int id;
private String address;
private Date lastUpdate;
public Client() {
}
public Client(int id, String address, Date lastUpdate) {
this.id = id;
this.address = address;
this.lastUpdate = lastUpdate;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getLastUpdate() {
return lastUpdate;
}
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
}

View File

@ -0,0 +1,47 @@
package com.pqt.core.entities.members;
import java.util.Date;
import java.util.Objects;
/**
* Created by Notmoo on 18/07/2017.
*/
public class Client extends PqtMember{
private String address;
public Client() {
super(-1, PqtMemberType.CLIENT);
}
public Client(long id, String address) {
super(id, PqtMemberType.CLIENT);
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), address);
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(!this.getClass().isInstance(obj))
return false;
Client other = Client.class.cast(obj);
return super.equals(obj)
&& Objects.equals(this.address, other.address);
}
}

Some files were not shown because too many files have changed in this diff Show More