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