Project

General

Profile

Download (10.4 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
	/**
59
     *
60
     */
61
    private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
62

    
63
    protected Composite container;
64

    
65
	private Label label_empty;
66

    
67
	private String title;
68

    
69
	/**
70
	 * <p>Constructor for AbstractEntityCollectionSection.</p>
71
	 *
72
	 * @param conversation
73
	 * @param parentElement a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
74
	 * @param style a int.
75
	 * @param formFactory a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
76
	 * @param title a {@link java.lang.String} object.
77
	 * @param <ENTITY> a ENTITY object.
78
	 * @param <ELEMENT> a ELEMENT object.
79
	 */
80
	public AbstractEntityCollectionSection(CdmFormFactory formFactory, ConversationHolder conversation, ICdmFormElement parentElement, String title, int style) {
81
		super(formFactory, parentElement, ExpandableComposite.CLIENT_INDENT | style);
82
		this.title = title;
83
		this.setText(getTitleString());
84
		updateToolbar();
85

    
86
		addExpansionListener(this);
87

    
88
		CdmStore.getLoginManager().addObserver(this);
89
		addDisposeListener(new DisposeListener() {
90
            @Override
91
            public void widgetDisposed(DisposeEvent e) {
92
                CdmStore.getLoginManager().deleteObserver(AbstractEntityCollectionSection.this);
93
            }
94
        });
95
	}
96

    
97
	protected Control createToolbar() {
98
		ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
99

    
100
		Action addAction = new Action("add", IAction.AS_PUSH_BUTTON){
101
			/* (non-Javadoc)
102
			 * @see org.eclipse.jface.action.Action#run()
103
			 */
104
			@Override
105
			public void run() {
106
				ELEMENT element = createNewElement();
107
				if(element != null){
108
					addElement(element);
109
					if(! getSection().isExpanded()) {
110
                        getSection().setExpanded(true);
111
                    }
112
					internalUpdateSection(true);
113
				}
114
			}
115
		};
116
		addAction.setImageDescriptor(new ImageDescriptor() {
117

    
118
			@Override
119
			public ImageData getImageData() {
120
				return ImageResources.getImage(ImageResources.ADD_ICON).getImageData();
121
			}
122
		});
123
		addAction.setToolTipText(getTooltipString());
124

    
125
		toolBarManager.add(addAction);
126

    
127
		return toolBarManager.createControl(this);
128
	}
129

    
130
	/**
131
	 * using this method is discouraged, use updateToolBar() instead
132
	 */
133
	public void showToolbar(){
134
		setTextClient(createToolbar());
135
	}
136

    
137
    /**
138
     * using this method is discouraged, use updateToolBar() instead
139
     */
140
	public void removeToolbar(){
141
		setTextClient(null);
142
	}
143

    
144
	/**
145
	 * <p>setEntity</p>
146
	 *
147
	 * @param entity a ENTITY object.
148
	 */
149
	@Override
150
	public void setEntity(ENTITY entity) {
151
		if(entity != null){
152
			super.setEntity(entity);
153
			internalUpdateSection(false);
154
		}
155
		setSectionTitle();
156
		updateToolbar();
157
		layout();
158
	}
159

    
160
	/**
161
	 * Sets the title for the section. Adds a "+" sign if the collection is not empty for this section.
162
	 * Override in subclasses if you want to have a different behaviour.
163
	 */
164
	protected void setSectionTitle() {
165
		if(getCollection(getEntity()) != null && getCollection(getEntity()).size() > 0){
166
			this.setText(getTitleString() + " +");
167
		}else{
168
			this.setText(getTitleString());
169
		}
170
	}
171

    
172
	/**
173
	 * Removes all content from the container
174
	 */
175
	private void destroyDynamicContent(){
176
		if(label_empty != null){
177
			label_empty.dispose();
178
			label_empty = null;
179
		}
180
		removeElements();
181
	}
182

    
183
	/**
184
	 * Call this method after dynamically changing the client area.
185
	 * If the options changed is set to <code>true</code>, will also fire a state changed
186
	 * event to inform the user of unsaved changes.
187
	 *
188
	 * @param changed a boolean.
189
	 */
190
	protected void internalUpdateSection(boolean changed){
191
	    setSectionTitle();
192
		destroyDynamicContent();
193
		if(isExpanded() || expandSectionWhenContentAvailable()) {
194
            renderContent(isExpanded());
195
        }
196
		if(changed) {
197
            firePropertyChangeEvent(this);
198
        }
199
	}
200

    
201
	/**
202
	 * Create the elements to be shown in this section client area
203
	 */
204
	private void renderContent(boolean forceExpansion)
205
	{
206
		Collection<ELEMENT> elements = getCollection(getEntity());
207

    
208
		if(elements == null || elements.isEmpty()){
209
			createEmptyContent();
210
		}else{
211
			createDynamicContents(elements);
212
			forceExpansion = true;
213
		}
214

    
215
		this.setExpanded(forceExpansion);
216

    
217
		reflow();
218
	}
219

    
220
	/**
221
	 * <p>createEmptyContent</p>
222
	 */
223
	protected void createEmptyContent(){
224
		label_empty = formFactory.createLabel(getLayoutComposite(), getEmptyString());
225
	}
226

    
227
	/**
228
	 * Creates the widgets for the collection
229
	 *
230
	 * @param elements a {@link java.util.Collection} object.
231
	 */
232
	protected void createDynamicContents(Collection<ELEMENT> elements)
233
	{
234
		int i = 0;
235
		for(final ELEMENT element : elements){
236
			SelectionAdapter removeListener = new SelectionAdapter(){
237
				@Override
238
				public void widgetSelected(SelectionEvent e) {
239
					removeElement(element);
240
					internalUpdateSection(true);
241
				}
242
			};
243
			boolean modulo = i++%2 == 0;
244
			String colorResource = modulo ? Resources.COLOR_LIST_EVEN : Resources.COLOR_LIST_ODD;
245
			createElementComposite(element, removeListener, AbstractUtility.getColor(colorResource));
246
		}
247
	}
248

    
249
	/**
250
	 * Create the specific widget for the element
251
	 *
252
	 * @param element a ELEMENT object.
253
	 * @param removeListener a {@link org.eclipse.swt.events.SelectionListener} object.
254
	 * @param backgroundColor a {@link org.eclipse.swt.graphics.Color} object.
255
	 */
256
	protected void createElementComposite(ELEMENT element, SelectionListener removeListener, Color backgroundColor){
257
		formFactory.createEntityCollectionElement(this, element, removeListener, backgroundColor, SWT.NULL);
258
	}
259

    
260
	/* (non-Javadoc)
261
	 * @see eu.etaxonomy.taxeditor.forms.section.AbstractEditorFormSection#setBackground(org.eclipse.swt.graphics.Color)
262
	 */
263
	/** {@inheritDoc} */
264
	@Override
265
	public void setBackground(Color color) {
266
		if(label_empty != null && !label_empty.isDisposed()){
267
			label_empty.setBackground(color);
268
		}
269
		super.setBackground(color);
270
	}
271

    
272
	/**
273
	 * <p>getTitleString</p>
274
	 *
275
	 * @return a {@link java.lang.String} object.
276
	 */
277
	public String getTitleString() {
278
		return CdmUtils.Nz(title);
279
	}
280

    
281
	/**
282
	 * <p>setTitleString</p>
283
	 *
284
	 * @param title a {@link java.lang.String} object.
285
	 */
286
	public void setTitleString(String title){
287
		this.title = title;
288
		setSectionTitle();
289
		layout();
290
	}
291

    
292
	/** {@inheritDoc} */
293
	@Override
294
    public void expansionStateChanging(ExpansionEvent e) {
295
//		logger.warn("Expansion State Changing");
296
	}
297

    
298
	/** {@inheritDoc} */
299
	@Override
300
    public void expansionStateChanged(ExpansionEvent e) {
301
		if(isExpanded()){
302
			renderContent(isExpanded());
303
		}else{
304
			destroyDynamicContent();
305
		}
306
	}
307

    
308
	private boolean expandSectionWhenContentAvailable(){
309
		return PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOULD_EXPAND_SECTION_WHEN_DATA_AVAILABLE);
310
	}
311

    
312
	/**
313
	 * Remove an element from the entities collection and update the section
314
	 *
315
	 * @param element a ELEMENT object.
316
	 */
317
	public void removeElementAndUpdate(ELEMENT element) {
318
		removeElement(element);
319
		internalUpdateSection(true);
320
	}
321

    
322
	/* (non-Javadoc)
323
	 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
324
	 */
325
	@Override
326
    public void update(Observable o, Object arg){
327
	    if(o instanceof LoginManager){
328
	        updateToolbar();
329
	    }
330
	}
331

    
332
    private void updateToolbar() {
333
        if(getEntity() != null && CdmStore.currentAuthentiationHasPermission(StoreUtil.getCdmEntity(getEntity()), UPDATE)){
334
            showToolbar();
335
        } else {
336
            removeToolbar();
337
        }
338
    }
339

    
340
	/**
341
	 * Get the specific collection of this entity
342
	 *
343
	 * @param entity a ENTITY object.
344
	 * @return a {@link java.util.Collection} object.
345
	 */
346
	public abstract Collection<ELEMENT> getCollection(ENTITY entity);
347

    
348
	/**
349
	 * Create a new Element for this collection
350
	 *
351
	 * @return a ELEMENT object.
352
	 */
353
	public abstract ELEMENT createNewElement();
354

    
355
	/**
356
	 * Add an element to the entities collection
357
	 *
358
	 * @param element a ELEMENT object.
359
	 */
360
	public abstract void addElement(ELEMENT element);
361

    
362
	/**
363
	 * Remove an element from the entities collection
364
	 *
365
	 * @param element a ELEMENT object.
366
	 */
367
	public abstract void removeElement(ELEMENT element);
368

    
369
	/**
370
	 * String to display when the collection is empty
371
	 *
372
	 * @return a {@link java.lang.String} object.
373
	 */
374
	public abstract String getEmptyString();
375

    
376
	/**
377
	 * <p>getTooltipString</p>
378
	 *
379
	 * @return String to display when hovering the add button
380
	 */
381
	protected abstract String getTooltipString();
382
}
(4-4/8)