4 package eu
.etaxonomy
.taxeditor
.ui
.element
;
6 import java
.util
.ConcurrentModificationException
;
7 import java
.util
.HashSet
;
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
.forms
.events
.ExpansionEvent
;
29 import org
.eclipse
.ui
.forms
.events
.IExpansionListener
;
30 import org
.eclipse
.ui
.forms
.widgets
.Section
;
31 import org
.eclipse
.ui
.forms
.widgets
.TableWrapLayout
;
32 import org
.eclipse
.ui
.forms
.widgets
.ToggleHyperlink
;
34 import eu
.etaxonomy
.cdm
.api
.conversation
.ConversationHolder
;
35 import eu
.etaxonomy
.cdm
.api
.conversation
.IConversationEnabled
;
36 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.CdmDataChangeMap
;
37 import eu
.etaxonomy
.taxeditor
.model
.AbstractUtility
;
38 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
39 import eu
.etaxonomy
.taxeditor
.preference
.PreferencesUtil
;
43 * Abstract super class for a {@link Section} GUI element that visualizes a CDM
44 * entity, manages a conversation and listens to selections
47 * @param <ENTITY> A CDM entity which should be visualized by this section.
50 * @created Feb 22, 2010
54 //TODO shouldn't ENTITY be bound with super class ICdmBase for example (AbstractFormSection<ENTITY extends ICdmBase>)?
55 public abstract class AbstractFormSection
<ENTITY
> extends Section
implements ISelectionChangedListener
, IEntityElement
<ENTITY
>, IConversationEnabled
{
58 * The default number of columns in detail sections
60 public static final int DEFAULT_NUM_COLUMNS
= 2;
62 private ISelectionProvider selectionProvider
;
64 private ENTITY entity
;
66 private final Set
<ICdmFormElement
> elements
= new HashSet
<ICdmFormElement
>();
68 protected CdmFormFactory formFactory
;
70 private List
<IPropertyChangeListener
> propertyChangeListeners
;
72 private ICdmFormElement parentElement
;
74 private Color persistentBackgroundColor
;
78 * Constructor for AbstractFormSection.
86 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
88 * @param parentElement
89 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
94 protected AbstractFormSection(CdmFormFactory formFactory
, ICdmFormElement parentElement
, int style
) {
95 super(parentElement
.getLayoutComposite(), style
);
97 this.parentElement
= parentElement
;
99 this.formFactory
= formFactory
;
101 this.setLayoutData(LayoutConstants
.FILL());
103 Composite client
= formFactory
.createComposite(this, SWT
.WRAP
);
104 client
.setBackgroundMode(SWT
.INHERIT_DEFAULT
);
106 TableWrapLayout layout
= LayoutConstants
.LAYOUT();
107 layout
.bottomMargin
= 10;
108 layout
.rightMargin
= 5;
109 layout
.horizontalSpacing
= 5;
111 client
.setLayout(layout
);
113 this.setClient(client
);
119 * Constructor for AbstractFormSection.
123 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
125 * @param conversation
126 * a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
128 * @param parentElement
129 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
131 * @param selectionProvider
132 * a {@link org.eclipse.jface.viewers.ISelectionProvider} object.
136 protected AbstractFormSection(CdmFormFactory formFactory
, ICdmFormElement parentElement
, ISelectionProvider selectionProvider
, int style
) {
137 this(formFactory
, parentElement
, style
);
138 this.selectionProvider
= selectionProvider
;
143 * Getter for the field <code>propertyChangeListeners</code>.
146 * @return a {@link java.util.Set} object.
149 public List
<IPropertyChangeListener
> getPropertyChangeListeners() {
150 return propertyChangeListeners
;
155 public void setPropertyChangeListeners(
156 List
<IPropertyChangeListener
> propertyChangeListeners
) {
157 this.propertyChangeListeners
= propertyChangeListeners
;
162 * Setter for the field <code>entity</code>.
168 public void setEntity(ENTITY entity
) {
169 this.entity
= entity
;
176 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
180 * Getter for the field <code>entity</code>.
183 * @return a ENTITY object.
186 public ENTITY
getEntity() {
195 * @return a {@link org.eclipse.ui.forms.widgets.ToggleHyperlink} object.
197 public ToggleHyperlink
getToggle() {
206 * @return a {@link eu.etaxonomy.taxeditor.ui.element.AbstractFormSection}
209 public AbstractFormSection
<ENTITY
> getSection() {
217 * eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent
222 public void firePropertyChangeEvent(CdmPropertyChangeEvent event
) {
223 Assert
.isNotNull(propertyChangeListeners
, "No property change listeners.");
225 for (Object listener
: propertyChangeListeners
) {
226 ((IPropertyChangeListener
) listener
).propertyChange(event
);
228 } catch (ConcurrentModificationException e
) {
229 MessagingUtils
.warn(getClass(), "ConcurrentModificationException while handling PropertyChangeEvents."
230 + " It seems like this is not critical");
235 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
238 * the object on which the property changed
240 public void firePropertyChangeEvent(Object object
) {
241 firePropertyChangeEvent(object
, null);
245 * Fires a {@link CdmPropertyChangeEvent} with the given object as source
246 * also containing the originating event
249 * the object on which the property changed
250 * @param originatingEvent
251 * the originating event
253 public void firePropertyChangeEvent(Object object
,
254 PropertyChangeEvent originatingEvent
) {
255 firePropertyChangeEvent(new CdmPropertyChangeEvent(object
,
262 * @see org.eclipse.swt.widgets.Composite#setFocus()
266 public boolean setFocus() {
267 return getClient().setFocus();
274 * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
275 * .jface.util.PropertyChangeEvent)
279 public void propertyChange(PropertyChangeEvent event
) {
280 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event
));
287 * org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics
292 public void setBackground(Color color
) {
293 for (ICdmFormElement element
: getElements()) {
294 element
.setBackground(color
);
296 getLayoutComposite().setBackground(color
);
297 super.setBackground(color
);
301 public void setPersistentBackground(Color color
) {
302 persistentBackgroundColor
= color
;
303 setBackground(color
);
307 public Color
getPersistentBackground() {
308 return persistentBackgroundColor
;
318 * a {@link org.eclipse.swt.events.SelectionEvent} object.
320 public void widgetSelected(SelectionEvent e
) {
321 Widget widget
= e
.widget
;
323 if (widget
instanceof Control
) {
324 Control control
= (Control
) widget
;
325 if (checkControlAncestryForWidget(control
)) {
326 if (getEntity() != null) {
327 IStructuredSelection selection
= new StructuredSelection(getEntity());
328 if (selectionProvider
!= null) {
329 selectionProvider
.setSelection(selection
);
336 private boolean checkControlAncestryForWidget(Control control
) {
337 if (control
.equals(this)) {
340 Control parent
= control
.getParent();
341 if (parent
== null) {
344 return checkControlAncestryForWidget(parent
);
351 public void setSelected(boolean selected
) {
353 setBackground(Display
.getCurrent().getSystemColor(
354 SWT
.COLOR_LIST_SELECTION
));
356 setBackground(Display
.getCurrent().getSystemColor(SWT
.COLOR_WHITE
));
362 public void selectionChanged(SelectionChangedEvent event
) {
363 if (event
.getSelection() == CdmFormFactory
.EMPTY_SELECTION
) {
367 IStructuredSelection selection
= (IStructuredSelection
) event
371 Object selectedObject
= selection
.getFirstElement();
373 if (selectedObject
!= null && selectedObject
.equals(getEntity())) {
380 * addSelectionListener
384 * a {@link org.eclipse.swt.events.SelectionListener} object.
386 public void addSelectionListener(SelectionListener listener
) {
387 addListener(SWT
.Selection
, new TypedListener(listener
));
392 * removeSelectionListener
396 * a {@link org.eclipse.swt.events.SelectionListener} object.
398 public void removeSelectionListener(SelectionListener listener
) {
399 removeListener(SWT
.Selection
, listener
);
404 public void addElement(ICdmFormElement element
) {
405 elements
.add(element
);
414 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
417 protected void removeElement(ICdmFormElement element
) {
418 elements
.remove(element
);
427 public void removeElements() {
428 for (ICdmFormElement childElement
: getElements()) {
430 childElement
.removeElements();
432 // unregister selection arbitrator
433 if (childElement
instanceof ISelectableElement
) {
434 ISelectableElement selectableElement
= (ISelectableElement
) childElement
;
435 if (selectableElement
.getSelectionArbitrator() != null) {
436 formFactory
.destroySelectionArbitrator(selectableElement
437 .getSelectionArbitrator());
441 // unregister propertyChangeListener
442 formFactory
.removePropertyChangeListener(childElement
);
444 // dispose of the controls
445 for (Control control
: childElement
.getControls()) {
446 // we added the layoutComposite of the parental element as the
447 // layout composite to this formElement
448 // but we do not want to destroy it.
449 if (control
.equals(childElement
.getLayoutComposite())) {
463 * Getter for the field <code>parentElement</code>.
466 * @return a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
469 public ICdmFormElement
getParentElement() {
470 return parentElement
;
475 * Getter for the field <code>elements</code>.
478 * @return a {@link java.util.Set} object.
481 public Set
<ICdmFormElement
> getElements() {
490 * @return a {@link java.util.Set} object.
493 public Set
<Control
> getControls() {
494 Set
<Control
> controls
= new HashSet
<Control
>();
496 for (Control control
: getChildren()) {
497 controls
.add(control
);
505 public void dispose() {
515 * @return a {@link org.eclipse.swt.widgets.Composite} object.
518 public Composite
getLayoutComposite() {
519 return (Composite
) getClient();
524 public boolean containsFormElement(ICdmFormElement formElement
) {
525 if (formElement
== this) {
528 for (ICdmFormElement element
: getElements()) {
529 boolean contains
= element
.containsFormElement(formElement
);
530 if (contains
== true) {
540 * Getter for the field <code>formFactory</code>.
543 * @return a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
546 public CdmFormFactory
getFormFactory() {
553 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
561 public void refresh() {
562 // empty default implementation
568 * getConversationHolder
571 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
575 public ConversationHolder
getConversationHolder() {
576 if(AbstractUtility
.getActiveE4Part() instanceof IConversationEnabled
){
577 return ((IConversationEnabled
) AbstractUtility
.getActiveE4Part()).getConversationHolder();
579 if(getParentElement() instanceof RootElement
|| getParentElement() == null){
581 Object activeEditor
= AbstractUtility
.getActiveE4Editor();
582 if(activeEditor
instanceof IConversationEnabled
){
583 ConversationHolder conversation
= ((IConversationEnabled
) AbstractUtility
.getActiveE4Editor()).getConversationHolder();
586 }else if(getParentElement() instanceof IConversationEnabled
){
587 return ((IConversationEnabled
) getParentElement()).getConversationHolder();
589 MessagingUtils
.messageDialog("Could not get conversation for AbstractFormSection",
590 getClass(), "There is an error in the implementation. There should have been an active editor but it wasn't",
591 new IllegalArgumentException());
598 public void update(CdmDataChangeMap changeEvents
) {
602 private class ExpandListener
implements IExpansionListener
{
604 public void expansionStateChanging(ExpansionEvent e
) {
607 public void expansionStateChanged(ExpansionEvent e
) {
608 PreferencesUtil
.getPreferenceStore().setValue(getPrefKey(), e
.getState());
613 * Adds a custom implementation of IExpansionListener to this section
614 * which stores the expansion state in the preferences
616 private void addExpandListener() {
617 PreferencesUtil
.getPreferenceStore().setDefault(getPrefKey(), isExpanded());
618 setExpanded(PreferencesUtil
.getPreferenceStore().getBoolean(getPrefKey()));
619 addExpansionListener(new ExpandListener());
622 private String
getPrefKey() {
623 return this.getClass().getCanonicalName()+";"+entity
.getClass().getCanonicalName();