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