Project

General

Profile

Download (14.5 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

    
108
		client.setLayout(layout);
109

    
110
		this.setClient(client);
111

    
112
	}
113

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
307

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

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

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

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

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

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

    
367
		Object selectedObject = selection.getFirstElement();
368

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

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

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

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

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

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

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

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

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

    
454
		elements.clear();
455
	}
456

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

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

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

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

    
496
		return controls;
497
	}
498

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

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

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

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

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

    
560
	}
561

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

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

    
587
	}
588

    
589
	/** {@inheritDoc} */
590

    
591
	@Override
592
    public void update(CdmDataChangeMap changeEvents) {
593

    
594
	}
595

    
596

    
597
}
(4-4/42)