1a9f43ee577c869e74cbd59b9fb1deb56d87e0f4
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / section / AbstractEntityCollectionSection.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.ui.section;
5
6 import java.util.Collection;
7
8 import org.eclipse.jface.action.Action;
9 import org.eclipse.jface.action.ToolBarManager;
10 import org.eclipse.jface.resource.ImageDescriptor;
11 import org.eclipse.swt.SWT;
12 import org.eclipse.swt.events.SelectionAdapter;
13 import org.eclipse.swt.events.SelectionEvent;
14 import org.eclipse.swt.events.SelectionListener;
15 import org.eclipse.swt.graphics.Color;
16 import org.eclipse.swt.graphics.ImageData;
17 import org.eclipse.swt.widgets.Composite;
18 import org.eclipse.swt.widgets.Control;
19 import org.eclipse.swt.widgets.Label;
20 import org.eclipse.ui.forms.events.ExpansionEvent;
21 import org.eclipse.ui.forms.events.IExpansionListener;
22 import org.eclipse.ui.forms.widgets.Section;
23
24 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
25 import eu.etaxonomy.cdm.common.CdmUtils;
26 import eu.etaxonomy.taxeditor.model.ImageResources;
27 import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
28 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
29 import eu.etaxonomy.taxeditor.preference.Resources;
30 import eu.etaxonomy.taxeditor.store.StoreUtil;
31 import eu.etaxonomy.taxeditor.ui.element.AbstractFormSection;
32 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
33 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
34
35 /**
36 * <p>Abstract AbstractEntityCollectionSection class.</p>
37 *
38 * @author n.hoffmann
39 * @version $Id: $
40 */
41 public abstract class AbstractEntityCollectionSection<ENTITY, ELEMENT> extends AbstractFormSection<ENTITY> implements IExpansionListener{
42
43 protected Composite container;
44
45 private Label label_empty;
46
47 private String title;
48
49 /**
50 * <p>Constructor for AbstractEntityCollectionSection.</p>
51 *
52 * @param conversation
53 * @param parentElement a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement} object.
54 * @param style a int.
55 * @param formFactory a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory} object.
56 * @param title a {@link java.lang.String} object.
57 * @param <ENTITY> a ENTITY object.
58 * @param <ELEMENT> a ELEMENT object.
59 */
60 public AbstractEntityCollectionSection(CdmFormFactory formFactory, ConversationHolder conversation, ICdmFormElement parentElement, String title, int style) {
61 super(formFactory, parentElement, Section.CLIENT_INDENT | style);
62 this.title = title;
63 this.setText(getTitleString());
64 showToolbar();
65
66 addExpansionListener(this);
67 }
68
69 protected Control createToolbar() {
70 ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT);
71
72 Action addAction = new Action("add", Action.AS_PUSH_BUTTON){
73 /* (non-Javadoc)
74 * @see org.eclipse.jface.action.Action#run()
75 */
76 @Override
77 public void run() {
78 ELEMENT element = createNewElement();
79 if(element != null){
80 addElement(element);
81 if(! getSection().isExpanded())
82 getSection().setExpanded(true);
83 internalUpdateSection(true);
84 }
85 }
86 };
87 addAction.setImageDescriptor(new ImageDescriptor() {
88
89 @Override
90 public ImageData getImageData() {
91 return ImageResources.getImage(ImageResources.ADD_ICON).getImageData();
92 }
93 });
94 addAction.setToolTipText(getTooltipString());
95
96 toolBarManager.add(addAction);
97
98 return toolBarManager.createControl(this);
99 }
100
101 public void showToolbar(){
102 setTextClient(createToolbar());
103 }
104
105 public void removeToolbar(){
106 setTextClient(null);
107 }
108
109 /**
110 * <p>setEntity</p>
111 *
112 * @param entity a ENTITY object.
113 */
114 @Override
115 public void setEntity(ENTITY entity) {
116 if(entity != null){
117 super.setEntity(entity);
118 internalUpdateSection(false);
119 }
120 setSectionTitle();
121 layout();
122 };
123
124 /**
125 * Sets the title for the section. Adds a "+" sign if the collection is not empty for this section.
126 * Override in subclasses if you want to have a different behaviour.
127 */
128 protected void setSectionTitle() {
129 if(getCollection(getEntity()) != null && getCollection(getEntity()).size() > 0){
130 this.setText(getTitleString() + " +");
131 }else{
132 this.setText(getTitleString());
133 }
134 }
135
136 /**
137 * Removes all content from the container
138 */
139 private void destroyDynamicContent(){
140 if(label_empty != null){
141 label_empty.dispose();
142 label_empty = null;
143 }
144 removeElements();
145 }
146
147 /**
148 * Call this method after dynamically changing the client area.
149 * If the options changed is set to true, will also fire a state changed
150 * event to inform the user of unsaved changes.
151 *
152 * @param changed a boolean.
153 */
154 protected void internalUpdateSection(boolean changed){
155 destroyDynamicContent();
156 if(isExpanded() || expandSectionWhenContentAvailable())
157 renderContent(isExpanded());
158 if(changed)
159 firePropertyChangeEvent(this);
160 }
161
162 /**
163 * Create the elements to be shown in this seciton client area
164 */
165 private void renderContent(boolean forceExpansion)
166 {
167 Collection<ELEMENT> elements = getCollection(getEntity());
168
169 if(elements == null || elements.isEmpty()){
170 createEmptyContent();
171 }else{
172 createDynamicContents(elements);
173 forceExpansion = true;
174 }
175
176 this.setExpanded(forceExpansion);
177
178 reflow();
179 }
180
181 /**
182 * <p>createEmptyContent</p>
183 */
184 protected void createEmptyContent(){
185 label_empty = formFactory.createLabel(getLayoutComposite(), getEmptyString());
186 }
187
188 /**
189 * Creates the widgets for the collection
190 *
191 * @param elements a {@link java.util.Collection} object.
192 */
193 protected void createDynamicContents(Collection<ELEMENT> elements)
194 {
195 int i = 0;
196 for(final ELEMENT element : elements){
197 SelectionAdapter removeListener = new SelectionAdapter(){
198 @Override
199 public void widgetSelected(SelectionEvent e) {
200 removeElement(element);
201 internalUpdateSection(true);
202 }
203 };
204 boolean modulo = i++%2 == 0;
205 String colorResource = modulo ? Resources.COLOR_LIST_EVEN : Resources.COLOR_LIST_ODD;
206 createElementComposite(element, removeListener, StoreUtil.getColor(colorResource));
207 }
208 }
209
210 /**
211 * Create the specific widget for the element
212 *
213 * @param element a ELEMENT object.
214 * @param removeListener a {@link org.eclipse.swt.events.SelectionListener} object.
215 * @param backgroundColor a {@link org.eclipse.swt.graphics.Color} object.
216 */
217 protected void createElementComposite(ELEMENT element, SelectionListener removeListener, Color backgroundColor){
218 formFactory.createEntityCollectionElement(this, element, removeListener, backgroundColor, SWT.NULL);
219 }
220
221 /* (non-Javadoc)
222 * @see eu.etaxonomy.taxeditor.forms.section.AbstractEditorFormSection#setBackground(org.eclipse.swt.graphics.Color)
223 */
224 /** {@inheritDoc} */
225 @Override
226 public void setBackground(Color color) {
227 if(label_empty != null && !label_empty.isDisposed()){
228 label_empty.setBackground(color);
229 }
230 super.setBackground(color);
231 }
232
233 /**
234 * <p>getTitleString</p>
235 *
236 * @return a {@link java.lang.String} object.
237 */
238 public String getTitleString() {
239 return CdmUtils.Nz(title);
240 }
241
242 /**
243 * <p>setTitleString</p>
244 *
245 * @param title a {@link java.lang.String} object.
246 */
247 public void setTitleString(String title){
248 this.title = title;
249 setSectionTitle();
250 layout();
251 }
252
253 /** {@inheritDoc} */
254 public void expansionStateChanging(ExpansionEvent e) {
255 // logger.warn("Expansion State Changing");
256 }
257
258 /** {@inheritDoc} */
259 public void expansionStateChanged(ExpansionEvent e) {
260 if(isExpanded()){
261 renderContent(isExpanded());
262 }else{
263 destroyDynamicContent();
264 }
265 }
266
267 private boolean expandSectionWhenContentAvailable(){
268 return PreferencesUtil.getPreferenceStore().getBoolean(IPreferenceKeys.SHOULD_EXPAND_SECTION_WHEN_DATA_AVAILABLE);
269 }
270
271 /**
272 * Get the specific collection of this entity
273 *
274 * @param entity a ENTITY object.
275 * @return a {@link java.util.Collection} object.
276 */
277 public abstract Collection<ELEMENT> getCollection(ENTITY entity);
278
279 /**
280 * Create a new Element for this collection
281 *
282 * @return a ELEMENT object.
283 */
284 public abstract ELEMENT createNewElement();
285
286 /**
287 * Add an element to the entities collection
288 *
289 * @param element a ELEMENT object.
290 */
291 public abstract void addElement(ELEMENT element);
292
293 /**
294 * Remove an element from the entities collection
295 *
296 * @param element a ELEMENT object.
297 */
298 public abstract void removeElement(ELEMENT element);
299
300 /**
301 * String to display when the collection is empty
302 *
303 * @return a {@link java.lang.String} object.
304 */
305 public abstract String getEmptyString();
306
307 /**
308 * <p>getTooltipString</p>
309 *
310 * @return String to display when hovering the add button
311 */
312 protected abstract String getTooltipString();
313 }