Project

General

Profile

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

    
6
import java.util.Collection;
7
import java.util.EnumSet;
8
import java.util.Observable;
9
import java.util.Observer;
10

    
11
import org.eclipse.jface.action.Action;
12
import org.eclipse.jface.action.IAction;
13
import org.eclipse.jface.action.ToolBarManager;
14
import org.eclipse.jface.resource.ImageDescriptor;
15
import org.eclipse.swt.SWT;
16
import org.eclipse.swt.events.DisposeEvent;
17
import org.eclipse.swt.events.DisposeListener;
18
import org.eclipse.swt.events.SelectionAdapter;
19
import org.eclipse.swt.events.SelectionEvent;
20
import org.eclipse.swt.events.SelectionListener;
21
import org.eclipse.swt.graphics.Color;
22
import org.eclipse.swt.graphics.ImageData;
23
import org.eclipse.swt.widgets.Composite;
24
import org.eclipse.swt.widgets.Control;
25
import org.eclipse.swt.widgets.Label;
26
import org.eclipse.ui.forms.events.ExpansionEvent;
27
import org.eclipse.ui.forms.events.IExpansionListener;
28
import org.eclipse.ui.forms.widgets.ExpandableComposite;
29

    
30
import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
31
import eu.etaxonomy.cdm.common.CdmUtils;
32
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
33
import eu.etaxonomy.taxeditor.model.AbstractUtility;
34
import eu.etaxonomy.taxeditor.model.ImageResources;
35
import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
36
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
37
import eu.etaxonomy.taxeditor.preference.Resources;
38
import eu.etaxonomy.taxeditor.store.CdmStore;
39
import eu.etaxonomy.taxeditor.store.LoginManager;
40
import eu.etaxonomy.taxeditor.store.StoreUtil;
41
import eu.etaxonomy.taxeditor.ui.element.AbstractFormSection;
42
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
43
import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
44

    
45
/**
46
 * This class visualizes an CDM entity of type ENTITY and additionally provides the functionality to add
47
 * other elements of type ELEMENT to them.
48
 *
49
 * @param <ENTITY> A CDM entity which should be visualized by this section.
50
 * @param <ELEMENT> An element that can be added (multiple times) to this entity.
51
 *
52
 * @author n.hoffmann
53
 * @version $Id: $
54
 */
55

    
56
public abstract class AbstractEntityCollectionSection<ENTITY, ELEMENT> extends AbstractFormSection<ENTITY> implements IExpansionListener, Observer {
57

    
58
    private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
59

    
60
    protected Composite container;
61

    
62
	private Label label_empty;
63

    
64
	private String title;
65

    
66
    private AbstractEntityCollectionElement entityCollectionElement;
67

    
68
	public AbstractEntityCollectionSection(CdmFormFactory formFactory, ConversationHolder conversation, ICdmFormElement parentElement, String title, int style) {
69
		super(formFactory, parentElement, ExpandableComposite.CLIENT_INDENT | style);
70
		this.title = title;
71
		this.setText(getTitleString());
72
		updateToolbar();
73

    
74
		addExpansionListener(this);
75

    
76
		CdmStore.getLoginManager().addObserver(this);
77
		addDisposeListener(new DisposeListener() {
78
            @Override
79
            public void widgetDisposed(DisposeEvent e) {
80
                CdmStore.getLoginManager().deleteObserver(AbstractEntityCollectionSection.this);
81
            }
82
        });
83
	}
84

    
85
	protected Control createToolbar() {
86
		ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
87

    
88
		Action addAction = new Action("add", IAction.AS_PUSH_BUTTON){
89
			@Override
90
			public void run() {
91
				ELEMENT element = createNewElement();
92
				if(element != null){
93
					addElement(element);
94
					if(! getSection().isExpanded()) {
95
                        getSection().setExpanded(true);
96
                    }
97
					internalUpdateSection(true);
98
				}
99
			}
100
		};
101
		addAction.setImageDescriptor(new ImageDescriptor() {
102

    
103
			@Override
104
			public ImageData getImageData() {
105
				return ImageResources.getImage(ImageResources.ADD_ICON).getImageData();
106
			}
107
		});
108
		addAction.setToolTipText(getTooltipString());
109

    
110
		toolBarManager.add(addAction);
111

    
112
		return toolBarManager.createControl(this);
113
	}
114

    
115
	/**
116
	 * using this method is discouraged, use updateToolBar() instead
117
	 */
118
	public void showToolbar(){
119
		setTextClient(createToolbar());
120
	}
121

    
122
    /**
123
     * using this method is discouraged, use updateToolBar() instead
124
     */
125
	public void removeToolbar(){
126
		setTextClient(null);
127
	}
128

    
129
	@Override
130
	public void setEntity(ENTITY entity) {
131
		if(entity != null){
132
			super.setEntity(entity);
133
			internalUpdateSection(false);
134
		}
135
		setSectionTitle();
136
		updateToolbar();
137
		layout();
138
	}
139

    
140
	/**
141
	 * Sets the title for the section. Adds a "+" sign if the collection is not empty for this section.
142
	 * Override in subclasses if you want to have a different behaviour.
143
	 */
144
	protected void setSectionTitle() {
145
		if(getCollection(getEntity()) != null && getCollection(getEntity()).size() > 0){
146
			this.setText(getTitleString() + " +");
147
		}else{
148
			this.setText(getTitleString());
149
		}
150
	}
151

    
152
	/**
153
	 * Removes all content from the container
154
	 */
155
	private void destroyDynamicContent(){
156
		if(label_empty != null){
157
			label_empty.dispose();
158
			label_empty = null;
159
		}
160
		removeElements();
161
	}
162

    
163
	/**
164
	 * Call this method after dynamically changing the client area.
165
	 * If the options changed is set to <code>true</code>, will also fire a state changed
166
	 * event to inform the user of unsaved changes.
167
	 *
168
	 * @param changed a boolean.
169
	 */
170
	protected void internalUpdateSection(boolean changed){
171
	    setSectionTitle();
172
		destroyDynamicContent();
173
		if(isExpanded() || expandSectionWhenContentAvailable()) {
174
            renderContent(isExpanded());
175
        }
176
		if(changed) {
177
            firePropertyChangeEvent(this);
178
        }
179
	}
180

    
181
	/**
182
	 * Create the elements to be shown in this section client area
183
	 */
184
	private void renderContent(boolean forceExpansion)
185
	{
186
		Collection<ELEMENT> elements = getCollection(getEntity());
187

    
188
		if(elements == null || elements.isEmpty()){
189
			createEmptyContent();
190
		}else{
191
			createDynamicContents(elements);
192
			forceExpansion = true;
193
		}
194

    
195
		this.setExpanded(forceExpansion);
196

    
197
		reflow();
198
	}
199

    
200
	protected void createEmptyContent(){
201
		label_empty = formFactory.createLabel(getLayoutComposite(), getEmptyString());
202
	}
203

    
204
	/**
205
	 * Creates the widgets for the collection
206
	 *
207
	 * @param elements a {@link java.util.Collection} object.
208
	 */
209
	protected void createDynamicContents(Collection<ELEMENT> elements)
210
	{
211
		int i = 0;
212
		for(final ELEMENT element : elements){
213
			SelectionAdapter removeListener = new SelectionAdapter(){
214
				@Override
215
				public void widgetSelected(SelectionEvent e) {
216
					removeElement(element);
217
					internalUpdateSection(true);
218
				}
219
			};
220
			boolean modulo = i++%2 == 0;
221
			String colorResource = modulo ? Resources.COLOR_LIST_EVEN : Resources.COLOR_LIST_ODD;
222
			createElementComposite(element, removeListener, AbstractUtility.getColor(colorResource));
223
		}
224
	}
225

    
226
	/**
227
	 * Create the specific widget for the element
228
	 *
229
	 * @param element a ELEMENT object.
230
	 * @param removeListener a {@link org.eclipse.swt.events.SelectionListener} object.
231
	 * @param backgroundColor a {@link org.eclipse.swt.graphics.Color} object.
232
	 */
233
	protected void createElementComposite(ELEMENT element, SelectionListener removeListener, Color backgroundColor){
234
		entityCollectionElement = formFactory.createEntityCollectionElement(this, element, removeListener, backgroundColor, SWT.NULL);
235
	}
236

    
237
	/** {@inheritDoc} */
238
	@Override
239
	public void setBackground(Color color) {
240
		if(label_empty != null && !label_empty.isDisposed()){
241
			label_empty.setBackground(color);
242
		}
243
		super.setBackground(color);
244
	}
245

    
246
	/**
247
	 * <p>getTitleString</p>
248
	 *
249
	 * @return a {@link java.lang.String} object.
250
	 */
251
	public String getTitleString() {
252
		return CdmUtils.Nz(title);
253
	}
254

    
255
	/**
256
	 * <p>setTitleString</p>
257
	 *
258
	 * @param title a {@link java.lang.String} object.
259
	 */
260
	public void setTitleString(String title){
261
		this.title = title;
262
		setSectionTitle();
263
		layout();
264
	}
265

    
266
	/** {@inheritDoc} */
267
	@Override
268
    public void expansionStateChanging(ExpansionEvent e) {
269
//		logger.warn("Expansion State Changing");
270
	}
271

    
272
	/** {@inheritDoc} */
273
	@Override
274
    public void expansionStateChanged(ExpansionEvent e) {
275
		if(isExpanded()){
276
			renderContent(isExpanded());
277
		}else{
278
			destroyDynamicContent();
279
		}
280
	}
281

    
282
	private boolean expandSectionWhenContentAvailable(){
283
		return PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOULD_EXPAND_SECTION_WHEN_DATA_AVAILABLE);
284
	}
285

    
286
	/**
287
	 * Remove an element from the entities collection and update the section
288
	 *
289
	 * @param element a ELEMENT object.
290
	 */
291
	public void removeElementAndUpdate(ELEMENT element) {
292
		removeElement(element);
293
		internalUpdateSection(true);
294
	}
295

    
296
	@Override
297
    public void update(Observable o, Object arg){
298
	    if(o instanceof LoginManager){
299
	        updateToolbar();
300
	    }
301
	}
302

    
303
    private void updateToolbar() {
304
        if(getEntity() != null && CdmStore.currentAuthentiationHasPermission(StoreUtil.getCdmEntity(getEntity()), UPDATE)){
305
            showToolbar();
306
        } else {
307
            removeToolbar();
308
        }
309
    }
310

    
311
    public AbstractEntityCollectionElement getEntityCollectionElement() {
312
        return entityCollectionElement;
313
    }
314

    
315
	/**
316
	 * Get the specific collection of this entity
317
	 *
318
	 * @param entity a ENTITY object.
319
	 * @return a {@link java.util.Collection} object.
320
	 */
321
	public abstract Collection<ELEMENT> getCollection(ENTITY entity);
322

    
323
	/**
324
	 * Create a new Element for this collection
325
	 *
326
	 * @return a ELEMENT object.
327
	 */
328
	public abstract ELEMENT createNewElement();
329

    
330
	/**
331
	 * Add an element to the entities collection
332
	 *
333
	 * @param element a ELEMENT object.
334
	 */
335
	public abstract void addElement(ELEMENT element);
336

    
337
	/**
338
	 * Remove an element from the entities collection
339
	 *
340
	 * @param element a ELEMENT object.
341
	 */
342
	public abstract void removeElement(ELEMENT element);
343

    
344
	/**
345
	 * String to display when the collection is empty
346
	 *
347
	 * @return a {@link java.lang.String} object.
348
	 */
349
	public abstract String getEmptyString();
350

    
351
	/**
352
	 * <p>getTooltipString</p>
353
	 *
354
	 * @return String to display when hovering the add button
355
	 */
356
	protected abstract String getTooltipString();
357
}
(4-4/8)