minor
[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 /** {@inheritDoc} */
257 @Override
258 public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
259 //TODO: replace propertyChangeListeners with formFactory.getPropertyChangeListeners() and remove member propertyChangeListeners from AbstractCdmFormElement
260 Assert.isNotNull(propertyChangeListeners, "Property change listeners are not present");
261
262 try{
263 for(Object listener : propertyChangeListeners){
264 ((IPropertyChangeListener)listener).propertyChange(event);
265 }
266 }catch(ConcurrentModificationException e){
267 // There are two cases that produce a CME.
268 // Described here: http://dev.e-taxonomy.eu/trac/ticket/2363#comment:2
269 // and here: http://dev.e-taxonomy.eu/trac/ticket/2438
270 // Ignoring the CME because nothing bad is happening
271 MessagingUtils.warn(getClass(), "ConcurrentModificationException. Can be ignored.");
272 }
273 }
274
275 /**
276 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
277 *
278 * @param object the object on which the property changed
279 */
280 public void firePropertyChangeEvent(Object object){
281 firePropertyChangeEvent(object, null);
282 }
283
284 /**
285 * Fires a {@link CdmPropertyChangeEvent} with the given object as source also containing the
286 * originating event
287 *
288 * @param object the object on which the property changed
289 * @param originatingEvent the originating event
290 */
291 public void firePropertyChangeEvent(Object object, PropertyChangeEvent originatingEvent){
292 firePropertyChangeEvent(new CdmPropertyChangeEvent(object, originatingEvent));
293 }
294
295
296 /**
297 * {@inheritDoc}
298 *
299 * This method gets called whenever the toolkit this composite was created with gets a property change notification.
300 *
301 * It is good advice to check whether the PropertyChangeEvent is destined for the implementing composite.
302 * Implementations should also check for null PropertyChangeEvents and return immediately in that case.
303 * @see eu.etaxonomy.taxeditor.ui.element.ICdmFormElement#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
304 */
305 @Override
306 public void propertyChange(PropertyChangeEvent event) {
307 // implement in subclasses
308 }
309
310 /** {@inheritDoc} */
311 @Override
312 public boolean containsFormElement(ICdmFormElement formElement){
313 if(formElement == this){
314 return true;
315 }else{
316 for(ICdmFormElement element : getElements()){
317 boolean contains = element.containsFormElement(formElement);
318 if(contains == true){
319 return true;
320 }
321 }
322 return false;
323 }
324 }
325
326 /*
327 * (non-Javadoc)
328 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
329 */
330 /**
331 * <p>refresh</p>
332 */
333 @Override
334 public void refresh() {
335 // empty default implementation
336 }
337
338
339 /** {@inheritDoc} */
340 @Override
341 public void setBackground(Color color) {
342 for(ICdmFormElement element : getElements()){
343 element.setBackground(color);
344 }
345 }
346
347 @Override
348 public void setPersistentBackground(Color color) {
349 persistentBackgroundColor = color;
350 setBackground(color);
351 }
352
353 @Override
354 public Color getPersistentBackground() {
355 return persistentBackgroundColor;
356 }
357
358 public Color getColor(String colorId){
359 return AbstractUtility.getColor(colorId);
360 }
361 }