Restructure ui.combo package
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / combo / term / TermComboElement.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.ui.combo.term;
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.apache.commons.lang.StringUtils;
13 import org.eclipse.jface.util.PropertyChangeEvent;
14 import org.eclipse.swt.SWT;
15 import org.eclipse.swt.events.SelectionEvent;
16 import org.eclipse.swt.widgets.Listener;
17
18 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
19 import eu.etaxonomy.cdm.model.term.TermType;
20 import eu.etaxonomy.cdm.model.term.TermVocabulary;
21 import eu.etaxonomy.taxeditor.model.MessagingUtils;
22 import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
23 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
24 import eu.etaxonomy.taxeditor.store.CdmStore;
25 import eu.etaxonomy.taxeditor.store.TermManager;
26 import eu.etaxonomy.taxeditor.ui.combo.AbstractComboElement;
27 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
28 import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
29 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
30
31 /**
32 * @author n.hoffmann
33 * @created Nov 5, 2009
34 * @version 1.0
35 * @param <T>
36 */
37 public class TermComboElement<T extends DefinedTermBase>
38 extends AbstractComboElement<T> {
39
40 private T emptyElement;
41 private static String EMPTY_ELEMENT_LABEL = "";
42
43 private ArrayList<T> terms;
44
45 private Comparator<T> termComparator;
46
47 public Comparator<T> getTermComparator() {
48 return termComparator;
49 }
50
51 public void setTermComparator(Comparator<T> termComparator) {
52 this.termComparator = termComparator;
53 List<T> termsWithoutNull = terms.subList(1, terms.size());
54
55 populateTerms(termsWithoutNull);
56
57 }
58
59 private final TermType termType;
60 private final TermVocabulary termVocabulary;
61 private final Class<T> termClass;
62
63 private List<T> customPreferredTerms;
64
65 private boolean useAbbrevLabel = false;
66 private boolean addEmptyElement;
67
68 public TermComboElement(CdmFormFactory formFactory,
69 ICdmFormElement parentElement, TermType termType, String labelString, T selection, boolean addEmptyElement,
70 int style, boolean useAbbrevLabel, Comparator<T> comparator) {
71 this(formFactory, parentElement, null, termType, null, null, labelString, selection, addEmptyElement, style, useAbbrevLabel, comparator);
72 }
73
74 public TermComboElement(CdmFormFactory formFactory,
75 ICdmFormElement parentElement, TermVocabulary<?> termVocabulary, String labelString, T selection, boolean addEmptyElement,
76 int style, boolean useAbbrevLabel, Comparator<T> comparator) {
77 this(formFactory, parentElement, null, null, termVocabulary, null,labelString, selection, addEmptyElement, style, useAbbrevLabel, comparator);
78 }
79
80 public TermComboElement(CdmFormFactory formFactory,
81 ICdmFormElement parentElement, Class<T> termClass, String labelString, T selection, boolean addEmptyElement,
82 int style) {
83 this(formFactory, parentElement, termClass, null, null, null, labelString, selection, addEmptyElement, style, false, null);
84 }
85 public TermComboElement(CdmFormFactory formFactory,
86 ICdmFormElement parentElement, Class<T> termClass, String labelString, T selection, boolean addEmptyElement,
87 int style, boolean useAbbrevLabel) {
88 this(formFactory, parentElement, termClass, null, null, null,labelString, selection, addEmptyElement, style, useAbbrevLabel, null);
89
90 }
91
92 public TermComboElement(CdmFormFactory formFactory,
93 ICdmFormElement parentElement, List<T> terms, String labelString, T selection, boolean addEmptyElement,
94 int style, boolean useAbbrevLabel) {
95 this(formFactory, parentElement, null, null, null, terms,labelString, selection, addEmptyElement, style, useAbbrevLabel, null);
96
97 }
98
99 private TermComboElement(CdmFormFactory formFactory,
100 ICdmFormElement parentElement, Class<T> termClass, TermType termType, TermVocabulary<?> termVocabulary, List<T> terms,String labelString, T selection, boolean addEmptyElement,
101 int style, boolean useAbbrevLabel, Comparator<T> comparator) {
102 super(formFactory, parentElement);
103
104 this.termType = termType;
105 this.termVocabulary = termVocabulary;
106 this.termClass = termClass;
107 this.addEmptyElement = addEmptyElement;
108 this.useAbbrevLabel = useAbbrevLabel;
109 this.termComparator = comparator;
110 if (labelString != null) {
111 label.setText(labelString);
112 }
113 this.selection = selection;
114
115 if(termType!=null){
116 //TODO try to remove generic T and avoid classes to be used
117 populateTerms((List<T>) getTermManager().getPreferredTerms(termType));
118 }
119 else if(termVocabulary!=null){
120 populateTerms((List<T>) getTermManager().getPreferredTerms(termVocabulary));
121 }
122 else if(this.termClass!=null){
123 populateTerms(getPreferredTerms());
124 }else if (terms != null){
125 populateTerms(terms);
126 }
127
128 combo.addSelectionListener(this);
129 combo.addDisposeListener(this);
130 PreferencesUtil.getPreferenceStore().addPropertyChangeListener(this);
131
132 if (selection != null) {
133 setSelection(selection);
134 }
135 }
136
137 /**
138 * <p>Sets the selection of the combo to the given T object.</p>
139 * <p>Passing <code>null</code> to this method will set the selection to
140 * the empty element and effectively clear the selection</p>
141 *
142 * @param selection
143 * a T object or <code>null</code> to clear the selection
144 */
145 @Override
146 public void setSelection(T selection) {
147 this.selection = selection;
148
149 Listener[] listeners = combo.getListeners(SWT.Selection);
150
151 for (Listener listener : listeners) {
152 combo.removeListener(SWT.Selection, listener);
153 }
154 int selectedIndex;
155 if(selection == null){
156 // set selection to the emptyElement
157 selectedIndex = 0;
158 }else{
159 selectedIndex = terms.indexOf(selection);
160 if (selectedIndex == -1) {
161 createTermNotInPreferredTerms(selection, this.terms);
162 selectedIndex = terms.indexOf(selection);
163 }
164 }
165 combo.select(selectedIndex);
166
167 for (Listener listener : listeners) {
168 combo.addListener(SWT.Selection, listener);
169 }
170 }
171
172 /**
173 * Fills the combo with elements and sets up the convenience functions
174 * for selection index
175 *
176 * @param preferredTerms
177 */
178 protected void populateTerms(List<T> preferredTerms) {
179
180 combo.removeAll();
181
182 terms = new ArrayList<T>();
183
184 int i = 1;
185 int index = 0;
186
187 if(addEmptyElement){
188 // Add an empty element for when nothing was selected yet
189 combo.add(EMPTY_ELEMENT_LABEL);
190 terms.add(emptyElement);
191 }
192
193 if (termComparator != null) {
194 Collections.sort(preferredTerms, termComparator);
195 }
196 for (T term : preferredTerms) {
197 String label = getLabel(term);
198 if (label == null) {
199 if (term.getTitleCache() != null) {
200 label = term.getTitleCache();
201 MessagingUtils.warn(getClass(),
202 "Term does not have a default language representation: " + label
203 + ", " + term.getUuid());
204 } else {
205 label = "Unknown";
206 MessagingUtils.warn(getClass(),
207 "Representation Label and TitleCache empty for term: "
208 + term + ", " + term.getUuid());
209 }
210
211 }
212
213 combo.add(label);
214 terms.add(term);
215
216 i++;
217 if (selection != null) {
218 if (selection.equals(term)) {
219 index = i;
220 }
221 }
222 }
223
224 if (selection != null && index == 0) {
225 createTermNotInPreferredTerms(selection, preferredTerms);
226 }
227
228 combo.select(index);
229
230 }
231
232 protected List<T> getPreferredTerms(){
233 List<T> preferredTerms = new ArrayList<T>();
234 if (customPreferredTerms != null){
235 return customPreferredTerms;
236 }
237 else if(termType!=null){
238 preferredTerms = getTermManager().getPreferredTerms(termType);
239 }
240 else if(termVocabulary!=null){
241 preferredTerms = getTermManager().getPreferredTerms(termVocabulary);
242 }
243 if(termClass!=null){
244 preferredTerms = getTermManager().getPreferredTerms(termClass);
245 }
246 return preferredTerms;
247 }
248
249 /**
250 * May be overridden by derived classes if the desired label string does not
251 * reside in term.getLabel();
252 *
253 * @param term
254 * a T object.
255 * @return a {@link java.lang.String} object.
256 */
257 protected String getLabel(T term) {
258 if (term == null){
259 return "";
260 }else{
261 String termLabel = null;
262 if (useAbbrevLabel){
263 if (!StringUtils.isBlank(term.getIdInVocabulary())){
264 termLabel = term.getIdInVocabulary();
265 }
266 }
267 if (termLabel == null){
268 termLabel = term.getLabel(CdmStore.getDefaultLanguage());
269 }
270 if (termLabel == null){
271 termLabel = term.getLabel();
272 }
273 if(PreferencesUtil.getBooleanValue(IPreferenceKeys.SHOW_VOCABULARY_ID_FOR_TERM_LABELS)
274 && term.getVocabulary()!=null){
275 String vocLabel = term.getVocabulary().getLabel(CdmStore.getDefaultLanguage());
276 if (vocLabel == null){
277 vocLabel = term.getVocabulary().getLabel();
278 }
279 termLabel += " ["+vocLabel+"]";
280 }
281 return termLabel;
282 }
283 }
284
285 /**
286 *
287 *
288 * @param term
289 */
290 private void createTermNotInPreferredTerms(T term, List<T> preferredTerms) {
291 //List<T> preferredTerms = getPreferredTerms();
292
293 preferredTerms.add(term);
294
295 populateTerms(preferredTerms);
296 }
297
298 /** {@inheritDoc} */
299 @Override
300 public void widgetSelected(SelectionEvent e) {
301 selection = terms.get(combo.getSelectionIndex());
302 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, e));
303 }
304
305 /** {@inheritDoc} */
306 @Override
307 public void propertyChange(PropertyChangeEvent event) {
308 super.propertyChange(event);
309 T selection = this.selection;
310 if (event != null
311 && PreferencesUtil.PREFERRED_TERMS_CHANGE.equals(event
312 .getProperty())) {
313 populateTerms(getPreferredTerms());
314 }
315 this.setSelection(selection);
316 }
317
318 protected TermManager getTermManager() {
319 return CdmStore.getTermManager();
320 }
321
322 public int getVisibleItemCount(){
323 return combo.getVisibleItemCount();
324 }
325
326 /**
327 * <p>A {@link List} of term objects may be passed to this combo box. In this case, the default behaviour
328 * of displaying the preferred terms for the T type will be overridden and the combo will only display the
329 * given terms. Also, any previous selection will be reseted.</p>
330 *
331 * <p>To return to the default of displaying the preferred terms, simply pass <code>null</code>.</p>
332 *
333 * @param terms a {@link List} of T objects or <code>null</code> for default preferred terms
334 */
335 public void setTerms(List<T> terms) {
336 setSelection(null);
337 customPreferredTerms = terms;
338 populateTerms(customPreferredTerms);
339 }
340
341 public void removeEmptyElement(){
342 if(addEmptyElement){
343 if(terms.contains(emptyElement)){
344 terms.remove(emptyElement);
345 }
346 if(Arrays.asList(combo.getItems()).contains(EMPTY_ELEMENT_LABEL)){
347 combo.remove(EMPTY_ELEMENT_LABEL);
348 }
349 }
350 }
351
352 }