Project

General

Profile

Download (10.7 KB) Statistics
| Branch: | Tag: | Revision:
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
}
(1-1/4)