Project

General

Profile

Download (11.5 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.api.conversation.ConversationHolder;
39
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
40
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
41
import eu.etaxonomy.taxeditor.model.AbstractUtility;
42
import eu.etaxonomy.taxeditor.model.MessagingUtils;
43

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

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

    
65
	private ISelectionProvider selectionProvider;
66

    
67
	private ENTITY entity;
68

    
69
	private final Set<ICdmFormElement> elements = new HashSet<>();
70

    
71
	protected CdmFormFactory formFactory;
72

    
73
	private List<IPropertyChangeListener> propertyChangeListeners;
74

    
75
	private ICdmFormElement parentElement;
76

    
77
	private Color persistentBackgroundColor;
78

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

    
85
		this.parentElement = parentElement;
86

    
87
		this.formFactory = formFactory;
88

    
89
		this.setLayoutData(LayoutConstants.FILL());
90

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

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

    
99
		client.setLayout(layout);
100

    
101
		this.setClient(client);
102
	}
103

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

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

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

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

    
134
	public ToggleHyperlink getToggle() {
135
		return this.toggle;
136
	}
137

    
138
	public AbstractFormSection<ENTITY> getSection() {
139
		return this;
140
	}
141

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

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

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

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

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

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

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

    
207
	@Override
208
	public Color getPersistentBackground() {
209
		return persistentBackgroundColor;
210
	}
211

    
212
	public void widgetSelected(SelectionEvent e) {
213
        Widget widget = e.widget;
214

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

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

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

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

    
257
		IStructuredSelection selection = (IStructuredSelection) event
258
				.getSelection();
259
		setSelected(false);
260

    
261
		Object selectedObject = selection.getFirstElement();
262

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

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

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

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

    
281
	protected void removeElement(ICdmFormElement element) {
282
		elements.remove(element);
283
	}
284

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

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

    
301
			// unregister propertyChangeListener
302
			formFactory.removePropertyChangeListener(childElement);
303

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

    
319
		elements.clear();
320
	}
321

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

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

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

    
342
		for (Control control : getChildren()) {
343
			controls.add(control);
344
		}
345

    
346
		return controls;
347
	}
348

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

    
355
	@Override
356
    public Composite getLayoutComposite() {
357
		return (Composite) getClient();
358
	}
359

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

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

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

    
388
	@Override
389
    public ConversationHolder getConversationHolder() {
390
	    if(AbstractUtility.getActivePart() instanceof IConversationEnabled){
391
            return ((IConversationEnabled) AbstractUtility.getActivePart()).getConversationHolder();
392
        }
393
	    if(getParentElement() instanceof RootElement || getParentElement() == null){
394

    
395
	        Object activeEditor = AbstractUtility.getActiveEditor();
396
	        if(activeEditor instanceof IConversationEnabled){
397
	            ConversationHolder conversation = ((IConversationEnabled) AbstractUtility.getActiveEditor()).getConversationHolder();
398
	            return conversation;
399
	        }
400
	    }else if(getParentElement() instanceof IConversationEnabled){
401
	        return ((IConversationEnabled) getParentElement()).getConversationHolder();
402
	    }
403
		MessagingUtils.error(getClass(), "Could not get conversation for AbstractFormSection. There is an error in the implementation. There should have been an active editor but it wasn't",
404
				new IllegalArgumentException());
405
		return null;
406

    
407
	}
408

    
409
	@Override
410
    public void update(CdmDataChangeMap changeEvents) {
411

    
412
	}
413

    
414
}
(4-4/58)