d1587708d4ca1a5956b1836e5e4179525257b971
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / forms / AbstractFormSection.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.ui.forms;
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.forms.widgets.Section;
29 import org.eclipse.ui.forms.widgets.TableWrapLayout;
30 import org.eclipse.ui.forms.widgets.ToggleHyperlink;
31
32 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
33 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
34 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
35 import eu.etaxonomy.taxeditor.store.StoreUtil;
36 import eu.etaxonomy.taxeditor.ui.selection.AbstractSelectionElement;
37 import eu.etaxonomy.taxeditor.ui.term.AbstractEnumComboElement;
38 import eu.etaxonomy.taxeditor.ui.term.AbstractTermComboElement;
39
40 /**
41 * <p>Abstract AbstractFormSection class.</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 ISelectionChangedListener, IEntityElement<ENTITY>, IConversationEnabled{
49
50 private ISelectionProvider selectionProvider;
51
52 private ENTITY entity;
53
54 private Set<ICdmFormElement> elements = new HashSet<ICdmFormElement>();
55
56 protected CdmFormFactory formFactory;
57
58 private List<IPropertyChangeListener> propertyChangeListeners;
59
60 private ICdmFormElement parentElement;
61
62 private ConversationHolder conversation;
63
64 private boolean handlingPropertyChange;
65
66 /**
67 * <p>Constructor for AbstractFormSection.</p>
68 *
69 * @param conversation TODO
70 * @param style a int.
71 * @param formFactory a {@link eu.etaxonomy.taxeditor.ui.forms.CdmFormFactory} object.
72 * @param parentElement a {@link eu.etaxonomy.taxeditor.ui.forms.ICdmFormElement} object.
73 * @param <ENTITY> a ENTITY object.
74 */
75 protected AbstractFormSection(CdmFormFactory formFactory, ConversationHolder conversation, ICdmFormElement parentElement, int style) {
76 super(parentElement.getLayoutComposite(), style);
77
78 this.parentElement = parentElement;
79
80 this.formFactory = formFactory;
81
82 this.conversation = conversation;
83
84 this.setLayoutData(CdmFormFactory.FILL());
85
86 Composite client = formFactory.createComposite(this, SWT.WRAP);
87 client.setBackgroundMode(SWT.INHERIT_DEFAULT);
88
89 TableWrapLayout layout = CdmFormFactory.LAYOUT();
90 layout.bottomMargin = 10;
91 layout.rightMargin = 5;
92
93 client.setLayout(layout);
94
95 this.setClient(client);
96 }
97
98 /**
99 * <p>Constructor for AbstractFormSection.</p>
100 *
101 * @param formFactory a {@link eu.etaxonomy.taxeditor.ui.forms.CdmFormFactory} object.
102 * @param conversation a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
103 * @param parentElement a {@link eu.etaxonomy.taxeditor.ui.forms.ICdmFormElement} object.
104 * @param selectionProvider a {@link org.eclipse.jface.viewers.ISelectionProvider} object.
105 * @param style a int.
106 */
107 protected AbstractFormSection(CdmFormFactory formFactory, ConversationHolder conversation, ICdmFormElement parentElement, ISelectionProvider selectionProvider, int style){
108 this(formFactory, conversation, parentElement, style);
109 this.selectionProvider = selectionProvider;
110 }
111
112 /**
113 * <p>Getter for the field <code>propertyChangeListeners</code>.</p>
114 *
115 * @return a {@link java.util.Set} object.
116 */
117 public List<IPropertyChangeListener> getPropertyChangeListeners() {
118 return propertyChangeListeners;
119 }
120
121 /** {@inheritDoc} */
122 public void setPropertyChangeListeners(
123 List<IPropertyChangeListener> propertyChangeListeners) {
124 this.propertyChangeListeners = propertyChangeListeners;
125 }
126
127 /**
128 * <p>Setter for the field <code>entity</code>.</p>
129 *
130 * @param entity a ENTITY object.
131 */
132 public void setEntity(ENTITY entity){
133 this.entity = entity;
134 }
135
136 /*
137 * (non-Javadoc)
138 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
139 */
140 /**
141 * <p>Getter for the field <code>entity</code>.</p>
142 *
143 * @return a ENTITY object.
144 */
145 public ENTITY getEntity() {
146 return entity;
147 }
148
149 /**
150 * <p>getToggle</p>
151 *
152 * @return a {@link org.eclipse.ui.forms.widgets.ToggleHyperlink} object.
153 */
154 public ToggleHyperlink getToggle(){
155 return this.toggle;
156 }
157
158 /**
159 * <p>getSection</p>
160 *
161 * @return a {@link eu.etaxonomy.taxeditor.ui.forms.AbstractFormSection} object.
162 */
163 public AbstractFormSection<ENTITY> getSection(){
164 return this;
165 }
166
167 /* (non-Javadoc)
168 * @see eu.etaxonomy.taxeditor.forms.IPropertyChangeEmitter#firePropertyChangeEvent()
169 */
170 /** {@inheritDoc} */
171 public void firePropertyChangeEvent(CdmPropertyChangeEvent event) {
172 Assert.isNotNull(propertyChangeListeners, "No property change listeners.");
173 try{
174 for(Object listener : propertyChangeListeners){
175 ((IPropertyChangeListener) listener).propertyChange(event);
176 }
177 }catch(ConcurrentModificationException e){
178 StoreUtil.warn(getClass(), "ConcurrentModificationException while handling PropertyChangeEvents." +
179 " It seems like this is not critical");
180 }
181 }
182
183 /* (non-Javadoc)
184 * @see org.eclipse.swt.widgets.Composite#setFocus()
185 */
186 /** {@inheritDoc} */
187 @Override
188 public boolean setFocus() {
189 return getClient().setFocus();
190 }
191
192 /* (non-Javadoc)
193 * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
194 */
195 /** {@inheritDoc} */
196 public void propertyChange(PropertyChangeEvent event) {
197 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, event));
198 }
199
200 /* (non-Javadoc)
201 * @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
202 */
203 /** {@inheritDoc} */
204 @Override
205 public void setBackground(Color color) {
206 for(ICdmFormElement element : getElements()){
207 element.setBackground(color);
208 }
209 getLayoutComposite().setBackground(color);
210 super.setBackground(color);
211 }
212
213 /**
214 * <p>widgetSelected</p>
215 *
216 * @param e a {@link org.eclipse.swt.events.SelectionEvent} object.
217 */
218 public void widgetSelected(SelectionEvent e) {
219 Widget widget = e.widget;
220
221 if(widget instanceof Control){
222 Control control = (Control) widget;
223 if(checkControlAncestryForWidget(control)){
224 if(getEntity() != null){
225 IStructuredSelection selection = new StructuredSelection(getEntity());
226 if(selectionProvider != null){
227 selectionProvider.setSelection(selection);
228 }
229 }
230 }
231 }
232 }
233
234 private boolean checkControlAncestryForWidget(Control control){
235 if(control.equals(this)){
236 return true;
237 }else{
238 Control parent = control.getParent();
239 if(parent == null){
240 return false;
241 }else{
242 return checkControlAncestryForWidget(parent);
243 }
244 }
245 }
246
247 /** {@inheritDoc} */
248 public void setSelected(boolean selected) {
249 if(selected){
250 setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION));
251 }else{
252 setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
253 }
254 }
255
256
257 /** {@inheritDoc} */
258 public void selectionChanged(SelectionChangedEvent event) {
259 if(event.getSelection() == CdmFormFactory.EMPTY_SELECTION){
260 return;
261 }
262
263 IStructuredSelection selection = (IStructuredSelection) event.getSelection();
264 setSelected(false);
265
266 Object selectedObject = selection.getFirstElement();
267
268 if(selectedObject != null && selectedObject.equals(getEntity())){
269 setSelected(true);
270 }
271 }
272
273 /**
274 * <p>addSelectionListener</p>
275 *
276 * @param listener a {@link org.eclipse.swt.events.SelectionListener} object.
277 */
278 public void addSelectionListener(SelectionListener listener) {
279 addListener(SWT.Selection, new TypedListener(listener));
280 }
281
282 /**
283 * <p>removeSelectionListener</p>
284 *
285 * @param listener a {@link org.eclipse.swt.events.SelectionListener} object.
286 */
287 public void removeSelectionListener(SelectionListener listener) {
288 removeListener(SWT.Selection, listener);
289 }
290
291 /** {@inheritDoc} */
292 public Color getColor(boolean selected) {
293 return selected ? SELECTED : NOT_SELECTED;
294 }
295
296 /** {@inheritDoc} */
297 public void addElement(ICdmFormElement element){
298 elements.add(element);
299 }
300
301 /**
302 * <p>removeElement</p>
303 *
304 * @param element a {@link eu.etaxonomy.taxeditor.ui.forms.ICdmFormElement} object.
305 */
306 protected void removeElement(ICdmFormElement element){
307 elements.remove(element);
308 }
309
310 /**
311 * <p>removeElements</p>
312 */
313 public void removeElements() {
314 for(ICdmFormElement childElement : getElements()){
315 // recursion
316 childElement.removeElements();
317
318 // unregister selection arbitrator
319 if(childElement instanceof ISelectableElement){
320 ISelectableElement selectableElement = (ISelectableElement) childElement;
321 if (selectableElement != null && selectableElement.getSelectionArbitrator() != null) {
322 formFactory.destroySelectionArbitrator(selectableElement.getSelectionArbitrator());
323 }
324 }
325
326 // unregister propertyChangeListener
327 formFactory.removePropertyChangeListener(childElement);
328
329 // dispose of the controls
330 for(Control control : childElement.getControls()){
331 // we added the layoutComposite of the parental element as the layout composite to this formElement
332 // but we do not want to destroy it.
333 if(control.equals(childElement.getLayoutComposite())){
334 continue;
335 }else{
336 control.dispose();
337 control = null;
338 }
339 }
340 }
341
342 elements.clear();
343 }
344
345 /**
346 * <p>Getter for the field <code>parentElement</code>.</p>
347 *
348 * @return a {@link eu.etaxonomy.taxeditor.ui.forms.ICdmFormElement} object.
349 */
350 public ICdmFormElement getParentElement() {
351 return parentElement;
352 }
353
354 /**
355 * <p>Getter for the field <code>elements</code>.</p>
356 *
357 * @return a {@link java.util.Set} object.
358 */
359 public Set<ICdmFormElement> getElements() {
360 return elements;
361 }
362
363 /**
364 * <p>getControls</p>
365 *
366 * @return a {@link java.util.Set} object.
367 */
368 public Set<Control> getControls() {
369 Set<Control> controls = new HashSet<Control>();
370
371 for (Control control : getChildren()){
372 controls.add(control);
373 }
374
375 return controls;
376 }
377
378 /** {@inheritDoc} */
379 @Override
380 public void dispose() {
381 removeElements();
382 super.dispose();
383 }
384
385 /**
386 * <p>getLayoutComposite</p>
387 *
388 * @return a {@link org.eclipse.swt.widgets.Composite} object.
389 */
390 public Composite getLayoutComposite() {
391 return (Composite) getClient();
392 }
393
394 /** {@inheritDoc} */
395 public boolean containsFormElement(ICdmFormElement formElement){
396 if(formElement == this){
397 return true;
398 }else{
399 for(ICdmFormElement element : getElements()){
400 boolean contains = element.containsFormElement(formElement);
401 if(contains == true){
402 return true;
403 }
404 }
405 return false;
406 }
407 }
408
409
410 /**
411 * <p>Getter for the field <code>formFactory</code>.</p>
412 *
413 * @return a {@link eu.etaxonomy.taxeditor.ui.forms.CdmFormFactory} object.
414 */
415 public CdmFormFactory getFormFactory() {
416 return formFactory;
417 }
418
419 /*
420 * (non-Javadoc)
421 * @see eu.etaxonomy.taxeditor.forms.ICdmFormElement#refresh()
422 */
423 /**
424 * <p>refresh</p>
425 */
426 public void refresh() {
427 // empty default implementation
428
429 }
430
431 /**
432 * <p>getConversationHolder</p>
433 *
434 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
435 */
436 public ConversationHolder getConversationHolder() {
437 return conversation;
438 }
439
440 /** {@inheritDoc} */
441 public void update(CdmDataChangeMap changeEvents) {}
442 }