2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.taxeditor
.ui
.element
;
11 import java
.util
.ConcurrentModificationException
;
12 import java
.util
.HashSet
;
13 import java
.util
.Iterator
;
14 import java
.util
.List
;
17 import org
.eclipse
.core
.runtime
.Assert
;
18 import org
.eclipse
.jface
.util
.IPropertyChangeListener
;
19 import org
.eclipse
.jface
.util
.PropertyChangeEvent
;
20 import org
.eclipse
.jface
.viewers
.ISelectionChangedListener
;
21 import org
.eclipse
.jface
.viewers
.ISelectionProvider
;
22 import org
.eclipse
.jface
.viewers
.IStructuredSelection
;
23 import org
.eclipse
.jface
.viewers
.SelectionChangedEvent
;
24 import org
.eclipse
.jface
.viewers
.StructuredSelection
;
25 import org
.eclipse
.swt
.SWT
;
26 import org
.eclipse
.swt
.events
.SelectionEvent
;
27 import org
.eclipse
.swt
.events
.SelectionListener
;
28 import org
.eclipse
.swt
.graphics
.Color
;
29 import org
.eclipse
.swt
.widgets
.Composite
;
30 import org
.eclipse
.swt
.widgets
.Control
;
31 import org
.eclipse
.swt
.widgets
.Display
;
32 import org
.eclipse
.swt
.widgets
.TypedListener
;
33 import org
.eclipse
.swt
.widgets
.Widget
;
34 import org
.eclipse
.ui
.forms
.widgets
.Section
;
35 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
36 import org
.eclipse
.ui
.forms
.widgets
.ToggleHyperlink
;
38 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
39 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
40 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
44 * Abstract super class for a {@link Section} GUI element that visualizes a CDM
45 * entity, manages a conversation and listens to selections
48 * @param <ENTITY> A CDM entity which should be visualized by this section.
51 * @created Feb 22, 2010
53 //TODO shouldn't ENTITY be bound with super class ICdmBase for example (AbstractFormSection<ENTITY extends ICdmBase>)?
54 public abstract class AbstractFormSection
<ENTITY
>
56 implements ISelectionChangedListener
, IEntityElement
<ENTITY
> {
59 * The default number of columns in detail sections
61 public static final int DEFAULT_NUM_COLUMNS
= 2;
63 private ISelectionProvider selectionProvider
;
65 private ENTITY entity
;
67 private final Set
<ICdmFormElement
> elements
= new HashSet
<>();
69 protected CdmFormFactory formFactory
;
71 private List
<IPropertyChangeListener
> propertyChangeListeners
;
73 private ICdmFormElement parentElement
;
75 private Color persistentBackgroundColor
;
78 * Constructor for AbstractFormSection.
80 protected AbstractFormSection(CdmFormFactory formFactory
, ICdmFormElement parentElement
, int style
) {
81 super(parentElement
.getLayoutComposite(), style
);
83 this.parentElement
= parentElement
;
85 this.formFactory
= formFactory
;
87 this.setLayoutData(LayoutConstants
.FILL());
89 Composite client
= formFactory
.createComposite(this, SWT
.WRAP
);
90 client
.setBackgroundMode(SWT
.INHERIT_DEFAULT
);
92 TableWrapLayout layout
= LayoutConstants
.LAYOUT();
93 layout
.bottomMargin
= 10;
94 layout
.rightMargin
= 5;
95 layout
.horizontalSpacing
= 5;
97 client
.setLayout(layout
);
99 this.setClient(client
);
103 * Constructor for AbstractFormSection.
105 protected AbstractFormSection(CdmFormFactory formFactory
, ICdmFormElement parentElement
, ISelectionProvider selectionProvider
, int style
) {
106 this(formFactory
, parentElement
, style
);
107 this.selectionProvider
= selectionProvider
;
111 * Getter for the field <code>propertyChangeListeners</code>.
114 public List
<IPropertyChangeListener
> getPropertyChangeListeners() {
115 return propertyChangeListeners
;
119 public void setPropertyChangeListeners(
120 List
<IPropertyChangeListener
> propertyChangeListeners
) {
121 this.propertyChangeListeners
= propertyChangeListeners
;
125 public ENTITY
getEntity() {
128 public void setEntity(ENTITY entity
) {
129 this.entity
= entity
;
132 public ToggleHyperlink
getToggle() {
136 public AbstractFormSection
<ENTITY
> getSection() {
141 public void firePropertyChangeEvent(CdmPropertyChangeEvent event
) {
142 Assert
.isNotNull(propertyChangeListeners
, "No property change listeners.");
144 for (Object listener
: propertyChangeListeners
) {
145 ((IPropertyChangeListener
) listener
).propertyChange(event
);
147 } catch (ConcurrentModificationException e
) {
148 MessagingUtils
.warn(getClass(), "ConcurrentModificationException while handling PropertyChangeEvents."
149 + " It seems like this is not critical");
154 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
157 * the object on which the property changed
159 public void firePropertyChangeEvent(Object object
) {
160 firePropertyChangeEvent(object
, null);
164 * Fires a {@link CdmPropertyChangeEvent} with the given object as source
165 * also containing the originating event
168 * the object on which the property changed
169 * @param originatingEvent
170 * the originating event
172 public void firePropertyChangeEvent(Object object
,
173 PropertyChangeEvent originatingEvent
) {
174 firePropertyChangeEvent(new CdmPropertyChangeEvent(object
,
179 public boolean setFocus() {
180 return getClient().setFocus();
184 public void propertyChange(PropertyChangeEvent event
) {
185 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event
));
189 public void setBackground(Color color
) {
190 for (ICdmFormElement element
: getElements()) {
191 element
.setBackground(color
);
193 if (!getLayoutComposite().isDisposed()){
194 getLayoutComposite().setBackground(color
);
196 super.setBackground(color
);
200 public void setPersistentBackground(Color color
) {
201 persistentBackgroundColor
= color
;
202 setBackground(color
);
206 public Color
getPersistentBackground() {
207 return persistentBackgroundColor
;
210 public void widgetSelected(SelectionEvent e
) {
211 Widget widget
= e
.widget
;
213 if (widget
instanceof Control
) {
214 Control control
= (Control
) widget
;
215 if (checkControlAncestryForWidget(control
)) {
216 if (getEntity() != null) {
217 IStructuredSelection selection
= new StructuredSelection(getEntity());
218 if (selectionProvider
!= null) {
219 selectionProvider
.setSelection(selection
);
226 private boolean checkControlAncestryForWidget(Control control
) {
227 if (control
.equals(this)) {
230 Control parent
= control
.getParent();
231 if (parent
== null) {
234 return checkControlAncestryForWidget(parent
);
240 public void setSelected(boolean selected
) {
242 setBackground(Display
.getCurrent().getSystemColor(
243 SWT
.COLOR_LIST_SELECTION
));
245 setBackground(Display
.getCurrent().getSystemColor(SWT
.COLOR_WHITE
));
250 public void selectionChanged(SelectionChangedEvent event
) {
251 if (event
.getSelection() == CdmFormFactory
.EMPTY_SELECTION
) {
255 IStructuredSelection selection
= (IStructuredSelection
) event
259 Object selectedObject
= selection
.getFirstElement();
261 if (selectedObject
!= null && selectedObject
.equals(getEntity())) {
266 public void addSelectionListener(SelectionListener listener
) {
267 addListener(SWT
.Selection
, new TypedListener(listener
));
270 public void removeSelectionListener(SelectionListener listener
) {
271 removeListener(SWT
.Selection
, listener
);
275 public void addElement(ICdmFormElement element
) {
276 elements
.add(element
);
279 protected void removeElement(ICdmFormElement element
) {
280 elements
.remove(element
);
284 public void removeElements() {
285 for (Iterator
<ICdmFormElement
> formElementIterator
= getElements().iterator();formElementIterator
.hasNext();) {
286 ICdmFormElement childElement
= formElementIterator
.next();
288 childElement
.removeElements();
290 // unregister selection arbitrator
291 if (childElement
instanceof ISelectableElement
) {
292 ISelectableElement selectableElement
= (ISelectableElement
) childElement
;
293 if (selectableElement
.getSelectionArbitrator() != null) {
294 formFactory
.destroySelectionArbitrator(selectableElement
295 .getSelectionArbitrator());
299 // unregister propertyChangeListener
300 formFactory
.removePropertyChangeListener(childElement
);
302 // dispose of the controls
303 for (Iterator
<Control
> controlIterator
= childElement
.getControls().iterator();controlIterator
.hasNext();) {
304 Control control
= controlIterator
.next();
305 // we added the layoutComposite of the parental element as the
306 // layout composite to this formElement
307 // but we do not want to destroy it.
308 if (control
.equals(childElement
.getLayoutComposite())) {
321 * Getter for the field <code>parentElement</code>.
324 public ICdmFormElement
getParentElement() {
325 return parentElement
;
329 * Getter for the field <code>elements</code>.
332 public Set
<ICdmFormElement
> getElements() {
337 public Set
<Control
> getControls() {
338 Set
<Control
> controls
= new HashSet
<>();
340 for (Control control
: getChildren()) {
341 controls
.add(control
);
348 public void dispose() {
354 public Composite
getLayoutComposite() {
355 return (Composite
) getClient();
359 public boolean containsFormElement(ICdmFormElement formElement
) {
360 if (formElement
== this) {
363 for (ICdmFormElement element
: getElements()) {
364 boolean contains
= element
.containsFormElement(formElement
);
365 if (contains
== true) {
374 * Getter for the field <code>formFactory</code>.
377 public CdmFormFactory
getFormFactory() {
382 public void refresh() {
383 // empty default implementation