- extracted design and layout of GUI objects from AbstractCdmFormElement to be able...
authorPatric Plitzner <p.plitzner@bgbm.org>
Thu, 1 Aug 2013 11:30:05 +0000 (11:30 +0000)
committerPatric Plitzner <p.plitzner@bgbm.org>
Thu, 1 Aug 2013 11:30:05 +0000 (11:30 +0000)
    - specifically tested it for GatheringEventDetailElement

19 files changed:
.gitattributes
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmFormElementComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractEntityCollectionElementComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractFormSection.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/CdmFormFactory.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/NumberWithLabelElement.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/NumberWithLabelElementComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelElement2.java [deleted file]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailElement.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailElementComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailSection.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractEntityCollectionSection.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/ICdmDetailElement.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionSourceComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailElementComposite.java [new file with mode: 0644]
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailSection.java
eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/detail/CdmSectionPart.java
eu.etaxonomy.taxeditor.store/src/main/java/org/eclipse/wb/swt/SWTResourceManager.java [new file with mode: 0644]

index 0689b0531a2409510d6bcd97b1d2cb387e189d6e..2855efc25e4f91279e2719a329df645d31876d46 100644 (file)
@@ -1256,7 +1256,9 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/dialog/sele
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/dialog/selection/UserSelectionDialog.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmEntityWizardPage.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmFormElement.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmFormElementComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmFormElementWithErrors.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractEntityCollectionElementComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractFormSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/BrowserElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/CdmFormFactory.java -text
@@ -1281,13 +1283,14 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/Lan
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/LayoutConstants.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/MultilanguageTextElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/NumberWithLabelElement.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/NumberWithLabelElementComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/PartialElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/PointElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/RootElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/SelectionArbitrator.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextActionElement.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelElement.java -text
-eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelElement2.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TimePeriodElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/ToggleableTextElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/UriWithLabelElement.java -text
@@ -1307,11 +1310,13 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/password/Ed
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/password/PasswordWizard.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/password/PasswordWizardPage.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailElement.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailElementComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractEntityCollectionElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractEntityCollectionSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractIdentifiableEntityDetailElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/EmptyElement.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/ICdmDetailElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/ITaxonBaseDetailSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/agent/InstitutionDetailElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/agent/InstitutionDetailSection.java -text
@@ -1342,6 +1347,7 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/des
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionElementMediaSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionElementSourceElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionElementSourceSection.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionSourceComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionSourceElement.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionSourceSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/GeoScopeElement.java -text
@@ -1432,6 +1438,7 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occ
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/FieldObservationDetailSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/FieldObservationWizardPage.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailElement.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailElementComposite.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailSection.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventWizardPage.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GeneralDetailElement.java -text
@@ -1522,6 +1529,7 @@ eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/detail/De
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/reporting/ReportingViewPart.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/supplementaldata/SupplementalDataViewPart.java -text
 eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/view/supplementaldata/SupplementalDataViewer.java -text
+eu.etaxonomy.taxeditor.store/src/main/java/org/eclipse/wb/swt/SWTResourceManager.java -text
 eu.etaxonomy.taxeditor.store/src/main/resources/eu/etaxonomy/cdm/editorApplicationContext.xml -text
 eu.etaxonomy.taxeditor.store/src/main/resources/log4j.properties -text
 eu.etaxonomy.taxeditor.store/src/test/java/eu/etaxonomy/taxeditor/store/NameProtectTitleCacheTest.java -text
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmFormElementComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractCdmFormElementComposite.java
new file mode 100644 (file)
index 0000000..81cf6a6
--- /dev/null
@@ -0,0 +1,330 @@
+package eu.etaxonomy.taxeditor.ui.element;
+
+import java.util.ConcurrentModificationException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.Section;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+
+public class AbstractCdmFormElementComposite extends Composite implements ICdmFormElement {
+
+       protected CdmFormFactory formFactory;
+
+       private final Set<Control> controls = new HashSet<Control>();
+
+       private final Set<ICdmFormElement> elements = new HashSet<ICdmFormElement>();
+       private final ICdmFormElement parentElement;
+
+       private Color persistentBackgroundColor;
+
+       /**
+        * Create the composite.
+        * @param parent
+        * @param style
+        */
+       public AbstractCdmFormElementComposite(Composite parent, final FormToolkit formFactory, ICdmFormElement parentFormElement, int style) {
+               super(parent, style);
+
+               this.parentElement = parentFormElement;
+               if(formFactory instanceof CdmFormFactory){
+                   this.formFactory = (CdmFormFactory) formFactory;
+               }
+
+               TableWrapLayout twl_layoutComposite = new TableWrapLayout();
+               twl_layoutComposite.numColumns = 2;
+               this.setLayout(twl_layoutComposite);
+
+//             addDisposeListener(new DisposeListener() {
+//                     @Override
+//            public void widgetDisposed(DisposeEvent e) {
+//                         formFactory.dispose();
+//                     }
+//             });
+//             formFactory.adapt(this);
+//             formFactory.paintBordersFor(this);
+       }
+       /**
+        * <p>Getter for the field <code>formFactory</code>.</p>
+        *
+        * @return a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
+        */
+       public CdmFormFactory getFormFactory() {
+               return formFactory;
+       }
+
+
+       /**
+        * Returns all Controls that are managed by this element
+        *
+        * @return a {@link java.util.Set} object.
+        */
+       @Override
+    public Set<Control> getControls(){
+               return controls;
+       }
+
+       /**
+        * adds the control to the set of controls that are managed by this element
+        *
+        * @param child a {@link org.eclipse.swt.widgets.Control} object.
+        */
+       protected void addControl(Control child){
+               controls.add(child);
+       }
+
+       /**
+        * <p>removeControl</p>
+        *
+        * @param child a {@link org.eclipse.swt.widgets.Control} object.
+        */
+       protected void removeControl(Control child){
+               controls.remove(child);
+       }
+
+       /**
+        * <p>Getter for the field <code>elements</code>.</p>
+        *
+        * @return a {@link java.util.Set} object.
+        */
+       @Override
+    public Set<ICdmFormElement> getElements(){
+               return elements;
+       }
+
+       /**
+        * <p>Getter for the field <code>parentElement</code>.</p>
+        *
+        * @return a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
+        */
+       @Override
+    public ICdmFormElement getParentElement(){
+               return parentElement;
+       }
+
+       /** {@inheritDoc} */
+       @Override
+    public void addElement(ICdmFormElement element){
+               elements.add(element);
+       }
+
+       /**
+        * <p>removeElement</p>
+        *
+        * @param element a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
+        */
+       protected void removeElement(ICdmFormElement element){
+               elements.remove(element);
+       }
+
+       /**
+        * <p>removeElements</p>
+        */
+       @Override
+    public void removeElements(){
+               for(ICdmFormElement childElement : getElements()){
+                       // recursion
+                       childElement.removeElements();
+
+                       // unregister selection arbitrator
+                       if(childElement instanceof ISelectableElement){
+                               SelectionArbitrator selectionArbitrator = ((ISelectableElement) childElement).getSelectionArbitrator();
+                               if(selectionArbitrator != null){
+                                       formFactory.destroySelectionArbitrator(selectionArbitrator);
+                               }
+                       }
+
+                       // unregister from property changes
+                       formFactory.removePropertyChangeListener(childElement);
+
+                       // dispose of the controls
+                       removeControls(childElement);
+               }
+               removeControls(this);
+               elements.clear();
+       }
+
+       private void removeControls(ICdmFormElement element){
+               if(element instanceof Section){
+                       ((Section) element).dispose();
+                       element = null;
+               }else{
+                       for(Control control : element.getControls()){
+                               // we added the layoutComposite of the parental element as the layout composite to this formElement
+                               // but we do not want to destroy it.
+                               if(control.equals(element.getLayoutComposite())){
+                                       continue;
+                               }else{
+                                       control.dispose();
+                                       control = null;
+                               }
+                       }
+               }
+       }
+
+       /**
+        * <p>Getter for the field <code>layoutComposite</code>.</p>
+        *
+        * @return a {@link org.eclipse.swt.widgets.Composite} object.
+        */
+       @Override
+    public Composite getLayoutComposite() {
+               return this;
+       }
+
+       /**
+        * <p>Setter for the field <code>layoutComposite</code>.</p>
+        *
+        * @param layoutComposite a {@link org.eclipse.swt.widgets.Composite} object.
+        */
+       public void setLayoutComposite(Composite layoutComposite){
+           //removed layoutComposite
+//             this.layoutComposite = layoutComposite;
+       }
+
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.taxeditor.forms.ICdmFormComposite#getPropertyChangeListeners()
+        */
+       /**
+        * <p>Getter for the field <code>propertyChangeListeners</code>.</p>
+        *
+        * @return a {@link java.util.Set} object.
+        */
+       @Override
+    public List<IPropertyChangeListener> getPropertyChangeListeners() {
+               return formFactory.getPropertyChangeListeners();
+       }
+
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.taxeditor.forms.ICdmFormComposite#setPropertyChangeListeners(org.eclipse.core.runtime.ListenerList)
+        */
+       /** {@inheritDoc} */
+       @Override
+    public void setPropertyChangeListeners(List<IPropertyChangeListener> propertyChangeListeners){
+           //TODO: remove method
+               // listeners are already set in factory. no need for them here
+       }
+
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent()
+        */
+       /* (non-Javadoc)
+        * @see eu.etaxonomy.taxeditor.forms.ICdmFormComposite#firePropertyChangeEvent(org.eclipse.jface.util.PropertyChangeEvent)
+        */
+       /** {@inheritDoc} */
+       @Override
+    public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
+               Assert.isNotNull(formFactory.getPropertyChangeListeners(), "Property change listeners are not present");
+
+               try{
+                       for(Object listener : formFactory.getPropertyChangeListeners()){
+                               ((IPropertyChangeListener)listener).propertyChange(event);
+                       }
+               }catch(ConcurrentModificationException e){
+                       // There are two cases that produce a CME.
+                       // Described here: http://dev.e-taxonomy.eu/trac/ticket/2363#comment:2
+                       // and here: http://dev.e-taxonomy.eu/trac/ticket/2438
+                       // Ignoring the CME because nothing bad is happening
+                       AbstractUtility.warn(getClass(), "ConcurrentModificationException. Can be ignored.");
+               }
+       }
+
+       /**
+        * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
+        *
+        * @param object the object on which the property changed
+        */
+       public void firePropertyChangeEvent(Object object){
+               firePropertyChangeEvent(object, null);
+       }
+
+       /**
+        * Fires a {@link CdmPropertyChangeEvent} with the given object as source also containing the
+        * originating event
+        *
+        * @param object the object on which the property changed
+        * @param originatingEvent the originating event
+        */
+       public void firePropertyChangeEvent(Object object, PropertyChangeEvent originatingEvent){
+               firePropertyChangeEvent(new CdmPropertyChangeEvent(object, originatingEvent));
+       }
+
+
+       /**
+        * {@inheritDoc}
+        *
+        * This method gets called whenever the toolkit this composite was created with gets a property change notification.
+        *
+        * It is good advice to check whether the PropertyChangeEvent is destined for the implementing composite.
+        * Implementations should also check for null PropertyChangeEvents and return immediately in that case.
+        * @see eu.etaxonomy.taxeditor.ui.element.ICdmFormElement#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+        */
+       @Override
+    public void propertyChange(PropertyChangeEvent event) {
+               // implement in subclasses
+       }
+
+       /** {@inheritDoc} */
+       @Override
+    public boolean containsFormElement(ICdmFormElement formElement){
+               if(formElement == this){
+                       return true;
+               }else{
+                       for(ICdmFormElement element : getElements()){
+                               boolean contains = element.containsFormElement(formElement);
+                               if(contains == true){
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+       }
+
+       /*
+        * (non-Javadoc)
+        * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
+        */
+       /**
+        * <p>refresh</p>
+        */
+       @Override
+    public void refresh() {
+               // empty default implementation
+       }
+
+
+       /** {@inheritDoc} */
+       @Override
+       public void setBackground(Color color) {
+               for(ICdmFormElement element : getElements()){
+                       element.setBackground(color);
+               }
+               super.setBackground(color);
+       }
+
+       @Override
+       public void setPersistentBackground(Color color) {
+               persistentBackgroundColor = color;
+               setBackground(color);
+       }
+
+       @Override
+       public Color getPersistentBackground() {
+               return persistentBackgroundColor;
+       }
+
+       public Color getColor(String colorId){
+               return AbstractUtility.getColor(colorId);
+       }
+
+}
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractEntityCollectionElementComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/AbstractEntityCollectionElementComposite.java
new file mode 100644 (file)
index 0000000..c83b4c7
--- /dev/null
@@ -0,0 +1,229 @@
+package eu.etaxonomy.taxeditor.ui.element;
+
+import org.eclipse.jface.resource.ResourceManager;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+
+public abstract class AbstractEntityCollectionElementComposite<ENTITY>
+       extends AbstractCdmFormElementComposite
+       implements IEntityElement<ENTITY>, SelectionListener, IConversationEnabled {
+
+       protected ENTITY entity;
+
+       private final Composite container;
+
+       private final Composite box;
+
+       private final Button button_remove;
+
+       private Color backgroundColor;
+
+    /**
+     * Create the composite.
+     *
+     * @param parent
+     * @param style
+     */
+    public AbstractEntityCollectionElementComposite(Composite parent, ICdmFormElement parentFormElement, FormToolkit formFactory, ENTITY entity, SelectionListener removeListener, int style) {
+        super(parent, parentFormElement, style);
+
+        box = formFactory.createComposite(parent);
+        box.setBackgroundMode(SWT.INHERIT_DEFAULT);
+        addControl(box);
+
+        TableWrapLayout boxLayout = LayoutConstants.LAYOUT(2, false);
+        boxLayout.topMargin = 4;
+        boxLayout.bottomMargin = 4;
+        box.setLayout(boxLayout);
+
+        box.setLayoutData(LayoutConstants.FILL_HORIZONTALLY());
+
+        container = formFactory.createComposite(box);
+        container.setBackgroundMode(SWT.INHERIT_DEFAULT);
+
+        setLayoutComposite(container);
+
+        addControl(container);
+        Layout containerLayout = LayoutConstants.LAYOUT(2, false);
+
+        container.setLayout(containerLayout);
+        container.setLayoutData(LayoutConstants.FILL_HORIZONTALLY());
+
+        // if (removeListener != null) {
+        button_remove = formFactory.createButton(box, null, SWT.PUSH);
+        addControl(button_remove);
+        button_remove.setLayoutData(LayoutConstants.RIGHT());
+        button_remove.setImage(ResourceManager.getPluginImage("eu.etaxonomy.taxeditor.store", "icons/trash.gif"));
+        button_remove.setToolTipText("Remove");
+//        button_remove.addSelectionListener(removeListener);
+        // }
+
+        createControls(this, style);
+        setEntity(entity);
+
+    }
+
+       /**
+        * Init gets executed before any other setup of the section takes place
+        *
+        * Implement this if you want to configure the section
+        */
+       public void init() {
+               // default implementation is empty
+       }
+
+       /**
+        * <p>
+        * Setter for the field <code>entity</code>.
+        * </p>
+        *
+        * @param entity
+        *            a ENTITY object.
+        */
+       public abstract void setEntity(ENTITY entity);
+
+       /**
+        * <p>
+        * Getter for the field <code>entity</code>.
+        * </p>
+        *
+        * @return a ENTITY object.
+        */
+       @Override
+    public ENTITY getEntity() {
+               return entity;
+       }
+
+       /**
+        * <p>
+        * createControls
+        * </p>
+        *
+        * @param element
+        *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
+        *            object.
+        * @param style
+        *            a int.
+        */
+       public abstract void createControls(ICdmFormElement element, int style);
+
+       /**
+        * Mark <code>this</code> element as selected.
+        */
+       @Override
+    public void setSelected(boolean selected) {
+
+               for (ICdmFormElement element : getElements()) {
+                       if (element instanceof ISelectable) {
+                               ((ISelectable) element).setSelected(selected);
+                       }
+               }
+               setBackground(selected ? SELECTED : getPersistentBackground());
+       }
+
+       /*
+        * (non-Javadoc)
+        *
+        * @see
+        * eu.etaxonomy.taxeditor.forms.AbstractCdmFormElement#propertyChange(org
+        * .eclipse.jface.util.PropertyChangeEvent)
+        */
+       /** {@inheritDoc} */
+       @Override
+       public void propertyChange(PropertyChangeEvent event) {
+               if (event == null) {
+                       return;
+               }
+               Object eventSource = event.getSource();
+               if (getElements().contains(eventSource)) {
+                       handleEvent(eventSource);
+               }
+       }
+
+       /**
+        * <p>
+        * handleEvent
+        * </p>
+        *
+        * @param eventSource
+        *            a {@link java.lang.Object} object.
+        */
+       public abstract void handleEvent(Object eventSource);
+
+       /** {@inheritDoc} */
+       @Override
+    public void setBackground(Color color) {
+               backgroundColor = color;
+               super.setBackground(backgroundColor);
+               box.setBackground(backgroundColor);
+               container.setBackground(backgroundColor);
+       }
+
+       /**
+        * {@inheritDoc}
+        *
+        * React when selection occurs
+        */
+       @Override
+    public void widgetSelected(SelectionEvent e) {
+
+       }
+
+       /** {@inheritDoc} */
+       @Override
+    public void widgetDefaultSelected(SelectionEvent e) {
+       }
+
+       /** {@inheritDoc} */
+       @Override
+       public Composite getLayoutComposite() {
+               return container;
+       }
+
+       /**
+        * <p>
+        * Getter for the field <code>backgroundColor</code>.
+        * </p>
+        *
+        * @return the backgroundColor
+        */
+       public Color getBackgroundColor() {
+               return backgroundColor;
+       }
+
+       /**
+        * <p>
+        * getConversationHolder
+        * </p>
+        *
+        * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
+        *         object.
+        */
+       @Override
+    public ConversationHolder getConversationHolder() {
+               if (getParentElement() instanceof IConversationEnabled) {
+                       return ((IConversationEnabled) getParentElement())
+                                       .getConversationHolder();
+               }
+               throw new IllegalArgumentException(
+                               "Parent element should be IConversationEnabled");
+       }
+
+       /** {@inheritDoc} */
+       @Override
+    public void update(CdmDataChangeMap changeEvents) {
+       }
+
+}
index cece9928bba24c05f590518a3603b11d2651c766..9679087c3bd9d6ae41f04bfae1d98e320494ebe8 100644 (file)
@@ -49,9 +49,7 @@ import eu.etaxonomy.taxeditor.model.AbstractUtility;
  * @param <T>
  */
 //TODO shouldn't ENTITY be bound with super class ICdmBase for example (AbstractFormSection<ENTITY extends ICdmBase>)?
-public abstract class AbstractFormSection<ENTITY> extends Section implements
-               ISelectionChangedListener, IEntityElement<ENTITY>,
-               IConversationEnabled {
+public abstract class AbstractFormSection<ENTITY> extends Section implements ISelectionChangedListener, IEntityElement<ENTITY>, IConversationEnabled {
 
        private ISelectionProvider selectionProvider;
 
index 408e0acfea307c29a39237870be66c0eaa3639d0..62d0740e44bb2618884007f585d501671c9764d7 100644 (file)
@@ -203,6 +203,7 @@ import eu.etaxonomy.taxeditor.ui.section.occurrence.DeterminationHistoryDetailSe
 import eu.etaxonomy.taxeditor.ui.section.occurrence.FieldObservationDetailElement;
 import eu.etaxonomy.taxeditor.ui.section.occurrence.FieldObservationDetailSection;
 import eu.etaxonomy.taxeditor.ui.section.occurrence.GatheringEventDetailElement;
+import eu.etaxonomy.taxeditor.ui.section.occurrence.GatheringEventDetailElementComposite;
 import eu.etaxonomy.taxeditor.ui.section.occurrence.GatheringEventDetailSection;
 import eu.etaxonomy.taxeditor.ui.section.occurrence.GeneralDetailElement;
 import eu.etaxonomy.taxeditor.ui.section.occurrence.GeneralDetailSection;
@@ -397,13 +398,6 @@ public class CdmFormFactory extends FormToolkit {
         }
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public void adapt(Composite composite) {
-        composite.addMouseListener(selectionMouseHandler);
-        super.adapt(composite);
-    }
-
     /**
      * <p>
      * Adapts the {@link AbstractCdmFormElement}:<br>
@@ -419,6 +413,12 @@ public class CdmFormFactory extends FormToolkit {
         formElement.setPropertyChangeListeners(propertyChangeListeners);
     }
 
+    public void adapt(AbstractCdmFormElementComposite formElement) {
+        formElement.setPropertyChangeListeners(propertyChangeListeners);
+    }
+
+
+
     /** {@inheritDoc} */
     @Override
     public void adapt(Control control, boolean trackFocus, boolean trackKeyboard) {
@@ -428,6 +428,13 @@ public class CdmFormFactory extends FormToolkit {
         super.adapt(control, trackFocus, trackKeyboard);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public void adapt(Composite composite) {
+        composite.addMouseListener(selectionMouseHandler);
+        super.adapt(composite);
+    }
+
     /**
      * <p>
      * destroyElement
@@ -1164,6 +1171,13 @@ public class CdmFormFactory extends FormToolkit {
         propertyChangeListeners.remove(listener);
     }
 
+    /**
+     * @return the propertyChangeListeners
+     */
+    public List<IPropertyChangeListener> getPropertyChangeListeners() {
+        return propertyChangeListeners;
+    }
+
     /**
      * <p>
      * createHorizontalSeparator
@@ -1764,6 +1778,13 @@ public class CdmFormFactory extends FormToolkit {
         return element;
     }
 
+    public GatheringEventDetailElementComposite createGatheringEventDetailElementComposite(ICdmFormElement parentElement) {
+        GatheringEventDetailElementComposite element = new GatheringEventDetailElementComposite(parentElement.getLayoutComposite(), this, parentElement, SWT.NONE);
+        adapt(element);
+        parentElement.addElement(element);
+        return element;
+    }
+
     public FieldObservationDetailElement createFieldObservationDetailElement(ICdmFormElement parentElement) {
         FieldObservationDetailElement element = new FieldObservationDetailElement(this, parentElement);
         addAndAdaptElement(parentElement, element);
@@ -2264,4 +2285,41 @@ public class CdmFormFactory extends FormToolkit {
         return text;
     }
 
+    /**
+     * @param formFactory
+     * @param parentElement
+     * @param element
+     */
+    private static void addAndAdapt(FormToolkit formFactory, ICdmFormElement parentElement, TextWithLabelComposite element) {
+        if(formFactory instanceof CdmFormFactory){
+            ((CdmFormFactory) formFactory).adapt(element);
+            parentElement.addElement(element);
+        }
+    }
+    /**
+     * @wbp.factory
+     * @wbp.factory.parameter.source formFactory formFactory
+     * @wbp.factory.parameter.source parentFormElement parentFormElement
+     * @wbp.factory.parameter.source labelString "Elevation Minimum (m)"
+     * @wbp.factory.parameter.source initialText (java.lang.String) null
+     * @wbp.factory.parameter.source textHeight (java.lang.Integer) null
+     * @wbp.factory.parameter.source style 0
+     */
+    public static TextWithLabelComposite createTextWithLabelComposite(Composite parent, FormToolkit formFactory, ICdmFormElement parentFormElement, String labelString, String initialText, Integer textHeight, int style) {
+        TextWithLabelComposite textWithLabelComposite = new TextWithLabelComposite(parent, formFactory, parentFormElement, labelString, initialText, textHeight, style);
+//        addAndAdapt(formFactory, parentFormElement, textWithLabelComposite);
+        return textWithLabelComposite;
+    }
+    /**
+     * @wbp.factory
+     * @wbp.factory.parameter.source formFactory getFormFactory()
+     * @wbp.factory.parameter.source parentElement parentFormElement
+     * @wbp.factory.parameter.source labelString "Elevation Minimum (m)"
+     * @wbp.factory.parameter.source initialFloat new java.lang.Float(0)
+     * @wbp.factory.parameter.source style org.eclipse.swt.SWT.NONE
+     */
+    public static NumberWithLabelElementComposite createNumberWithLabelElementComposite(Composite parent, FormToolkit formFactory, ICdmFormElement parentElement, String labelString, Float initialFloat, int style) {
+        NumberWithLabelElementComposite numberWithLabelElementComposite = new NumberWithLabelElementComposite(parent, formFactory, parentElement, labelString, initialFloat, style);
+        return numberWithLabelElementComposite;
+    }
 }
index eab43db6772d2cbfd646e48ef84aa47a030f5540..3f95afc3a70a04dd2f1b0d5882117553aa29e6e5 100644 (file)
@@ -1,9 +1,9 @@
 // $Id$
 /**
 * Copyright (C) 2007 EDIT
-* European Distributed Institute of Taxonomy 
+* European Distributed Institute of Taxonomy
 * http://www.e-taxonomy.eu
-* 
+*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * See LICENSE.TXT at the top of this package for the full license terms.
 */
@@ -28,7 +28,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
 
        private Float start;
        private Float end;
-       
+
        private NumberFormatException exception;
 
        /**
@@ -46,7 +46,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
                super(toolkit, parentElement, labelString, null, null, style);
                setInteger(initialInteger);
        }
-       
+
        /**
         * <p>Constructor for NumberWithLabelElement.</p>
         *
@@ -62,7 +62,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
                super(toolkit, parentElement, labelString, null, null, style);
                setFloat(initialFloat);
        }
-       
+
        /**
         * <p>setInteger</p>
         *
@@ -71,7 +71,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
        public void setInteger(Integer number) {
                super.setText(getStringRepresentation(number));
        }
-       
+
        /**
         * <p>setFloat</p>
         *
@@ -80,7 +80,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
        public void setFloat(Float number) {
                super.setText(getStringRepresentation(number));
        }
-       
+
        /**
         * <p>getInteger</p>
         *
@@ -90,7 +90,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
                String text = super.getText().trim();
                return text.equals("") ? 0 : new Integer(text);
        }
-       
+
        /**
         * <p>getFloat</p>
         *
@@ -100,14 +100,14 @@ public class NumberWithLabelElement extends TextWithLabelElement {
                String text = super.getText();
                return new Float(text);
        }
-       
+
        private String getStringRepresentation(Object number){
                if(number != null){
                        return number.toString();
-               }               
+               }
                return null;
        }
-       
+
        /* (non-Javadoc)
         * @see eu.etaxonomy.taxeditor.forms.AbstractCdmFormElement#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
         */
@@ -119,27 +119,28 @@ public class NumberWithLabelElement extends TextWithLabelElement {
                        text.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
                        return;
                }
-               
+
                try{
-                       
+
                        Float number = Float.parseFloat(value);
-                       
+
                        if((start != null && number < start) || (end != null && number > end)){
                                throw new NumberFormatException("You entered a number that is not within the allowed bounds.");
                        }
-                       
+
                }catch(NumberFormatException e){
                        text.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
                        firePropertyChangeEvent(new CdmPropertyChangeEvent(this, e));
+                       exception = e;
                        return;
                }
-               
+
                exception = null;
                text.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
-               
+
                super.modifyText(event);
        }
-       
+
        /**
         * <p>setLimits</p>
         *
@@ -150,7 +151,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
        public void setLimits(int numberOfDigits, Integer start, Integer end){
                setLimits(numberOfDigits, start.floatValue(), end.floatValue());
        }
-       
+
        /**
         * <p>setLimits</p>
         *
@@ -163,7 +164,7 @@ public class NumberWithLabelElement extends TextWithLabelElement {
                this.start = start;
                this.end = end;
        }
-       
+
        /**
         * <p>Getter for the field <code>exception</code>.</p>
         *
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/NumberWithLabelElementComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/NumberWithLabelElementComposite.java
new file mode 100644 (file)
index 0000000..a80e02b
--- /dev/null
@@ -0,0 +1,173 @@
+// $Id$
+/**
+* Copyright (C) 2013 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.ui.element;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import eu.etaxonomy.cdm.common.CdmUtils;
+
+/**
+ * @author pplitzner
+ * @date 31.07.2013
+ *
+ */
+public class NumberWithLabelElementComposite extends TextWithLabelComposite{
+
+    private Float start;
+    private Float end;
+
+    private NumberFormatException exception;
+
+    /**
+     * <p>Constructor for NumberWithLabelElement.</p>
+     *
+     * @param toolkit a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
+     * @param parentElement a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
+     * @param labelString a {@link java.lang.String} object.
+     * @param initialInteger a {@link java.lang.Integer} object.
+     * @param style a int.
+     */
+    public NumberWithLabelElementComposite(Composite parent, FormToolkit formFactory, ICdmFormElement parentFormElement,
+            String labelString, Integer initialInteger, int style){
+        this(parent, formFactory, parentFormElement, labelString, new Float(initialInteger), style);
+    }
+
+    /**
+     * <p>Constructor for NumberWithLabelElement.</p>
+     *
+     * @param toolkit a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
+     * @param parentElement a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
+     * @param labelString a {@link java.lang.String} object.
+     * @param initialFloat a {@link java.lang.Float} object.
+     * @param style a int.
+     * @wbp.parser.constructor
+     */
+    public NumberWithLabelElementComposite(Composite parent, FormToolkit formFactory,
+            ICdmFormElement parentElement, String labelString,
+            Float initialFloat, int style) {
+        super(parent, formFactory, parentElement, labelString, null, null, style);
+        setFloat(initialFloat);
+    }
+
+    /**
+     * <p>setInteger</p>
+     *
+     * @param number a {@link java.lang.Integer} object.
+     */
+    public void setInteger(Integer number) {
+        super.setText(getStringRepresentation(number));
+    }
+
+    /**
+     * <p>setFloat</p>
+     *
+     * @param number a {@link java.lang.Float} object.
+     */
+    public void setFloat(Float number) {
+        super.setText(getStringRepresentation(number));
+    }
+
+    /**
+     * <p>getInteger</p>
+     *
+     * @return a {@link java.lang.Integer} object.
+     */
+    public Integer getInteger() {
+        String text = super.getText().trim();
+        return text.equals("") ? 0 : new Integer(text);
+    }
+
+    /**
+     * <p>getFloat</p>
+     *
+     * @return a {@link java.lang.Float} object.
+     */
+    public Float getFloat(){
+        String text = super.getText();
+        return new Float(text);
+    }
+
+    private String getStringRepresentation(Object number){
+        if(number != null){
+            return number.toString();
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see eu.etaxonomy.taxeditor.forms.AbstractCdmFormElement#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
+     */
+    /** {@inheritDoc} */
+    @Override
+    public void modifyText(ModifyEvent event) {
+        String value = text.getText();
+        if(CdmUtils.isEmpty(value)){
+            text.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+            return;
+        }
+
+        try{
+
+            Float number = Float.parseFloat(value);
+
+            if((start != null && number < start) || (end != null && number > end)){
+                throw new NumberFormatException("You entered a number that is not within the allowed bounds.");
+            }
+
+        }catch(NumberFormatException e){
+            text.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
+            firePropertyChangeEvent(new CdmPropertyChangeEvent(this, e));
+            exception = e;
+            return;
+        }
+
+        exception = null;
+        text.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+
+        super.modifyText(event);
+    }
+
+    /**
+     * <p>setLimits</p>
+     *
+     * @param numberOfDigits a int.
+     * @param start a {@link java.lang.Integer} object.
+     * @param end a {@link java.lang.Integer} object.
+     */
+    public void setLimits(int numberOfDigits, Integer start, Integer end){
+        setLimits(numberOfDigits, start.floatValue(), end.floatValue());
+    }
+
+    /**
+     * <p>setLimits</p>
+     *
+     * @param numberOfDigits a int.
+     * @param start a {@link java.lang.Float} object.
+     * @param end a {@link java.lang.Float} object.
+     */
+    public void setLimits(int numberOfDigits, Float start, Float end){
+        text.setTextLimit(numberOfDigits);
+        this.start = start;
+        this.end = end;
+    }
+
+    /**
+     * <p>Getter for the field <code>exception</code>.</p>
+     *
+     * @return the exception
+     */
+    public NumberFormatException getException() {
+        return exception;
+    }
+}
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelComposite.java
new file mode 100644 (file)
index 0000000..e2a7ba5
--- /dev/null
@@ -0,0 +1,223 @@
+// $Id$
+/**
+* Copyright (C) 2013 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.ui.element;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.wb.swt.SWTResourceManager;
+
+import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.taxeditor.preference.Resources;
+
+/**
+ * @author pplitzner
+ * @date 23.07.2013
+ *
+ */
+public class TextWithLabelComposite extends AbstractCdmFormElementComposite implements ModifyListener, IEnableableFormElement, ISelectable {
+
+    protected Text text;
+    private final Label label;
+
+    /** Constant <code>MAX_HEIGHT=0</code> */
+    public static final int MAX_HEIGHT = 0;
+    /** Constant <code>SINGLE=-1</code> */
+    public static final int SINGLE = -1;
+
+    /**
+     *
+     *
+     */
+    public TextWithLabelComposite(Composite parent, FormToolkit formFactory, ICdmFormElement parentFormElement, String labelString,
+            String initialText, Integer textHeight, int style) {
+        super(parent, formFactory, parentFormElement, style);
+        setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+
+        //vvvvvvvvvvvvv
+
+        initialText = initialText==null?"":initialText;
+
+        int scrollStyle = textHeight == null ? SWT.NULL : (SWT.V_SCROLL | SWT.MULTI);
+
+        int combinedStyle = style | SWT.BORDER | scrollStyle;
+
+        // SWT.PASSWORD does not work when SWT.WRAP is set.
+        if (style != SWT.PASSWORD) {
+            combinedStyle = combinedStyle | SWT.WRAP;
+        }
+        //^^^^^^^^^^^^^^
+
+        label = new Label(this, SWT.NONE);
+        TableWrapData twd_lblNewLabel = new TableWrapData(TableWrapData.RIGHT, TableWrapData.TOP);
+        twd_lblNewLabel.grabHorizontal = true;
+        twd_lblNewLabel.align = TableWrapData.LEFT;
+        label.setLayoutData(twd_lblNewLabel);
+        label.setText(labelString);
+
+        text = new Text(this, SWT.NONE);
+        TableWrapData twd_text_1 = new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.TOP);
+        twd_text_1.align = TableWrapData.RIGHT;
+        twd_text_1.grabHorizontal = false;
+        text.setText(initialText);
+        text.setLayoutData(twd_text_1);
+
+
+        //vvvvvvvvvvvvvvvvvv
+        if (textHeight == null) {
+            text.addKeyListener(new KeyAdapter() {
+                @Override
+                public void keyPressed(KeyEvent e) {
+                    if (e.character == SWT.CR) {
+                        // Don't accept carriage returns as input when in single
+                        // line mode
+                        e.doit = false;
+                    } else if (e.character == SWT.TAB) {
+                        // traverse is not working for wrapped text widgets so
+                        // we reintroduce it here
+                        e.doit = false;
+                        TextWithLabelComposite.this.text.traverse(SWT.TRAVERSE_TAB_NEXT);
+                    }
+                }
+            });
+        }
+
+        TableWrapData layoutData = LayoutConstants.FILL();
+        if (textHeight != null && textHeight > 0) {
+            (layoutData).heightHint = textHeight;
+        }
+
+        text.setLayoutData(layoutData);
+
+        text.addModifyListener(this);
+
+        addControl(label);
+        addControl(text);
+    }
+
+
+    /**
+     * Get the text of this composites text composite
+     *
+     * @return a {@link java.lang.String} object.
+     */
+    public String getText() {
+        return text.getText();
+    }
+
+    /**
+     * Set the text of this composites text composite
+     *
+     * @param string
+     *            a {@link java.lang.String} object.
+     */
+    public void setText(String string) {
+        Listener[] listeners = text.getListeners(SWT.Modify);
+
+        for (Listener listener : listeners) {
+            text.removeListener(SWT.Modify, listener);
+        }
+
+        text.setText(CdmUtils.Nz(string));
+
+        for (Listener listener : listeners) {
+            text.addListener(SWT.Modify, listener);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events
+     * .ModifyEvent)
+     */
+    /** {@inheritDoc} */
+    @Override
+    public void modifyText(ModifyEvent e) {
+        firePropertyChangeEvent(new CdmPropertyChangeEvent(this, e));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setEnabled(boolean enabled) {
+        text.setEnabled(enabled);
+        String symbolicName = enabled ? Resources.COLOR_FONT_DEFAULT : Resources.COLOR_TEXT_DISABLED;
+        text.setForeground(getColor(symbolicName));
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setIrrelevant(boolean irrelevant) {
+        String colorId = irrelevant ? Resources.COLOR_COMPOSITE_IRRELEVANT : Resources.COLOR_COMPOSITE_BACKGROUND;
+
+        Color color = getColor(colorId);
+        text.setBackground(color);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setBackground(Color color) {
+        super.setBackground(color);
+        if (label != null) {
+            label.setBackground(color);
+        }
+    }
+
+    @Override
+    public void setSelected(boolean selected) {
+        setBackground(selected ? SELECTED : getPersistentBackground());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see eu.etaxonomy.taxeditor.forms.AbstractCdmFormElement#setFocus()
+     */
+    /** {@inheritDoc}
+     * @return */
+    @Override
+    public boolean setFocus() {
+        return text.setFocus();
+    }
+
+    /**
+     * <p>
+     * getMainControl
+     * </p>
+     *
+     * @return a {@link org.eclipse.swt.widgets.Control} object.
+     */
+    public Control getMainControl() {
+        return text;
+    }
+
+    /**
+     * <p>
+     * setTextLimit
+     * </p>
+     *
+     * @param limit
+     *            a int.
+     */
+    public void setTextLimit(int limit) {
+        text.setTextLimit(limit);
+    }
+}
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelElement2.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/element/TextWithLabelElement2.java
deleted file mode 100644 (file)
index 8837628..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// $Id$
-/**
-* Copyright (C) 2013 EDIT
-* European Distributed Institute of Taxonomy
-* http://www.e-taxonomy.eu
-*
-* The contents of this file are subject to the Mozilla Public License Version 1.1
-* See LICENSE.TXT at the top of this package for the full license terms.
-*/
-package eu.etaxonomy.taxeditor.ui.element;
-
-import org.eclipse.swt.widgets.Composite;
-
-/**
- * @author pplitzner
- * @date 11.06.2013
- *
- */
-public class TextWithLabelElement2 extends Composite {
-
-    /**
-     * Create the composite.
-     * @param parent
-     * @param style
-     */
-    public TextWithLabelElement2(Composite parent, int style) {
-        super(parent, style);
-
-    }
-
-    @Override
-    protected void checkSubclass() {
-        // Disable the check that prevents subclassing of SWT components
-    }
-}
index 4704d2b24f15e6283effeb2466a3e75cee169197..3450dd889c5cfbf4538885b2b98853d3e1b475cf 100644 (file)
@@ -27,7 +27,6 @@ import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
 import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
 import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
-import eu.etaxonomy.taxeditor.ui.element.IEntityElement;
 
 /**
  * <p>
@@ -38,7 +37,7 @@ import eu.etaxonomy.taxeditor.ui.element.IEntityElement;
  * @created Feb 26, 2010
  * @version 1.0
  */
-public abstract class AbstractCdmDetailElement<T> extends AbstractCdmFormElement implements IEntityElement<T>, IEnableableFormElement, IConversationEnabled {
+public abstract class AbstractCdmDetailElement<T> extends AbstractCdmFormElement implements ICdmDetailElement<T> {
 
        private T entity;
 
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailElementComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/AbstractCdmDetailElementComposite.java
new file mode 100644 (file)
index 0000000..de28154
--- /dev/null
@@ -0,0 +1,300 @@
+// $Id$
+/**
+* Copyright (C) 2013 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.ui.section;
+
+import java.util.Collection;
+
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.ui.element.AbstractCdmFormElementComposite;
+import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
+import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
+import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
+import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
+
+/**
+ * @author pplitzner
+ * @date 25.07.2013
+ *
+ */
+public abstract class AbstractCdmDetailElementComposite<T> extends AbstractCdmFormElementComposite implements ICdmDetailElement<T>{
+
+    private T entity;
+
+    private boolean irrelevant;
+
+    /**
+     * <p>
+     * Constructor for AbstractCdmDetailElement.
+     * </p>
+     *
+     * @param formFactory
+     *            a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
+     *            object.
+     * @param formElement
+     *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
+     *            object.
+     * @param <T>
+     *            a T object.
+     */
+    public AbstractCdmDetailElementComposite(Composite parent, FormToolkit formFactory, ICdmFormElement parentFormElement, int style) {
+        super(parent, formFactory, parentFormElement, style);
+        // register as property change listener
+        if(formFactory instanceof CdmFormFactory){
+            ((CdmFormFactory) formFactory).addPropertyChangeListener(this);
+        }
+    }
+
+    /**
+     * Sets the entity and updates controls
+     *
+     * @param entity
+     *            a T object.
+     */
+    @Override
+    public void setEntity(T entity) {
+        this.entity = entity;
+        updateContent();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
+     */
+    /**
+     * <p>
+     * Getter for the field <code>entity</code>.
+     * </p>
+     *
+     * @return a T object.
+     */
+    @Override
+    public T getEntity() {
+        return entity;
+    }
+
+    /**
+     * Updates all widgets to display the latest data
+     */
+    protected void updateContent() {
+        removeElements();
+        createControls(this, entity, SWT.WRAP);
+        getLayoutComposite().layout();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see
+     * eu.etaxonomy.taxeditor.forms.ISelectableComposite#setSelected(boolean)
+     */
+    /** {@inheritDoc} */
+    @Override
+    public void setSelected(boolean selected) {
+        Composite section = getLayoutComposite().getParent();
+        section.setBackground(selected ? SELECTED : getPersistentBackground());
+    }
+
+    /**
+     * Sets all field to the given enablement state except the objects in
+     * collection except
+     *
+     * @see eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement#setEnabled(boolean)
+     * @param enabled
+     *            a boolean.
+     * @param except
+     *            a {@link java.util.Collection} object.
+     */
+    public void setEnabled(boolean enabled, Collection<Object> except) {
+        for (ICdmFormElement element : getElements()) {
+            if (element instanceof IEnableableFormElement) {
+                IEnableableFormElement enableableElement = (IEnableableFormElement) element;
+                if (except != null && except.contains(enableableElement)) {
+                    // enableableElement.setEnabled(enabled);
+                } else {
+                    enableableElement.setEnabled(enabled);
+                }
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Setter for the field <code>irrelevant</code>.
+     * </p>
+     *
+     * @param irrelevant
+     *            a boolean.
+     * @param except
+     *            a {@link java.util.Collection} object.
+     */
+    public void setIrrelevant(boolean irrelevant, Collection<Object> except) {
+        // logger.warn("Setting " + this.getClass().getSimpleName() +
+        // " to irrelevant state: " + irrelevant);
+        for (ICdmFormElement element : getElements()) {
+            if (element instanceof IEnableableFormElement) {
+                IEnableableFormElement relevantElement = (IEnableableFormElement) element;
+                if (except != null && except.contains(relevantElement)) {
+                    // do nothing
+                    // logger.warn("not setting elements irrelevance: " +
+                    // relevantElement.getClass().getSimpleName() + " in :" +
+                    // this.getClass().getSimpleName());
+                } else {
+                    relevantElement.setIrrelevant(irrelevant);
+                }
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setEnabled(boolean enabled) {
+        setEnabled(enabled, null);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setIrrelevant(boolean irrelevant) {
+        this.irrelevant = irrelevant;
+        setIrrelevant(irrelevant, null);
+    }
+
+    /**
+     * Create all content elements
+     *
+     * @param formElement
+     *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
+     *            object.
+     * @param entity
+     *            a T object.
+     * @param style
+     *            a int.
+     */
+    protected abstract void createControls(ICdmFormElement formElement, T entity, int style);
+
+    /** {@inheritDoc} */
+    @Override
+    public void propertyChange(PropertyChangeEvent event) {
+        if (event == null) {
+            return;
+        }
+
+        handleTitleCacheRelevantChange(event);
+
+        Object eventSource = event.getSource();
+
+        if (eventSource instanceof ICdmFormElement) {
+            ICdmFormElement eventElement = (ICdmFormElement) eventSource;
+            ICdmFormElement eventElementContainer = eventElement
+                    .getParentElement();
+
+            if (eventElementContainer == this) {
+                if (event instanceof CdmPropertyChangeEvent) {
+                    if (((CdmPropertyChangeEvent) event).hasException()) {
+                        handleException((CdmPropertyChangeEvent) event);
+                        return;
+                    }
+                }
+                // call specific handler implementation
+                handleEvent(eventSource);
+                // refire the event
+                firePropertyChangeEvent(this, event);
+                // update possible parents
+                updateParentSection();
+            }
+        }
+    }
+
+    protected void handleTitleCacheRelevantChange(PropertyChangeEvent event) {
+        //FIXME uncomment
+
+//        boolean isRelevant = getEntity() instanceof TaxonNameBase
+//                || getEntity() instanceof TaxonBase;
+//        isRelevant &= this instanceof AbstractIdentifiableEntityDetailElement;
+//
+//        if (isRelevant) {
+//            ((AbstractIdentifiableEntityDetailElement) this)
+//                    .updateToggleableCacheField();
+//            updateParentSection();
+//        }
+    }
+
+    private void updateParentSection() {
+        if (getParentElement() instanceof AbstractCdmDetailSection) {
+            ((AbstractCdmDetailSection) getParentElement()).updateTitle();
+        }
+    }
+
+    /**
+     * Gets called when the source of the event is a child widget of this
+     * widget.
+     *
+     * @param eventSource
+     *            a {@link java.lang.Object} object.
+     */
+    public abstract void handleEvent(Object eventSource);
+
+    /**
+     * <p>
+     * handleException
+     * </p>
+     *
+     * @param event
+     *            a
+     *            {@link eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent}
+     *            object.
+     */
+    public void handleException(CdmPropertyChangeEvent event) {
+        // override this in subclasses if you want to deal with the error
+        AbstractUtility.error(event.getSource().getClass(), event.getException());
+    }
+
+    /**
+     * <p>
+     * isIrrelevant
+     * </p>
+     *
+     * @return a boolean.
+     */
+    public boolean isIrrelevant() {
+        return irrelevant;
+    }
+
+    /**
+     * <p>
+     * getConversationHolder
+     * </p>
+     *
+     * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
+     *         object.
+     */
+    @Override
+    public ConversationHolder getConversationHolder() {
+        if (getParentElement() instanceof IConversationEnabled) {
+            return ((IConversationEnabled) getParentElement())
+                    .getConversationHolder();
+        }
+        throw new IllegalArgumentException(
+                "Parent element should be IConversationEnabled");
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void update(CdmDataChangeMap changeEvents) {
+    }
+}
index ee222adad8914b47c7c1daafd4e324e88cfd723b..c9ddfffb8af7fa38b4e267ce7099084339cf5bc2 100644 (file)
@@ -39,7 +39,7 @@ import eu.etaxonomy.taxeditor.ui.element.ISelectableElement;
  */
 public abstract class AbstractCdmDetailSection<ENTITY> extends AbstractFormSection<ENTITY> implements IEnableableFormElement, IExpansionListener {
 
-       private AbstractCdmDetailElement<ENTITY> detailElement;
+       protected ICdmDetailElement<ENTITY> detailElement;
 
        /**
         * <p>
@@ -123,9 +123,9 @@ public abstract class AbstractCdmDetailSection<ENTITY> extends AbstractFormSecti
            createControlsByType(formElement, null, style);
        }
 
-       protected abstract AbstractCdmDetailElement<ENTITY> createCdmDetailElement(AbstractCdmDetailSection<ENTITY> parentElement, int style);
+       protected abstract ICdmDetailElement<ENTITY> createCdmDetailElement(AbstractCdmDetailSection<ENTITY> parentElement, int style);
 
-       protected AbstractCdmDetailElement<ENTITY> createCdmDetailElementByType(AbstractCdmDetailSection<ENTITY> parentElement, Class<ENTITY> entityClass, int style){
+       protected ICdmDetailElement<ENTITY> createCdmDetailElementByType(AbstractCdmDetailSection<ENTITY> parentElement, Class<ENTITY> entityClass, int style){
            return createCdmDetailElement(parentElement, style);
        }
 
index ecc7c9107e8a6ed102df8893b5465e78a04a5525..38ecea49fe4a3f1dddee003bd4e68086474a4d82 100644 (file)
@@ -279,6 +279,16 @@ public abstract class AbstractEntityCollectionSection<ENTITY, ELEMENT> extends A
                return PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOULD_EXPAND_SECTION_WHEN_DATA_AVAILABLE);
        }
 
+       /**
+        * Remove an element from the entities collection and update the section 
+        *
+        * @param element a ELEMENT object.
+        */
+       public void removeElementAndUpdate(ELEMENT element) {
+               removeElement(element);
+               internalUpdateSection(true);
+       }
+       
        /**
         * Get the specific collection of this entity
         *
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/ICdmDetailElement.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/ICdmDetailElement.java
new file mode 100644 (file)
index 0000000..20110e3
--- /dev/null
@@ -0,0 +1,25 @@
+// $Id$
+/**
+* Copyright (C) 2013 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.taxeditor.ui.section;
+
+import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
+import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
+import eu.etaxonomy.taxeditor.ui.element.IEntityElement;
+
+/**
+ * @author pplitzner
+ * @date 30.07.2013
+ *
+ */
+public interface ICdmDetailElement<T> extends IEntityElement<T>, IEnableableFormElement, IConversationEnabled{
+
+    public abstract void setEntity(T entity);
+
+}
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionSourceComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/description/DescriptionSourceComposite.java
new file mode 100644 (file)
index 0000000..bfdb0bf
--- /dev/null
@@ -0,0 +1,72 @@
+// $Id$
+/**
+ * Copyright (C) 2013 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+package eu.etaxonomy.taxeditor.ui.section.description;
+
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Composite;
+
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.taxeditor.ui.element.AbstractEntityCollectionElementComposite;
+import eu.etaxonomy.taxeditor.ui.element.AbstractFormSection;
+import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
+import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
+import eu.etaxonomy.taxeditor.ui.selection.EntitySelectionElement;
+
+/**
+ * @author pplitzner
+ * @date 24.07.2013
+ *
+ */
+public class DescriptionSourceComposite extends AbstractEntityCollectionElementComposite<Reference> {
+
+    private EntitySelectionElement<Reference> selection_descriptionSource;
+
+    /**
+     * <p>
+     * Constructor for DescriptionSourceElement.
+     * </p>
+     *
+     * @param cdmFormFactory
+     *            a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
+     *            object.
+     * @param formElement
+     *            a
+     *            {@link eu.etaxonomy.taxeditor.ui.element.AbstractFormSection}
+     *            object.
+     * @param element
+     *            a {@link eu.etaxonomy.cdm.model.reference.ReferenceBase}
+     *            object.
+     * @param removeListener
+     *            a {@link org.eclipse.swt.events.SelectionListener} object.
+     * @param style
+     *            a int.
+     */
+    public DescriptionSourceComposite(Composite parent, CdmFormFactory cdmFormFactory, AbstractFormSection formElement, Reference element, SelectionListener removeListener, int style) {
+        super(parent, cdmFormFactory, element, removeListener, style);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void createControls(ICdmFormElement element, int style) {
+        selection_descriptionSource = formFactory.createSelectionElement(Reference.class, getConversationHolder(), element, "Description Source", null, EntitySelectionElement.ALL, style);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setEntity(Reference element) {
+        selection_descriptionSource.setEntity(element);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void handleEvent(Object eventSource) {
+
+    }
+}
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailElementComposite.java b/eu.etaxonomy.taxeditor.store/src/main/java/eu/etaxonomy/taxeditor/ui/section/occurrence/GatheringEventDetailElementComposite.java
new file mode 100644 (file)
index 0000000..d5c3262
--- /dev/null
@@ -0,0 +1,170 @@
+// $Id$
+/**
+ * Copyright (C) 2013 EDIT
+ * European Distributed Institute of Taxonomy
+ * http://www.e-taxonomy.eu
+ *
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * See LICENSE.TXT at the top of this package for the full license terms.
+ */
+package eu.etaxonomy.taxeditor.ui.section.occurrence;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.TableWrapData;
+import org.eclipse.ui.forms.widgets.TableWrapLayout;
+
+import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
+import eu.etaxonomy.taxeditor.model.AbstractUtility;
+import eu.etaxonomy.taxeditor.preference.Resources;
+import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
+import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
+import eu.etaxonomy.taxeditor.ui.element.NumberWithLabelElementComposite;
+import eu.etaxonomy.taxeditor.ui.element.TextWithLabelComposite;
+import eu.etaxonomy.taxeditor.ui.section.AbstractCdmDetailElementComposite;
+
+/**
+ * @author pplitzner
+ * @date 25.07.2013
+ *
+ */
+public class GatheringEventDetailElementComposite extends AbstractCdmDetailElementComposite<DerivedUnitFacade> {
+
+
+
+//    private CollectingAreasDetailSection section_collectingAreas;
+    private final NumberWithLabelElementComposite absoluteElevationError;
+    private final NumberWithLabelElementComposite number_absoluteElevationMinimum;
+    private final NumberWithLabelElementComposite number_absoluteElevationMaximum;
+    private final TextWithLabelComposite collectingMethod;
+    private final NumberWithLabelElementComposite number_distanceToGround;
+    private final NumberWithLabelElementComposite number_distanceToWaterSurface;
+    private final TextWithLabelComposite gatheringEventDescription;
+
+    /**
+     * <p>
+     * Constructor for GatheringEventDetailElement.
+     * </p>
+     *
+     * @param formFactory
+     *            a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
+     *            object.
+     * @param formElement
+     *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
+     *            object.
+     */
+    public GatheringEventDetailElementComposite(Composite parent, FormToolkit formFactory, ICdmFormElement parentFormElement, int style) {
+        super(parent, formFactory, parentFormElement, style);
+        TableWrapLayout tableWrapLayout = (TableWrapLayout) getLayout();
+        tableWrapLayout.numColumns = 1;
+
+        absoluteElevationError = CdmFormFactory.createNumberWithLabelElementComposite(this, getFormFactory(), this, "Elevation Error", new Float(0), SWT.NONE);
+        TableWrapData twd_absoluteElevationError = new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP, 1, 1);
+        twd_absoluteElevationError.grabHorizontal = true;
+        absoluteElevationError.setLayoutData(twd_absoluteElevationError);
+        getFormFactory().adapt(absoluteElevationError);
+        getFormFactory().paintBordersFor(absoluteElevationError);
+
+        number_absoluteElevationMinimum = CdmFormFactory.createNumberWithLabelElementComposite(this, getFormFactory(), this, "Elevation Minimum (m)", new Float(0), SWT.NONE);
+        TableWrapData twd_number_absoluteElevationMinimum = new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP, 1, 1);
+        twd_number_absoluteElevationMinimum.grabHorizontal = true;
+        number_absoluteElevationMinimum.setLayoutData(twd_number_absoluteElevationMinimum);
+        formFactory.paintBordersFor(number_absoluteElevationMinimum);
+
+        number_absoluteElevationMaximum = CdmFormFactory.createNumberWithLabelElementComposite(this, getFormFactory(), parentFormElement, "Elevation Maximum (m)", new Float(0), SWT.NONE);
+        TableWrapData twd_numberWithLabelElementComposite = new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP, 1, 1);
+        twd_numberWithLabelElementComposite.grabVertical = true;
+        twd_numberWithLabelElementComposite.grabHorizontal = true;
+        number_absoluteElevationMaximum.setLayoutData(twd_numberWithLabelElementComposite);
+        formFactory.paintBordersFor(number_absoluteElevationMaximum);
+
+        collectingMethod = CdmFormFactory.createTextWithLabelComposite(this, getFormFactory(), this, "Collecting Method", "", (Integer) null, SWT.NONE);
+        TableWrapData twd_collectingMethod = new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP, 1, 1);
+        twd_collectingMethod.grabHorizontal = true;
+        collectingMethod.setLayoutData(twd_collectingMethod);
+        getFormFactory().adapt(collectingMethod);
+        getFormFactory().paintBordersFor(collectingMethod);
+
+        number_distanceToGround = CdmFormFactory.createNumberWithLabelElementComposite(this, getFormFactory(), parentFormElement, "Distance To Ground (m)", new Float(0), SWT.NONE);
+        formFactory.paintBordersFor(number_distanceToGround);
+
+        number_distanceToWaterSurface = CdmFormFactory.createNumberWithLabelElementComposite(this, getFormFactory(), parentFormElement, "Distance To Water Surface (m)", new Float(0), SWT.NONE);
+        formFactory.paintBordersFor(number_distanceToWaterSurface);
+
+        gatheringEventDescription = CdmFormFactory.createTextWithLabelComposite(this, getFormFactory(), this, "Gathering Event Description", "", (Integer) null, SWT.NONE);
+        TableWrapData twd_gatheringEventDescription = new TableWrapData(TableWrapData.LEFT, TableWrapData.TOP, 1, 1);
+        twd_gatheringEventDescription.grabHorizontal = true;
+        gatheringEventDescription.setLayoutData(twd_gatheringEventDescription);
+        getFormFactory().adapt(gatheringEventDescription);
+        getFormFactory().paintBordersFor(gatheringEventDescription);
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    protected void createControls(ICdmFormElement formElement, DerivedUnitFacade entity, int style) {
+
+        absoluteElevationError.setText(String.valueOf(entity.getAbsoluteElevation()));
+        number_absoluteElevationMinimum.setText(String.valueOf(entity.getAbsoluteElevationMinimum()));
+        number_absoluteElevationMaximum.setText(String.valueOf(entity.getAbsoluteElevationMaximum()));
+        collectingMethod.setText(entity.getCollectingMethod());
+        number_distanceToGround.setText(String.valueOf(entity.getDistanceToGround()));
+        number_distanceToWaterSurface.setText(String.valueOf(entity.getDistanceToWaterSurface()));
+        gatheringEventDescription.setText(entity.getGatheringEventDescription());
+
+        // collectingArea
+//        number_absoluteElevationError = formFactory.createIntegerTextWithLabelElement(formElement, "Elevation Error", entity.getAbsoluteElevationError(), style);
+//        number_absoluteElevationMinimum = formFactory.createIntegerTextWithLabelElement(formElement, "Elevation Minimum (m)", entity.getAbsoluteElevationMinimum(), style);
+//        number_absoluteElevationMaximum = formFactory.createIntegerTextWithLabelElement(formElement, "Elevation Maximum (m)", entity.getAbsoluteElevationMaximum(), style);
+
+//        text_collectingMethod = formFactory.createTextWithLabelElement(formElement, "Collecting Method", entity.getCollectingMethod(), style);
+
+//        number_distanceToGround = formFactory.createIntegerTextWithLabelElement(formElement, "Distance To Ground (m)", entity.getDistanceToGround(), style);
+//        number_distanceToWaterSurface = formFactory.createIntegerTextWithLabelElement(formElement, "Distance To Water Surface (m)", entity.getDistanceToWaterSurface(), style);
+        // exactLocation
+//        text_gatheringEventDescription = formFactory.createTextWithLabelElement(formElement, "Gathering Event Description", entity.getGatheringEventDescription(), style);
+
+//        section_collectingAreas = formFactory.createCollectingAreasDetailSection(getConversationHolder(), formElement, ExpandableComposite.TWISTIE);
+//        section_collectingAreas.setLayoutData(LayoutConstants.FILL_HORIZONTALLY(2, 1));
+//        section_collectingAreas.setEntity(entity);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void handleEvent(Object eventSource) {
+        if (eventSource == absoluteElevationError) {
+            getEntity().setAbsoluteElevationError(absoluteElevationError.getInteger());
+        } else if (eventSource == number_absoluteElevationMinimum) {
+            try {
+                getEntity().setAbsoluteElevationRange(number_absoluteElevationMinimum.getInteger(), number_absoluteElevationMaximum.getInteger());
+                number_absoluteElevationMinimum.setBackground(getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
+            } catch (IllegalArgumentException e) {
+                number_absoluteElevationMinimum.setBackground(getColor(Resources.COLOR_PARSE_ERROR));
+                AbstractUtility.warn(getClass(), e.getLocalizedMessage());
+            }
+        } else if (eventSource == number_absoluteElevationMaximum) {
+            try {
+                getEntity().setAbsoluteElevationRange(number_absoluteElevationMinimum.getInteger(), number_absoluteElevationMaximum.getInteger());
+                number_absoluteElevationMaximum.setBackground(getColor(Resources.COLOR_COMPOSITE_BACKGROUND));
+            } catch (IllegalArgumentException e) {
+                number_absoluteElevationMaximum.setBackground(getColor(Resources.COLOR_PARSE_ERROR));
+                AbstractUtility.warn(getClass(), e.getLocalizedMessage());
+            }
+        } else if (eventSource == getCollectingMethod()) {
+            getEntity().setCollectingMethod(getCollectingMethod().getText());
+        } else if (eventSource == number_distanceToGround) {
+            getEntity().setDistanceToGround(number_distanceToGround.getInteger());
+        } else if (eventSource == number_distanceToWaterSurface) {
+            getEntity().setDistanceToWaterSurface(number_distanceToWaterSurface.getInteger());
+        } else if (eventSource == getGatheringEventDescription()) {
+            getEntity().setGatheringEventDescription(getGatheringEventDescription().getText());
+        }
+    }
+    public TextWithLabelComposite getGatheringEventDescription() {
+        return gatheringEventDescription;
+    }
+    public TextWithLabelComposite getCollectingMethod() {
+        return collectingMethod;
+    }
+}
index 44c86337ced629fe37cc2d9cfe7c1d8e52ea6510..097a2ac7199c1530a52e571b6b55f35739413558 100644 (file)
@@ -16,8 +16,8 @@ import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
-import eu.etaxonomy.taxeditor.ui.section.AbstractCdmDetailElement;
 import eu.etaxonomy.taxeditor.ui.section.AbstractCdmDetailSection;
+import eu.etaxonomy.taxeditor.ui.section.ICdmDetailElement;
 
 /**
  * <p>GatheringEventDetailSection class.</p>
@@ -57,7 +57,7 @@ public class GatheringEventDetailSection extends AbstractCdmDetailSection<Derive
         * @see eu.etaxonomy.taxeditor.ui.section.AbstractCdmDetailSection#createCdmDetailElement(eu.etaxonomy.taxeditor.ui.section.AbstractCdmDetailSection, int)
         */
        @Override
-       protected AbstractCdmDetailElement<DerivedUnitFacade> createCdmDetailElement(AbstractCdmDetailSection<DerivedUnitFacade> parentElement, int style) {
-           return formFactory.createGatheringEventDetailElement(parentElement);
+       protected ICdmDetailElement<DerivedUnitFacade> createCdmDetailElement(AbstractCdmDetailSection<DerivedUnitFacade> parentElement, int style) {
+           return formFactory.createGatheringEventDetailElementComposite(this);
        }
 }
index eeddbac30e66026f76a1f06cb4c03af6d99e2565..50ddcd65a4fd1b6efa619c4763be850c9a535861 100644 (file)
@@ -1,9 +1,9 @@
 // $Id$
 /**
  * Copyright (C) 2007 EDIT
- * European Distributed Institute of Taxonomy 
+ * European Distributed Institute of Taxonomy
  * http://www.e-taxonomy.eu
- * 
+ *
  * The contents of this file are subject to the Mozilla Public License Version 1.1
  * See LICENSE.TXT at the top of this package for the full license terms.
  */
@@ -23,8 +23,8 @@ import eu.etaxonomy.taxeditor.model.IElementHasDetails;
 import eu.etaxonomy.taxeditor.model.PolytomousKeyRelationship;
 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
 import eu.etaxonomy.taxeditor.store.StoreUtil;
-import eu.etaxonomy.taxeditor.ui.element.AbstractCdmFormElement;
 import eu.etaxonomy.taxeditor.ui.element.AbstractFormSection;
+import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
 import eu.etaxonomy.taxeditor.ui.section.ITaxonBaseDetailSection;
 import eu.etaxonomy.taxeditor.ui.section.key.GeographicalScopeDetailSection;
 import eu.etaxonomy.taxeditor.ui.section.key.PolytomousKeyDetailSection;
@@ -36,7 +36,7 @@ import eu.etaxonomy.taxeditor.ui.section.occurrence.IDerivedUnitFacadeDetailSect
  * <p>
  * CdmSectionPart class.
  * </p>
- * 
+ *
  * @author n.hoffmann
  * @created Feb 8, 2010
  * @version 1.0
@@ -50,7 +50,7 @@ public class CdmSectionPart<T> extends SectionPart implements
         * <p>
         * Constructor for CdmSectionPart.
         * </p>
-        * 
+        *
         * @param section
         *            a {@link eu.etaxonomy.taxeditor.ui.element.AbstractFormSection}
         *            object.
@@ -92,24 +92,24 @@ public class CdmSectionPart<T> extends SectionPart implements
                if (input instanceof PolytomousKeyRelationship) {
                        input = ((PolytomousKeyRelationship) input).getDestination();
                }
-               
-           if ((input instanceof PolytomousKeyNode) && 
-                   (formSection instanceof PolytomousKeyDetailSection || 
-                           formSection instanceof GeographicalScopeDetailSection || 
-                           formSection instanceof ScopeRestrictionSection || 
+
+           if ((input instanceof PolytomousKeyNode) &&
+                   (formSection instanceof PolytomousKeyDetailSection ||
+                           formSection instanceof GeographicalScopeDetailSection ||
+                           formSection instanceof ScopeRestrictionSection ||
                            formSection instanceof TaxonomicScopeSection)) {
                input = ((PolytomousKeyNode)input).getKey();
            }
-           
-               
+
+
                formSection.setEntity((T) input);
-               
+
                return true;
        }
 
        /*
         * (non-Javadoc)
-        * 
+        *
         * @see
         * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
         * .jface.util.PropertyChangeEvent)
@@ -119,14 +119,14 @@ public class CdmSectionPart<T> extends SectionPart implements
        public void propertyChange(PropertyChangeEvent event) {
                if (event != null) {
 
-                       Object eventSource = event.getSource();                 
-                       
+                       Object eventSource = event.getSource();
+
                        if (formSection.equals(eventSource)){
                                markDirty();
                        }
                        if((
-                                               (eventSource instanceof AbstractCdmFormElement) 
-                                               && formSection.containsFormElement((AbstractCdmFormElement) eventSource))
+                                               (eventSource instanceof ICdmFormElement)
+                                               && formSection.containsFormElement((ICdmFormElement) eventSource))
                                                ) {
                                markDirty();
                        }
diff --git a/eu.etaxonomy.taxeditor.store/src/main/java/org/eclipse/wb/swt/SWTResourceManager.java b/eu.etaxonomy.taxeditor.store/src/main/java/org/eclipse/wb/swt/SWTResourceManager.java
new file mode 100644 (file)
index 0000000..8b6d4cc
--- /dev/null
@@ -0,0 +1,447 @@
+/*******************************************************************************\r
+ * Copyright (c) 2011 Google, Inc.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *    Google, Inc. - initial API and implementation\r
+ *******************************************************************************/\r
+package org.eclipse.wb.swt;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Utility class for managing OS resources associated with SWT controls such as colors, fonts, images, etc.
+ * <p>
+ * !!! IMPORTANT !!! Application code must explicitly invoke the <code>dispose()</code> method to release the
+ * operating system resources managed by cached objects when those objects and OS resources are no longer
+ * needed (e.g. on application shutdown)
+ * <p>
+ * This class may be freely distributed as part of any application or plugin.
+ * <p>
+ * @author scheglov_ke
+ * @author Dan Rubel
+ */
+public class SWTResourceManager {
+       ////////////////////////////////////////////////////////////////////////////
+       //
+       // Color
+       //
+       ////////////////////////////////////////////////////////////////////////////
+       private static Map<RGB, Color> m_colorMap = new HashMap<RGB, Color>();
+       /**
+        * Returns the system {@link Color} matching the specific ID.
+        * 
+        * @param systemColorID
+        *            the ID value for the color
+        * @return the system {@link Color} matching the specific ID
+        */
+       public static Color getColor(int systemColorID) {
+               Display display = Display.getCurrent();
+               return display.getSystemColor(systemColorID);
+       }
+       /**
+        * Returns a {@link Color} given its red, green and blue component values.
+        * 
+        * @param r
+        *            the red component of the color
+        * @param g
+        *            the green component of the color
+        * @param b
+        *            the blue component of the color
+        * @return the {@link Color} matching the given red, green and blue component values
+        */
+       public static Color getColor(int r, int g, int b) {
+               return getColor(new RGB(r, g, b));
+       }
+       /**
+        * Returns a {@link Color} given its RGB value.
+        * 
+        * @param rgb
+        *            the {@link RGB} value of the color
+        * @return the {@link Color} matching the RGB value
+        */
+       public static Color getColor(RGB rgb) {
+               Color color = m_colorMap.get(rgb);
+               if (color == null) {
+                       Display display = Display.getCurrent();
+                       color = new Color(display, rgb);
+                       m_colorMap.put(rgb, color);
+               }
+               return color;
+       }
+       /**
+        * Dispose of all the cached {@link Color}'s.
+        */
+       public static void disposeColors() {
+               for (Color color : m_colorMap.values()) {
+                       color.dispose();
+               }
+               m_colorMap.clear();
+       }
+       ////////////////////////////////////////////////////////////////////////////
+       //
+       // Image
+       //
+       ////////////////////////////////////////////////////////////////////////////
+       /**
+        * Maps image paths to images.
+        */
+       private static Map<String, Image> m_imageMap = new HashMap<String, Image>();
+       /**
+        * Returns an {@link Image} encoded by the specified {@link InputStream}.
+        * 
+        * @param stream
+        *            the {@link InputStream} encoding the image data
+        * @return the {@link Image} encoded by the specified input stream
+        */
+       protected static Image getImage(InputStream stream) throws IOException {
+               try {
+                       Display display = Display.getCurrent();
+                       ImageData data = new ImageData(stream);
+                       if (data.transparentPixel > 0) {
+                               return new Image(display, data, data.getTransparencyMask());
+                       }
+                       return new Image(display, data);
+               } finally {
+                       stream.close();
+               }
+       }
+       /**
+        * Returns an {@link Image} stored in the file at the specified path.
+        * 
+        * @param path
+        *            the path to the image file
+        * @return the {@link Image} stored in the file at the specified path
+        */
+       public static Image getImage(String path) {
+               Image image = m_imageMap.get(path);
+               if (image == null) {
+                       try {
+                               image = getImage(new FileInputStream(path));
+                               m_imageMap.put(path, image);
+                       } catch (Exception e) {
+                               image = getMissingImage();
+                               m_imageMap.put(path, image);
+                       }
+               }
+               return image;
+       }
+       /**
+        * Returns an {@link Image} stored in the file at the specified path relative to the specified class.
+        * 
+        * @param clazz
+        *            the {@link Class} relative to which to find the image
+        * @param path
+        *            the path to the image file, if starts with <code>'/'</code>
+        * @return the {@link Image} stored in the file at the specified path
+        */
+       public static Image getImage(Class<?> clazz, String path) {
+               String key = clazz.getName() + '|' + path;
+               Image image = m_imageMap.get(key);
+               if (image == null) {
+                       try {
+                               image = getImage(clazz.getResourceAsStream(path));
+                               m_imageMap.put(key, image);
+                       } catch (Exception e) {
+                               image = getMissingImage();
+                               m_imageMap.put(key, image);
+                       }
+               }
+               return image;
+       }
+       private static final int MISSING_IMAGE_SIZE = 10;
+       /**
+        * @return the small {@link Image} that can be used as placeholder for missing image.
+        */
+       private static Image getMissingImage() {
+               Image image = new Image(Display.getCurrent(), MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
+               //
+               GC gc = new GC(image);
+               gc.setBackground(getColor(SWT.COLOR_RED));
+               gc.fillRectangle(0, 0, MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
+               gc.dispose();
+               //
+               return image;
+       }
+       /**
+        * Style constant for placing decorator image in top left corner of base image.
+        */
+       public static final int TOP_LEFT = 1;
+       /**
+        * Style constant for placing decorator image in top right corner of base image.
+        */
+       public static final int TOP_RIGHT = 2;
+       /**
+        * Style constant for placing decorator image in bottom left corner of base image.
+        */
+       public static final int BOTTOM_LEFT = 3;
+       /**
+        * Style constant for placing decorator image in bottom right corner of base image.
+        */
+       public static final int BOTTOM_RIGHT = 4;
+       /**
+        * Internal value.
+        */
+       protected static final int LAST_CORNER_KEY = 5;
+       /**
+        * Maps images to decorated images.
+        */
+       @SuppressWarnings("unchecked")
+       private static Map<Image, Map<Image, Image>>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY];
+       /**
+        * Returns an {@link Image} composed of a base image decorated by another image.
+        * 
+        * @param baseImage
+        *            the base {@link Image} that should be decorated
+        * @param decorator
+        *            the {@link Image} to decorate the base image
+        * @return {@link Image} The resulting decorated image
+        */
+       public static Image decorateImage(Image baseImage, Image decorator) {
+               return decorateImage(baseImage, decorator, BOTTOM_RIGHT);
+       }
+       /**
+        * Returns an {@link Image} composed of a base image decorated by another image.
+        * 
+        * @param baseImage
+        *            the base {@link Image} that should be decorated
+        * @param decorator
+        *            the {@link Image} to decorate the base image
+        * @param corner
+        *            the corner to place decorator image
+        * @return the resulting decorated {@link Image}
+        */
+       public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) {
+               if (corner <= 0 || corner >= LAST_CORNER_KEY) {
+                       throw new IllegalArgumentException("Wrong decorate corner");
+               }
+               Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[corner];
+               if (cornerDecoratedImageMap == null) {
+                       cornerDecoratedImageMap = new HashMap<Image, Map<Image, Image>>();
+                       m_decoratedImageMap[corner] = cornerDecoratedImageMap;
+               }
+               Map<Image, Image> decoratedMap = cornerDecoratedImageMap.get(baseImage);
+               if (decoratedMap == null) {
+                       decoratedMap = new HashMap<Image, Image>();
+                       cornerDecoratedImageMap.put(baseImage, decoratedMap);
+               }
+               //
+               Image result = decoratedMap.get(decorator);
+               if (result == null) {
+                       Rectangle bib = baseImage.getBounds();
+                       Rectangle dib = decorator.getBounds();
+                       //
+                       result = new Image(Display.getCurrent(), bib.width, bib.height);
+                       //
+                       GC gc = new GC(result);
+                       gc.drawImage(baseImage, 0, 0);
+                       if (corner == TOP_LEFT) {
+                               gc.drawImage(decorator, 0, 0);
+                       } else if (corner == TOP_RIGHT) {
+                               gc.drawImage(decorator, bib.width - dib.width, 0);
+                       } else if (corner == BOTTOM_LEFT) {
+                               gc.drawImage(decorator, 0, bib.height - dib.height);
+                       } else if (corner == BOTTOM_RIGHT) {
+                               gc.drawImage(decorator, bib.width - dib.width, bib.height - dib.height);
+                       }
+                       gc.dispose();
+                       //
+                       decoratedMap.put(decorator, result);
+               }
+               return result;
+       }
+       /**
+        * Dispose all of the cached {@link Image}'s.
+        */
+       public static void disposeImages() {
+               // dispose loaded images
+               {
+                       for (Image image : m_imageMap.values()) {
+                               image.dispose();
+                       }
+                       m_imageMap.clear();
+               }
+               // dispose decorated images
+               for (int i = 0; i < m_decoratedImageMap.length; i++) {
+                       Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[i];
+                       if (cornerDecoratedImageMap != null) {
+                               for (Map<Image, Image> decoratedMap : cornerDecoratedImageMap.values()) {
+                                       for (Image image : decoratedMap.values()) {
+                                               image.dispose();
+                                       }
+                                       decoratedMap.clear();
+                               }
+                               cornerDecoratedImageMap.clear();
+                       }
+               }
+       }
+       ////////////////////////////////////////////////////////////////////////////
+       //
+       // Font
+       //
+       ////////////////////////////////////////////////////////////////////////////
+       /**
+        * Maps font names to fonts.
+        */
+       private static Map<String, Font> m_fontMap = new HashMap<String, Font>();
+       /**
+        * Maps fonts to their bold versions.
+        */
+       private static Map<Font, Font> m_fontToBoldFontMap = new HashMap<Font, Font>();
+       /**
+        * Returns a {@link Font} based on its name, height and style.
+        * 
+        * @param name
+        *            the name of the font
+        * @param height
+        *            the height of the font
+        * @param style
+        *            the style of the font
+        * @return {@link Font} The font matching the name, height and style
+        */
+       public static Font getFont(String name, int height, int style) {
+               return getFont(name, height, style, false, false);
+       }
+       /**
+        * Returns a {@link Font} based on its name, height and style. Windows-specific strikeout and underline
+        * flags are also supported.
+        * 
+        * @param name
+        *            the name of the font
+        * @param size
+        *            the size of the font
+        * @param style
+        *            the style of the font
+        * @param strikeout
+        *            the strikeout flag (warning: Windows only)
+        * @param underline
+        *            the underline flag (warning: Windows only)
+        * @return {@link Font} The font matching the name, height, style, strikeout and underline
+        */
+       public static Font getFont(String name, int size, int style, boolean strikeout, boolean underline) {
+               String fontName = name + '|' + size + '|' + style + '|' + strikeout + '|' + underline;
+               Font font = m_fontMap.get(fontName);
+               if (font == null) {
+                       FontData fontData = new FontData(name, size, style);
+                       if (strikeout || underline) {
+                               try {
+                                       Class<?> logFontClass = Class.forName("org.eclipse.swt.internal.win32.LOGFONT"); //$NON-NLS-1$
+                                       Object logFont = FontData.class.getField("data").get(fontData); //$NON-NLS-1$
+                                       if (logFont != null && logFontClass != null) {
+                                               if (strikeout) {
+                                                       logFontClass.getField("lfStrikeOut").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$
+                                               }
+                                               if (underline) {
+                                                       logFontClass.getField("lfUnderline").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$
+                                               }
+                                       }
+                               } catch (Throwable e) {
+                                       System.err.println("Unable to set underline or strikeout" + " (probably on a non-Windows platform). " + e); //$NON-NLS-1$ //$NON-NLS-2$
+                               }
+                       }
+                       font = new Font(Display.getCurrent(), fontData);
+                       m_fontMap.put(fontName, font);
+               }
+               return font;
+       }
+       /**
+        * Returns a bold version of the given {@link Font}.
+        * 
+        * @param baseFont
+        *            the {@link Font} for which a bold version is desired
+        * @return the bold version of the given {@link Font}
+        */
+       public static Font getBoldFont(Font baseFont) {
+               Font font = m_fontToBoldFontMap.get(baseFont);
+               if (font == null) {
+                       FontData fontDatas[] = baseFont.getFontData();
+                       FontData data = fontDatas[0];
+                       font = new Font(Display.getCurrent(), data.getName(), data.getHeight(), SWT.BOLD);
+                       m_fontToBoldFontMap.put(baseFont, font);
+               }
+               return font;
+       }
+       /**
+        * Dispose all of the cached {@link Font}'s.
+        */
+       public static void disposeFonts() {
+               // clear fonts
+               for (Font font : m_fontMap.values()) {
+                       font.dispose();
+               }
+               m_fontMap.clear();
+               // clear bold fonts
+               for (Font font : m_fontToBoldFontMap.values()) {
+                       font.dispose();
+               }
+               m_fontToBoldFontMap.clear();
+       }
+       ////////////////////////////////////////////////////////////////////////////
+       //
+       // Cursor
+       //
+       ////////////////////////////////////////////////////////////////////////////
+       /**
+        * Maps IDs to cursors.
+        */
+       private static Map<Integer, Cursor> m_idToCursorMap = new HashMap<Integer, Cursor>();
+       /**
+        * Returns the system cursor matching the specific ID.
+        * 
+        * @param id
+        *            int The ID value for the cursor
+        * @return Cursor The system cursor matching the specific ID
+        */
+       public static Cursor getCursor(int id) {
+               Integer key = Integer.valueOf(id);
+               Cursor cursor = m_idToCursorMap.get(key);
+               if (cursor == null) {
+                       cursor = new Cursor(Display.getDefault(), id);
+                       m_idToCursorMap.put(key, cursor);
+               }
+               return cursor;
+       }
+       /**
+        * Dispose all of the cached cursors.
+        */
+       public static void disposeCursors() {
+               for (Cursor cursor : m_idToCursorMap.values()) {
+                       cursor.dispose();
+               }
+               m_idToCursorMap.clear();
+       }
+       ////////////////////////////////////////////////////////////////////////////
+       //
+       // General
+       //
+       ////////////////////////////////////////////////////////////////////////////
+       /**
+        * Dispose of cached objects and their underlying OS resources. This should only be called when the cached
+        * objects are no longer needed (e.g. on application shutdown).
+        */
+       public static void dispose() {
+               disposeColors();
+               disposeImages();
+               disposeFonts();
+               disposeCursors();
+       }
+}
\ No newline at end of file