1 package fr.ifremer.dali.ui.swing.content.manage.program.programs;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import fr.ifremer.dali.dto.DaliBeans;
27 import fr.ifremer.dali.dto.configuration.programStrategy.ProgramDTO;
28 import fr.ifremer.dali.service.DaliTechnicalException;
29 import fr.ifremer.dali.ui.swing.content.manage.program.ProgramsUI;
30 import fr.ifremer.dali.ui.swing.content.manage.program.programs.departments.DepartmentsDialogUI;
31 import fr.ifremer.dali.ui.swing.content.manage.program.programs.users.UsersDialogUI;
32 import fr.ifremer.dali.ui.swing.util.DaliUIs;
33 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableModel;
34 import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIHandler;
35 import fr.ifremer.quadrige3.ui.swing.action.ActionFactory;
36 import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
37 import jaxx.runtime.validator.swing.SwingValidator;
38 import org.apache.commons.lang3.StringUtils;
39 import org.jdesktop.swingx.table.TableColumnExt;
40
41 import javax.swing.SortOrder;
42 import javax.swing.SwingUtilities;
43 import javax.swing.SwingWorker;
44 import java.awt.event.MouseAdapter;
45 import java.awt.event.MouseEvent;
46 import java.util.Collection;
47 import java.util.List;
48 import java.util.concurrent.ExecutionException;
49 import java.util.concurrent.ThreadPoolExecutor;
50
51 import static org.nuiton.i18n.I18n.t;
52
53
54
55
56 public class ProgramsTableUIHandler extends AbstractDaliTableUIHandler<ProgramsTableRowModel, ProgramsTableUIModel, ProgramsTableUI> {
57
58 private ThreadPoolExecutor executor;
59 private boolean newRowSelected;
60
61
62
63
64 public ProgramsTableUIHandler() {
65 super(ProgramsTableRowModel.PROPERTY_NAME,
66 ProgramsTableRowModel.PROPERTY_DESCRIPTION,
67 ProgramsTableRowModel.PROPERTY_COMMENT,
68 ProgramsTableRowModel.PROPERTY_CODE);
69 }
70
71
72
73
74 @Override
75 protected String[] getRowPropertiesToIgnore() {
76 return new String[]{ProgramsTableRowModel.PROPERTY_STRATEGIES, ProgramsTableRowModel.PROPERTY_STRATEGIES_LOADED,
77 ProgramsTableRowModel.PROPERTY_LOCATIONS, ProgramsTableRowModel.PROPERTY_LOCATIONS_LOADED,
78 ProgramsTableRowModel.PROPERTY_ERRORS};
79 }
80
81
82
83
84 @Override
85 public AbstractDaliTableModel<ProgramsTableRowModel> getTableModel() {
86 return (ProgramsTableModel) getTable().getModel();
87 }
88
89
90
91
92 @Override
93 public SwingTable getTable() {
94 return getUI().getProgramsTable();
95 }
96
97
98
99
100 @Override
101 public void beforeInit(final ProgramsTableUI ui) {
102 super.beforeInit(ui);
103
104
105 final ProgramsTableUIModel model = new ProgramsTableUIModel();
106 ui.setContextValue(model);
107 }
108
109
110
111
112 @Override
113 public void afterInit(ProgramsTableUI ui) {
114
115
116 initUI(ui);
117
118
119 initTable();
120
121
122 initListeners();
123
124
125 initActionComboBox(getUI().getEditCombobox());
126
127
128 registerValidators(getValidator());
129 listenValidatorValid(getValidator(), getModel());
130
131 executor = ActionFactory.createSingleThreadExecutor(ActionFactory.ExecutionMode.LATEST);
132
133 }
134
135 @Override
136 public void onCloseUI() {
137 executor.shutdownNow();
138 super.onCloseUI();
139 }
140
141
142
143
144 @Override
145 public boolean isRowValid(final ProgramsTableRowModel row) {
146 row.getErrors().clear();
147
148 return !row.isEditable() || (super.isRowValid(row) && isProgramValid(row));
149 }
150
151 private boolean isProgramValid(ProgramsTableRowModel row) {
152
153
154 if (row.sizeManagerPersons() == 0) {
155 DaliBeans.addError(row, t("dali.programs.validation.error.noManager"), ProgramsTableRowModel.PROPERTY_CODE);
156 }
157
158
159 if (row.isLocationsLoaded() && row.isLocationsEmpty()) {
160 DaliBeans.addError(row, t("dali.programs.validation.error.noLocationOnProg"), ProgramsTableRowModel.PROPERTY_CODE);
161 }
162
163
164 if (!row.isStrategiesValid() || !row.isLocationsValid()) {
165 DaliBeans.addError(row, t("dali.program.tables.error"), ProgramsTableRowModel.PROPERTY_CODE);
166 }
167
168 return row.isErrorsEmpty();
169 }
170
171
172
173
174
175
176 public void loadPrograms(Collection<ProgramDTO> programs) {
177
178 getModel().setSingleSelectedRow(null);
179 getModel().setBeans(programs);
180
181 getModel().getRows().forEach(programsTableRowModel ->
182 {
183
184 programsTableRowModel.setEditable(getModel().isSaveEnabled());
185
186
187 programsTableRowModel.setCurrentUserIsManager(
188 programsTableRowModel.getManagerPersons().stream().anyMatch(personDTO -> personDTO.getId().equals(getContext().getDataContext().getRecorderPersonId()))
189 );
190 });
191
192 recomputeRowsValidState();
193 autoSelectRow();
194 }
195
196
197
198
199 @Override
200 protected void onRowModified(int rowIndex, ProgramsTableRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
201 super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
202
203 row.setDirty(true);
204 }
205
206
207
208
209 private void initListeners() {
210
211
212 getModel().addPropertyChangeListener(ProgramsTableUIModel.PROPERTY_SINGLE_ROW_SELECTED, evt -> {
213
214 final ProgramsTableRowModel selectedProgram = getModel().getSingleSelectedRow();
215
216
217 if (selectedProgram != null) {
218
219 newRowSelected = true;
220
221
222 getContext().setSelectedProgramCode(selectedProgram.getCode());
223
224 getModel().getParentModel().getStrategiesUIModel().setLoading(true);
225 getModel().getParentModel().getLocationsUIModel().setLoading(true);
226 executor.execute(new StrategyAndLocationLoader(selectedProgram));
227
228 }
229 });
230
231
232 getTable().addMouseListener(new MouseAdapter() {
233 @Override
234 public void mouseClicked(MouseEvent e) {
235 if (!newRowSelected) {
236 getModel().firePropertyChanged(ProgramsTableUIModel.PROPERTY_SINGLE_ROW_SELECTED, null, null);
237 }
238 newRowSelected = false;
239 }
240
241 });
242
243
244 getModel().addPropertyChangeListener(ProgramsTableUIModel.PROPERTY_SAVE_ENABLED, evt -> {
245 getModel().getRows().forEach(programsTableRowModel -> programsTableRowModel.setEditable(getModel().isSaveEnabled()));
246 getUI().getProgramsTable().invalidate();
247 getUI().getProgramsTable().repaint();
248 autoSelectRow();
249 });
250
251 getModel().addPropertyChangeListener(ProgramsTableUIModel.EVENT_SAVE_STRATEGIES, evt -> {
252 if (getModel().getSingleSelectedRow() != null) {
253 getModel().getSingleSelectedRow().setStrategies(getModel().getParentModel().getStrategiesUIModel().getBeans());
254 getModel().getSingleSelectedRow().setStrategiesLoaded(true);
255 }
256 });
257
258
259 getModel().addPropertyChangeListener(ProgramsTableUIModel.EVENT_REMOVE_LOCATIONS, evt -> removeLocations((List<Integer>) evt.getNewValue()));
260 getModel().addPropertyChangeListener(ProgramsTableUIModel.EVENT_RESELECT, evt -> autoSelectRow());
261 }
262
263
264
265
266
267
268 public void removeLocations(List<Integer> locationIds) {
269 ProgramsTableRowModel programModel = getModel().getSingleSelectedRow();
270 if (programModel != null) {
271 programModel.getLocations().removeIf(location -> locationIds.contains(location.getId()));
272 recomputeRowValidState(programModel);
273 }
274 }
275
276
277
278
279 public void showManagers() {
280
281 if (getModel().getSingleSelectedRow() == null) {
282 return;
283 }
284
285 UsersDialogUI usersDialogUI = new UsersDialogUI(getContext());
286 usersDialogUI.getModel().setManagerList(true);
287 usersDialogUI.getModel().setProgram(getModel().getSingleSelectedRow());
288
289 openDialog(usersDialogUI);
290
291 }
292
293
294
295
296 public void showRecorderPersons() {
297
298 if (getModel().getSingleSelectedRow() == null) {
299 return;
300 }
301
302 UsersDialogUI usersDialogUI = new UsersDialogUI(getContext());
303 usersDialogUI.getModel().setManagerList(false);
304 usersDialogUI.getModel().setProgram(getModel().getSingleSelectedRow());
305
306 openDialog(usersDialogUI);
307
308 }
309
310
311
312
313 public void showRecorderDepartments() {
314
315 if (getModel().getSingleSelectedRow() == null) {
316 return;
317 }
318
319 DepartmentsDialogUI usersDialogUI = new DepartmentsDialogUI(getContext());
320 usersDialogUI.getModel().setProgram(getModel().getSingleSelectedRow());
321
322 openDialog(usersDialogUI);
323
324 }
325
326
327
328
329 private void initTable() {
330
331
332 final SwingTable table = getTable();
333
334
335 final TableColumnExt columnCode = addColumn(
336 ProgramsTableModel.CODE);
337 columnCode.setSortable(true);
338 columnCode.setEditable(false);
339
340
341 final TableColumnExt columnLibelle = addColumn(
342 ProgramsTableModel.NAME);
343 columnLibelle.setSortable(true);
344
345
346 TableColumnExt columnDescription = addCommentColumn(ProgramsTableModel.DESCRIPTION, ProgramDTO.PROPERTY_DESCRIPTION, true);
347
348
349 addCommentColumn(ProgramsTableModel.COMMENT);
350 TableColumnExt creationDateCol = addDatePickerColumnToModel(ProgramsTableModel.CREATION_DATE, getConfig().getDateTimeFormat(), false);
351 fixColumnWidth(creationDateCol, 120);
352 TableColumnExt updateDateCol = addDatePickerColumnToModel(ProgramsTableModel.UPDATE_DATE, getConfig().getDateTimeFormat(), false);
353 fixColumnWidth(updateDateCol, 120);
354
355 final TableColumnExt departmentHermeticCol = addBooleanColumnToModel(ProgramsTableModel.DEPARTMENT_HERMETIC, table);
356 fixColumnWidth(departmentHermeticCol, DaliUIs.DALI_CHECKBOX_WIDTH);
357 departmentHermeticCol.setSortable(true);
358
359
360 final ProgramsTableModel tableModel = new ProgramsTableModel(getTable().getColumnModel());
361 table.setModel(tableModel);
362
363
364 columnCode.setHideable(false);
365 columnLibelle.setHideable(false);
366 columnDescription.setHideable(false);
367 departmentHermeticCol.setHideable(false);
368
369
370 initTable(table);
371
372 creationDateCol.setVisible(false);
373 updateDateCol.setVisible(false);
374
375
376 table.setVisibleRowCount(4);
377
378
379 table.setSortOrder(ProgramsTableModel.CODE, SortOrder.ASCENDING);
380 }
381
382
383
384
385 public void autoSelectRow() {
386
387 String previousSelectedProgramCode = getContext().getSelectProgramCode();
388
389 if (StringUtils.isBlank(previousSelectedProgramCode) && getModel().getRowCount() > 1) {
390 return;
391 }
392
393
394 getModel().setSingleSelectedRow(null);
395
396 ProgramsTableRowModel rowToSelect = null;
397 if (getModel().getRowCount() == 1) {
398
399
400 rowToSelect = getModel().getRows().get(0);
401
402 } else {
403
404
405 for (final ProgramsTableRowModel row : getModel().getRows()) {
406 if (row.getCode().equals(previousSelectedProgramCode)) {
407 rowToSelect = row;
408 break;
409 }
410 }
411 }
412
413
414 if (rowToSelect != null) {
415 ProgramsTableRowModel finalRowToSelect = rowToSelect;
416 SwingUtilities.invokeLater(() -> {
417 selectRow(finalRowToSelect);
418 getModel().setSingleSelectedRow(finalRowToSelect);
419 });
420 }
421
422 }
423
424
425
426
427 @Override
428 public SwingValidator<ProgramsTableUIModel> getValidator() {
429 return getUI().getValidator();
430 }
431
432 private class StrategyAndLocationLoader extends SwingWorker<Object, Object> {
433
434 private final ProgramsUI adminProgrammeUI = getUI().getParentContainer(ProgramsUI.class);
435 private final ProgramsTableRowModel selectedProgram;
436
437 StrategyAndLocationLoader(ProgramsTableRowModel selectedProgram) {
438 this.selectedProgram = selectedProgram;
439 }
440
441 @Override
442 protected Object doInBackground() {
443
444 getContext().getProgramStrategyService().loadStrategiesAndLocations(selectedProgram);
445
446 return null;
447 }
448
449 @Override
450 protected void done() {
451 if (isCancelled()) {
452 return;
453 }
454 try {
455 get();
456 } catch (InterruptedException | ExecutionException e) {
457 throw new DaliTechnicalException(e.getMessage(), e);
458 }
459
460
461 adminProgrammeUI.getStrategiesTableUI().getHandler().load(selectedProgram);
462
463
464 adminProgrammeUI.getLocationsTableUI().getHandler().loadMonitoringLocationsFromProgram(selectedProgram);
465
466
467 adminProgrammeUI.getModel().getPmfmsUIModel().clear();
468
469
470 recomputeRowValidState(selectedProgram);
471 adminProgrammeUI.getHandler().getValidator().doValidate();
472
473 }
474 }
475 }