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