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