Project

General

Profile

Download (11.1 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
		Action browseAction = null;
111
		if(allowAddExisting()){
112
		    browseAction = new Action("Browse", IAction.AS_PUSH_BUTTON){
113
		        @Override
114
		        public void run() {
115
		            ELEMENT element = addExisting();
116
		            if(element != null){
117
		                addElement(element);
118
		                if(! getSection().isExpanded()) {
119
		                    getSection().setExpanded(true);
120
		                }
121
		                internalUpdateSection(true);
122
		            }
123
		        }
124
		    };
125
		    browseAction.setImageDescriptor(new ImageDescriptor() {
126

    
127
		        @Override
128
		        public ImageData getImageData() {
129
		            return ImageResources.getImage(ImageResources.BROWSE_ICON).getImageData();
130
		        }
131
		    });
132
		    browseAction.setToolTipText("Browse");
133
		}
134

    
135
		toolBarManager.add(addAction);
136
		if(browseAction!=null){
137
		    toolBarManager.add(browseAction);
138
		}
139

    
140
		return toolBarManager.createControl(this);
141
	}
142

    
143
	/**
144
	 * using this method is discouraged, use updateToolBar() instead
145
	 */
146
	public void showToolbar(){
147
		setTextClient(createToolbar());
148
	}
149

    
150
    /**
151
     * using this method is discouraged, use updateToolBar() instead
152
     */
153
	public void removeToolbar(){
154
		setTextClient(null);
155
	}
156

    
157
	@Override
158
	public void setEntity(ENTITY entity) {
159
		if(entity != null){
160
			super.setEntity(entity);
161
			internalUpdateSection(false);
162
		}
163
		setSectionTitle();
164
		updateToolbar();
165
		layout();
166
	}
167

    
168
	/**
169
	 * Sets the title for the section. Adds a "+" sign if the collection is not empty for this section.
170
	 * Override in subclasses if you want to have a different behaviour.
171
	 */
172
	protected void setSectionTitle() {
173
		Collection<ELEMENT> collection = getCollection(getEntity());
174
		if(collection != null && collection.size() > 0){
175
			this.setText(getTitleString() + " +");
176
		}else{
177
			this.setText(getTitleString());
178
		}
179
	}
180

    
181
	/**
182
	 * Removes all content from the container
183
	 */
184
	private void destroyDynamicContent(){
185
		if(label_empty != null){
186
			label_empty.dispose();
187
			label_empty = null;
188
		}
189
		removeElements();
190
	}
191

    
192
	/**
193
	 * Call this method after dynamically changing the client area.
194
	 * If the options changed is set to <code>true</code>, will also fire a state changed
195
	 * event to inform the user of unsaved changes.
196
	 *
197
	 * @param changed a boolean.
198
	 */
199
	protected void internalUpdateSection(boolean changed){
200
	    setSectionTitle();
201
		destroyDynamicContent();
202
		if(isExpanded() || expandSectionWhenContentAvailable()) {
203
            renderContent(isExpanded());
204
        }
205
		if(changed) {
206
            firePropertyChangeEvent(this);
207
        }
208
	}
209

    
210
	/**
211
	 * Create the elements to be shown in this section client area
212
	 */
213
	private void renderContent(boolean forceExpansion)
214
	{
215
		Collection<ELEMENT> elements = getCollection(getEntity());
216

    
217
		if(elements == null || elements.isEmpty()){
218
			createEmptyContent();
219
		}else{
220
			createDynamicContents(elements);
221
			forceExpansion = true;
222
		}
223

    
224
		this.setExpanded(forceExpansion);
225

    
226
		reflow();
227
	}
228

    
229
	protected void createEmptyContent(){
230
		label_empty = formFactory.createLabel(getLayoutComposite(), getEmptyString());
231
	}
232

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

    
255
	/**
256
	 * Create the specific widget for the element
257
	 *
258
	 * @param element a ELEMENT object.
259
	 * @param removeListener a {@link org.eclipse.swt.events.SelectionListener} object.
260
	 * @param backgroundColor a {@link org.eclipse.swt.graphics.Color} object.
261
	 */
262
	protected void createElementComposite(ELEMENT element, SelectionListener removeListener, Color backgroundColor){
263
		entityCollectionElement = formFactory.createEntityCollectionElement(this, element, removeListener, backgroundColor, SWT.NULL);
264
	}
265

    
266
	/** {@inheritDoc} */
267
	@Override
268
	public void setBackground(Color color) {
269
		if(label_empty != null && !label_empty.isDisposed()){
270
			label_empty.setBackground(color);
271
		}
272
		super.setBackground(color);
273
	}
274

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

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

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

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

    
311
	private boolean expandSectionWhenContentAvailable(){
312
		return PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOULD_EXPAND_SECTION_WHEN_DATA_AVAILABLE);
313
	}
314

    
315
	/**
316
	 * Remove an element from the entities collection and update the section
317
	 *
318
	 * @param element a ELEMENT object.
319
	 */
320
	public void removeElementAndUpdate(ELEMENT element) {
321
		removeElement(element);
322
		internalUpdateSection(true);
323
	}
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
    public AbstractEntityCollectionElement getEntityCollectionElement() {
341
        return entityCollectionElement;
342
    }
343

    
344

    
345
	/**
346
	 * Get the specific collection of this entity
347
	 *
348
	 * @param entity a ENTITY object.
349
	 * @return a {@link java.util.Collection} object.
350
	 */
351
	public abstract Collection<ELEMENT> getCollection(ENTITY entity);
352

    
353
	/**
354
	 * Create a new Element for this collection
355
	 *
356
	 * @return a ELEMENT object.
357
	 */
358
	public abstract ELEMENT createNewElement();
359

    
360
	/**
361
	 * Add an element to the entities collection
362
	 *
363
	 * @param element a ELEMENT object.
364
	 */
365
	public abstract void addElement(ELEMENT element);
366

    
367
	/**
368
	 * Add an existing element to the entities collection.
369
	 * @return the existing element
370
	 */
371
	public abstract ELEMENT addExisting();
372

    
373
	/**
374
	 * If <code>true</code> the section will also display
375
	 * a browse icon to choose from existing elements.
376
	 * <br>
377
	 * <b>Note:</b> when returning true you have to make sure
378
	 * to implement the {@link #addExisting()} method
379
	 * @return true if existing entities can be added;
380
	 * false otherwise
381
	 */
382
	public abstract boolean allowAddExisting();
383

    
384
	/**
385
	 * Remove an element from the entities collection
386
	 *
387
	 * @param element a ELEMENT object.
388
	 */
389
	public abstract void removeElement(ELEMENT element);
390

    
391
	/**
392
	 * String to display when the collection is empty
393
	 *
394
	 * @return a {@link java.lang.String} object.
395
	 */
396
	public abstract String getEmptyString();
397

    
398
	/**
399
	 * <p>getTooltipString</p>
400
	 *
401
	 * @return String to display when hovering the add button
402
	 */
403
	protected abstract String getTooltipString();
404
}
(4-4/8)