- formatted code
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / element / AbstractFormSection.java
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.store.StoreUtil;
37
38 /**
39 * <p>
40 * Abstract AbstractFormSection class.
41 * </p>
42 *
43 * @author n.hoffmann
44 * @created Feb 22, 2010
45 * @version 1.0
46 * @param <T>
47 */
48 public abstract class AbstractFormSection<ENTITY> extends Section implements
49 ISelectionChangedListener, ICdmFormElement, IEntityElement<ENTITY>,
50 IConversationEnabled {
51
52 private ISelectionProvider selectionProvider;
53
54 private ENTITY entity;
55
56 private final Set<ICdmFormElement> elements = new HashSet<ICdmFormElement>();
57
58 protected CdmFormFactory formFactory;
59
60 private List<IPropertyChangeListener> propertyChangeListeners;
61
62 private ICdmFormElement parentElement;
63
64 private Color persistentBackgroundColor;
65
66 /**
67 * <p>
68 * Constructor for AbstractFormSection.
69 * </p>
70 *
71 * @param conversation
72 * TODO
73 * @param style
74 * a int.
75 * @param formFactory
76 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
77 * object.
78 * @param parentElement
79 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
80 * object.
81 * @param <ENTITY>
82 * a ENTITY object.
83 */
84 protected AbstractFormSection(CdmFormFactory formFactory, ICdmFormElement parentElement,
85 int style) {
86 super(parentElement.getLayoutComposite(), style);
87
88 this.parentElement = parentElement;
89
90 this.formFactory = formFactory;
91
92 this.setLayoutData(LayoutConstants.FILL());
93
94 Composite client = formFactory.createComposite(this, SWT.WRAP);
95 client.setBackgroundMode(SWT.INHERIT_DEFAULT);
96
97 TableWrapLayout layout = LayoutConstants.LAYOUT();
98 layout.bottomMargin = 10;
99 layout.rightMargin = 5;
100
101 client.setLayout(layout);
102
103 this.setClient(client);
104 }
105
106 /**
107 * <p>
108 * Constructor for AbstractFormSection.
109 * </p>
110 *
111 * @param formFactory
112 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
113 * object.
114 * @param conversation
115 * a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
116 * object.
117 * @param parentElement
118 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
119 * object.
120 * @param selectionProvider
121 * a {@link org.eclipse.jface.viewers.ISelectionProvider} object.
122 * @param style
123 * a int.
124 */
125 protected AbstractFormSection(CdmFormFactory formFactory,
126 ICdmFormElement parentElement,
127 ISelectionProvider selectionProvider, int style) {
128 this(formFactory, parentElement, style);
129 this.selectionProvider = selectionProvider;
130 }
131
132 /**
133 * <p>
134 * Getter for the field <code>propertyChangeListeners</code>.
135 * </p>
136 *
137 * @return a {@link java.util.Set} object.
138 */
139 @Override
140 public List<IPropertyChangeListener> getPropertyChangeListeners() {
141 return propertyChangeListeners;
142 }
143
144 /** {@inheritDoc} */
145 @Override
146 public void setPropertyChangeListeners(
147 List<IPropertyChangeListener> propertyChangeListeners) {
148 this.propertyChangeListeners = propertyChangeListeners;
149 }
150
151 /**
152 * <p>
153 * Setter for the field <code>entity</code>.
154 * </p>
155 *
156 * @param entity
157 * a ENTITY object.
158 */
159 public void setEntity(ENTITY entity) {
160 this.entity = entity;
161 }
162
163 /*
164 * (non-Javadoc)
165 *
166 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
167 */
168 /**
169 * <p>
170 * Getter for the field <code>entity</code>.
171 * </p>
172 *
173 * @return a ENTITY object.
174 */
175 @Override
176 public ENTITY getEntity() {
177 return entity;
178 }
179
180 /**
181 * <p>
182 * getToggle
183 * </p>
184 *
185 * @return a {@link org.eclipse.ui.forms.widgets.ToggleHyperlink} object.
186 */
187 public ToggleHyperlink getToggle() {
188 return this.toggle;
189 }
190
191 /**
192 * <p>
193 * getSection
194 * </p>
195 *
196 * @return a {@link eu.etaxonomy.taxeditor.ui.element.AbstractFormSection}
197 * object.
198 */
199 public AbstractFormSection<ENTITY> getSection() {
200 return this;
201 }
202
203 /*
204 * (non-Javadoc)
205 *
206 * @see
207 * eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent
208 * ()
209 */
210 /** {@inheritDoc} */
211 @Override
212 public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
213 Assert.isNotNull(propertyChangeListeners,
214 "No property change listeners.");
215 try {
216 for (Object listener : propertyChangeListeners) {
217 ((IPropertyChangeListener) listener).propertyChange(event);
218 }
219 } catch (ConcurrentModificationException e) {
220 StoreUtil.warn(getClass(),
221 "ConcurrentModificationException while handling PropertyChangeEvents."
222 + " It seems like this is not critical");
223 }
224 }
225
226 /**
227 * Fires a {@link CdmPropertyChangeEvent} with the given object as source.
228 *
229 * @param object
230 * the object on which the property changed
231 */
232 public void firePropertyChangeEvent(Object object) {
233 firePropertyChangeEvent(object, null);
234 }
235
236 /**
237 * Fires a {@link CdmPropertyChangeEvent} with the given object as source
238 * also containing the originating event
239 *
240 * @param object
241 * the object on which the property changed
242 * @param originatingEvent
243 * the originating event
244 */
245 public void firePropertyChangeEvent(Object object,
246 PropertyChangeEvent originatingEvent) {
247 firePropertyChangeEvent(new CdmPropertyChangeEvent(object,
248 originatingEvent));
249 }
250
251 /*
252 * (non-Javadoc)
253 *
254 * @see org.eclipse.swt.widgets.Composite#setFocus()
255 */
256 /** {@inheritDoc} */
257 @Override
258 public boolean setFocus() {
259 return getClient().setFocus();
260 }
261
262 /*
263 * (non-Javadoc)
264 *
265 * @see
266 * org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse
267 * .jface.util.PropertyChangeEvent)
268 */
269 /** {@inheritDoc} */
270 @Override
271 public void propertyChange(PropertyChangeEvent event) {
272 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event));
273 }
274
275 /*
276 * (non-Javadoc)
277 *
278 * @see
279 * org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics
280 * .Color)
281 */
282 /** {@inheritDoc} */
283 @Override
284 public void setBackground(Color color) {
285 for (ICdmFormElement element : getElements()) {
286 element.setBackground(color);
287 }
288 getLayoutComposite().setBackground(color);
289 super.setBackground(color);
290 }
291
292 @Override
293 public void setPersistentBackground(Color color) {
294 persistentBackgroundColor = color;
295 setBackground(color);
296 }
297
298 @Override
299 public Color getPersistentBackground() {
300 return persistentBackgroundColor;
301 }
302
303
304 /**
305 * <p>
306 * widgetSelected
307 * </p>
308 *
309 * @param e
310 * a {@link org.eclipse.swt.events.SelectionEvent} object.
311 */
312 public void widgetSelected(SelectionEvent e) {
313 Widget widget = e.widget;
314
315 if (widget instanceof Control) {
316 Control control = (Control) widget;
317 if (checkControlAncestryForWidget(control)) {
318 if (getEntity() != null) {
319 IStructuredSelection selection = new StructuredSelection(
320 getEntity());
321 if (selectionProvider != null) {
322 selectionProvider.setSelection(selection);
323 }
324 }
325 }
326 }
327 }
328
329 private boolean checkControlAncestryForWidget(Control control) {
330 if (control.equals(this)) {
331 return true;
332 } else {
333 Control parent = control.getParent();
334 if (parent == null) {
335 return false;
336 } else {
337 return checkControlAncestryForWidget(parent);
338 }
339 }
340 }
341
342 /** {@inheritDoc} */
343 @Override
344 public void setSelected(boolean selected) {
345 if (selected) {
346 setBackground(Display.getCurrent().getSystemColor(
347 SWT.COLOR_LIST_SELECTION));
348 } else {
349 setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
350 }
351 }
352
353 /** {@inheritDoc} */
354 @Override
355 public void selectionChanged(SelectionChangedEvent event) {
356 if (event.getSelection() == CdmFormFactory.EMPTY_SELECTION) {
357 return;
358 }
359
360 IStructuredSelection selection = (IStructuredSelection) event
361 .getSelection();
362 setSelected(false);
363
364 Object selectedObject = selection.getFirstElement();
365
366 if (selectedObject != null && selectedObject.equals(getEntity())) {
367 setSelected(true);
368 }
369 }
370
371 /**
372 * <p>
373 * addSelectionListener
374 * </p>
375 *
376 * @param listener
377 * a {@link org.eclipse.swt.events.SelectionListener} object.
378 */
379 public void addSelectionListener(SelectionListener listener) {
380 addListener(SWT.Selection, new TypedListener(listener));
381 }
382
383 /**
384 * <p>
385 * removeSelectionListener
386 * </p>
387 *
388 * @param listener
389 * a {@link org.eclipse.swt.events.SelectionListener} object.
390 */
391 public void removeSelectionListener(SelectionListener listener) {
392 removeListener(SWT.Selection, listener);
393 }
394
395 /** {@inheritDoc} */
396 @Override
397 public void addElement(ICdmFormElement element) {
398 elements.add(element);
399 }
400
401 /**
402 * <p>
403 * removeElement
404 * </p>
405 *
406 * @param element
407 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
408 * object.
409 */
410 protected void removeElement(ICdmFormElement element) {
411 elements.remove(element);
412 }
413
414 /**
415 * <p>
416 * removeElements
417 * </p>
418 */
419 @Override
420 public void removeElements() {
421 for (ICdmFormElement childElement : getElements()) {
422 // recursion
423 childElement.removeElements();
424
425 // unregister selection arbitrator
426 if (childElement instanceof ISelectableElement) {
427 ISelectableElement selectableElement = (ISelectableElement) childElement;
428 if (selectableElement != null
429 && selectableElement.getSelectionArbitrator() != null) {
430 formFactory.destroySelectionArbitrator(selectableElement
431 .getSelectionArbitrator());
432 }
433 }
434
435 // unregister propertyChangeListener
436 formFactory.removePropertyChangeListener(childElement);
437
438 // dispose of the controls
439 for (Control control : childElement.getControls()) {
440 // we added the layoutComposite of the parental element as the
441 // layout composite to this formElement
442 // but we do not want to destroy it.
443 if (control.equals(childElement.getLayoutComposite())) {
444 continue;
445 } else {
446 control.dispose();
447 control = null;
448 }
449 }
450 }
451
452 elements.clear();
453 }
454
455 /**
456 * <p>
457 * Getter for the field <code>parentElement</code>.
458 * </p>
459 *
460 * @return a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
461 */
462 @Override
463 public ICdmFormElement getParentElement() {
464 return parentElement;
465 }
466
467 /**
468 * <p>
469 * Getter for the field <code>elements</code>.
470 * </p>
471 *
472 * @return a {@link java.util.Set} object.
473 */
474 @Override
475 public Set<ICdmFormElement> getElements() {
476 return elements;
477 }
478
479 /**
480 * <p>
481 * getControls
482 * </p>
483 *
484 * @return a {@link java.util.Set} object.
485 */
486 @Override
487 public Set<Control> getControls() {
488 Set<Control> controls = new HashSet<Control>();
489
490 for (Control control : getChildren()) {
491 controls.add(control);
492 }
493
494 return controls;
495 }
496
497 /** {@inheritDoc} */
498 @Override
499 public void dispose() {
500 removeElements();
501 super.dispose();
502 }
503
504 /**
505 * <p>
506 * getLayoutComposite
507 * </p>
508 *
509 * @return a {@link org.eclipse.swt.widgets.Composite} object.
510 */
511 @Override
512 public Composite getLayoutComposite() {
513 return (Composite) getClient();
514 }
515
516 /** {@inheritDoc} */
517 @Override
518 public boolean containsFormElement(ICdmFormElement formElement) {
519 if (formElement == this) {
520 return true;
521 } else {
522 for (ICdmFormElement element : getElements()) {
523 boolean contains = element.containsFormElement(formElement);
524 if (contains == true) {
525 return true;
526 }
527 }
528 return false;
529 }
530 }
531
532 /**
533 * <p>
534 * Getter for the field <code>formFactory</code>.
535 * </p>
536 *
537 * @return a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
538 */
539 public CdmFormFactory getFormFactory() {
540 return formFactory;
541 }
542
543 /*
544 * (non-Javadoc)
545 *
546 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
547 */
548 /**
549 * <p>
550 * refresh
551 * </p>
552 */
553 @Override
554 public void refresh() {
555 // empty default implementation
556
557 }
558
559 /**
560 * <p>
561 * getConversationHolder
562 * </p>
563 *
564 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
565 * object.
566 */
567 @Override
568 public ConversationHolder getConversationHolder() {
569 if(getParentElement() instanceof RootElement || getParentElement() == null){
570
571 IEditorPart activeEditor = StoreUtil.getActiveEditor();
572 if(activeEditor instanceof IConversationEnabled){
573 ConversationHolder conversation = ((IConversationEnabled) StoreUtil.getActiveEditor()).getConversationHolder();
574 return conversation;
575 }
576 }else if(getParentElement() instanceof IConversationEnabled){
577 return ((IConversationEnabled) getParentElement()).getConversationHolder();
578 }
579 StoreUtil.errorDialog("Could not get conversation for AbstractFormSection",
580 getClass(), "There is an error in the implementation. There should have been an active editor but it wasn't",
581 new IllegalArgumentException());
582 return null;
583
584 }
585
586 /** {@inheritDoc} */
587 @Override
588 public void update(CdmDataChangeMap changeEvents) {
589 }
590
591
592 }