View Javadoc
1   package fr.ifremer.dali.ui.swing.content.home.survey;
2   
3   /*
4    * #%L
5    * Dali :: UI
6    * $Id:$
7    * $HeadURL:$
8    * %%
9    * Copyright (C) 2014 - 2015 Ifremer
10   * %%
11   * This program is free software: you can redistribute it and/or modify
12   * it under the terms of the GNU Affero General Public License as published by
13   * the Free Software Foundation, either version 3 of the License, or
14   * (at your option) any later version.
15   * 
16   * This program is distributed in the hope that it will be useful,
17   * but WITHOUT ANY WARRANTY; without even the implied warranty of
18   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   * GNU General Public License for more details.
20   * 
21   * You should have received a copy of the GNU Affero General Public License
22   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23   * #L%
24   */
25  
26  import fr.ifremer.dali.decorator.DecoratorService;
27  import fr.ifremer.dali.dto.DaliBeans;
28  import fr.ifremer.dali.dto.configuration.programStrategy.ProgramDTO;
29  import fr.ifremer.dali.dto.data.survey.CampaignDTO;
30  import fr.ifremer.dali.dto.enums.FilterTypeValues;
31  import fr.ifremer.dali.dto.referential.LocationDTO;
32  import fr.ifremer.dali.ui.swing.DaliUIContext;
33  import fr.ifremer.dali.ui.swing.content.home.HomeUI;
34  import fr.ifremer.dali.ui.swing.content.home.HomeUIHandler;
35  import fr.ifremer.dali.ui.swing.util.DaliUI;
36  import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableModel;
37  import fr.ifremer.dali.ui.swing.util.table.AbstractDaliTableUIHandler;
38  import fr.ifremer.dali.ui.swing.util.table.renderer.StateIconCellRenderer;
39  import fr.ifremer.dali.ui.swing.util.table.renderer.SynchronizationStatusIconCellRenderer;
40  import fr.ifremer.quadrige3.ui.swing.component.coordinate.CoordinateEditor;
41  import fr.ifremer.quadrige3.ui.swing.table.SwingTable;
42  import fr.ifremer.quadrige3.ui.swing.table.editor.ExtendedComboBoxCellEditor;
43  import fr.ifremer.quadrige3.ui.swing.table.editor.LocalTimeCellEditor;
44  import org.jdesktop.swingx.table.TableColumnExt;
45  
46  import javax.swing.BorderFactory;
47  import javax.swing.SortOrder;
48  import javax.swing.SwingUtilities;
49  import java.beans.PropertyChangeListener;
50  import java.util.List;
51  
52  import static org.nuiton.i18n.I18n.t;
53  
54  /**
55   * Controller pour le tableau des observations.
56   */
57  public class SurveysTableUIHandler extends
58          AbstractDaliTableUIHandler<SurveysTableRowModel, SurveysTableUIModel, SurveysTableUI> {
59  
60      private ExtendedComboBoxCellEditor<ProgramDTO> programCellEditor;
61      private ExtendedComboBoxCellEditor<CampaignDTO> campaignCellEditor;
62      private ExtendedComboBoxCellEditor<LocationDTO> locationCellEditor;
63      private PropertyChangeListener authenticationListener;
64  
65      /**
66       * {@inheritDoc}
67       */
68      @Override
69      protected String[] getRowPropertiesToIgnore() {
70          return new String[]{
71                  SurveysTableRowModel.PROPERTY_SAMPLING_OPERATIONS,
72                  SurveysTableRowModel.PROPERTY_SAMPLING_OPERATIONS_LOADED,
73                  SurveysTableRowModel.PROPERTY_DIRTY,
74                  SurveysTableRowModel.PROPERTY_ERRORS,
75                  SurveysTableRowModel.PROPERTY_CONTROL_DATE,
76                  SurveysTableRowModel.PROPERTY_VALIDATION_DATE,
77                  SurveysTableRowModel.PROPERTY_QUALIFICATION_COMMENT,
78                  SurveysTableRowModel.PROPERTY_SYNCHRONIZATION_STATUS,
79                  SurveysTableRowModel.PROPERTY_COORDINATE
80          };
81      }
82  
83      /**
84       * {@inheritDoc}
85       */
86      @Override
87      public void beforeInit(final SurveysTableUI ui) {
88          super.beforeInit(ui);
89  
90          // create model and register to the JAXX context
91          final SurveysTableUIModel model = new SurveysTableUIModel();
92          ui.setContextValue(model);
93      }
94  
95      /**
96       * {@inheritDoc}
97       */
98      @Override
99      public void afterInit(final SurveysTableUI ui) {
100 
101         // Initialisation de l ecran
102         initUI(ui);
103 
104         // Désactivation des boutons
105         getUI().getDuplicateButton().setEnabled(false);
106         getUI().getEditCombo().setEnabled(false);
107         getUI().getStateCombo().setEnabled(false);
108         getUI().getDeleteButton().setEnabled(false);
109 
110         enablePrivilegedControls();
111 
112         createProgramCellEditor();
113         createCampaignCellEditor();
114         createLocationCellEditor();
115 
116         // Initialisation du tableau
117         initTable();
118 
119         // Initialisation de la combobox Editer
120         initActionComboBox(getUI().getEditCombo());
121 
122         // Intialisation de la combobox Changer etat
123         initActionComboBox(getUI().getStateCombo());
124 
125         // Initialisation des listeners
126         initListeners();
127 
128         // button border
129         getUI().getNextButton().setBorder(
130                 BorderFactory.createCompoundBorder(BorderFactory.createMatteBorder(2, 2, 2, 2, getConfig().getColorHighlightButtonBorder()), ui.getNextButton().getBorder())
131         );
132 
133     }
134 
135     /**
136      * {@inheritDoc}
137      */
138     @Override
139     protected boolean isRowValid(final SurveysTableRowModel row) {
140 
141         return (!row.isEditable() || super.isRowValid(row)) && isSurveyRowValid(row);
142     }
143 
144     private boolean isSurveyRowValid(SurveysTableRowModel row) {
145 
146         // coordinates
147         if (row.getLatitudeMin() == null ^ row.getLongitudeMin() == null) {
148             DaliBeans.addError(row, t("dali.validator.error.coordinate.invalid"), SurveysTableRowModel.PROPERTY_LATITUDE_MIN, SurveysTableRowModel.PROPERTY_LONGITUDE_MIN);
149         }
150         if (row.getLatitudeMax() == null ^ row.getLongitudeMax() == null) {
151             DaliBeans.addError(row, t("dali.validator.error.coordinate.invalid"), SurveysTableRowModel.PROPERTY_LATITUDE_MAX, SurveysTableRowModel.PROPERTY_LONGITUDE_MAX);
152         }
153         if (row.getLatitudeMin() == null && row.getLatitudeMax() != null) {
154             DaliBeans.addError(row, t("dali.validator.error.coordinate.invalid"), SurveysTableRowModel.PROPERTY_LATITUDE_MIN, SurveysTableRowModel.PROPERTY_LATITUDE_MAX);
155         }
156         if (row.getLongitudeMin() == null && row.getLongitudeMax() != null) {
157             DaliBeans.addError(row, t("dali.validator.error.coordinate.invalid"), SurveysTableRowModel.PROPERTY_LONGITUDE_MIN, SurveysTableRowModel.PROPERTY_LONGITUDE_MAX);
158         }
159 
160         // positioning
161         if (row.getLatitudeMin() != null && row.getLongitudeMin() != null && row.getPositioning() == null) {
162             DaliBeans.addError(row, t("dali.validator.error.positioning.required"), SurveysTableRowModel.PROPERTY_POSITIONING);
163         }
164 
165         // dummy error if operations invalid
166         if (!row.isOperationsValid()) {
167             DaliBeans.addError(row, t("dali.home.survey.table.operationsInvalid"));
168         }
169 
170         boolean hasNoError = DaliBeans.hasNoBlockingError(row);
171 
172         if (!hasNoError) {
173             ensureColumnsWithErrorAreVisible(row);
174         }
175 
176         return hasNoError;
177     }
178 
179     /**
180      * Initialisation du tableau.
181      */
182     private void initTable() {
183 
184         // Program cell editor
185         TableColumnExt programCol = addColumn(
186                 programCellEditor,
187                 newTableCellRender(SurveysTableModel.PROGRAM),
188                 SurveysTableModel.PROGRAM);
189         programCol.setSortable(true);
190         programCol.setPreferredWidth(200);
191 
192         // Campaign
193         TableColumnExt campaignCol = addColumn(
194                 campaignCellEditor,
195                 newTableCellRender(SurveysTableModel.CAMPAIGN),
196                 SurveysTableModel.CAMPAIGN);
197         campaignCol.setSortable(true);
198         campaignCol.setPreferredWidth(200);
199 
200         // lieu
201         TableColumnExt locationCol = addColumn(
202                 locationCellEditor,
203                 newTableCellRender(SurveysTableModel.LOCATION),
204                 SurveysTableModel.LOCATION);
205         locationCol.setSortable(true);
206         locationCol.setPreferredWidth(200);
207 
208         // Date
209         TableColumnExt dateCol = addLocalDatePickerColumnToModel(SurveysTableModel.DATE, getConfig().getDateFormat());
210         dateCol.setSortable(true);
211         dateCol.setPreferredWidth(50);
212 
213         // mnemonique
214         TableColumnExt nameCol = addColumn(SurveysTableModel.NAME);
215         nameCol.setSortable(true);
216         nameCol.setPreferredWidth(100);
217 
218         // Commentaire
219         addCommentColumn(SurveysTableModel.COMMENT);
220 
221         // Partage
222         TableColumnExt synchroStatusCol = addColumn(
223                 null,
224                 new SynchronizationStatusIconCellRenderer(getContext()),
225                 SurveysTableModel.SYNCHRONIZATION_STATUS);
226         synchroStatusCol.setSortable(true);
227         synchroStatusCol.setPreferredWidth(20);
228 
229         // Etat
230         TableColumnExt stateCol = addColumn(
231                 null,
232                 new StateIconCellRenderer(getContext()),
233                 SurveysTableModel.STATE);
234         stateCol.setSortable(true);
235         stateCol.setPreferredWidth(100);
236 
237         // Profondeur precise
238         TableColumnExt bottomDepthCol = addColumn(SurveysTableModel.BOTTOM_DEPTH);
239         bottomDepthCol.setCellEditor(newNumberCellEditor(Double.class, false, DaliUI.DECIMAL2_PATTERN));
240         bottomDepthCol.setCellRenderer(newNumberCellRenderer(2));
241         bottomDepthCol.setSortable(true);
242         bottomDepthCol.setPreferredWidth(100);
243 
244         // Latitude Min
245         TableColumnExt latitudeMinCol = addCoordinateColumnToModel(
246                 CoordinateEditor.CoordinateType.LATITUDE_MIN,
247                 SurveysTableModel.LATITUDE_MIN);
248         latitudeMinCol.setSortable(true);
249         latitudeMinCol.setPreferredWidth(100);
250 
251         // longitude Min
252         TableColumnExt longitudeMinCol = addCoordinateColumnToModel(
253                 CoordinateEditor.CoordinateType.LONGITUDE_MIN,
254                 SurveysTableModel.LONGITUDE_MIN);
255         longitudeMinCol.setSortable(true);
256         longitudeMinCol.setPreferredWidth(100);
257 
258         // Latitude Max
259         TableColumnExt latitudeMaxCol = addCoordinateColumnToModel(
260                 CoordinateEditor.CoordinateType.LATITUDE_MAX,
261                 SurveysTableModel.LATITUDE_MAX);
262         latitudeMaxCol.setSortable(true);
263         latitudeMaxCol.setPreferredWidth(100);
264 
265         // longitude Max
266         TableColumnExt longitudeMaxCol = addCoordinateColumnToModel(
267                 CoordinateEditor.CoordinateType.LONGITUDE_MAX,
268                 SurveysTableModel.LONGITUDE_MAX);
269         longitudeMaxCol.setSortable(true);
270         longitudeMaxCol.setPreferredWidth(100);
271 
272         // positionnement
273         TableColumnExt positioningCol = addExtendedComboDataColumnToModel(
274                 SurveysTableModel.POSITIONING,
275                 getContext().getReferentialService().getPositioningSystems(),
276                 false);
277         positioningCol.setSortable(true);
278         positioningCol.setPreferredWidth(100);
279 
280         // positionnement
281         TableColumnExt positioningPrecisionCol = addColumn(
282                 SurveysTableModel.POSITIONING_PRECISION);
283         positioningPrecisionCol.setSortable(true);
284         positioningPrecisionCol.setPreferredWidth(100);
285         positioningPrecisionCol.setEditable(false);
286 
287         // Service Saisisseur
288         TableColumnExt recorderDepartmentCol = addColumn(
289                 null, //departmentCellEditor,
290                 newTableCellRender(SurveysTableModel.RECORDER_DEPARTMENT),
291                 SurveysTableModel.RECORDER_DEPARTMENT
292         );
293         recorderDepartmentCol.setSortable(true);
294         recorderDepartmentCol.setPreferredWidth(200);
295         recorderDepartmentCol.setEditable(false);
296 
297         // Colonne Heure
298         final TableColumnExt timeCol = addColumn(
299                 new LocalTimeCellEditor(),
300                 newTableCellRender(Integer.class, DecoratorService.TIME_IN_HOURS_MINUTES),
301                 SurveysTableModel.TIME);
302         timeCol.setMaxWidth(100);
303         timeCol.setWidth(100);
304         timeCol.setSortable(true);
305 
306         // Date Modif
307         TableColumnExt updateDateCol = addColumn(null, newDateCellRenderer(getConfig().getDateTimeFormat()), SurveysTableModel.UPDATE_DATE);
308         updateDateCol.setSortable(true);
309         updateDateCol.setPreferredWidth(50);
310 
311         // Date Control
312         TableColumnExt controlDateCol = addColumn(null, newDateCellRenderer(getConfig().getDateTimeFormat()), SurveysTableModel.CONTROL_DATE);
313         controlDateCol.setSortable(true);
314         controlDateCol.setPreferredWidth(50);
315 
316         // Date Valid
317         TableColumnExt validationDateCol = addColumn(null, newDateCellRenderer(getConfig().getDateTimeFormat()), SurveysTableModel.VALIDATION_DATE);
318         validationDateCol.setSortable(true);
319         validationDateCol.setPreferredWidth(50);
320 
321         // Commentaire Valid
322         TableColumnExt validationCommentCol = addCommentColumn(SurveysTableModel.VALIDATION_COMMENT, SurveysTableRowModel.PROPERTY_VALIDATION_COMMENT, false);
323 
324         // Date Qualif
325         TableColumnExt qualificationDateCol = addColumn(null, newDateCellRenderer(getConfig().getDateTimeFormat()), SurveysTableModel.QUALIFICATION_DATE);
326         qualificationDateCol.setSortable(true);
327         qualificationDateCol.setPreferredWidth(50);
328 
329         // Commentaire Qualif
330         TableColumnExt qualificationCommentCol = addCommentColumn(SurveysTableModel.QUALIFICATION_COMMENT, SurveysTableRowModel.PROPERTY_QUALIFICATION_COMMENT, false);
331 
332         // Quality flag
333         TableColumnExt qualityFlagCol = addColumn(SurveysTableModel.QUALITY_FLAG);
334         qualityFlagCol.setPreferredWidth(50);
335 
336         SurveysTableModel tableModel = new SurveysTableModel(getTable().getColumnModel());
337         getTable().setModel(tableModel);
338 
339         // Colonnes non editable
340         tableModel.setNoneEditableCols(
341                 SurveysTableModel.SYNCHRONIZATION_STATUS,
342                 SurveysTableModel.STATE,
343                 SurveysTableModel.UPDATE_DATE,
344                 SurveysTableModel.CONTROL_DATE,
345                 SurveysTableModel.VALIDATION_DATE,
346                 SurveysTableModel.QUALIFICATION_DATE,
347                 SurveysTableModel.QUALITY_FLAG);
348 
349         // Les colonnes obligatoire sont toujours presentes
350         dateCol.setHideable(false);
351         programCol.setHideable(false);
352 
353         // Initialisation du tableau
354         initTable(getTable());
355 
356         // Les colonnes optionnelles sont invisibles
357         recorderDepartmentCol.setVisible(false);
358         bottomDepthCol.setVisible(false);
359         latitudeMinCol.setVisible(false);
360         longitudeMinCol.setVisible(false);
361         latitudeMaxCol.setVisible(false);
362         longitudeMaxCol.setVisible(false);
363         positioningCol.setVisible(false);
364         positioningPrecisionCol.setVisible(false);
365         timeCol.setVisible(false);
366         updateDateCol.setVisible(false);
367         controlDateCol.setVisible(false);
368         validationDateCol.setVisible(false);
369         validationCommentCol.setVisible(false);
370         qualificationDateCol.setVisible(false);
371         qualificationCommentCol.setVisible(false);
372         qualityFlagCol.setVisible(false);
373 
374         // Tri par defaut
375         getTable().setSortOrder(SurveysTableModel.LOCATION, SortOrder.ASCENDING);
376 
377         // border
378         addEditionPanelBorder();
379 
380     }
381 
382     private void createProgramCellEditor() {
383 
384         programCellEditor = newExtendedComboBoxCellEditor(null, ProgramDTO.class, false);
385 
386         programCellEditor.setAction("unfilter", "dali.common.unfilter", e -> {
387             if (!askBefore(t("dali.common.unfilter"), t("dali.common.unfilter.confirmation"))) {
388                 return;
389             }
390             // unfilter programs
391             updateProgramCellEditor(getModel().getSingleSelectedRow(), true);
392             getTable().requestFocus();
393         });
394 
395     }
396 
397     private void updateProgramCellEditor(SurveysTableRowModel row, boolean forceNoFilter) {
398 
399         updateProgramCellEditor(row, forceNoFilter, true);
400     }
401 
402     private void updateProgramCellEditor(SurveysTableRowModel row, boolean forceNoFilter, boolean canResetValue) {
403 
404         // Keep the forceNoFilter on this row (Mantis #46655)
405         if (forceNoFilter) row.setForceNoProgramFilter(true);
406         if (row.isForceNoProgramFilter()) forceNoFilter = true;
407 
408         programCellEditor.getCombo().setActionEnabled(!forceNoFilter && getContext().getDataContext().isContextFiltered(FilterTypeValues.PROGRAM));
409 
410         List<ProgramDTO> availablePrograms =
411                 getContext().getObservationService().getAvailablePrograms(
412                         row.getLocation() == null ? null : row.getLocation().getId(),
413                         row.getDate(), forceNoFilter);
414 
415         // Mantis #0027340 & #0027282 : Avoid Program/Location/Date incompatibility
416         if (canResetValue && row.isEditable() && row.getProgram() != null && !availablePrograms.contains(row.getProgram())) {
417             row.setProgram(null);
418         }
419         programCellEditor.getCombo().setData(availablePrograms);
420 
421     }
422 
423     private void createCampaignCellEditor() {
424 
425         campaignCellEditor = newExtendedComboBoxCellEditor(null, CampaignDTO.class, false);
426 
427         campaignCellEditor.setAction("unfilter", "dali.common.unfilter", e -> {
428             if (!askBefore(t("dali.common.unfilter"), t("dali.common.unfilter.confirmation"))) {
429                 return;
430             }
431             // unfilter campaigns
432             updateCampaignCellEditor(getModel().getSingleSelectedRow(), true);
433             getTable().requestFocus();
434         });
435 
436     }
437 
438     private void updateCampaignCellEditor(SurveysTableRowModel row, boolean forceNoFilter) {
439 
440         updateCampaignCellEditor(row, forceNoFilter, true);
441     }
442 
443     private void updateCampaignCellEditor(SurveysTableRowModel row, boolean forceNoFilter, boolean canResetValue) {
444 
445         // Keep the forceNoFilter on this row (Mantis #46655)
446         if (forceNoFilter) row.setForceNoCampaignFilter(true);
447         if (row.isForceNoCampaignFilter()) forceNoFilter = true;
448 
449         campaignCellEditor.getCombo().setActionEnabled(!forceNoFilter && getContext().getDataContext().isContextFiltered(FilterTypeValues.CAMPAIGN));
450 
451         List<CampaignDTO> availableCampaigns =
452                 getContext().getObservationService().getAvailableCampaigns(row.getDate(), forceNoFilter);
453 
454         // Avoid Campaign/Date incompatibility
455         if (canResetValue && row.isEditable() && row.getCampaign() != null && !availableCampaigns.contains(row.getCampaign())) {
456             row.setCampaign(null);
457         }
458 
459         campaignCellEditor.getCombo().setData(availableCampaigns);
460 
461     }
462 
463     private void createLocationCellEditor() {
464 
465         locationCellEditor = newExtendedComboBoxCellEditor(null, LocationDTO.class, false);
466 
467         locationCellEditor.setAction("unfilter", "dali.common.unfilter", e -> {
468             if (!askBefore(t("dali.common.unfilter"), t("dali.common.unfilter.confirmation"))) {
469                 return;
470             }
471             // unfilter location
472             updateLocationCellEditor(getModel().getSingleSelectedRow(), true);
473             getTable().requestFocus();
474         });
475 
476     }
477 
478     private void updateLocationCellEditor(SurveysTableRowModel row, boolean forceNoFilter) {
479 
480         updateLocationCellEditor(row, forceNoFilter, true);
481     }
482 
483     private void updateLocationCellEditor(SurveysTableRowModel row, boolean forceNoFilter, boolean canResetValue) {
484 
485         // Keep the forceNoFilter on this row (Mantis #46655)
486         if (forceNoFilter) row.setForceNoLocationFilter(true);
487         if (row.isForceNoLocationFilter()) forceNoFilter = true;
488 
489         locationCellEditor.getCombo().setActionEnabled(!forceNoFilter && getContext().getDataContext().isContextFiltered(FilterTypeValues.LOCATION));
490 
491         List<LocationDTO> availableLocations =
492                 getContext().getObservationService().getAvailableLocations(
493                         null, // TODO pas de filtrage sur campaign ? row.getCampaign() == null ? null : row.getCampaign().getId(),
494                         row.getProgram() == null ? null : row.getProgram().getCode(),
495                         forceNoFilter);
496 
497         // Mantis #0027340 & #0027282 : Avoid Program/Location/Date incompatibility
498         if (canResetValue && row.isEditable() && row.getLocation() != null && !availableLocations.contains(row.getLocation())) {
499             row.setLocation(null);
500         }
501         locationCellEditor.getCombo().setData(availableLocations);
502     }
503 
504     private void initListeners() {
505 
506         // listen to this JTable property
507         getTable().addPropertyChangeListener("tableCellEditor", evt -> {
508             if (evt.getNewValue() != null) {
509 
510                 // a table edition begins
511                 final SurveysTableRowModel survey = getModel().getSingleSelectedRow();
512 
513                 // update cell editors because its too long
514                 if (survey != null) {
515                     updateProgramCellEditor(survey, false, false);
516                     updateCampaignCellEditor(survey, false, false);
517                     updateLocationCellEditor(survey, false, false);
518                 }
519 
520             }
521         });
522 
523         // add special listener if the privileges of the authenticated user have changed (see Mantis #38841)
524         authenticationListener = evt -> enablePrivilegedControls();
525         // Change access to these function if privilege changed
526         getContext().addPropertyChangeListener(DaliUIContext.PROPERTY_AUTHENTICATION_TOOLTIPTEXT, authenticationListener);
527 
528         // propagate the 'sorting' property of the table to the map model
529         getTable().addPropertyChangeListener(SwingTable.PROPERTY_SORTING, evt ->
530                 getModel().getMainUIModel().getMapUIModel().setBuildMapOnSelectionChanged(!getTable().isSorting()));
531     }
532 
533     private void enablePrivilegedControls() {
534         // enable or not these controls depending on user privileges
535         getUI().getValidateButton().setEnabled(getContext().getDataContext().isRecorderValidator());
536         getUI().getUnvalidateButton().setEnabled(getContext().getDataContext().isRecorderValidator());
537         getUI().getQualifyButton().setEnabled(getContext().getDataContext().isRecorderQualifier());
538     }
539 
540     @Override
541     public void onCloseUI() {
542 
543         // remove special listener to prevent memory leaks (Mantis #48757)
544         getContext().removePropertyChangeListener(DaliUIContext.PROPERTY_AUTHENTICATION_TOOLTIPTEXT, authenticationListener);
545 
546         super.onCloseUI();
547     }
548 
549     /**
550      * {@inheritDoc}
551      */
552     @Override
553     protected void onRowModified(int rowIndex, SurveysTableRowModel row, String propertyName, Integer propertyIndex, Object oldValue, Object newValue) {
554         super.onRowModified(rowIndex, row, propertyName, propertyIndex, oldValue, newValue);
555 
556         row.setDirty(true);
557 
558         // TODO Pas de filtrage sur campaign ?
559 //        if (SurveysTableRowModel.PROPERTY_CAMPAIGN.equals(propertyName)) {
560 //
561 //            updateProgramCellEditor(row, false);
562 //            updateLocationCellEditor(row, false);
563 //
564 //        }
565 
566         // Listen to PROGRAM modification to load sampling operations table
567         if (SurveysTableRowModel.PROPERTY_PROGRAM.equals(propertyName)) {
568 
569             updateLocationCellEditor(row, false);
570 
571             // use context variable to trigger PROPERTY_SELECTED_SURVEY event
572             selectSurvey(row);
573         }
574 
575         // Listen to LOCATION and DATE modification to load available programs and sampling operations table
576         if (SurveysTableRowModel.PROPERTY_LOCATION.equals(propertyName) || SurveysTableRowModel.PROPERTY_DATE.equals(propertyName)) {
577 
578             updateProgramCellEditor(row, false);
579 
580             if (SurveysTableRowModel.PROPERTY_DATE.equals(propertyName)) {
581                 updateCampaignCellEditor(row, false);
582             }
583 
584             // use context variable to trigger PROPERTY_SELECTED_SURVEY event
585             selectSurvey(row);
586         }
587 
588         // Listen to latitude or longitude to clear positioning when both are null
589         if (SurveysTableRowModel.PROPERTY_LATITUDE_MIN.equals(propertyName)
590                 || SurveysTableRowModel.PROPERTY_LATITUDE_MAX.equals(propertyName)
591                 || SurveysTableRowModel.PROPERTY_LONGITUDE_MIN.equals(propertyName)
592                 || SurveysTableRowModel.PROPERTY_LONGITUDE_MAX.equals(propertyName)
593                 ) {
594 
595             if (row.getLatitudeMin() == null && row.getLongitudeMin() == null
596                     && row.getLatitudeMax() == null && row.getLongitudeMax() == null) {
597                 row.setPositioning(null);
598                 getTable().repaint();
599             }
600         }
601 
602         forceRevalidateModel();
603     }
604 
605     private void selectSurvey(SurveysTableRowModel survey) {
606 
607         getModel().getMainUIModel().setSelectedSurvey(survey);
608     }
609 
610     /**
611      * {@inheritDoc}
612      */
613     @Override
614     public AbstractDaliTableModel<SurveysTableRowModel> getTableModel() {
615         return (SurveysTableModel) getTable().getModel();
616     }
617 
618     /**
619      * {@inheritDoc}
620      */
621     @Override
622     public SwingTable getTable() {
623         return ui.getSurveysTable();
624     }
625 
626     /**
627      * {@inheritDoc}
628      */
629     @Override
630     protected void onRowsAdded(List<SurveysTableRowModel> addedRows) {
631         super.onRowsAdded(addedRows);
632 
633         // should be only one row
634         if (addedRows.size() == 1) {
635             SurveysTableRowModel row = addedRows.get(0);
636 
637             // Ajout d'un mode de partage local pour une ligne ajoutee en local
638             row.setSynchronizationStatus(getContext().getSystemService().getLocalShare());
639 
640             // Add actual department of current user
641             Integer recorderDepId = getContext().getDataContext().getRecorderDepartmentId();
642             if (recorderDepId != null) {
643                 row.setDepartment(getContext().getReferentialService().getDepartmentById(recorderDepId));
644             }
645 
646             // Ajouter le focus sur la cellule de la ligne cree
647             setFocusOnCell(row);
648         }
649     }
650 
651     /**
652      * <p>onNext.</p>
653      */
654     public void onNext() {
655 
656         if (getTable().isEditing()) {
657             getTable().getCellEditor().stopCellEditing();
658         }
659 
660         getModel().getMainUIModel().getOperationsTableUIModel().addNewRow();
661 
662     }
663 
664     public HomeUIHandler getHomeUIHandler() {
665         return getParentContainer(HomeUI.class).getHandler();
666     }
667 
668     public void showMap() {
669         getHomeUIHandler().showSurveysMap();
670     }
671 
672     public void hideMap() {
673         getHomeUIHandler().showSamplingOperations();
674     }
675 
676     public void beforeLoad() {
677         uninstallSaveTableStateListener();
678     }
679 
680     public void afterLoad() {
681         restoreTableState();
682         SwingUtilities.invokeLater(this::installSaveTableStateListener);
683     }
684 }