View Javadoc
1   package fr.ifremer.tutti.ui.swing.content.cruise;
2   
3   /*
4    * #%L
5    * Tutti :: UI
6    * %%
7    * Copyright (C) 2012 - 2014 Ifremer
8    * %%
9    * This program is free software: you can redistribute it and/or modify
10   * it under the terms of the GNU General Public License as
11   * published by the Free Software Foundation, either version 3 of the 
12   * License, or (at your option) any later version.
13   * 
14   * This program is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU General Public License for more details.
18   * 
19   * You should have received a copy of the GNU General Public 
20   * License along with this program.  If not, see
21   * <http://www.gnu.org/licenses/gpl-3.0.html>.
22   * #L%
23   */
24  
25  import com.google.common.base.Predicate;
26  import com.google.common.collect.Lists;
27  import fr.ifremer.tutti.persistence.entities.data.Attachment;
28  import fr.ifremer.tutti.persistence.entities.data.Cruise;
29  import fr.ifremer.tutti.persistence.entities.data.Program;
30  import fr.ifremer.tutti.persistence.entities.referential.Gear;
31  import fr.ifremer.tutti.persistence.entities.referential.GearWithOriginalRankOrder;
32  import fr.ifremer.tutti.persistence.entities.referential.GearWithOriginalRankOrders;
33  import fr.ifremer.tutti.persistence.entities.referential.Gears;
34  import fr.ifremer.tutti.persistence.entities.referential.Person;
35  import fr.ifremer.tutti.persistence.entities.referential.Vessel;
36  import fr.ifremer.tutti.service.DecoratorService;
37  import fr.ifremer.tutti.service.PersistenceService;
38  import fr.ifremer.tutti.ui.swing.util.AbstractTuttiUIHandler;
39  import jaxx.runtime.JAXXUtil;
40  import jaxx.runtime.context.JAXXContextEntryDef;
41  import jaxx.runtime.swing.editor.bean.BeanDoubleListModel;
42  import jaxx.runtime.validator.swing.SwingValidator;
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  import org.nuiton.jaxx.application.swing.util.CloseableUI;
46  
47  import javax.swing.JComponent;
48  import javax.swing.JList;
49  import javax.swing.JPopupMenu;
50  import javax.swing.JSeparator;
51  import javax.swing.SwingUtilities;
52  import java.awt.Point;
53  import java.awt.Rectangle;
54  import java.awt.event.KeyAdapter;
55  import java.awt.event.KeyEvent;
56  import java.awt.event.MouseAdapter;
57  import java.awt.event.MouseEvent;
58  import java.util.List;
59  import java.util.Set;
60  
61  import static org.nuiton.i18n.I18n.t;
62  
63  /**
64   * Handler of UI {@link EditCruiseUI}.
65   *
66   * @author Tony Chemit - chemit@codelutin.com
67   * @since 0.1
68   */
69  public class EditCruiseUIHandler extends AbstractTuttiUIHandler<EditCruiseUIModel, EditCruiseUI> implements CloseableUI {
70  
71      /** Logger. */
72      private static final Log log = LogFactory.getLog(EditCruiseUIHandler.class);
73  
74      public static final String CRUISE_CARD = "cruise";
75  
76      public static final String GEAR_CARACTERISTICS_CARD = "gearCaracteristics";
77  
78      public static String getTitle(boolean exist) {
79  
80          String result;
81          if (exist) {
82              result = t("tutti.editCruise.title.edit.cruise");
83          } else {
84              result = t("tutti.editCruise.title.create.cruise");
85          }
86          return result;
87      }
88  
89      /**
90       * The gear selected popup grab from the double list.
91       *
92       * @since 2.6
93       */
94      protected JPopupMenu gearPopupMenu;
95  
96      @Override
97      public void beforeInit(EditCruiseUI ui) {
98  
99          super.beforeInit(ui);
100 
101         getDataContext().resetValidationDataContext();
102 
103         EditCruiseUIModel model = new EditCruiseUIModel();
104         model.setSynchronizationStatus("DIRTY");
105         model.setValidationContext(getContext().getValidationContext());
106 
107         if (getContext().isCruiseFilled()) {
108 
109             // load existing cruise
110             Cruise cruise = getDataContext().getCruise();
111 
112             model.fromEntity(cruise);
113 
114             if (!model.isGearEmpty()) {
115 
116                 // load gear caracteristics + set originalRankOrder
117                 for (GearWithOriginalRankOrder gear : model.getGear()) {
118 
119                     // original rank order is the incoming rank order
120                     gear.setOriginalRankOrder(gear.getRankOrder());
121                 }
122             }
123 
124             // load attachments
125             List<Attachment> attachments = getPersistenceService().getAllAttachments(
126                     model.getObjectType(), model.getObjectId());
127             model.addAllAttachment(attachments);
128 
129             if (log.isDebugEnabled()) {
130                 log.debug("Will edit cruise: " + cruise.getId());
131             }
132         } else {
133 
134             // create new cruise
135             Program program = getDataContext().getProgram();
136             model.setProgram(program);
137             model.setMultirigNumber(1);
138 
139 
140             if (log.isDebugEnabled()) {
141                 log.debug("Will create a new cruise from program: " + program);
142             }
143         }
144         listModelIsModify(model);
145         this.ui.setContextValue(model);
146     }
147 
148     @Override
149     public void afterInit(EditCruiseUI ui) {
150 
151         initUI(this.ui);
152 
153         // init date by hand (otherwise databinding in beforeInit method has already set the
154         // date in time editor, but the editor is still not init, so won't work)
155         ui.getBeginTimeField().setDate(getModel().getBeginDate());
156         ui.getEndTimeField().setDate(getModel().getEndDate());
157 
158         PersistenceService persistenceService = getPersistenceService();
159 
160         List<Person> users = persistenceService.getAllPerson();
161 
162         EditCruiseUIModel model = getModel();
163 
164         List<Vessel> scientificVesselList = getDataContext().getScientificVessels();
165         List<Vessel> fishingVesselList = getDataContext().getFishingVessels();
166         List<Vessel> allVesselList = Lists.newArrayList();
167         allVesselList.addAll(scientificVesselList);
168         allVesselList.addAll(fishingVesselList);
169 
170         List<Gear> scientificGearList = getDataContext().getScientificGears();
171         List<Gear> fishingGearList = getDataContext().getFishingGears();
172         List<Gear> allGearList = Lists.newArrayList();
173         allGearList.addAll(scientificGearList);
174         allGearList.addAll(fishingGearList);
175 
176         // Change vessel list and gear list when vessel type changes
177         model.addPropertyChangeListener(EditCruiseUIModel.PROPERTY_VESSEL_TYPE, evt -> {
178 
179             VesselTypeEnum vesselType = (VesselTypeEnum) evt.getNewValue();
180 
181             Predicate<Gear> gearPredicate = null;
182 
183             List<Vessel> allVesselList1 = Lists.newArrayList();
184 
185 
186             switch (vesselType) {
187                 case FISHING:
188                     gearPredicate = Gears.IS_FISHING_GEAR;
189                     allVesselList1.addAll(getDataContext().getFishingVessels());
190                     break;
191 
192                 case SCIENTIFIC:
193                     gearPredicate = Gears.IS_SCIENTIFIC_GEAR;
194 
195                     allVesselList1.addAll(getDataContext().getScientificVessels());
196                     break;
197                 default: {
198                     allVesselList1.addAll(getDataContext().getScientificVessels());
199                     allVesselList1.addAll(getDataContext().getFishingVessels());
200                 }
201             }
202 
203             EditCruiseUIHandler.this.ui.getGearList().getHandler().clearFilters();
204             EditCruiseUIHandler.this.ui.getVesselComboBox().setData(null);
205             EditCruiseUIHandler.this.ui.getVesselComboBox().setData(allVesselList1);
206 
207             if (gearPredicate != null) {
208                 EditCruiseUIHandler.this.ui.getGearList().getHandler().addFilter(gearPredicate);
209             }
210 
211         });
212 
213         initBeanFilterableComboBox(this.ui.getProgramComboBox(),
214                                    Lists.newArrayList(persistenceService.getAllProgram()),
215                                    model.getProgram(),
216                                    DecoratorService.ONLY_NAME);
217 
218         initBeanFilterableComboBox(this.ui.getDepartureLocationComboBox(),
219                                    Lists.newArrayList(persistenceService.getAllHarbour()),
220                                    model.getDepartureLocation());
221 
222         initBeanFilterableComboBox(this.ui.getReturnLocationComboBox(),
223                                    Lists.newArrayList(persistenceService.getAllHarbour()),
224                                    model.getReturnLocation());
225 
226         initBeanFilterableComboBox(this.ui.getVesselComboBox(),
227                                    allVesselList,
228                                    model.getVessel());
229 
230         this.ui.getGearList().setModel(new BeanDoubleListModel<Gear>() {
231 
232             private static final long serialVersionUID = 1L;
233 
234             private boolean valueAdjusting;
235 
236             @Override
237             public void moveUpSelected(Gear item) {
238                 super.moveUpSelected(item);
239                 rebuildRankOrder();
240             }
241 
242             @Override
243             public void moveDownSelected(Gear item) {
244                 super.moveDownSelected(item);
245                 rebuildRankOrder();
246             }
247 
248             @Override
249             public void setSelected(List<Gear> selected) {
250                 valueAdjusting = true;
251                 try {
252                     super.setSelected(selected);
253                 } finally {
254                     valueAdjusting = false;
255                 }
256                 rebuildRankOrder();
257             }
258 
259             @Override
260             public void addToSelected(Gear item) {
261 
262                 // always use a copy (with original rank order)
263                 GearWithOriginalRankOrder target =
264                         GearWithOriginalRankOrders.newGearWithOriginalRankOrder(item);
265 
266                 Short originalRankOrder = null;
267 
268                 if (item instanceof GearWithOriginalRankOrder) {
269                     // take the incoming original rank order
270                     originalRankOrder = ((GearWithOriginalRankOrder) item).getOriginalRankOrder();
271                 }
272                 if (originalRankOrder == null) {
273                     originalRankOrder = 0;
274                 }
275                 target.setOriginalRankOrder(originalRankOrder);
276                 super.addToSelected(target);
277                 rebuildRankOrder();
278             }
279 
280             @Override
281             public void addToSelected(List<Gear> items) {
282                 valueAdjusting = true;
283                 try {
284                     for (Gear item : items) {
285                         addToSelected(item);
286                     }
287                 } finally {
288                     valueAdjusting = false;
289                 }
290                 rebuildRankOrder();
291             }
292 
293             @Override
294             public void removeFromSelected(Gear item) {
295                 super.removeFromSelected(item);
296                 rebuildRankOrder();
297             }
298 
299             @Override
300             public void removeFromSelected(List<Gear> items) {
301                 valueAdjusting = true;
302                 try {
303                     for (Gear item : items) {
304                         removeFromSelected(item);
305                     }
306                 } finally {
307                     valueAdjusting = false;
308                 }
309                 rebuildRankOrder();
310             }
311 
312             protected void rebuildRankOrder() {
313                 if (!valueAdjusting) {
314                     int index = 1;
315                     for (Gear gear : getSelected()) {
316                         gear.setRankOrder((short) (index++));
317                     }
318                 }
319                 selectedModel.refresh();
320             }
321         });
322         initBeanList(this.ui.getGearList(),
323                      allGearList,
324                      (List) model.getGear(),
325                      getDecorator(Gear.class, DecoratorService.GEAR_WITH_RANK_ORDER));
326 
327         // add more actions on selected gear popup
328         gearPopupMenu = this.ui.getGearList().getSelectedList().getComponentPopupMenu();
329         this.ui.getGearList().getSelectedList().setComponentPopupMenu(null);
330 
331         gearPopupMenu.add(new JSeparator(), 0);
332         gearPopupMenu.add(this.ui.getViewGearCaracteristicsItem(), 0);
333         gearPopupMenu.add(this.ui.getEditGearCaracteristicsItem(), 0);
334 
335         initBeanList(this.ui.getHeadOfMissionList(),
336                      users,
337                      model.getHeadOfMission());
338 
339         initBeanList(this.ui.getHeadOfSortRoomList(),
340                      users,
341                      model.getHeadOfSortRoom());
342 
343         this.ui.getGearList().getSelectedList().addMouseListener(new MouseAdapter() {
344             @Override
345             public void mouseClicked(MouseEvent e) {
346 
347                 if (SwingUtilities.isRightMouseButton(e)) {
348                     JList jList = (JList) e.getSource();
349                     Point point = e.getPoint();
350                     int selectedIndex = jList.locationToIndex(point);
351                     Rectangle rect = jList.getCellBounds(selectedIndex, selectedIndex);
352                     if (rect.contains(point)) {
353                         jList.setSelectedIndex(selectedIndex); //select the item
354                     } else {
355                         jList.clearSelection();
356                     }
357 
358                     GearWithOriginalRankOrder gear = (GearWithOriginalRankOrder) jList.getSelectedValue();
359                     updateGearActionsAndShowPoup(gear, jList, e.getX(), e.getY());
360 
361                 }
362             }
363         });
364 
365         this.ui.getGearList().getSelectedList().addKeyListener(new KeyAdapter() {
366             @Override
367             public void keyPressed(KeyEvent e) {
368                 if (e.getKeyCode() == KeyEvent.VK_CONTEXT_MENU) {
369 
370                     JList source = (JList) e.getSource();
371 
372                     // get the lowest selected row
373                     int[] selectedRows = source.getSelectedIndices();
374                     int lowestRow = -1;
375                     for (int row : selectedRows) {
376                         lowestRow = Math.max(lowestRow, row);
377                     }
378                     Rectangle r = source.getCellBounds(lowestRow, lowestRow);
379 
380                     // get the point in the middle lower of the cell
381                     Point p = new Point(r.x + r.width / 2, r.y + r.height);
382 
383                     Object[] gears = source.getSelectedValues();
384                     GearWithOriginalRankOrder gear = gears != null && gears.length == 1 ? (GearWithOriginalRankOrder) gears[0] : null;
385                     updateGearActionsAndShowPoup(gear, source, p.x, p.y);
386                 }
387             }
388         });
389 
390         SwingValidator validator = this.ui.getValidator();
391         changeValidatorContext(model.getValidationContext(), ui.getValidator());
392 
393         listenValidatorValid(validator, model);
394 
395         model.setVesselType(VesselTypeEnum.SCIENTIFIC);
396 
397         // if new fishingOperation can already cancel his creation
398         model.setModify(model.isCreate());
399 
400         registerValidators(validator);
401 
402         //FIXME Binding does not work
403         JAXXUtil.applyDataBinding(ui, EditCruiseUI.BINDING_RESET_BUTTON_ENABLED);
404     }
405 
406     @Override
407     protected JComponent getComponentToFocus() {
408         return getUI().getProgramComboBox();
409     }
410 
411     @Override
412     protected Set<String> getPropertiesToIgnore() {
413         Set<String> result = super.getPropertiesToIgnore();
414         result.add(EditCruiseUIModel.PROPERTY_ATTACHMENT);
415         result.add(EditCruiseUIModel.PROPERTY_VESSEL_TYPE);
416         result.add(EditCruiseUIModel.PROPERTY_VESSEL_TYPE_ALL);
417         result.add(EditCruiseUIModel.PROPERTY_VESSEL_TYPE_SCIENTIFIC);
418         result.add(EditCruiseUIModel.PROPERTY_VESSEL_TYPE_FISHING);
419         result.add(EditCruiseUIModel.PROPERTY_CAN_EDIT_GEAR_CARACTERISTIC);
420         result.add(EditCruiseUIModel.PROPERTY_CAN_SHOW_GEAR_CARACTERISTIC);
421         return result;
422     }
423 
424     @Override
425     public void onCloseUI() {
426         if (log.isDebugEnabled()) {
427             log.debug("closing: " + ui);
428         }
429         clearValidators();
430 
431         ui.getAttachmentsButton().onCloseUI();
432     }
433 
434     @Override
435     public boolean quitUI() {
436         return quitScreen(
437                 getModel().isValid(),
438                 getModel().isModify(),
439                 t("tutti.editCruise.askCancelEditBeforeLeaving.cancelSaveCruise"),
440                 t("tutti.editCruise.askSaveBeforeLeaving.saveCruise"),
441                 ui.getSaveButton().getAction()
442         );
443     }
444 
445     @Override
446     public SwingValidator<EditCruiseUIModel> getValidator() {
447         return ui.getValidator();
448     }
449 
450 //    public void generateCampaignName() {
451 //
452 //        EditCruiseUIModel model = getModel();
453 //        String name = model.getGeneratedCampaignName();
454 //        model.setName(name);
455 //    }
456 
457     public static final JAXXContextEntryDef<GearWithOriginalRankOrder> GEAR_EDIT_CONTEXT =
458             JAXXUtil.newContextEntryDef("editGear", GearWithOriginalRankOrder.class);
459 
460     protected void updateGearActionsAndShowPoup(GearWithOriginalRankOrder gear,
461                                                 JComponent source,
462                                                 int x,
463                                                 int y) {
464         boolean editMenuEnabled = false;
465         boolean viewMenuEnabled = false;
466         if (gear != null) {
467             editMenuEnabled = !getModel().isCreate() &&
468                               !getModel().isModify() &&
469                               (!gear.isScientificGear() ||
470                                Gears.isTemporary(gear));
471             viewMenuEnabled = true;
472             GEAR_EDIT_CONTEXT.setContextValue(ui, gear);
473         }
474         getModel().setCanEditGearCatacteristic(editMenuEnabled);
475         getModel().setCanShowGearCatacteristic(viewMenuEnabled);
476 
477         gearPopupMenu.show(source, x, y); //and show the menu
478     }
479 
480     public void reloadCruise(Cruise cruise) {
481 
482         EditCruiseUIModel model = getModel();
483 
484         model.fromEntity(cruise);
485 
486         if (!model.isGearEmpty()) {
487 
488             // load gear caracteristics + set originalRankOrder
489             for (GearWithOriginalRankOrder gear : model.getGear()) {
490 
491                 // original rank order is the incoming rank order
492                 gear.setOriginalRankOrder(gear.getRankOrder());
493             }
494         }
495 
496         // load attachments
497         List<Attachment> attachments = getPersistenceService().getAllAttachments(
498                 model.getObjectType(), model.getObjectId());
499         model.addAllAttachment(attachments);
500 
501         ui.getHeadOfMissionList().getModel().setSelected(model.getHeadOfMission());
502         ui.getHeadOfSortRoomList().getModel().setSelected(model.getHeadOfSortRoom());
503         ui.getGearList().getModel().setSelected((List) model.getGear());
504 
505         getModel().setModify(false);
506 
507     }
508 }