1 package de.spiritscorp.datasync.gui;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import javafx.geometry.Insets;
24 import javafx.scene.control.Button;
25 import javafx.scene.control.ContextMenu;
26 import javafx.scene.control.Label;
27 import javafx.scene.control.ListCell;
28 import javafx.scene.control.ListView;
29 import javafx.scene.control.MenuButton;
30 import javafx.scene.control.MenuItem;
31 import javafx.scene.control.SeparatorMenuItem;
32 import javafx.scene.control.Tooltip;
33 import javafx.scene.input.ClipboardContent;
34 import javafx.scene.input.Dragboard;
35 import javafx.scene.input.TransferMode;
36 import javafx.scene.layout.Priority;
37 import javafx.scene.layout.VBox;
38
39 import org.kordamp.ikonli.javafx.FontIcon;
40 import org.kordamp.ikonli.materialdesign2.MaterialDesignC;
41 import org.kordamp.ikonli.materialdesign2.MaterialDesignD;
42 import org.kordamp.ikonli.materialdesign2.MaterialDesignF;
43 import org.kordamp.ikonli.materialdesign2.MaterialDesignH;
44 import org.kordamp.ikonli.materialdesign2.MaterialDesignI;
45 import org.kordamp.ikonli.materialdesign2.MaterialDesignP;
46 import org.kordamp.ikonli.materialdesign2.MaterialDesignS;
47
48 import de.spiritscorp.datasync.controller.SyncJobContext;
49 import de.spiritscorp.datasync.controller.ViewController;
50
51
52
53
54
55
56 final class SidebarView extends VBox {
57
58 private final ListView<SyncJobContext> sidebarListView;
59 private final Gui mainGui;
60 private final ViewController controller;
61
62 private static final String CSS_MENU_ICON = "menu-icon";
63 private static final String CSS_JOB_ICON = "job-icon";
64 private static final String CSS_DRAG = "drag-over-target";
65
66 private boolean dragAndDropEnabled = true;
67
68
69
70
71
72
73
74 SidebarView( final Gui mainGui, final ViewController controller ) {
75 this.mainGui = mainGui;
76 this.controller = controller;
77 this.setSpacing( 16 );
78 this.setPadding( new Insets( 16, 16, 24, 16 ) );
79 this.setPrefWidth( 300 );
80
81
82
83 final MenuButton hamburgerMenu = new MenuButton( "Navigation", Gui.createIcon( MaterialDesignH.HAMBURGER ) );
84 hamburgerMenu.getGraphic().getStyleClass().addAll( CSS_MENU_ICON );
85 hamburgerMenu.setMaxWidth( Double.MAX_VALUE );
86
87 final MenuItem taskViewItem = new MenuItem( "Aktiver Task-Monitor", Gui.createIcon( MaterialDesignF.FOLDER ) );
88 taskViewItem.getGraphic().getStyleClass().addAll( CSS_MENU_ICON );
89 taskViewItem.setOnAction( _ -> controller.handleNavigate( Gui.ViewState.MONITOR ) );
90
91 final MenuItem settingsItem = new MenuItem( "Erweiterte Parameter", Gui.createIcon( MaterialDesignS.STORE_SETTINGS ) );
92 settingsItem.getGraphic().getStyleClass().addAll( CSS_MENU_ICON );
93 settingsItem.setOnAction( _ -> controller.handleNavigate( Gui.ViewState.SETTINGS ) );
94
95 final MenuItem infoItem = new MenuItem( "System-Informationen", Gui.createIcon( MaterialDesignI.INFORMATION ) );
96 infoItem.getGraphic().getStyleClass().addAll( CSS_MENU_ICON );
97 infoItem.setOnAction( _ -> controller.handleNavigate( Gui.ViewState.INFO ) );
98
99 hamburgerMenu.getItems().addAll( taskViewItem, settingsItem, new SeparatorMenuItem(), infoItem );
100
101
102 final Label sidebarTitleLabel = new Label( "VERWALTETE TASK-INSTANZEN" );
103 sidebarTitleLabel.getStyleClass().addAll( "sidebar-title-label" );
104
105
106 sidebarListView = new ListView<>( mainGui.getJobList() );
107 setupCellFactory();
108
109
110 final Button addJobButton = new Button( "Task hinzufügen", Gui.createIcon( MaterialDesignP.PLUS ) );
111 addJobButton.setMaxWidth( Double.MAX_VALUE );
112 addJobButton.getGraphic().getStyleClass().addAll( Gui.CSS_BUTTON_ICON );
113 addJobButton.getStyleClass().addAll( "add-job-button" );
114 addJobButton.setOnAction( _ -> controller.handleCreateNewJob() );
115
116 final Button exitButton = new Button( "Programm beenden", Gui.createIcon( MaterialDesignP.POWER_STANDBY ) );
117 exitButton.setMaxWidth( Double.MAX_VALUE );
118 exitButton.getGraphic().getStyleClass().addAll( Gui.CSS_BUTTON_ICON );
119 exitButton.getStyleClass().addAll( "exit-button" );
120 exitButton.setOnAction( _ -> controller.handleApplicationShutdown() );
121
122 this.getChildren().addAll( hamburgerMenu, sidebarTitleLabel, sidebarListView, addJobButton, exitButton );
123 setVgrow( sidebarListView, Priority.ALWAYS );
124 }
125
126
127
128
129 private void setupCellFactory() {
130 sidebarListView.setCellFactory( _ -> {
131 @SuppressWarnings( { "PMD.CommentRequired" } )
132 final ListCell<SyncJobContext> cell = new ListCell<>() {
133 private final FontIcon itemIcon = Gui.createIcon( MaterialDesignF.FOLDER );
134 private final Tooltip toolTip = new Tooltip();
135
136 @Override
137 protected void updateItem( final SyncJobContext item, final boolean empty ) {
138 super.updateItem( item, empty );
139 textProperty().unbind();
140 toolTip.textProperty().unbind();
141 if( empty || item == null ) {
142 setText( "" );
143 setGraphic( null );
144 setTooltip( null );
145 }else {
146 textProperty().bind( item.jobNameProperty() );
147 itemIcon.getStyleClass().addAll( CSS_JOB_ICON );
148 setGraphic( itemIcon );
149 toolTip.textProperty().bind( item.jobNameProperty() );
150 setTooltip( toolTip );
151 }
152 }
153 };
154
155 final ContextMenu contextMenu = new ContextMenu();
156
157 final MenuItem renameItem = new MenuItem( "Task umbenennen", Gui.createIcon( MaterialDesignS.SWAP_HORIZONTAL ) );
158 renameItem.setOnAction( _ -> controller.handleRenameJob( cell.getItem() ) );
159
160 final MenuItem duplicateItem = new MenuItem( "Task duplizieren", Gui.createIcon( MaterialDesignC.CONTENT_DUPLICATE ) );
161 duplicateItem.setOnAction( _ -> controller.handleDuplicateJob( cell.getItem() ) );
162
163 final MenuItem deleteItem = new MenuItem( "Task löschen", Gui.createIcon( MaterialDesignD.DELETE ) );
164 deleteItem.setOnAction( _ -> controller.handleDeleteJob( cell.getItem() ) );
165
166 contextMenu.getItems().addAll( renameItem, duplicateItem, new SeparatorMenuItem(), deleteItem );
167
168 cell.setOnContextMenuRequested( event -> {
169
170 if( cell.isEmpty() || cell.getItem() == null ) {
171 event.consume();
172 return;
173 }
174
175
176
177 contextMenu.show( cell, event.getScreenX(), event.getScreenY() );
178 event.consume();
179 } );
180
181
182
183
184 cell.setOnDragDetected( event -> {
185
186 if( cell.isEmpty() || !dragAndDropEnabled ) { return; }
187
188
189 final Dragboard db = cell.startDragAndDrop( TransferMode.MOVE );
190 final ClipboardContent content = new ClipboardContent();
191 content.putString( String.valueOf( cell.getIndex() ) );
192 db.setContent( content );
193
194 event.consume();
195 } );
196
197 cell.setOnDragOver( event -> {
198
199 if( dragAndDropEnabled && event.getDragboard().hasString() ) {
200 event.acceptTransferModes( TransferMode.MOVE );
201 }
202 event.consume();
203 } );
204
205 cell.setOnDragEntered( event -> {
206
207 if( dragAndDropEnabled && !cell.isEmpty() && event.getDragboard().hasString() ) {
208 cell.getStyleClass().add( CSS_DRAG );
209 }
210 event.consume();
211 } );
212
213 cell.setOnDragExited( event -> {
214
215 cell.getStyleClass().remove( CSS_DRAG );
216 event.consume();
217 } );
218
219 cell.setOnDragDropped( event -> {
220
221 cell.getStyleClass().remove( CSS_DRAG );
222
223 if( !dragAndDropEnabled ) { return; }
224
225 final Dragboard db = event.getDragboard();
226 if( db.hasString() ) {
227 final int draggedIdx = Integer.parseInt( db.getString() );
228
229
230 int thisIdx = cell.isEmpty() ? sidebarListView.getItems().size() - 1 : cell.getIndex();
231 if( thisIdx < 0 ) thisIdx = 0;
232 if( draggedIdx < thisIdx ) thisIdx -= 1;
233 if( draggedIdx != thisIdx && draggedIdx >= 0 ) {
234 controller.handleDragJob( thisIdx, draggedIdx );
235
236 sidebarListView.getSelectionModel().select( thisIdx );
237 event.setDropCompleted( true );
238 }
239 }
240 event.consume();
241 } );
242
243
244
245
246 return cell;
247 } );
248
249 sidebarListView.getSelectionModel().selectedItemProperty().addListener( ( _, oldVal, newVal ) -> {
250 if( newVal != null && !newVal.equals( oldVal ) ) mainGui.setCurrentActiveJob( newVal );
251 } );
252 }
253
254
255
256
257 ListView<SyncJobContext> getSidebarListView() { return sidebarListView; }
258 }