174a52cf34a352a2833fc8711a97c551687ee8c6
[taxeditor.git] / taxeditor-editor / src / main / java / eu / etaxonomy / taxeditor / editor / description / DistributionDialog.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10
11 package eu.etaxonomy.taxeditor.editor.description;
12
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16
17 import org.apache.log4j.Logger;
18 import org.eclipse.jface.dialogs.Dialog;
19 import org.eclipse.jface.dialogs.IDialogConstants;
20 import org.eclipse.jface.window.Window;
21 import org.eclipse.swt.SWT;
22 import org.eclipse.swt.events.SelectionAdapter;
23 import org.eclipse.swt.events.SelectionEvent;
24 import org.eclipse.swt.layout.GridData;
25 import org.eclipse.swt.widgets.Combo;
26 import org.eclipse.swt.widgets.Composite;
27 import org.eclipse.swt.widgets.Control;
28 import org.eclipse.swt.widgets.Label;
29 import org.eclipse.swt.widgets.Shell;
30
31 import eu.etaxonomy.cdm.api.service.ILocationService;
32 import eu.etaxonomy.cdm.api.service.ILocationService.NamedAreaVocabularyType;
33 import eu.etaxonomy.cdm.model.description.Distribution;
34 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTermBase;
35 import eu.etaxonomy.cdm.model.location.NamedArea;
36 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
37 import eu.etaxonomy.taxeditor.editor.EditorUtil;
38 import eu.etaxonomy.taxeditor.editor.reference.ReferenceSelectComposite;
39 import eu.etaxonomy.taxeditor.store.CdmStore;
40
41 /**
42 * @author p.ciardelli
43 * @created 03.04.2009
44 * @version 1.0
45 */
46 public class DistributionDialog extends Dialog {
47 private static final Logger logger = Logger
48 .getLogger(DistributionDialog.class);
49
50 private ILocationService locationService;
51
52 private String title;
53 private String message;
54
55 /**
56 * Number of area menus to show
57 */
58 private static final int NUM_AREA_MENUS = 4;
59 /**
60 * UI elements
61 */
62 private Combo vocabTypeCombo;
63 private Combo[] areaCombos = new Combo[NUM_AREA_MENUS];
64 private Combo statusCombo;
65 private ReferenceSelectComposite referenceComposite;
66 /**
67 * Distribution fields
68 */
69 private NamedArea selectedArea;
70 private PresenceAbsenceTermBase<?> selectedStatus;
71 private Distribution distribution;
72 private NamedAreaVocabularyType selectedVocabType;
73 private ReferenceBase selectedReference;
74 /**
75 * Lists to populate drop downs
76 */
77 private ArrayList<NamedAreaVocabularyType> vocabularyTypes;
78 private List<PresenceAbsenceTermBase<?>> presenceAbsenceTerms;
79 private List<List<NamedArea>> areas = new ArrayList<List<NamedArea>>();
80 private NamedArea[] selectedAreas = new NamedArea[NUM_AREA_MENUS];
81 /**
82 * Static fields to persist default values
83 */
84 private static ReferenceBase lastReference;
85 private static PresenceAbsenceTermBase<?> lastPresenceAbsence;
86 private static NamedAreaVocabularyType lastVocabType;
87 private static NamedArea lastNamedArea;
88
89 /**
90 * @param shell
91 * @param dialogTitle
92 * @param dialogMessage
93 */
94 public DistributionDialog(Shell shell, String dialogTitle,
95 String dialogMessage) {
96 super(shell);
97
98 title = dialogTitle;
99 message = dialogMessage;
100
101 locationService = CdmStore.getLocationService();
102
103 recallPreviousSelections();
104 }
105
106 /**
107 * Set inputs to selections from last time dialog was used.
108 */
109 private void recallPreviousSelections() {
110 if (lastVocabType != null) {
111 selectedVocabType = lastVocabType;
112
113 // Last named area don't make much sense w/out a vocab type
114 if (lastNamedArea != null) {
115 selectedArea = lastNamedArea;
116 }
117 }
118 if (lastPresenceAbsence != null) {
119 selectedStatus = lastPresenceAbsence;
120 }
121 if (lastReference != null) {
122 selectedReference = lastReference;
123 }
124 }
125
126 /**
127 * @param dialogTitle
128 * @param dialogMessage
129 * @return
130 */
131 public static Distribution getDistribution(String dialogTitle,
132 String dialogMessage) {
133 DistributionDialog dialog = new DistributionDialog(EditorUtil.getShell(),
134 dialogTitle,
135 dialogMessage);
136 if (dialog.open() == Window.CANCEL) {
137 return null;
138 }
139 return dialog.getDistribution();
140 }
141
142 /**
143 * @return
144 */
145 private Distribution getDistribution() {
146 return distribution;
147 }
148
149 /*
150 * (non-Javadoc)
151 *
152 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
153 */
154 protected void configureShell(Shell shell) {
155 super.configureShell(shell);
156 if (title != null) {
157 shell.setText(title);
158 }
159 }
160
161 protected Control createDialogArea(Composite parent) {
162 // create composite
163 Composite composite = (Composite) super.createDialogArea(parent);
164 // create message
165 if (message != null) {
166 createLabel(message, composite, parent);
167 }
168 createLabel("Select an area vocabulary:", composite, parent);
169 // create vocab type
170 vocabTypeCombo = createCombo(composite);
171 vocabTypeCombo.addSelectionListener(new SelectionAdapter() {
172 @Override
173 public void widgetSelected(SelectionEvent e) {
174 selectVocabType();
175 }
176 });
177 // create areas
178 createLabel("Select an area:", composite, parent);
179 for (int i = 0; i < NUM_AREA_MENUS; i++) {
180 areaCombos[i] = createCombo(composite);
181 areaCombos[i].addSelectionListener(new AreaComboListener(i));
182 areaCombos[i].setEnabled(false);
183 }
184 // create presence / absence
185 createLabel("Select status:", composite, parent);
186 statusCombo = new Combo(composite, SWT.BORDER);
187 statusCombo.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
188 | GridData.HORIZONTAL_ALIGN_FILL));
189 statusCombo.addSelectionListener(new SelectionAdapter() {
190 @Override
191 public void widgetSelected(SelectionEvent e) {
192 selectStatusTerm();
193 }
194 });
195 // create reference
196 referenceComposite = new ReferenceSelectComposite(composite);
197
198 populateVocabTypes();
199 populateAreas();
200
201 populatePresenceAbsenceTerms();
202 populateReference();
203
204 applyDialogFont(composite);
205
206 return composite;
207 }
208
209 class AreaComboListener extends SelectionAdapter {
210 private int i;
211 AreaComboListener(int i) {
212 this.i = i;
213 }
214 @Override
215 public void widgetSelected(SelectionEvent e) {
216 selectArea(i);
217 }
218 }
219
220 /**
221 * @return
222 */
223 private Combo createCombo(Composite composite) {
224 Combo combo = new Combo(composite, SWT.BORDER);
225 combo.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
226 | GridData.HORIZONTAL_ALIGN_FILL));
227 return combo;
228 }
229
230 /**
231 *
232 */
233 private void populateVocabTypes() {
234 int i = 0;
235 int index = -1;
236 for (NamedAreaVocabularyType vocabularyType : getVocabularyTypes()) {
237 String vocabularyTypeLabel = vocabularyType == null ?
238 "" : vocabularyType.toString();
239 vocabTypeCombo.add(vocabularyTypeLabel);
240
241 if (vocabularyType != null && vocabularyType == selectedVocabType) {
242 index = i;
243 }
244 i++;
245 }
246 if (index > -1) {
247 vocabTypeCombo.select(index);
248 }
249 }
250
251 /**
252 * @param namedArea
253 * @return
254 */
255 private List<NamedArea> getNamedAreas(NamedArea namedArea, int depth) {
256 List<NamedArea> terms = new ArrayList<NamedArea>();
257 // Set<NamedArea> terms = namedArea.getIncludes();
258 terms.addAll(namedArea.getIncludes());
259
260 // // FIXME fixme how?!
261 // List<NamedArea> termList = new ArrayList<NamedArea>();
262 // for (NamedArea area : terms){
263 // termList.add(area);
264 // }
265
266 areas.add(depth, terms);
267
268 return terms;
269 }
270
271 /**
272 * @param selectedVocabType
273 * @return
274 */
275 private List<NamedArea> getNamedAreas(NamedAreaVocabularyType vocabularyType) {
276 List<NamedArea> topLevelTerms = locationService.getTopLevelNamedAreasByVocabularyType(vocabularyType);
277
278 // OrderedTermVocabulary<NamedArea> vocabulary = locationService.getNamedAreaVocabulary(vocabularyType);
279 //
280 // List<NamedArea> topLevelTerms = new ArrayList<NamedArea>();
281 // Iterator<NamedArea> it = vocabulary.iterator();
282 // while(it.hasNext()){
283 //
284 // NamedArea area = HibernateProxyHelper.deproxy(it.next(), NamedArea.class);
285 //// try{
286 //// area3 =
287 //// }catch(Exception e){
288 //// logger.warn("Nope");
289 //// }
290 //// NamedArea area2 = area3.getPartOf();
291 ////
292 //// if(!(area2 instanceof NamedArea)){
293 //// area2 = CdmBase.deproxy(area2, NamedArea.class);
294 //// }
295 //
296 // if(area.getPartOf() == null){
297 // topLevelTerms.add(area);
298 // }
299 //
300 // }
301 // TODO is this the right order?
302 Collections.reverse(topLevelTerms);
303
304 areas.add(0, topLevelTerms);
305 return topLevelTerms;
306 }
307 // for(NamedArea area : vocabulary){
308 // NamedArea area2 = area.getPartOf();
309 //
310 // if(!(area.getPartOf() instanceof NamedArea)){
311 // area2 = CdmBase.deproxy(area.getPartOf(), NamedArea.class);
312 // }
313 //
314 // if(area2 == null){
315 // topLevelTerms.add(area);
316 // }
317
318
319 /**
320 *
321 */
322 private void populatePresenceAbsenceTerms() {
323 int selectedIndex = -1;
324 int i = 0;
325 for (PresenceAbsenceTermBase<?> term : getPresenceAbsenceTerms()) {
326 if (term == null) {
327 } else {
328 statusCombo.add(term.getLabel(CdmStore.getDefaultLanguage()));
329 if (this.selectedStatus != null && this.selectedStatus.equals(term)) {
330 selectedIndex = i;
331 }
332 }
333 i++;
334 }
335 if (selectedIndex != -1) {
336 statusCombo.select(selectedIndex);
337 }
338 }
339
340 /**
341 *
342 */
343 private void populateReference() {
344 if (selectedReference != null) {
345 referenceComposite.setReference(selectedReference);
346 }
347 }
348
349 /**
350 * @return
351 */
352 private List<NamedAreaVocabularyType> getVocabularyTypes() {
353 if (vocabularyTypes == null) {
354 vocabularyTypes = new ArrayList<NamedAreaVocabularyType>();
355 vocabularyTypes.addAll(locationService.getNamedAreaVocabularyTypes());
356 }
357 return vocabularyTypes;
358 }
359
360 /**
361 * @return
362 */
363 private List<PresenceAbsenceTermBase<?>> getPresenceAbsenceTerms() {
364 if (presenceAbsenceTerms == null) {
365 presenceAbsenceTerms = new ArrayList<PresenceAbsenceTermBase<?>>();
366
367 for (PresenceAbsenceTermBase<?> term : locationService.getPresenceTermVocabulary().getTermsOrderedByLabels(CdmStore.getDefaultLanguage())) {
368 presenceAbsenceTerms.add(term);
369 }
370 for (PresenceAbsenceTermBase<?> term : locationService.getAbsenceTermVocabulary().getTermsOrderedByLabels(CdmStore.getDefaultLanguage())) {
371 presenceAbsenceTerms.add(term);
372 }
373 }
374 return presenceAbsenceTerms;
375 }
376
377 /**
378 * @param i
379 */
380 protected void selectArea(int depth) {
381 // This selection is made currently selected area
382 int i = areaCombos[depth].getSelectionIndex();
383
384 selectedArea = getSelectedArea(depth, i);
385
386 selectedAreas[depth] = selectedArea;
387
388 clearArea(depth + 1);
389 populateAreas(depth + 1);
390
391 updateButtons();
392 }
393
394 /**
395 * @param i
396 * @param index
397 * @return
398 */
399 private NamedArea getSelectedArea(int depth, int index) {
400 return areas.get(depth).get(index);
401 }
402
403 /**
404 *
405 */
406 protected void selectVocabType() {
407 int i = vocabTypeCombo.getSelectionIndex();
408 selectedVocabType = getVocabularyTypes().get(i);
409
410 clearAreas();
411
412 populateAreas(0);
413 }
414
415 /**
416 *
417 */
418 private void populateAreas() {
419 if (selectedArea == null) {
420 return;
421 }
422 List<NamedArea> areasTmp = new ArrayList<NamedArea>();
423 NamedArea namedAreaTmp = selectedArea;
424 NamedArea parentArea = null;
425 do {
426 areasTmp.add(namedAreaTmp);
427 parentArea = namedAreaTmp.getPartOf();
428 namedAreaTmp = parentArea;
429 } while (parentArea != null);
430 Collections.reverse(areasTmp);
431 int depth = 0;
432 for (NamedArea namedArea : areasTmp) {
433 selectedAreas[depth] = namedArea;
434 populateAreas(depth);
435 depth++;
436 }
437 }
438
439 /**
440 * @param i
441 */
442 private void populateAreas(int depth) {
443 List<NamedArea> areasTmp;
444 if(depth == 0){
445 areasTmp = getNamedAreas(selectedVocabType);
446 }else{
447 areasTmp = getNamedAreas(selectedAreas[depth - 1], depth);
448 }
449
450 int index = -1;
451 int i = 0;
452 if (areasTmp.size() > 0) {
453 for(NamedArea areaTmp : areasTmp){
454 String areaLabel = areaTmp == null ? "" : areaTmp.getLabel();
455 areaCombos[depth].add(areaLabel);
456
457 if (selectedAreas[depth] != null && selectedAreas[depth].equals(areaTmp)) {
458 index = i;
459 }
460 i++;
461 }
462 areaCombos[depth].setEnabled(true);
463 if (index > -1) {
464 areaCombos[depth].select(index);
465 }
466 }
467 }
468
469 /**
470 *
471 */
472 protected void selectStatusTerm() {
473 int i = statusCombo.getSelectionIndex();
474 selectedStatus = presenceAbsenceTerms.get(i);
475
476 updateButtons();
477 }
478
479 /**
480 * @param string
481 * @param parent
482 * @param composite
483 * @return
484 */
485 private Label createLabel(String string, Composite composite, Composite parent) {
486 Label label = new Label(composite, SWT.WRAP);
487 label.setText(string);
488 GridData data = new GridData(GridData.GRAB_HORIZONTAL
489 | GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL
490 | GridData.VERTICAL_ALIGN_CENTER);
491 data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
492 label.setLayoutData(data);
493 label.setFont(parent.getFont());
494 return label;
495 }
496
497 /**
498 * @param i
499 */
500 private void clearArea(int i) {
501 for (int j = i; j < NUM_AREA_MENUS; j++) {
502 // TODO add clear selectedArea
503 areaCombos[j].removeAll();
504 areaCombos[j].setEnabled(false);
505 }
506 }
507
508 /**
509 *
510 */
511 private void clearAreas() {
512 clearArea(0);
513 }
514
515 protected void createButtonsForButtonBar(Composite parent) {
516 createButton(parent, IDialogConstants.OK_ID,
517 IDialogConstants.OK_LABEL, true);
518 createButton(parent, IDialogConstants.CANCEL_ID,
519 IDialogConstants.CANCEL_LABEL, false);
520
521 updateButtons();
522 }
523
524 protected void buttonPressed(int buttonId) {
525 if (IDialogConstants.OK_ID == buttonId) {
526 okPressed();
527 } else if (IDialogConstants.CANCEL_ID == buttonId) {
528 cancelPressed();
529 }
530 }
531
532 protected void okPressed() {
533 createDistribution();
534 setStaticFields();
535 super.okPressed();
536 }
537
538 /**
539 *
540 */
541 private void setStaticFields() {
542 lastPresenceAbsence = getPresenceAbsenceTerm();
543 lastNamedArea = selectedArea;
544 lastReference = getReference();
545 lastVocabType = getVocabType();
546 }
547
548 /**
549 * @return
550 */
551 private NamedAreaVocabularyType getVocabType() {
552 int i = vocabTypeCombo.getSelectionIndex();
553 return vocabularyTypes.get(i);
554 }
555
556 /**
557 * @return
558 */
559 private ReferenceBase getReference() {
560 return referenceComposite.getReference();
561 }
562
563 /**
564 * @return
565 */
566 private String getMicroReference() {
567 return referenceComposite.getMicroReference();
568 }
569
570 /**
571 * @return
572 */
573 private PresenceAbsenceTermBase<?> getPresenceAbsenceTerm() {
574 int i = statusCombo.getSelectionIndex();
575 return presenceAbsenceTerms.get(i);
576 }
577
578 /**
579 *
580 */
581 private void createDistribution() {
582 distribution = Distribution.NewInstance(selectedArea, selectedStatus);
583 if (referenceComposite.getReference() != null) {
584 selectedReference = getReference();
585 distribution.setCitation(selectedReference);
586 }
587 if (referenceComposite.getMicroReference() != "") {
588 distribution.setCitationMicroReference(
589 getMicroReference());
590 }
591 }
592
593 private void updateButtons() {
594 setOkEnabled(isDialogComplete());
595 }
596
597 private boolean isDialogComplete() {
598 return
599 (selectedArea != null && selectedStatus != null);
600 }
601
602 private void setOkEnabled(boolean enabled) {
603 getButton(IDialogConstants.OK_ID).setEnabled(enabled);
604 }
605 }