Project

General

Profile

Download (14.8 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
 *
3
 */
4
package eu.etaxonomy.taxeditor.ui.element;
5

    
6
import java.util.ConcurrentModificationException;
7
import java.util.HashSet;
8
import java.util.List;
9
import java.util.Set;
10

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

    
33
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
34
import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
35
import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
36
import eu.etaxonomy.taxeditor.model.AbstractUtility;
37
import eu.etaxonomy.taxeditor.model.MessagingUtils;
38

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

    
55
    /**
56
     * The default number of columns in detail sections
57
     */
58
    public static final int DEFAULT_NUM_COLUMNS = 2;
59

    
60
	private ISelectionProvider selectionProvider;
61

    
62
	private ENTITY entity;
63

    
64
	private final Set<ICdmFormElement> elements = new HashSet<ICdmFormElement>();
65

    
66
	protected CdmFormFactory formFactory;
67

    
68
	private List<IPropertyChangeListener> propertyChangeListeners;
69

    
70
	private ICdmFormElement parentElement;
71

    
72
	private Color persistentBackgroundColor;
73

    
74
	/**
75
	 * <p>
76
	 * Constructor for AbstractFormSection.
77
	 * </p>
78
	 *
79
	 * @param conversation
80
	 *            TODO
81
	 * @param style
82
	 *            a int.
83
	 * @param formFactory
84
	 *            a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
85
	 *            object.
86
	 * @param parentElement
87
	 *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
88
	 *            object.
89
	 * @param <ENTITY>
90
	 *            a ENTITY object.
91
	 */
92
    protected AbstractFormSection(CdmFormFactory formFactory, ICdmFormElement parentElement, int style) {
93
		super(parentElement.getLayoutComposite(), style);
94

    
95
		this.parentElement = parentElement;
96

    
97
		this.formFactory = formFactory;
98

    
99
		this.setLayoutData(LayoutConstants.FILL());
100

    
101
		Composite client = formFactory.createComposite(this, SWT.WRAP);
102
		client.setBackgroundMode(SWT.INHERIT_DEFAULT);
103

    
104
		TableWrapLayout layout = LayoutConstants.LAYOUT();
105
		layout.bottomMargin = 10;
106
		layout.rightMargin = 5;
107
		layout.horizontalSpacing = 5;
108

    
109
		client.setLayout(layout);
110

    
111
		this.setClient(client);
112

    
113
	}
114

    
115
	    /**
116
     * <p>
117
     * Constructor for AbstractFormSection.
118
     * </p>
119
     *
120
     * @param formFactory
121
     *            a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
122
     *            object.
123
     * @param conversation
124
     *            a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
125
     *            object.
126
     * @param parentElement
127
     *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
128
     *            object.
129
     * @param selectionProvider
130
     *            a {@link org.eclipse.jface.viewers.ISelectionProvider} object.
131
     * @param style
132
     *            a int.
133
     */
134
    protected AbstractFormSection(CdmFormFactory formFactory, ICdmFormElement parentElement, ISelectionProvider selectionProvider, int style) {
135
        this(formFactory, parentElement, style);
136
        this.selectionProvider = selectionProvider;
137
    }
138

    
139
	/**
140
	 * <p>
141
	 * Getter for the field <code>propertyChangeListeners</code>.
142
	 * </p>
143
	 *
144
	 * @return a {@link java.util.Set} object.
145
	 */
146
	@Override
147
    public List<IPropertyChangeListener> getPropertyChangeListeners() {
148
		return propertyChangeListeners;
149
	}
150

    
151
	/** {@inheritDoc} */
152
	@Override
153
    public void setPropertyChangeListeners(
154
			List<IPropertyChangeListener> propertyChangeListeners) {
155
		this.propertyChangeListeners = propertyChangeListeners;
156
	}
157

    
158
	/**
159
	 * <p>
160
	 * Setter for the field <code>entity</code>.
161
	 * </p>
162
	 *
163
	 * @param entity
164
	 *            a ENTITY object.
165
	 */
166
	public void setEntity(ENTITY entity) {
167
		this.entity = entity;
168
	}
169

    
170
	/*
171
	 * (non-Javadoc)
172
	 *
173
	 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
174
	 */
175
	/**
176
	 * <p>
177
	 * Getter for the field <code>entity</code>.
178
	 * </p>
179
	 *
180
	 * @return a ENTITY object.
181
	 */
182
	@Override
183
    public ENTITY getEntity() {
184
		return entity;
185
	}
186

    
187
	/**
188
	 * <p>
189
	 * getToggle
190
	 * </p>
191
	 *
192
	 * @return a {@link org.eclipse.ui.forms.widgets.ToggleHyperlink} object.
193
	 */
194
	public ToggleHyperlink getToggle() {
195
		return this.toggle;
196
	}
197

    
198
	/**
199
	 * <p>
200
	 * getSection
201
	 * </p>
202
	 *
203
	 * @return a {@link eu.etaxonomy.taxeditor.ui.element.AbstractFormSection}
204
	 *         object.
205
	 */
206
	public AbstractFormSection<ENTITY> getSection() {
207
		return this;
208
	}
209

    
210
	/*
211
	 * (non-Javadoc)
212
	 *
213
	 * @see
214
	 * eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent
215
	 * ()
216
	 */
217
	/** {@inheritDoc} */
218
	@Override
219
    public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
220
        Assert.isNotNull(propertyChangeListeners, "No property change listeners.");
221
        try {
222
            for (Object listener : propertyChangeListeners) {
223
                ((IPropertyChangeListener) listener).propertyChange(event);
224
            }
225
        } catch (ConcurrentModificationException e) {
226
            MessagingUtils.warn(getClass(), "ConcurrentModificationException while handling PropertyChangeEvents."
227
                    + " It seems like this is not critical");
228
        }
229
	}
230

    
231
	/**
232
	 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
233
	 *
234
	 * @param object
235
	 *            the object on which the property changed
236
	 */
237
	public void firePropertyChangeEvent(Object object) {
238
		firePropertyChangeEvent(object, null);
239
	}
240

    
241
	/**
242
	 * Fires a {@link CdmPropertyChangeEvent} with the given object as source
243
	 * also containing the originating event
244
	 *
245
	 * @param object
246
	 *            the object on which the property changed
247
	 * @param originatingEvent
248
	 *            the originating event
249
	 */
250
	public void firePropertyChangeEvent(Object object,
251
			PropertyChangeEvent originatingEvent) {
252
		firePropertyChangeEvent(new CdmPropertyChangeEvent(object,
253
				originatingEvent));
254
	}
255

    
256
	/*
257
	 * (non-Javadoc)
258
	 *
259
	 * @see org.eclipse.swt.widgets.Composite#setFocus()
260
	 */
261
	/** {@inheritDoc} */
262
	@Override
263
	public boolean setFocus() {
264
		return getClient().setFocus();
265
	}
266

    
267
	/*
268
	 * (non-Javadoc)
269
	 *
270
	 * @see
271
	 * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
272
	 * .jface.util.PropertyChangeEvent)
273
	 */
274
	/** {@inheritDoc} */
275
	@Override
276
    public void propertyChange(PropertyChangeEvent event) {
277
		firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event));
278
	}
279

    
280
	/*
281
	 * (non-Javadoc)
282
	 *
283
	 * @see
284
	 * org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics
285
	 * .Color)
286
	 */
287
	/** {@inheritDoc} */
288
	@Override
289
	public void setBackground(Color color) {
290
		for (ICdmFormElement element : getElements()) {
291
			element.setBackground(color);
292
		}
293
		getLayoutComposite().setBackground(color);
294
		super.setBackground(color);
295
	}
296

    
297
	@Override
298
	public void setPersistentBackground(Color color) {
299
		persistentBackgroundColor = color;
300
		setBackground(color);
301
	}
302

    
303
	@Override
304
	public Color getPersistentBackground() {
305
		return persistentBackgroundColor;
306
	}
307

    
308

    
309
	/**
310
	 * <p>
311
	 * widgetSelected
312
	 * </p>
313
	 *
314
	 * @param e
315
	 *            a {@link org.eclipse.swt.events.SelectionEvent} object.
316
	 */
317
	public void widgetSelected(SelectionEvent e) {
318
        Widget widget = e.widget;
319

    
320
        if (widget instanceof Control) {
321
            Control control = (Control) widget;
322
            if (checkControlAncestryForWidget(control)) {
323
                if (getEntity() != null) {
324
                    IStructuredSelection selection = new StructuredSelection(getEntity());
325
                    if (selectionProvider != null) {
326
                        selectionProvider.setSelection(selection);
327
                    }
328
                }
329
            }
330
        }
331
	}
332

    
333
	private boolean checkControlAncestryForWidget(Control control) {
334
		if (control.equals(this)) {
335
			return true;
336
		} else {
337
			Control parent = control.getParent();
338
			if (parent == null) {
339
				return false;
340
			} else {
341
				return checkControlAncestryForWidget(parent);
342
			}
343
		}
344
	}
345

    
346
	/** {@inheritDoc} */
347
	@Override
348
    public void setSelected(boolean selected) {
349
		if (selected) {
350
			setBackground(Display.getCurrent().getSystemColor(
351
					SWT.COLOR_LIST_SELECTION));
352
		} else {
353
			setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
354
		}
355
	}
356

    
357
	/** {@inheritDoc} */
358
	@Override
359
    public void selectionChanged(SelectionChangedEvent event) {
360
		if (event.getSelection() == CdmFormFactory.EMPTY_SELECTION) {
361
			return;
362
		}
363

    
364
		IStructuredSelection selection = (IStructuredSelection) event
365
				.getSelection();
366
		setSelected(false);
367

    
368
		Object selectedObject = selection.getFirstElement();
369

    
370
		if (selectedObject != null && selectedObject.equals(getEntity())) {
371
			setSelected(true);
372
		}
373
	}
374

    
375
	/**
376
	 * <p>
377
	 * addSelectionListener
378
	 * </p>
379
	 *
380
	 * @param listener
381
	 *            a {@link org.eclipse.swt.events.SelectionListener} object.
382
	 */
383
	public void addSelectionListener(SelectionListener listener) {
384
		addListener(SWT.Selection, new TypedListener(listener));
385
	}
386

    
387
	/**
388
	 * <p>
389
	 * removeSelectionListener
390
	 * </p>
391
	 *
392
	 * @param listener
393
	 *            a {@link org.eclipse.swt.events.SelectionListener} object.
394
	 */
395
	public void removeSelectionListener(SelectionListener listener) {
396
		removeListener(SWT.Selection, listener);
397
	}
398

    
399
	/** {@inheritDoc} */
400
	@Override
401
    public void addElement(ICdmFormElement element) {
402
		elements.add(element);
403
	}
404

    
405
	/**
406
	 * <p>
407
	 * removeElement
408
	 * </p>
409
	 *
410
	 * @param element
411
	 *            a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
412
	 *            object.
413
	 */
414
	protected void removeElement(ICdmFormElement element) {
415
		elements.remove(element);
416
	}
417

    
418
	/**
419
	 * <p>
420
	 * removeElements
421
	 * </p>
422
	 */
423
	@Override
424
    public void removeElements() {
425
		for (ICdmFormElement childElement : getElements()) {
426
			// recursion
427
			childElement.removeElements();
428

    
429
			// unregister selection arbitrator
430
			if (childElement instanceof ISelectableElement) {
431
				ISelectableElement selectableElement = (ISelectableElement) childElement;
432
				if (selectableElement.getSelectionArbitrator() != null) {
433
					formFactory.destroySelectionArbitrator(selectableElement
434
							.getSelectionArbitrator());
435
				}
436
			}
437

    
438
			// unregister propertyChangeListener
439
			formFactory.removePropertyChangeListener(childElement);
440

    
441
			// dispose of the controls
442
			for (Control control : childElement.getControls()) {
443
				// we added the layoutComposite of the parental element as the
444
				// layout composite to this formElement
445
				// but we do not want to destroy it.
446
				if (control.equals(childElement.getLayoutComposite())) {
447
					continue;
448
				} else {
449
					control.dispose();
450
					control = null;
451
				}
452
			}
453
		}
454

    
455
		elements.clear();
456
	}
457

    
458
	/**
459
	 * <p>
460
	 * Getter for the field <code>parentElement</code>.
461
	 * </p>
462
	 *
463
	 * @return a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
464
	 */
465
	@Override
466
    public ICdmFormElement getParentElement() {
467
		return parentElement;
468
	}
469

    
470
	/**
471
	 * <p>
472
	 * Getter for the field <code>elements</code>.
473
	 * </p>
474
	 *
475
	 * @return a {@link java.util.Set} object.
476
	 */
477
	@Override
478
    public Set<ICdmFormElement> getElements() {
479
		return elements;
480
	}
481

    
482
	/**
483
	 * <p>
484
	 * getControls
485
	 * </p>
486
	 *
487
	 * @return a {@link java.util.Set} object.
488
	 */
489
	@Override
490
    public Set<Control> getControls() {
491
		Set<Control> controls = new HashSet<Control>();
492

    
493
		for (Control control : getChildren()) {
494
			controls.add(control);
495
		}
496

    
497
		return controls;
498
	}
499

    
500
	/** {@inheritDoc} */
501
	@Override
502
	public void dispose() {
503
		removeElements();
504
		super.dispose();
505
	}
506

    
507
	/**
508
	 * <p>
509
	 * getLayoutComposite
510
	 * </p>
511
	 *
512
	 * @return a {@link org.eclipse.swt.widgets.Composite} object.
513
	 */
514
	@Override
515
    public Composite getLayoutComposite() {
516
		return (Composite) getClient();
517
	}
518

    
519
	/** {@inheritDoc} */
520
	@Override
521
    public boolean containsFormElement(ICdmFormElement formElement) {
522
		if (formElement == this) {
523
			return true;
524
		} else {
525
			for (ICdmFormElement element : getElements()) {
526
				boolean contains = element.containsFormElement(formElement);
527
				if (contains == true) {
528
					return true;
529
				}
530
			}
531
			return false;
532
		}
533
	}
534

    
535
	/**
536
	 * <p>
537
	 * Getter for the field <code>formFactory</code>.
538
	 * </p>
539
	 *
540
	 * @return a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
541
	 */
542
	@Override
543
    public CdmFormFactory getFormFactory() {
544
		return formFactory;
545
	}
546

    
547
	/*
548
	 * (non-Javadoc)
549
	 *
550
	 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
551
	 */
552
	/**
553
	 * <p>
554
	 * refresh
555
	 * </p>
556
	 */
557
	@Override
558
    public void refresh() {
559
		// empty default implementation
560

    
561
	}
562

    
563
	/**
564
	 * <p>
565
	 * getConversationHolder
566
	 * </p>
567
	 *
568
	 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
569
	 *         object.
570
	 */
571
	@Override
572
    public ConversationHolder getConversationHolder() {
573
	    if(AbstractUtility.getActivePart() instanceof IConversationEnabled){
574
            return ((IConversationEnabled) AbstractUtility.getActivePart()).getConversationHolder();
575
        }
576
	    if(getParentElement() instanceof RootElement || getParentElement() == null){
577

    
578
	        IEditorPart activeEditor = AbstractUtility.getActiveEditor();
579
	        if(activeEditor instanceof IConversationEnabled){
580
	            ConversationHolder conversation = ((IConversationEnabled) AbstractUtility.getActiveEditor()).getConversationHolder();
581
	            return conversation;
582
	        }
583
	    }else if(getParentElement() instanceof IConversationEnabled){
584
	        return ((IConversationEnabled) getParentElement()).getConversationHolder();
585
	    }
586
		MessagingUtils.messageDialog("Could not get conversation for AbstractFormSection",
587
				getClass(), "There is an error in the implementation. There should have been an active editor but it wasn't",
588
				new IllegalArgumentException());
589
		return null;
590

    
591
	}
592

    
593
	/** {@inheritDoc} */
594

    
595
	@Override
596
    public void update(CdmDataChangeMap changeEvents) {
597

    
598
	}
599

    
600

    
601
}
(4-4/42)