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