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