33b37cb0bf65be9974bf1035eabef78dd49c82a4
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / combo / TermComboElement.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.ui.combo;
5
6 import java.util.ArrayList;
7 import java.util.Arrays;
8 import java.util.Collections;
9 import java.util.Comparator;
10 import java.util.List;
11
12 import org.eclipse.jface.util.PropertyChangeEvent;
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.events.DisposeEvent;
15 import org.eclipse.swt.events.DisposeListener;
16 import org.eclipse.swt.events.SelectionEvent;
17 import org.eclipse.swt.events.SelectionListener;
18 import org.eclipse.swt.graphics.Color;
19 import org.eclipse.swt.widgets.Combo;
20 import org.eclipse.swt.widgets.Label;
21 import org.eclipse.swt.widgets.Listener;
22
23 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
24 import eu.etaxonomy.cdm.model.common.TermType;
25 import eu.etaxonomy.cdm.model.common.TermVocabulary;
26 import eu.etaxonomy.taxeditor.model.MessagingUtils;
27 import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
28 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
29 import eu.etaxonomy.taxeditor.preference.Resources;
30 import eu.etaxonomy.taxeditor.store.CdmStore;
31 import eu.etaxonomy.taxeditor.store.StoreUtil;
32 import eu.etaxonomy.taxeditor.store.TermManager;
33 import eu.etaxonomy.taxeditor.ui.element.AbstractCdmFormElement;
34 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
35 import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
36 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
37 import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
38 import eu.etaxonomy.taxeditor.ui.element.ISelectable;
39 import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
40
41 /**
42 * <p>
43 * Abstract AbstractTermComboElement class.
44 * </p>
45 *
46 * @author n.hoffmann
47 * @created Nov 5, 2009
48 * @version 1.0
49 * @param <T>
50 */
51 public class TermComboElement<T extends DefinedTermBase>
52 extends AbstractCdmFormElement implements SelectionListener,
53 DisposeListener, IEnableableFormElement, ISelectable {
54
55 private static final int DEFAULT_VISIBLE_ITEMS = 10;
56
57 private T selection;
58
59 private T emptyElement;
60 private static String EMPTY_ELEMENT_LABEL = "";
61
62 protected Label label;
63 private final Combo combo;
64
65 private ArrayList<T> terms;
66
67 private Comparator<T> termComparator;
68
69 private final TermType termType;
70 private final TermVocabulary termVocabulary;
71 private final Class<T> termClass;
72
73 private List<T> customPreferredTerms;
74
75 private boolean addEmptyElement;
76
77 public TermComboElement(CdmFormFactory formFactory,
78 ICdmFormElement parentElement, TermType termType, String labelString, T selection, boolean addEmptyElement,
79 int style) {
80 this(formFactory, parentElement, null, termType, null, labelString, selection, addEmptyElement, style);
81 }
82
83 public TermComboElement(CdmFormFactory formFactory,
84 ICdmFormElement parentElement, TermVocabulary<?> termVocabulary, String labelString, T selection, boolean addEmptyElement,
85 int style) {
86 this(formFactory, parentElement, null, null, termVocabulary, labelString, selection, addEmptyElement, style);
87 }
88
89 public TermComboElement(CdmFormFactory formFactory,
90 ICdmFormElement parentElement, Class<T> termClass, String labelString, T selection, boolean addEmptyElement,
91 int style) {
92 this(formFactory, parentElement, termClass, null, null, labelString, selection, addEmptyElement, style);
93 }
94
95 private TermComboElement(CdmFormFactory formFactory,
96 ICdmFormElement parentElement, Class<T> termClass, TermType termType, TermVocabulary<?> termVocabulary, String labelString, T selection, boolean addEmptyElement,
97 int style) {
98 super(formFactory, parentElement);
99
100 this.termType = termType;
101 this.termVocabulary = termVocabulary;
102 this.termClass = termClass;
103 this.addEmptyElement = addEmptyElement;
104
105 if (labelString != null) {
106 label = formFactory.createLabel(getLayoutComposite(), labelString);
107 addControl(label);
108 }
109
110 // create combo
111 combo = new Combo(getLayoutComposite(), SWT.BORDER | SWT.READ_ONLY );//FIXME: removed this parameter seems break windows version: | style
112 addControl(combo);
113 combo.setLayoutData(LayoutConstants.FILL_HORIZONTALLY());
114 combo.setVisibleItemCount(DEFAULT_VISIBLE_ITEMS);
115
116 if(termType!=null){
117 //TODO try to remove generic T and avoid classes to be used
118 populateTerms((List<T>) getTermManager().getPreferredTerms(termType));
119 }
120 else if(termVocabulary!=null){
121 populateTerms((List<T>) getTermManager().getPreferredTerms(termVocabulary));
122 }
123 else if(this.termClass!=null){
124 populateTerms(getPreferredTerms());
125 }
126
127 combo.addSelectionListener(this);
128 combo.addDisposeListener(this);
129 PreferencesUtil.getPreferenceStore().addPropertyChangeListener(this);
130
131 if (selection != null) {
132 setSelection(selection);
133 }
134 }
135
136 /**
137 * <p>
138 * Getter for the field <code>selection</code>.
139 * </p>
140 *
141 * @return a T object.
142 */
143 public T getSelection() {
144 return selection;
145 }
146
147 /**
148 * <p>Sets the selection of the combo to the given T object.</p>
149 * <p>Passing <code>null</code> to this method will set the selection to
150 * the empty element and effectively clear the selection</p>
151 *
152 * @param selection
153 * a T object or <code>null</code> to clear the selection
154 */
155 public void setSelection(T selection) {
156 this.selection = selection;
157
158 Listener[] listeners = combo.getListeners(SWT.Selection);
159
160 for (Listener listener : listeners) {
161 combo.removeListener(SWT.Selection, listener);
162 }
163 int selectedIndex;
164 if(selection == null){
165 // set selection to the emptyElement
166 selectedIndex = 0;
167 }else{
168 selectedIndex = terms.indexOf(selection);
169 if (selectedIndex == -1) {
170 createTermNotInPreferredTerms(selection);
171 selectedIndex = terms.indexOf(selection);
172 }
173 }
174 combo.select(selectedIndex);
175
176 for (Listener listener : listeners) {
177 combo.addListener(SWT.Selection, listener);
178 }
179 }
180
181 /**
182 * Fills the combo with elements and sets up the convenience functions
183 * for selection index
184 *
185 * @param preferredTerms
186 */
187 private void populateTerms(List<T> preferredTerms) {
188
189 combo.removeAll();
190
191 terms = new ArrayList<T>();
192
193 int i = 1;
194 int index = 0;
195
196 if(addEmptyElement){
197 // Add an empty element for when nothing was selected yet
198 combo.add(EMPTY_ELEMENT_LABEL);
199 terms.add(emptyElement);
200 }
201
202 if (termComparator != null) {
203 Collections.sort(preferredTerms, termComparator);
204 }
205 for (T term : preferredTerms) {
206 String label = getLabel(term);
207 if (label == null) {
208 if (term.getTitleCache() != null) {
209 label = term.getTitleCache();
210 MessagingUtils.warn(getClass(),
211 "Term does not have a default language representation: " + label
212 + ", " + term.getUuid());
213 } else {
214 label = "Unknown";
215 MessagingUtils.warn(getClass(),
216 "Representation Label and TitleCache empty for term: "
217 + term + ", " + term.getUuid());
218 }
219
220 }
221
222 combo.add(label);
223 terms.add(term);
224
225 i++;
226 if (selection != null) {
227 if (selection.equals(term)) {
228 index = i;
229 }
230 }
231 }
232
233 if (selection != null && index == 0) {
234 createTermNotInPreferredTerms(selection);
235 }
236
237 combo.select(index);
238 }
239
240 /*
241 * (non-Javadoc)
242 * @see eu.etaxonomy.taxeditor.forms.IEnableableFormElement#setEnabled(boolean)
243 */
244 /** {@inheritDoc} */
245 @Override
246 public void setEnabled(boolean enabled) {
247 combo.setEnabled(enabled);
248 }
249
250 /* (non-Javadoc)
251 * @see eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement#isEnabled()
252 */
253 @Override
254 public boolean isEnabled() {
255 return combo.isEnabled();
256 }
257
258 /**
259 * <p>
260 * preferredTerms
261 * </p>
262 *
263 * @return a {@link java.util.List} object.
264 */
265 protected List<T> getPreferredTerms(){
266 List<T> preferredTerms = new ArrayList<T>();
267 if (customPreferredTerms != null){
268 return customPreferredTerms;
269 }
270 else if(termType!=null){
271 preferredTerms = getTermManager().getPreferredTerms(termType);
272 }
273 else if(termVocabulary!=null){
274 preferredTerms = getTermManager().getPreferredTerms(termVocabulary);
275 }
276 if(termClass!=null){
277 preferredTerms = getTermManager().getPreferredTerms(termClass);
278 }
279 return preferredTerms;
280 }
281
282 /**
283 * May be overridden by derived classes if the desired label string does not
284 * reside in term.getLabel();
285 *
286 * @param term
287 * a T object.
288 * @return a {@link java.lang.String} object.
289 */
290 protected String getLabel(T term) {
291 if (term == null){
292 return "";
293 }else{
294 String termLabel = term.getLabel(CdmStore.getDefaultLanguage());
295 if (termLabel == null){
296 termLabel = term.getLabel();
297 }
298 if(PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOW_VOCABULARY_ID_FOR_TERM_LABELS)
299 && term.getVocabulary()!=null){
300 String vocLabel = term.getVocabulary().getLabel(CdmStore.getDefaultLanguage());
301 if (vocLabel == null){
302 vocLabel = term.getVocabulary().getLabel();
303 }
304 termLabel += " ["+vocLabel+"]";
305 }
306 return termLabel;
307 }
308 }
309
310 /**
311 *
312 *
313 * @param term
314 */
315 private void createTermNotInPreferredTerms(T term) {
316 List<T> preferredTerms = getPreferredTerms();
317
318 preferredTerms.add(term);
319
320 populateTerms(preferredTerms);
321 }
322
323 /**
324 * <p>
325 * addSelectionListener
326 * </p>
327 *
328 * @param listener
329 * a {@link org.eclipse.swt.events.SelectionListener} object.
330 */
331 public void addSelectionListener(SelectionListener listener) {
332 combo.addSelectionListener(listener);
333 }
334
335 /**
336 * <p>
337 * removeSelectionListener
338 * </p>
339 *
340 * @param listener
341 * a {@link org.eclipse.swt.events.SelectionListener} object.
342 */
343 public void removeSelectionListener(SelectionListener listener) {
344 combo.removeSelectionListener(listener);
345 }
346
347 /*
348 * (non-Javadoc)
349 *
350 * @see
351 * org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt
352 * .events.SelectionEvent)
353 */
354 /** {@inheritDoc} */
355 @Override
356 public void widgetSelected(SelectionEvent e) {
357 selection = terms.get(combo.getSelectionIndex());
358 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, e));
359 }
360
361 /*
362 * (non-Javadoc)
363 *
364 * @see java.beans.PropertyChangeListener#propertyChange(java.beans.
365 * PropertyChangeEvent)
366 */
367 /** {@inheritDoc} */
368 @Override
369 public void propertyChange(PropertyChangeEvent event) {
370 super.propertyChange(event);
371 if (event != null
372 && PreferencesUtil.PREFERRED_TERMS_CHANGE.equals(event
373 .getProperty())) {
374 populateTerms(getPreferredTerms());
375 }
376 }
377
378 /** {@inheritDoc} */
379 @Override
380 public void setSelected(boolean selected) {
381 setBackground(selected ? SELECTED : getPersistentBackground());
382 }
383
384 /** {@inheritDoc} */
385 @Override
386 public void widgetDisposed(DisposeEvent e) {
387 PreferencesUtil.getPreferenceStore().removePropertyChangeListener(this);
388 }
389
390 // not used
391 /** {@inheritDoc} */
392 @Override
393 public void widgetDefaultSelected(SelectionEvent e) {
394 }
395
396 /** {@inheritDoc} */
397 @Override
398 public void setIrrelevant(boolean irrelevant) {
399 String colorId = irrelevant ? Resources.COLOR_COMPOSITE_IRRELEVANT
400 : Resources.COLOR_COMPOSITE_BACKGROUND;
401
402 Color color = StoreUtil.getColor(colorId);
403 combo.setBackground(color);
404 }
405
406 /** {@inheritDoc} */
407 @Override
408 public void setBackground(Color color) {
409 if (label != null) {
410 label.setBackground(color);
411 }
412 }
413
414 /**
415 *
416 */
417 protected TermManager getTermManager() {
418 return CdmStore.getTermManager();
419 }
420
421 /**
422 *
423 * @return
424 */
425 public int getVisibleItemCount(){
426 return combo.getVisibleItemCount();
427 }
428
429 /**
430 *
431 * @param count
432 */
433 public void setVisibleItemCount(int count){
434 combo.setVisibleItemCount(count);
435 }
436
437 /**
438 * <p>A {@link List} of term objects may be passed to this combo box. In this case, the default behaviour
439 * of displaying the preferred terms for the T type will be overridden and the combo will only display the
440 * given terms. Also, any previous selection will be reseted.</p>
441 *
442 * <p>To return to the default of displaying the preferred terms, simply pass <code>null</code>.</p>
443 *
444 * @param terms a {@link List} of T objects or <code>null</code> for default preferred terms
445 */
446 public void setTerms(List<T> terms) {
447 setSelection(null);
448 customPreferredTerms = terms;
449 populateTerms(customPreferredTerms);
450 }
451
452 public void removeEmptyElement(){
453 if(addEmptyElement){
454 if(terms.contains(emptyElement)){
455 terms.remove(emptyElement);
456 }
457 if(Arrays.asList(combo.getItems()).contains(EMPTY_ELEMENT_LABEL)){
458 combo.remove(EMPTY_ELEMENT_LABEL);
459 }
460 }
461 }
462 }