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
		getLayoutComposite().setBackground(color);
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
	@Override
387
    public ConversationHolder getConversationHolder() {
388
	    if(AbstractUtility.getActivePart() instanceof IConversationEnabled){
389
            return ((IConversationEnabled) AbstractUtility.getActivePart()).getConversationHolder();
390
        }
391
	    if(getParentElement() instanceof RootElement || getParentElement() == null){
392

    
393
	        Object activeEditor = AbstractUtility.getActiveEditor();
394
	        if(activeEditor instanceof IConversationEnabled){
395
	            ConversationHolder conversation = ((IConversationEnabled) AbstractUtility.getActiveEditor()).getConversationHolder();
396
	            return conversation;
397
	        }
398
	    }else if(getParentElement() instanceof IConversationEnabled){
399
	        return ((IConversationEnabled) getParentElement()).getConversationHolder();
400
	    }
401
		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",
402
				new IllegalArgumentException());
403
		return null;
404

    
405
	}
406

    
407
	@Override
408
    public void update(CdmDataChangeMap changeEvents) {
409

    
410
	}
411

    
412
}
(4-4/57)