- generalized simple user interface to add media (#3339)
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / element / AbstractCdmFormElement.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.ui.element;
5
6 import java.util.ConcurrentModificationException;
7 import java.util.HashSet;
8 import java.util.List;
9 import java.util.Set;
10
11 import org.eclipse.core.runtime.Assert;
12 import org.eclipse.jface.util.IPropertyChangeListener;
13 import org.eclipse.jface.util.PropertyChangeEvent;
14 import org.eclipse.swt.graphics.Color;
15 import org.eclipse.swt.widgets.Composite;
16 import org.eclipse.swt.widgets.Control;
17 import org.eclipse.ui.forms.widgets.Section;
18
19 import eu.etaxonomy.taxeditor.model.AbstractUtility;
20 import eu.etaxonomy.taxeditor.model.MessagingUtils;
21
22 /**
23 * <p>Abstract AbstractCdmFormElement class.</p>
24 *
25 * @author n.hoffmann
26 * @version $Id: $
27 */
28 public abstract class AbstractCdmFormElement implements ICdmFormElement {
29
30 protected CdmFormFactory formFactory;
31
32 private List<IPropertyChangeListener> propertyChangeListeners;
33
34 private Composite layoutComposite;
35
36 private final Set<Control> controls = new HashSet<Control>();
37
38 private final Set<ICdmFormElement> elements = new HashSet<ICdmFormElement>();
39 private ICdmFormElement parentElement;
40
41 private Color persistentBackgroundColor;
42
43
44 /**
45 * <p>Constructor for AbstractCdmFormElement.</p>
46 *
47 * @param formFactory a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
48 * @param layoutComposite a {@link org.eclipse.swt.widgets.Composite} object.
49 */
50 protected AbstractCdmFormElement(CdmFormFactory formFactory, Composite layoutComposite){
51 this.layoutComposite = layoutComposite;
52 this.formFactory = formFactory;
53 }
54
55 /**
56 * <p>Constructor for AbstractCdmFormElement.</p>
57 *
58 * @param formFactory a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
59 * @param formElement a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
60 */
61 public AbstractCdmFormElement(CdmFormFactory formFactory, ICdmFormElement formElement) {
62 this(formFactory, formElement.getLayoutComposite());
63 this.parentElement = formElement;
64 // addControl(layoutComposite);
65 }
66
67 @Override
68 public CdmFormFactory getFormFactory() {
69 return formFactory;
70 }
71
72 /**
73 * Delegates the focus to <code>this</code> elements main input control
74 */
75 public void setFocus(){
76 // Override in subclasses where needed
77 }
78
79 /**
80 * Returns all Controls that are managed by this element
81 *
82 * @return a {@link java.util.Set} object.
83 */
84 @Override
85 public Set<Control> getControls(){
86 return controls;
87 }
88
89 /**
90 * adds the control to the set of controls that are managed by this element
91 *
92 * @param child a {@link org.eclipse.swt.widgets.Control} object.
93 */
94 protected void addControl(Control child){
95 controls.add(child);
96 }
97
98 /**
99 * <p>removeControl</p>
100 *
101 * @param child a {@link org.eclipse.swt.widgets.Control} object.
102 */
103 protected void removeControl(Control child){
104 controls.remove(child);
105 }
106
107 /**
108 * <p>Getter for the field <code>elements</code>.</p>
109 *
110 * @return a {@link java.util.Set} object.
111 */
112 @Override
113 public Set<ICdmFormElement> getElements(){
114 return elements;
115 }
116
117 /**
118 * <p>Getter for the field <code>parentElement</code>.</p>
119 *
120 * @return a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
121 */
122 @Override
123 public ICdmFormElement getParentElement(){
124 return parentElement;
125 }
126
127 /** {@inheritDoc} */
128 @Override
129 public void addElement(ICdmFormElement element){
130 elements.add(element);
131 }
132
133 /**
134 * <p>removeElement</p>
135 *
136 * @param element a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
137 */
138 protected void removeElement(ICdmFormElement element){
139 elements.remove(element);
140 }
141
142 /**
143 * Remove all child {@link ICdmFormElement}s and child {@link Control}s
144 * of the given and the element itself.
145 * @param formElement The element to remove
146 */
147 public void removeElementsAndControls(ICdmFormElement formElement){
148 for(ICdmFormElement childElement : formElement.getElements()){
149 // recursion
150 childElement.removeElements();
151
152 // unregister selection arbitrator
153 if(childElement instanceof ISelectableElement){
154 SelectionArbitrator selectionArbitrator = ((ISelectableElement) childElement).getSelectionArbitrator();
155 if(selectionArbitrator != null){
156 formFactory.destroySelectionArbitrator(selectionArbitrator);
157 }
158 }
159
160 // unregister from property changes
161 formFactory.removePropertyChangeListener(childElement);
162
163 // dispose of the controls
164 removeControls(childElement);
165 }
166 removeControls(formElement);
167 }
168
169 /**
170 * Removes all child {@link ICdmFormElement}s and child {@link Control}s
171 * and the element itself.
172 */
173 @Override
174 public void removeElements(){
175 for(ICdmFormElement childElement : getElements()){
176 // recursion
177 childElement.removeElements();
178
179 // unregister selection arbitrator
180 if(childElement instanceof ISelectableElement){
181 SelectionArbitrator selectionArbitrator = ((ISelectableElement) childElement).getSelectionArbitrator();
182 if(selectionArbitrator != null){
183 formFactory.destroySelectionArbitrator(selectionArbitrator);
184 }
185 }
186
187 // unregister from property changes
188 formFactory.removePropertyChangeListener(childElement);
189
190 // dispose of the controls
191 removeControls(childElement);
192 }
193 removeControls(this);
194 elements.clear();
195 }
196
197 private void removeControls(ICdmFormElement element){
198 if(element instanceof Section){
199 ((Section) element).dispose();
200 element = null;
201 }else{
202 for(Control control : element.getControls()){
203 // we added the layoutComposite of the parental element as the layout composite to this formElement
204 // but we do not want to destroy it.
205 if(control.equals(element.getLayoutComposite())){
206 continue;
207 }else{
208 control.dispose();
209 control = null;
210 }
211 }
212 }
213 }
214
215 /**
216 * <p>Getter for the field <code>layoutComposite</code>.</p>
217 *
218 * @return a {@link org.eclipse.swt.widgets.Composite} object.
219 */
220 @Override
221 public Composite getLayoutComposite() {
222 return layoutComposite;
223 }
224
225 /**
226 * <p>Setter for the field <code>layoutComposite</code>.</p>
227 *
228 * @param layoutComposite a {@link org.eclipse.swt.widgets.Composite} object.
229 */
230 public void setLayoutComposite(Composite layoutComposite){
231 this.layoutComposite = layoutComposite;
232 }
233
234 /* (non-Javadoc)
235 * @see eu.etaxonomy.taxeditor.forms.ICdmFormComposite#getPropertyChangeListeners()
236 */
237 /**
238 * <p>Getter for the field <code>propertyChangeListeners</code>.</p>
239 *
240 * @return a {@link java.util.Set} object.
241 */
242 @Override
243 public List<IPropertyChangeListener> getPropertyChangeListeners() {
244 return propertyChangeListeners;
245 }
246
247 /* (non-Javadoc)
248 * @see eu.etaxonomy.taxeditor.forms.ICdmFormComposite#setPropertyChangeListeners(org.eclipse.core.runtime.ListenerList)
249 */
250 /** {@inheritDoc} */
251 @Override
252 public void setPropertyChangeListeners(List<IPropertyChangeListener> propertyChangeListeners){
253 this.propertyChangeListeners = propertyChangeListeners;
254 }
255
256 /* (non-Javadoc)
257 * @see eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent()
258 */
259 /* (non-Javadoc)
260 * @see eu.etaxonomy.taxeditor.forms.ICdmFormComposite#firePropertyChangeEvent(org.eclipse.jface.util.PropertyChangeEvent)
261 */
262 /** {@inheritDoc} */
263 @Override
264 public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
265 //TODO: replace propertyChangeListeners with formFactory.getPropertyChangeListeners() and remove member propertyChangeListeners from AbstractCdmFormElement
266 Assert.isNotNull(propertyChangeListeners, "Property change listeners are not present");
267
268 try{
269 for(Object listener : propertyChangeListeners){
270 ((IPropertyChangeListener)listener).propertyChange(event);
271 }
272 }catch(ConcurrentModificationException e){
273 // There are two cases that produce a CME.
274 // Described here: http://dev.e-taxonomy.eu/trac/ticket/2363#comment:2
275 // and here: http://dev.e-taxonomy.eu/trac/ticket/2438
276 // Ignoring the CME because nothing bad is happening
277 MessagingUtils.warn(getClass(), "ConcurrentModificationException. Can be ignored.");
278 }
279 }
280
281 /**
282 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
283 *
284 * @param object the object on which the property changed
285 */
286 public void firePropertyChangeEvent(Object object){
287 firePropertyChangeEvent(object, null);
288 }
289
290 /**
291 * Fires a {@link CdmPropertyChangeEvent} with the given object as source also containing the
292 * originating event
293 *
294 * @param object the object on which the property changed
295 * @param originatingEvent the originating event
296 */
297 public void firePropertyChangeEvent(Object object, PropertyChangeEvent originatingEvent){
298 firePropertyChangeEvent(new CdmPropertyChangeEvent(object, originatingEvent));
299 }
300
301
302 /**
303 * {@inheritDoc}
304 *
305 * This method gets called whenever the toolkit this composite was created with gets a property change notification.
306 *
307 * It is good advice to check whether the PropertyChangeEvent is destined for the implementing composite.
308 * Implementations should also check for null PropertyChangeEvents and return immediately in that case.
309 * @see eu.etaxonomy.taxeditor.ui.element.ICdmFormElement#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
310 */
311 @Override
312 public void propertyChange(PropertyChangeEvent event) {
313 // implement in subclasses
314 }
315
316 /** {@inheritDoc} */
317 @Override
318 public boolean containsFormElement(ICdmFormElement formElement){
319 if(formElement == this){
320 return true;
321 }else{
322 for(ICdmFormElement element : getElements()){
323 boolean contains = element.containsFormElement(formElement);
324 if(contains == true){
325 return true;
326 }
327 }
328 return false;
329 }
330 }
331
332 /*
333 * (non-Javadoc)
334 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
335 */
336 /**
337 * <p>refresh</p>
338 */
339 @Override
340 public void refresh() {
341 // empty default implementation
342 }
343
344
345 /** {@inheritDoc} */
346 @Override
347 public void setBackground(Color color) {
348 for(ICdmFormElement element : getElements()){
349 element.setBackground(color);
350 }
351 }
352
353 @Override
354 public void setPersistentBackground(Color color) {
355 persistentBackgroundColor = color;
356 setBackground(color);
357 }
358
359 @Override
360 public Color getPersistentBackground() {
361 return persistentBackgroundColor;
362 }
363
364 public Color getColor(String colorId){
365 return AbstractUtility.getColor(colorId);
366 }
367 }