(no commit message)
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / element / AbstractFormSection.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.jface.viewers.ISelectionChangedListener;
15 import org.eclipse.jface.viewers.ISelectionProvider;
16 import org.eclipse.jface.viewers.IStructuredSelection;
17 import org.eclipse.jface.viewers.SelectionChangedEvent;
18 import org.eclipse.jface.viewers.StructuredSelection;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.SelectionEvent;
21 import org.eclipse.swt.events.SelectionListener;
22 import org.eclipse.swt.graphics.Color;
23 import org.eclipse.swt.widgets.Composite;
24 import org.eclipse.swt.widgets.Control;
25 import org.eclipse.swt.widgets.Display;
26 import org.eclipse.swt.widgets.TypedListener;
27 import org.eclipse.swt.widgets.Widget;
28 import org.eclipse.ui.IEditorPart;
29 import org.eclipse.ui.forms.widgets.Section;
30 import org.eclipse.ui.forms.widgets.TableWrapLayout;
31 import org.eclipse.ui.forms.widgets.ToggleHyperlink;
32
33 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
34 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
35 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
36 import eu.etaxonomy.taxeditor.store.StoreUtil;
37
38 /**
39 * <p>
40 * Abstract AbstractFormSection class.
41 * </p>
42 *
43 * @author n.hoffmann
44 * @created Feb 22, 2010
45 * @version 1.0
46 * @param <T>
47 */
48 public abstract class AbstractFormSection<ENTITY> extends Section implements
49 ISelectionChangedListener, ICdmFormElement, IEntityElement<ENTITY>,
50 IConversationEnabled {
51
52 private ISelectionProvider selectionProvider;
53
54 private ENTITY entity;
55
56 private Set<ICdmFormElement> elements = new HashSet<ICdmFormElement>();
57
58 protected CdmFormFactory formFactory;
59
60 private List<IPropertyChangeListener> propertyChangeListeners;
61
62 private ICdmFormElement parentElement;
63
64 private Color persistentBackgroundColor;
65
66 /**
67 * <p>
68 * Constructor for AbstractFormSection.
69 * </p>
70 *
71 * @param conversation
72 * TODO
73 * @param style
74 * a int.
75 * @param formFactory
76 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
77 * object.
78 * @param parentElement
79 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
80 * object.
81 * @param <ENTITY>
82 * a ENTITY object.
83 */
84 protected AbstractFormSection(CdmFormFactory formFactory, ICdmFormElement parentElement,
85 int style) {
86 super(parentElement.getLayoutComposite(), style);
87
88 this.parentElement = parentElement;
89
90 this.formFactory = formFactory;
91
92 this.setLayoutData(CdmFormFactory.FILL());
93
94 Composite client = formFactory.createComposite(this, SWT.WRAP);
95 client.setBackgroundMode(SWT.INHERIT_DEFAULT);
96
97 TableWrapLayout layout = CdmFormFactory.LAYOUT();
98 layout.bottomMargin = 10;
99 layout.rightMargin = 5;
100
101 client.setLayout(layout);
102
103 this.setClient(client);
104 }
105
106 /**
107 * <p>
108 * Constructor for AbstractFormSection.
109 * </p>
110 *
111 * @param formFactory
112 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
113 * object.
114 * @param conversation
115 * a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
116 * object.
117 * @param parentElement
118 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
119 * object.
120 * @param selectionProvider
121 * a {@link org.eclipse.jface.viewers.ISelectionProvider} object.
122 * @param style
123 * a int.
124 */
125 protected AbstractFormSection(CdmFormFactory formFactory,
126 ICdmFormElement parentElement,
127 ISelectionProvider selectionProvider, int style) {
128 this(formFactory, parentElement, style);
129 this.selectionProvider = selectionProvider;
130 }
131
132 /**
133 * <p>
134 * Getter for the field <code>propertyChangeListeners</code>.
135 * </p>
136 *
137 * @return a {@link java.util.Set} object.
138 */
139 public List<IPropertyChangeListener> getPropertyChangeListeners() {
140 return propertyChangeListeners;
141 }
142
143 /** {@inheritDoc} */
144 public void setPropertyChangeListeners(
145 List<IPropertyChangeListener> propertyChangeListeners) {
146 this.propertyChangeListeners = propertyChangeListeners;
147 }
148
149 /**
150 * <p>
151 * Setter for the field <code>entity</code>.
152 * </p>
153 *
154 * @param entity
155 * a ENTITY object.
156 */
157 public void setEntity(ENTITY entity) {
158 this.entity = entity;
159 }
160
161 /*
162 * (non-Javadoc)
163 *
164 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
165 */
166 /**
167 * <p>
168 * Getter for the field <code>entity</code>.
169 * </p>
170 *
171 * @return a ENTITY object.
172 */
173 public ENTITY getEntity() {
174 return entity;
175 }
176
177 /**
178 * <p>
179 * getToggle
180 * </p>
181 *
182 * @return a {@link org.eclipse.ui.forms.widgets.ToggleHyperlink} object.
183 */
184 public ToggleHyperlink getToggle() {
185 return this.toggle;
186 }
187
188 /**
189 * <p>
190 * getSection
191 * </p>
192 *
193 * @return a {@link eu.etaxonomy.taxeditor.ui.element.AbstractFormSection}
194 * object.
195 */
196 public AbstractFormSection<ENTITY> getSection() {
197 return this;
198 }
199
200 /*
201 * (non-Javadoc)
202 *
203 * @see
204 * eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent
205 * ()
206 */
207 /** {@inheritDoc} */
208 public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
209 Assert.isNotNull(propertyChangeListeners,
210 "No property change listeners.");
211 try {
212 for (Object listener : propertyChangeListeners) {
213 ((IPropertyChangeListener) listener).propertyChange(event);
214 }
215 } catch (ConcurrentModificationException e) {
216 StoreUtil.warn(getClass(),
217 "ConcurrentModificationException while handling PropertyChangeEvents."
218 + " It seems like this is not critical");
219 }
220 }
221
222 /**
223 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
224 *
225 * @param object
226 * the object on which the property changed
227 */
228 public void firePropertyChangeEvent(Object object) {
229 firePropertyChangeEvent(object, null);
230 }
231
232 /**
233 * Fires a {@link CdmPropertyChangeEvent} with the given object as source
234 * also containing the originating event
235 *
236 * @param object
237 * the object on which the property changed
238 * @param originatingEvent
239 * the originating event
240 */
241 public void firePropertyChangeEvent(Object object,
242 PropertyChangeEvent originatingEvent) {
243 firePropertyChangeEvent(new CdmPropertyChangeEvent(object,
244 originatingEvent));
245 }
246
247 /*
248 * (non-Javadoc)
249 *
250 * @see org.eclipse.swt.widgets.Composite#setFocus()
251 */
252 /** {@inheritDoc} */
253 @Override
254 public boolean setFocus() {
255 return getClient().setFocus();
256 }
257
258 /*
259 * (non-Javadoc)
260 *
261 * @see
262 * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
263 * .jface.util.PropertyChangeEvent)
264 */
265 /** {@inheritDoc} */
266 public void propertyChange(PropertyChangeEvent event) {
267 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event));
268 }
269
270 /*
271 * (non-Javadoc)
272 *
273 * @see
274 * org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics
275 * .Color)
276 */
277 /** {@inheritDoc} */
278 @Override
279 public void setBackground(Color color) {
280 for (ICdmFormElement element : getElements()) {
281 element.setBackground(color);
282 }
283 getLayoutComposite().setBackground(color);
284 super.setBackground(color);
285 }
286
287 @Override
288 public void setPersistentBackground(Color color) {
289 persistentBackgroundColor = color;
290 setBackground(color);
291 }
292
293 @Override
294 public Color getPersistentBackground() {
295 return persistentBackgroundColor;
296 }
297
298
299 /**
300 * <p>
301 * widgetSelected
302 * </p>
303 *
304 * @param e
305 * a {@link org.eclipse.swt.events.SelectionEvent} object.
306 */
307 public void widgetSelected(SelectionEvent e) {
308 Widget widget = e.widget;
309
310 if (widget instanceof Control) {
311 Control control = (Control) widget;
312 if (checkControlAncestryForWidget(control)) {
313 if (getEntity() != null) {
314 IStructuredSelection selection = new StructuredSelection(
315 getEntity());
316 if (selectionProvider != null) {
317 selectionProvider.setSelection(selection);
318 }
319 }
320 }
321 }
322 }
323
324 private boolean checkControlAncestryForWidget(Control control) {
325 if (control.equals(this)) {
326 return true;
327 } else {
328 Control parent = control.getParent();
329 if (parent == null) {
330 return false;
331 } else {
332 return checkControlAncestryForWidget(parent);
333 }
334 }
335 }
336
337 /** {@inheritDoc} */
338 public void setSelected(boolean selected) {
339 if (selected) {
340 setBackground(Display.getCurrent().getSystemColor(
341 SWT.COLOR_LIST_SELECTION));
342 } else {
343 setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
344 }
345 }
346
347 /** {@inheritDoc} */
348 public void selectionChanged(SelectionChangedEvent event) {
349 if (event.getSelection() == CdmFormFactory.EMPTY_SELECTION) {
350 return;
351 }
352
353 IStructuredSelection selection = (IStructuredSelection) event
354 .getSelection();
355 setSelected(false);
356
357 Object selectedObject = selection.getFirstElement();
358
359 if (selectedObject != null && selectedObject.equals(getEntity())) {
360 setSelected(true);
361 }
362 }
363
364 /**
365 * <p>
366 * addSelectionListener
367 * </p>
368 *
369 * @param listener
370 * a {@link org.eclipse.swt.events.SelectionListener} object.
371 */
372 public void addSelectionListener(SelectionListener listener) {
373 addListener(SWT.Selection, new TypedListener(listener));
374 }
375
376 /**
377 * <p>
378 * removeSelectionListener
379 * </p>
380 *
381 * @param listener
382 * a {@link org.eclipse.swt.events.SelectionListener} object.
383 */
384 public void removeSelectionListener(SelectionListener listener) {
385 removeListener(SWT.Selection, listener);
386 }
387
388 /** {@inheritDoc} */
389 public void addElement(ICdmFormElement element) {
390 elements.add(element);
391 }
392
393 /**
394 * <p>
395 * removeElement
396 * </p>
397 *
398 * @param element
399 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
400 * object.
401 */
402 protected void removeElement(ICdmFormElement element) {
403 elements.remove(element);
404 }
405
406 /**
407 * <p>
408 * removeElements
409 * </p>
410 */
411 public void removeElements() {
412 for (ICdmFormElement childElement : getElements()) {
413 // recursion
414 childElement.removeElements();
415
416 // unregister selection arbitrator
417 if (childElement instanceof ISelectableElement) {
418 ISelectableElement selectableElement = (ISelectableElement) childElement;
419 if (selectableElement != null
420 && selectableElement.getSelectionArbitrator() != null) {
421 formFactory.destroySelectionArbitrator(selectableElement
422 .getSelectionArbitrator());
423 }
424 }
425
426 // unregister propertyChangeListener
427 formFactory.removePropertyChangeListener(childElement);
428
429 // dispose of the controls
430 for (Control control : childElement.getControls()) {
431 // we added the layoutComposite of the parental element as the
432 // layout composite to this formElement
433 // but we do not want to destroy it.
434 if (control.equals(childElement.getLayoutComposite())) {
435 continue;
436 } else {
437 control.dispose();
438 control = null;
439 }
440 }
441 }
442
443 elements.clear();
444 }
445
446 /**
447 * <p>
448 * Getter for the field <code>parentElement</code>.
449 * </p>
450 *
451 * @return a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
452 */
453 public ICdmFormElement getParentElement() {
454 return parentElement;
455 }
456
457 /**
458 * <p>
459 * Getter for the field <code>elements</code>.
460 * </p>
461 *
462 * @return a {@link java.util.Set} object.
463 */
464 public Set<ICdmFormElement> getElements() {
465 return elements;
466 }
467
468 /**
469 * <p>
470 * getControls
471 * </p>
472 *
473 * @return a {@link java.util.Set} object.
474 */
475 public Set<Control> getControls() {
476 Set<Control> controls = new HashSet<Control>();
477
478 for (Control control : getChildren()) {
479 controls.add(control);
480 }
481
482 return controls;
483 }
484
485 /** {@inheritDoc} */
486 @Override
487 public void dispose() {
488 removeElements();
489 super.dispose();
490 }
491
492 /**
493 * <p>
494 * getLayoutComposite
495 * </p>
496 *
497 * @return a {@link org.eclipse.swt.widgets.Composite} object.
498 */
499 public Composite getLayoutComposite() {
500 return (Composite) getClient();
501 }
502
503 /** {@inheritDoc} */
504 public boolean containsFormElement(ICdmFormElement formElement) {
505 if (formElement == this) {
506 return true;
507 } else {
508 for (ICdmFormElement element : getElements()) {
509 boolean contains = element.containsFormElement(formElement);
510 if (contains == true) {
511 return true;
512 }
513 }
514 return false;
515 }
516 }
517
518 /**
519 * <p>
520 * Getter for the field <code>formFactory</code>.
521 * </p>
522 *
523 * @return a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
524 */
525 public CdmFormFactory getFormFactory() {
526 return formFactory;
527 }
528
529 /*
530 * (non-Javadoc)
531 *
532 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
533 */
534 /**
535 * <p>
536 * refresh
537 * </p>
538 */
539 public void refresh() {
540 // empty default implementation
541
542 }
543
544 /**
545 * <p>
546 * getConversationHolder
547 * </p>
548 *
549 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
550 * object.
551 */
552 public ConversationHolder getConversationHolder() {
553 if(getParentElement() instanceof RootElement || getParentElement() == null){
554
555 IEditorPart activeEditor = StoreUtil.getActiveEditor();
556 if(activeEditor instanceof IConversationEnabled){
557 ConversationHolder conversation = ((IConversationEnabled) StoreUtil.getActiveEditor()).getConversationHolder();
558 return conversation;
559 }
560 }else if(getParentElement() instanceof IConversationEnabled){
561 return ((IConversationEnabled) getParentElement()).getConversationHolder();
562 }
563 StoreUtil.errorDialog("Could not get conversation for AbstractFormSection",
564 getClass(), "There is an error in the implementation. There should have been an active editor but it wasn't",
565 new IllegalArgumentException());
566 return null;
567
568 }
569
570 /** {@inheritDoc} */
571 public void update(CdmDataChangeMap changeEvents) {
572 }
573
574
575 }