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