Project

General

Profile

Download (10.3 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 * Copyright (C) 2007 EDIT
3
 * European Distributed Institute of Taxonomy
4
 * http://www.e-taxonomy.eu
5
 *
6
 * The contents of this file are subject to the Mozilla Public License Version 1.1
7
 * See LICENSE.TXT at the top of this package for the full license terms.
8
 */
9
package eu.etaxonomy.taxeditor.ui.element;
10

    
11
import java.util.ConcurrentModificationException;
12
import java.util.HashSet;
13
import java.util.Iterator;
14
import java.util.List;
15
import java.util.Set;
16

    
17
import org.eclipse.core.runtime.Assert;
18
import org.eclipse.jface.util.IPropertyChangeListener;
19
import org.eclipse.jface.util.PropertyChangeEvent;
20
import org.eclipse.jface.viewers.ISelectionChangedListener;
21
import org.eclipse.jface.viewers.ISelectionProvider;
22
import org.eclipse.jface.viewers.IStructuredSelection;
23
import org.eclipse.jface.viewers.SelectionChangedEvent;
24
import org.eclipse.jface.viewers.StructuredSelection;
25
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.events.SelectionEvent;
27
import org.eclipse.swt.events.SelectionListener;
28
import org.eclipse.swt.graphics.Color;
29
import org.eclipse.swt.widgets.Composite;
30
import org.eclipse.swt.widgets.Control;
31
import org.eclipse.swt.widgets.Display;
32
import org.eclipse.swt.widgets.TypedListener;
33
import org.eclipse.swt.widgets.Widget;
34
import org.eclipse.ui.forms.widgets.Section;
35
import org.eclipse.ui.forms.widgets.TableWrapLayout;
36
import org.eclipse.ui.forms.widgets.ToggleHyperlink;
37

    
38
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
39
import eu.etaxonomy.taxeditor.model.AbstractUtility;
40
import eu.etaxonomy.taxeditor.model.MessagingUtils;
41

    
42
/**
43
 * <p>
44
 * Abstract super class for a {@link Section} GUI element that visualizes a CDM
45
 * entity, manages a conversation and listens to selections
46
 * </p>
47
 *
48
 * @param <ENTITY> A CDM entity which should be visualized by this section.
49
 *
50
 * @author n.hoffmann
51
 * @created Feb 22, 2010
52
 */
53
//TODO shouldn't ENTITY be bound with super class ICdmBase for example (AbstractFormSection<ENTITY extends ICdmBase>)?
54
public abstract class AbstractFormSection<ENTITY>
55
        extends Section
56
        implements ISelectionChangedListener, IEntityElement<ENTITY> {
57

    
58
    /**
59
     * The default number of columns in detail sections
60
     */
61
    public static final int DEFAULT_NUM_COLUMNS = 2;
62

    
63
	private ISelectionProvider selectionProvider;
64

    
65
	private ENTITY entity;
66

    
67
	private final Set<ICdmFormElement> elements = new HashSet<>();
68

    
69
	protected CdmFormFactory formFactory;
70

    
71
	private List<IPropertyChangeListener> propertyChangeListeners;
72

    
73
	private ICdmFormElement parentElement;
74

    
75
	private Color persistentBackgroundColor;
76

    
77
	/**
78
	 * Constructor for AbstractFormSection.
79
	 */
80
    protected AbstractFormSection(CdmFormFactory formFactory, ICdmFormElement parentElement, int style) {
81
		super(parentElement.getLayoutComposite(), style);
82

    
83
		this.parentElement = parentElement;
84

    
85
		this.formFactory = formFactory;
86

    
87
		this.setLayoutData(LayoutConstants.FILL());
88

    
89
		Composite client = formFactory.createComposite(this, SWT.WRAP);
90
		client.setBackgroundMode(SWT.INHERIT_DEFAULT);
91

    
92
		TableWrapLayout layout = LayoutConstants.LAYOUT();
93
		layout.bottomMargin = 10;
94
		layout.rightMargin = 5;
95
		layout.horizontalSpacing = 5;
96

    
97
		client.setLayout(layout);
98

    
99
		this.setClient(client);
100
	}
101

    
102
	/**
103
     * Constructor for AbstractFormSection.
104
     */
105
    protected AbstractFormSection(CdmFormFactory formFactory, ICdmFormElement parentElement, ISelectionProvider selectionProvider, int style) {
106
        this(formFactory, parentElement, style);
107
        this.selectionProvider = selectionProvider;
108
    }
109

    
110
	/**
111
	 * Getter for the field <code>propertyChangeListeners</code>.
112
	 */
113
	@Override
114
    public List<IPropertyChangeListener> getPropertyChangeListeners() {
115
		return propertyChangeListeners;
116
	}
117

    
118
	@Override
119
    public void setPropertyChangeListeners(
120
			List<IPropertyChangeListener> propertyChangeListeners) {
121
		this.propertyChangeListeners = propertyChangeListeners;
122
	}
123

    
124
	@Override
125
	public ENTITY getEntity() {
126
	    return entity;
127
	}
128
	public void setEntity(ENTITY entity) {
129
		this.entity = entity;
130
	}
131

    
132
	public ToggleHyperlink getToggle() {
133
		return this.toggle;
134
	}
135

    
136
	public AbstractFormSection<ENTITY> getSection() {
137
		return this;
138
	}
139

    
140
	@Override
141
    public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
142
        Assert.isNotNull(propertyChangeListeners, "No property change listeners.");
143
        try {
144
            for (Object listener : propertyChangeListeners) {
145
                ((IPropertyChangeListener) listener).propertyChange(event);
146
            }
147
        } catch (ConcurrentModificationException e) {
148
            MessagingUtils.warn(getClass(), "ConcurrentModificationException while handling PropertyChangeEvents."
149
                    + " It seems like this is not critical");
150
        }
151
	}
152

    
153
	/**
154
	 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
155
	 *
156
	 * @param object
157
	 *            the object on which the property changed
158
	 */
159
	public void firePropertyChangeEvent(Object object) {
160
		firePropertyChangeEvent(object, null);
161
	}
162

    
163
	/**
164
	 * Fires a {@link CdmPropertyChangeEvent} with the given object as source
165
	 * also containing the originating event
166
	 *
167
	 * @param object
168
	 *            the object on which the property changed
169
	 * @param originatingEvent
170
	 *            the originating event
171
	 */
172
	public void firePropertyChangeEvent(Object object,
173
			PropertyChangeEvent originatingEvent) {
174
		firePropertyChangeEvent(new CdmPropertyChangeEvent(object,
175
				originatingEvent));
176
	}
177

    
178
	@Override
179
	public boolean setFocus() {
180
		return getClient().setFocus();
181
	}
182

    
183
	@Override
184
    public void propertyChange(PropertyChangeEvent event) {
185
		firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event));
186
	}
187

    
188
	@Override
189
	public void setBackground(Color color) {
190
		for (ICdmFormElement element : getElements()) {
191
			element.setBackground(color);
192
		}
193
		if (!getLayoutComposite().isDisposed()){
194
			getLayoutComposite().setBackground(color);
195
		}
196
		super.setBackground(color);
197
	}
198

    
199
	@Override
200
	public void setPersistentBackground(Color color) {
201
		persistentBackgroundColor = color;
202
		setBackground(color);
203
	}
204

    
205
	@Override
206
	public Color getPersistentBackground() {
207
		return persistentBackgroundColor;
208
	}
209

    
210
	public void widgetSelected(SelectionEvent e) {
211
        Widget widget = e.widget;
212

    
213
        if (widget instanceof Control) {
214
            Control control = (Control) widget;
215
            if (checkControlAncestryForWidget(control)) {
216
                if (getEntity() != null) {
217
                    IStructuredSelection selection = new StructuredSelection(getEntity());
218
                    if (selectionProvider != null) {
219
                        selectionProvider.setSelection(selection);
220
                    }
221
                }
222
            }
223
        }
224
	}
225

    
226
	private boolean checkControlAncestryForWidget(Control control) {
227
		if (control.equals(this)) {
228
			return true;
229
		} else {
230
			Control parent = control.getParent();
231
			if (parent == null) {
232
				return false;
233
			} else {
234
				return checkControlAncestryForWidget(parent);
235
			}
236
		}
237
	}
238

    
239
	@Override
240
    public void setSelected(boolean selected) {
241
		if (selected) {
242
			setBackground(Display.getCurrent().getSystemColor(
243
					SWT.COLOR_LIST_SELECTION));
244
		} else {
245
			setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
246
		}
247
	}
248

    
249
	@Override
250
    public void selectionChanged(SelectionChangedEvent event) {
251
		if (event.getSelection() == CdmFormFactory.EMPTY_SELECTION) {
252
			return;
253
		}
254

    
255
		IStructuredSelection selection = (IStructuredSelection) event
256
				.getSelection();
257
		setSelected(false);
258

    
259
		Object selectedObject = selection.getFirstElement();
260

    
261
		if (selectedObject != null && selectedObject.equals(getEntity())) {
262
			setSelected(true);
263
		}
264
	}
265

    
266
	public void addSelectionListener(SelectionListener listener) {
267
		addListener(SWT.Selection, new TypedListener(listener));
268
	}
269

    
270
	public void removeSelectionListener(SelectionListener listener) {
271
		removeListener(SWT.Selection, listener);
272
	}
273

    
274
	@Override
275
    public void addElement(ICdmFormElement element) {
276
		elements.add(element);
277
	}
278

    
279
	protected void removeElement(ICdmFormElement element) {
280
		elements.remove(element);
281
	}
282

    
283
	@Override
284
    public void removeElements() {
285
		for (Iterator<ICdmFormElement> formElementIterator = getElements().iterator();formElementIterator.hasNext();) {
286
		    ICdmFormElement childElement = formElementIterator.next();
287
			// recursion
288
			childElement.removeElements();
289

    
290
			// unregister selection arbitrator
291
			if (childElement instanceof ISelectableElement) {
292
				ISelectableElement selectableElement = (ISelectableElement) childElement;
293
				if (selectableElement.getSelectionArbitrator() != null) {
294
					formFactory.destroySelectionArbitrator(selectableElement
295
							.getSelectionArbitrator());
296
				}
297
			}
298

    
299
			// unregister propertyChangeListener
300
			formFactory.removePropertyChangeListener(childElement);
301

    
302
			// dispose of the controls
303
			for (Iterator<Control> controlIterator = childElement.getControls().iterator();controlIterator.hasNext();) {
304
			    Control control = controlIterator.next();
305
				// we added the layoutComposite of the parental element as the
306
				// layout composite to this formElement
307
				// but we do not want to destroy it.
308
				if (control.equals(childElement.getLayoutComposite())) {
309
					continue;
310
				} else {
311
					control.dispose();
312
					control = null;
313
				}
314
			}
315
		}
316

    
317
		elements.clear();
318
	}
319

    
320
	/**
321
	 * Getter for the field <code>parentElement</code>.
322
	 */
323
	@Override
324
    public ICdmFormElement getParentElement() {
325
		return parentElement;
326
	}
327

    
328
	/**
329
	 * Getter for the field <code>elements</code>.
330
	 */
331
	@Override
332
    public Set<ICdmFormElement> getElements() {
333
		return elements;
334
	}
335

    
336
	@Override
337
    public Set<Control> getControls() {
338
		Set<Control> controls = new HashSet<>();
339

    
340
		for (Control control : getChildren()) {
341
			controls.add(control);
342
		}
343

    
344
		return controls;
345
	}
346

    
347
	@Override
348
	public void dispose() {
349
		removeElements();
350
		super.dispose();
351
	}
352

    
353
	@Override
354
    public Composite getLayoutComposite() {
355
		return (Composite) getClient();
356
	}
357

    
358
	@Override
359
    public boolean containsFormElement(ICdmFormElement formElement) {
360
		if (formElement == this) {
361
			return true;
362
		} else {
363
			for (ICdmFormElement element : getElements()) {
364
				boolean contains = element.containsFormElement(formElement);
365
				if (contains == true) {
366
					return true;
367
				}
368
			}
369
			return false;
370
		}
371
	}
372

    
373
	/**
374
	 * Getter for the field <code>formFactory</code>.
375
	 */
376
	@Override
377
    public CdmFormFactory getFormFactory() {
378
		return formFactory;
379
	}
380

    
381
	@Override
382
    public void refresh() {
383
		// empty default implementation
384
	}
385

    
386
}
(4-4/58)