Merge branch 'release/4.0.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / ui / selection / EntitySelectionElement.java
1 /**
2 *
3 */
4 package eu.etaxonomy.taxeditor.ui.selection;
5
6 import java.util.EnumSet;
7 import java.util.Observable;
8 import java.util.Observer;
9
10 import org.eclipse.core.runtime.IStatus;
11 import org.eclipse.jface.dialogs.MessageDialog;
12 import org.eclipse.jface.wizard.WizardDialog;
13 import org.eclipse.swt.SWT;
14 import org.eclipse.swt.events.SelectionAdapter;
15 import org.eclipse.swt.events.SelectionEvent;
16 import org.eclipse.swt.events.SelectionListener;
17 import org.eclipse.swt.graphics.Color;
18 import org.eclipse.swt.widgets.Button;
19 import org.eclipse.swt.widgets.Composite;
20 import org.eclipse.swt.widgets.Label;
21 import org.eclipse.swt.widgets.Shell;
22 import org.eclipse.swt.widgets.Text;
23 import org.springframework.security.core.GrantedAuthority;
24
25 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
26 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
27 import eu.etaxonomy.cdm.api.service.IService;
28 import eu.etaxonomy.cdm.common.CdmUtils;
29 import eu.etaxonomy.cdm.model.common.CdmBase;
30 import eu.etaxonomy.cdm.model.common.Group;
31 import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
32 import eu.etaxonomy.cdm.model.common.User;
33 import eu.etaxonomy.cdm.model.molecular.Amplification;
34 import eu.etaxonomy.cdm.model.molecular.Primer;
35 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
36 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
37 import eu.etaxonomy.taxeditor.model.ImageResources;
38 import eu.etaxonomy.taxeditor.preference.Resources;
39 import eu.etaxonomy.taxeditor.store.CdmStore;
40 import eu.etaxonomy.taxeditor.store.LoginManager;
41 import eu.etaxonomy.taxeditor.store.StoreUtil;
42 import eu.etaxonomy.taxeditor.ui.dialog.selection.SelectionDialogFactory;
43 import eu.etaxonomy.taxeditor.ui.element.AbstractCdmFormElement;
44 import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
45 import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
46 import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
47 import eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement;
48 import eu.etaxonomy.taxeditor.ui.element.IEntityElement;
49 import eu.etaxonomy.taxeditor.ui.element.ILabeledElement;
50 import eu.etaxonomy.taxeditor.ui.element.ISelectableElement;
51 import eu.etaxonomy.taxeditor.ui.element.LayoutConstants;
52 import eu.etaxonomy.taxeditor.ui.element.SelectionArbitrator;
53 import eu.etaxonomy.taxeditor.ui.section.grantedAuthority.GrantedAuthorityLabelTextProvider;
54
55 /**
56 * <p>
57 * Abstract AbstractSelectionElement class.
58 * </p>
59 *
60 * @author n.hoffmann
61 * @created Nov 17, 2009
62 * @version 1.0
63 * @param <T>
64 */
65 public class EntitySelectionElement<T extends CdmBase> extends
66 AbstractCdmFormElement implements SelectionListener, IEnableableFormElement, ISelectableElement, IEntityElement<T>, ILabeledElement, IConversationEnabled, Observer {
67
68 private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
69 private static final EnumSet<CRUD> DELETE = EnumSet.of(CRUD.DELETE);
70 private static final EnumSet<CRUD> CREATE = EnumSet.of(CRUD.CREATE);
71
72 /**
73 * Bitmask for configuring functionality of selection element
74 */
75 public static final int NOTHING = 0; // 000
76 public static final int EDITABLE = 1 << 0; // 001
77 public static final int DELETABLE = 1 << 1; // 010
78 public static final int SELECTABLE = 1 << 2; // 100
79 public static final int ALL = EDITABLE | DELETABLE | SELECTABLE; // 111
80
81 protected T entity;
82
83 protected Label label;
84 protected Text text;
85 protected Button button_selection;
86
87 private SelectionArbitrator selectionArbitrator;
88
89 protected Button button_edit;
90
91 private final String labelString;
92
93 private Composite selectableComposite;
94
95 private Button button_remove;
96
97 private final boolean isEditable;
98
99 private final boolean isDeletable;
100
101 private final ConversationHolder conversation;
102 private Class<T> clazz;
103
104 /**
105 * <p>
106 * Constructor for AbstractSelectionElement.
107 * </p>
108 *
109 * @param formFactory
110 * a {@link eu.etaxonomy.taxeditor.ui.element.CdmFormFactory}
111 * object.
112 * @param conversation
113 * TODO
114 * @param parentElement
115 * a {@link eu.etaxonomy.taxeditor.ui.element.ICdmFormElement}
116 * object.
117 * @param labelString
118 * a {@link java.lang.String} object.
119 * @param entity
120 * a T object.
121 * @param isEditable
122 * a boolean.
123 * @param isSelectable
124 * a boolean.
125 * @param isDeletable
126 * a boolean.
127 * @param style
128 * a int.
129 * @param <T>
130 * a T object.
131 */
132 public EntitySelectionElement(CdmFormFactory formFactory,
133 ConversationHolder conversation, ICdmFormElement parentElement,
134 String labelString, T entity, int mode, int style) {
135 super(formFactory, parentElement);
136
137 this.isEditable = (mode & EDITABLE) == EDITABLE;
138 this.isDeletable = (mode & DELETABLE) == DELETABLE;
139 boolean isSelectable = (mode & SELECTABLE) == SELECTABLE;
140
141 this.labelString = (labelString == null || labelString.equals("")) ? "" : labelString;
142
143 this.conversation = conversation;
144
145 if (isSelectable && formFactory.getSelectionProvider() != null) {
146 selectionArbitrator = formFactory.createSelectionArbitrator(this);
147 }
148
149 createControls(getLayoutComposite(), SWT.NULL);
150
151 setEntity(entity);
152 }
153
154 public EntitySelectionElement(CdmFormFactory formFactory,
155 ConversationHolder conversation, ICdmFormElement parentElement, Class<T> clazz,
156 String labelString, T entity, int mode, int style) {
157 this(formFactory, conversation, parentElement, labelString, entity, mode, style);
158 this.clazz = clazz;
159 }
160
161 private void createControls(Composite parent, int style) {
162
163 label = formFactory.createLabel(getLayoutComposite(), labelString,
164 SWT.NULL);
165
166 addControl(label);
167
168 selectableComposite = formFactory.createComposite(getLayoutComposite());
169
170 int columns = 2;
171 if (isEditable) {
172 columns += 1;
173 }
174 if (isDeletable) {
175 columns += 1;
176 }
177
178 selectableComposite.setLayout(LayoutConstants.LAYOUT(columns, false));
179 selectableComposite.setLayoutData(LayoutConstants.FILL_HORIZONTALLY());
180
181 addControl(selectableComposite);
182
183 text = formFactory.createText(selectableComposite, null, SWT.WRAP);
184 text.setEditable(false);
185 addControl(text);
186
187 text.setLayoutData(LayoutConstants.FILL_HORIZONTALLY());
188 text.setBackground(StoreUtil
189 .getColor(Resources.COLOR_TEXT_DISABLED_BACKGROUND));
190
191 button_selection = formFactory.createButton(selectableComposite, null,
192 SWT.PUSH);
193 button_selection.setImage(ImageResources
194 .getImage(ImageResources.BROWSE_ICON));
195 button_selection.setToolTipText("Browse existing");
196
197 addControl(button_selection);
198 button_selection.addSelectionListener(this);
199
200 if (isEditable) {
201 button_edit = formFactory.createButton(selectableComposite, null,
202 SWT.PUSH);
203 button_edit.setImage(ImageResources
204 .getImage(ImageResources.EDIT_ICON));
205 button_edit.setToolTipText("Edit");
206 addControl(button_edit);
207 button_edit.addSelectionListener(new EditListener(this));
208 }
209
210 if (isDeletable) {
211 button_remove = formFactory.createButton(selectableComposite, null,
212 SWT.PUSH);
213 button_remove.setImage(ImageResources
214 .getImage(ImageResources.TRASH_ICON));
215 button_remove.setToolTipText("Remove");
216 addControl(button_remove);
217 button_remove.addSelectionListener(new DeleteListener(this));
218 }
219 }
220
221 @Override
222 public void widgetSelected(SelectionEvent e) {
223 T selection = SelectionDialogFactory.getSelectionFromDialog(clazz, getShell(), getConversationHolder(), getEntity(), getParentElement());
224 setSelectionInternal(selection);
225 }
226
227 /**
228 * Return the selected object
229 *
230 * @return a T object.
231 */
232 public T getSelection() {
233 return entity;
234 }
235
236 /*
237 * (non-Javadoc)
238 *
239 * @see
240 * eu.etaxonomy.taxeditor.forms.IEnableableFormElement#setEnabled(boolean)
241 */
242 /** {@inheritDoc} */
243 @Override
244 public void setEnabled(boolean enabled) {
245
246 button_selection.setEnabled(enabled);
247 if (isDeletable){
248 button_remove.setEnabled(enabled);
249 }
250 if (isEditable) {
251 updateButtonStates();
252 }
253
254 }
255
256 /* (non-Javadoc)
257 * @see eu.etaxonomy.taxeditor.ui.element.IEnableableFormElement#isEnabled()
258 */
259 @Override
260 public boolean isEnabled() {
261 return button_selection.isEnabled();
262 }
263
264 /**
265 * <p>
266 * setSelectionInternal
267 * </p>
268 *
269 * @param selection
270 * a T object.
271 */
272 protected void setSelectionInternal(T selection) {
273 if (selection != null && !selection.equals(this.entity)) {
274 setEntity(selection);
275 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, null));
276 }
277 }
278
279 /**
280 * <p>
281 * Setter for the field <code>entity</code>.
282 * </p>
283 *
284 * @param selection
285 * a T object.
286 */
287 public void setEntity(T selection) {
288 this.entity = selection;
289 updateElement();
290 }
291
292 /**
293 * Updates this elements view
294 */
295 protected void updateElement() {
296 String title = CdmUtils.Nz(getTitle());
297 text.setText(title); // title can be null
298 if (isEditable) {
299 updateButtonStates();
300 }
301 }
302
303 public void updateFromWizard() {
304 updateElement();
305 firePropertyChangeEvent(new CdmPropertyChangeEvent(this, null));
306 }
307
308 /**
309 * <p>
310 * getTitle
311 * </p>
312 *
313 * @return a {@link java.lang.String} object.
314 */
315 protected String getTitle() {
316 if (entity != null){
317 if(entity instanceof Group){
318 return ((Group) entity).getName();
319 } else if(entity instanceof GrantedAuthority){
320 return GrantedAuthorityLabelTextProvider.getText(((GrantedAuthority) entity));
321 } else if(entity instanceof User){
322 return ((User) entity).getUsername();
323 } else if (entity instanceof Primer){
324 return ((Primer) entity).getLabel();
325 } else if (entity instanceof Amplification){
326 return ((Amplification) entity).getLabelCache();
327 }
328 else if(entity instanceof IIdentifiableEntity) {
329 return ((IIdentifiableEntity) entity).getTitleCache();
330 }
331
332 }
333 return "";
334 }
335
336 /** {@inheritDoc} */
337 @Override
338 public void setSelected(boolean selected) {
339 setBackground(selected ? SELECTED : getPersistentBackground());
340 }
341
342 /*
343 * (non-Javadoc)
344 *
345 * @see eu.etaxonomy.taxeditor.forms.IEntityElement#getEntity()
346 */
347 /**
348 * <p>
349 * Getter for the field <code>entity</code>.
350 * </p>
351 *
352 * @return a T object.
353 */
354 @Override
355 public T getEntity() {
356 return entity;
357 }
358
359 /*
360 * (non-Javadoc)
361 *
362 * @see eu.etaxonomy.taxeditor.forms.section.cdmdetail.ISelectableElement#
363 * getSelectionArbitrator()
364 */
365 /**
366 * <p>
367 * Getter for the field <code>selectionArbitrator</code>.
368 * </p>
369 *
370 * @return a {@link eu.etaxonomy.taxeditor.ui.element.SelectionArbitrator}
371 * object.
372 */
373 @Override
374 public SelectionArbitrator getSelectionArbitrator() {
375 return selectionArbitrator;
376 }
377
378 /**
379 * Convenient access to current shell
380 *
381 * @return a {@link org.eclipse.swt.widgets.Shell} object.
382 */
383 public Shell getShell() {
384 return getLayoutComposite().getShell();
385 }
386
387 /** {@inheritDoc} */
388 @Override
389 public void setIrrelevant(boolean irrelevant) {
390 String colorId = irrelevant ? Resources.COLOR_COMPOSITE_IRRELEVANT
391 : Resources.COLOR_TEXT_DISABLED_BACKGROUND;
392
393 Color color = StoreUtil.getColor(colorId);
394 text.setBackground(color);
395 }
396
397 private class DeleteListener extends SelectionAdapter {
398
399 private final EntitySelectionElement<T> selectionElement;
400
401 public DeleteListener(EntitySelectionElement<T> selectionElement) {
402 this.selectionElement = selectionElement;
403 }
404
405 @Override
406 public void widgetSelected(SelectionEvent e) {
407 setEntity(null);
408 firePropertyChangeEvent(new CdmPropertyChangeEvent(
409 selectionElement, null));
410 }
411 }
412
413 private class EditListener extends SelectionAdapter {
414
415 private final EntitySelectionElement<T> selectionElement;
416
417 public EditListener(EntitySelectionElement<T> selectionElement) {
418 this.selectionElement = selectionElement;
419 }
420
421 /** {@inheritDoc} */
422 @Override
423 public void widgetSelected(SelectionEvent e) {
424 WizardDialog dialog = new WizardDialog(selectionElement.getShell(),
425 new EditFromSelectionWizard(selectionElement));
426 if (dialog.open() == IStatus.OK) {
427 selectionElement.updateFromWizard();
428 //if the edited entity has already been persisted
429 //but the transient entity is still set in this
430 //EntitySelectionElement, re-load it and set it
431 IService<T> service = CdmStore.getService(entity);
432 if(entity.getId()==0){
433 T loadedEntity = service.load(entity.getUuid());
434 if(loadedEntity!=null){
435 setEntity(loadedEntity);
436 }
437 }
438 }
439 }
440 }
441
442 // not used
443 /** {@inheritDoc} */
444 @Override
445 public void widgetDefaultSelected(SelectionEvent e) {
446 }
447
448 /**
449 * <p>
450 * getConversationHolder
451 * </p>
452 *
453 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder}
454 * object.
455 */
456 @Override
457 public ConversationHolder getConversationHolder() {
458 return conversation;
459 }
460
461 /** {@inheritDoc} */
462 @Override
463 public void setBackground(Color color) {
464 if(!label.isDisposed()){
465 label.setBackground(color);
466 }
467 }
468
469 /** {@inheritDoc} */
470 @Override
471 public void setLabel(String labelString) {
472 if (label != null) {
473 label.setText(labelString);
474 }
475 }
476
477 /**
478 * <p>
479 * Getter for the field <code>label</code>.
480 * </p>
481 *
482 * @return a {@link java.lang.String} object.
483 */
484 @Override
485 public String getLabel() {
486 if (label != null) {
487 return label.getText() + " : ";
488 }
489 return null;
490 }
491
492 /** {@inheritDoc} */
493 @Override
494 public void update(CdmDataChangeMap changeEvents) {
495 }
496
497 /* (non-Javadoc)
498 * @see eu.etaxonomy.taxeditor.ui.element.AbstractCdmFormElement#removeElements()
499 */
500 @Override
501 public void removeElements(){
502 super.removeElements();
503 LoginManager loginManager = CdmStore.getLoginManager();
504 loginManager.addObserver(this);
505 }
506
507 @Override
508 public void update(Observable o, Object arg) {
509 if(o instanceof LoginManager){
510 updateButtonStates();
511 }
512 }
513
514 private void updateButtonStates() {
515 if(button_edit != null && !button_selection.isDisposed()){
516 button_edit.setEnabled(isEditable && button_selection.isEnabled() && getEntity() != null && CdmStore.currentAuthentiationHasPermission(getEntity(), UPDATE));
517 }
518 }
519 }