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