ref #7458 implementation of the note field for the TypeSpecimenEditor
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / view / name / SpecimenTypeDesignationWorkingsetPopupEditor.java
1 /**
2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.cdm.vaadin.view.name;
10
11 import java.util.Collection;
12 import java.util.EnumSet;
13
14 import org.springframework.context.annotation.Scope;
15 import org.springframework.security.core.GrantedAuthority;
16 import org.vaadin.viritin.fields.ElementCollectionField;
17
18 import com.vaadin.data.validator.DoubleRangeValidator;
19 import com.vaadin.spring.annotation.SpringComponent;
20 import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
21 import com.vaadin.ui.Component;
22 import com.vaadin.ui.GridLayout;
23 import com.vaadin.ui.ListSelect;
24 import com.vaadin.ui.Panel;
25 import com.vaadin.ui.TextArea;
26
27 import eu.etaxonomy.cdm.model.common.AnnotationType;
28 import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
29 import eu.etaxonomy.cdm.vaadin.component.CollectionRowRepresentative;
30 import eu.etaxonomy.cdm.vaadin.component.PartialDateField;
31 import eu.etaxonomy.cdm.vaadin.component.common.FilterableAnnotationsField;
32 import eu.etaxonomy.cdm.vaadin.component.common.GeoLocationField;
33 import eu.etaxonomy.cdm.vaadin.component.common.MinMaxTextField;
34 import eu.etaxonomy.cdm.vaadin.component.common.TeamOrPersonField;
35 import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationDTO;
36 import eu.etaxonomy.cdm.vaadin.model.registration.SpecimenTypeDesignationWorkingSetDTO;
37 import eu.etaxonomy.cdm.vaadin.permission.AccessRestrictedView;
38 import eu.etaxonomy.cdm.vaadin.ui.RegistrationUIDefaults;
39 import eu.etaxonomy.cdm.vaadin.util.TeamOrPersonBaseCaptionGenerator;
40 import eu.etaxonomy.cdm.vaadin.util.converter.DoubleConverter;
41 import eu.etaxonomy.cdm.vaadin.util.converter.IntegerConverter;
42 import eu.etaxonomy.cdm.vaadin.view.PerEntityAuthorityGrantingEditor;
43 import eu.etaxonomy.vaadin.mvp.AbstractPopupEditor;
44
45 /**
46 * @author a.kohlbecker
47 * @since May 15, 2017
48 *
49 */
50 @SpringComponent
51 @Scope("prototype")
52 public class SpecimenTypeDesignationWorkingsetPopupEditor
53 extends AbstractPopupEditor<SpecimenTypeDesignationWorkingSetDTO, SpecimenTypeDesignationWorkingsetEditorPresenter>
54 implements SpecimenTypeDesignationWorkingsetPopupEditorView, AccessRestrictedView, PerEntityAuthorityGrantingEditor {
55 /**
56 *
57 */
58 private static final String CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING = "Can't save as long as type designations are missing.";
59
60 /**
61 * @param layout
62 * @param dtoType
63 */
64 public SpecimenTypeDesignationWorkingsetPopupEditor() {
65 super(new GridLayout(), SpecimenTypeDesignationWorkingSetDTO.class);
66 GridLayout grid = (GridLayout) getFieldLayout();
67 grid.setMargin(true);
68 grid.setSpacing(true);
69 }
70
71 private static final long serialVersionUID = 5418275817834009509L;
72
73 private ListSelect countrySelectField;
74
75 private ElementCollectionField<SpecimenTypeDesignationDTO> typeDesignationsCollectionField;
76
77 private EnumSet<CRUD> crud;
78
79 private TeamOrPersonField collectorField;
80
81 private FilterableAnnotationsField annotationsListField;
82
83 private AnnotationType[] editableAnotationTypes = RegistrationUIDefaults.EDITABLE_ANOTATION_TYPES;
84
85 /**
86 * @return the countrySelectField
87 */
88 @Override
89 public ListSelect getCountrySelectField() {
90 return countrySelectField;
91 }
92
93 /**
94 * {@inheritDoc}
95 */
96 @Override
97 protected void initContent() {
98
99 GridLayout grid = (GridLayout)getFieldLayout();
100 grid.setSpacing(true);
101 grid.setMargin(true);
102 grid.setColumns(3);
103 grid.setRows(10);
104
105 //TODO typifyingAuthors
106
107 // FieldUnit + GatheringEvent
108
109 int row = 0;
110 countrySelectField = new ListSelect("Country");
111 addField(countrySelectField, "country", 1, row , 2, row);
112 countrySelectField.setWidth("100%");
113 countrySelectField.setItemCaptionMode(ItemCaptionMode.PROPERTY);
114 countrySelectField.setItemCaptionPropertyId("label");
115 countrySelectField.setRows(1);
116
117 row++;
118 TextArea localityField = new TextArea("Locality");
119 localityField.setNullRepresentation("");
120 addField(localityField, "locality", 0, row , 2, row);
121 localityField.setWidth("100%");
122 // NOTE: setRows and SetCold breaks he width setting,
123 // see https://github.com/vaadin/framework/issues/3617
124
125 row++;
126 GeoLocationField exactLocation = new GeoLocationField("Geo location");
127 addField(exactLocation, "exactLocation", 0, row, 2, row);
128 exactLocation.setWidth("100%");
129
130 row++;
131 MinMaxTextField absElevationMinMax = new MinMaxTextField("Altitude", "m");
132 absElevationMinMax.setWidth("100%");
133 absElevationMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
134 grid.addComponent(absElevationMinMax, 0, row, 2, row);
135
136 bindField(absElevationMinMax.getMinField(), "absoluteElevation");
137 bindField(absElevationMinMax.getMaxField(), "absoluteElevationMax");
138 bindField(absElevationMinMax.getTextField(), "absoluteElevationText");
139
140 absElevationMinMax.getMaxField().setConverter(new IntegerConverter());
141 absElevationMinMax.getMinField().setConverter(new IntegerConverter());
142
143 row++;
144 MinMaxTextField distanceToWaterSurfaceMinMax = new MinMaxTextField("Distance to water surface", "m");
145 distanceToWaterSurfaceMinMax.setWidth("100%");
146 distanceToWaterSurfaceMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
147 grid.addComponent(distanceToWaterSurfaceMinMax, 0, row, 2, row);
148
149 bindField(distanceToWaterSurfaceMinMax.getMinField(), "distanceToWaterSurface");
150 bindField(distanceToWaterSurfaceMinMax.getMaxField(), "distanceToWaterSurfaceMax");
151 bindField(distanceToWaterSurfaceMinMax.getTextField(), "distanceToWaterSurfaceText");
152 distanceToWaterSurfaceMinMax.getMaxField().setConverter(new DoubleConverter());
153 distanceToWaterSurfaceMinMax.getMinField().setConverter(new DoubleConverter());
154 distanceToWaterSurfaceMinMax.getMaxField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double.MAX_VALUE));
155 distanceToWaterSurfaceMinMax.getMinField().addValidator(new DoubleRangeValidator("Negative values are not allowed here.", 0.0, Double.MAX_VALUE));
156
157 row++;
158 MinMaxTextField distanceToGroundMinMax = new MinMaxTextField("Distance to substrate", "m");
159 distanceToGroundMinMax.setWidth("100%");
160 distanceToGroundMinMax.addSubComponentsStyleName(getDefaultComponentStyles());
161 grid.addComponent(distanceToGroundMinMax, 0, row, 2, row);
162
163 bindField(distanceToGroundMinMax.getMinField(), "distanceToGround");
164 bindField(distanceToGroundMinMax.getMaxField(), "distanceToGroundMax");
165 bindField(distanceToGroundMinMax.getTextField(), "distanceToGroundText");
166 distanceToGroundMinMax.getMaxField().setConverter(new DoubleConverter());
167 distanceToGroundMinMax.getMinField().setConverter(new DoubleConverter());
168
169 row++;
170 collectorField = new TeamOrPersonField("Collector", TeamOrPersonBaseCaptionGenerator.CacheType.NOMENCLATURAL_TITLE);
171 addField(collectorField, "collector", 0, row, 2, row);
172
173 row++;
174 PartialDateField collectionDateField = new PartialDateField("Collection date");
175 collectionDateField.setInputPrompt("dd.mm.yyyy");
176 addField(collectionDateField, "gatheringDate", 0, row, 1, row);
177 addTextField("Field number", "fieldNumber", 2, row);
178
179
180 row++;
181
182 // FIXME: can we use the Grid instead?
183 typeDesignationsCollectionField = new ElementCollectionField<>(
184 SpecimenTypeDesignationDTO.class,
185 SpecimenTypeDesignationDTORow.class
186 );
187 typeDesignationsCollectionField.withCaption("Types");
188 typeDesignationsCollectionField.getLayout().setSpacing(false);
189 typeDesignationsCollectionField.getLayout().setColumns(3);
190
191 typeDesignationsCollectionField.setVisibleProperties(SpecimenTypeDesignationDTORow.visibleFields());
192
193 typeDesignationsCollectionField.setPropertyHeader("accessionNumber", "Access. num.");
194 typeDesignationsCollectionField.setPropertyHeader("preferredStableUri", "Stable URI");
195 typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReference", "Image reference");
196 typeDesignationsCollectionField.setPropertyHeader("mediaSpecimenReferenceDetail", "Reference detail");
197 typeDesignationsCollectionField.addElementAddedListener( e -> updateAllowSave());
198 typeDesignationsCollectionField.addElementRemovedListener( e -> updateAllowSave());
199
200 // typeDesignationsCollectionField.getLayout().setMargin(false);
201 // typeDesignationsCollectionField.addStyleName("composite-field-wrapper");
202 // addField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs", 0, row, 2, row);
203
204 Panel scrollPanel = new Panel(typeDesignationsCollectionField.getLayout());
205 scrollPanel.setCaption("Types");
206 scrollPanel.setWidth(800, Unit.PIXELS);
207
208 bindField(typeDesignationsCollectionField, "specimenTypeDesignationDTOs");
209 addComponent(scrollPanel, 0, row, 2, row);
210
211 row++;
212 annotationsListField = new FilterableAnnotationsField("Editorial notes");
213 annotationsListField.setWidth(100, Unit.PERCENTAGE);
214 annotationsListField.setAnnotationTypesVisible(editableAnotationTypes);
215 addField(annotationsListField, "annotations", 0, row, 2, row);
216
217 }
218
219
220 /**
221 * {@inheritDoc}
222 */
223 @Override
224 public String getWindowCaption() {
225 return "Specimen typedesignations editor";
226 }
227
228 /**
229 * {@inheritDoc}
230 */
231 @Override
232 public void focusFirst() {
233 // none
234 }
235
236 /**
237 * {@inheritDoc}
238 */
239 @Override
240 protected String getDefaultComponentStyles() {
241 return "tiny";
242 }
243
244 /**
245 * {@inheritDoc}
246 */
247 @Override
248 public boolean allowAnonymousAccess() {
249 return false;
250 }
251
252 /**
253 * {@inheritDoc}
254 */
255 @Override
256 public Collection<Collection<GrantedAuthority>> allowedGrantedAuthorities() {
257 return null;
258 }
259
260 /**
261 * {@inheritDoc}
262 */
263 @Override
264 public boolean isResizable() {
265 return true;
266 }
267
268
269 // ------- SpecimenTypeDesignationWorkingsetPopupEditorView methods ---- //
270 @Override
271 public ElementCollectionField<SpecimenTypeDesignationDTO> getTypeDesignationsCollectionField() {
272 return typeDesignationsCollectionField;
273 }
274
275 @Override
276 public void applyDefaultComponentStyle(Component ... components){
277 for(int i = 0; i <components.length; i++){
278 components[i].setStyleName(getDefaultComponentStyles());
279 }
280 }
281
282 /**
283 * {@inheritDoc}
284 */
285 @Override
286 public void grantToCurrentUser(EnumSet<CRUD> crud) {
287 getPresenter().setGrantsForCurrentUser(crud);
288
289 }
290
291 /**
292 * {@inheritDoc}
293 */
294 @Override
295 protected void afterItemDataSourceSet() {
296 super.afterItemDataSourceSet();
297 GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
298 for(int rowIndex = 1; rowIndex < gridLayout.getRows(); rowIndex++){ // first row is header
299 Component item = gridLayout.getComponent(SpecimenTypeDesignationDTORow.rowListSelectColumn(), rowIndex);
300 ((CollectionRowRepresentative)item).updateRowItemsEnabledStates();
301 }
302 updateAllowDelete();
303 updateAllowSave();
304 }
305
306 /**
307 * {@inheritDoc}
308 */
309 @Override
310 public void updateAllowDelete(){
311 // disable the delete button if there is only one typeDesignation
312 // if this typeDesignation is deleted the fieldUnit would become orphan in the
313 // TypeDesignationWorkingSet
314 GridLayout gridLayout = this.typeDesignationsCollectionField.getLayout();
315 if(gridLayout.getRows() == 3){ // first row is header, last row is next new item
316 gridLayout.getComponent(gridLayout.getColumns() - 1, 1).setEnabled(false);
317 }
318 }
319
320 public void updateAllowSave(){
321 boolean hasTypeDesignations = getBean().getSpecimenTypeDesignationDTOs().size() > 0;
322 setSaveButtonEnabled(hasTypeDesignations);
323 if(!hasTypeDesignations){
324 addStatusMessage(CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING);
325 } else {
326 removeStatusMessage(CAN_T_SAVE_AS_LONG_AS_TYPE_DESIGNATIONS_ARE_MISSING);
327 }
328
329 }
330
331 /**
332 * {@inheritDoc}
333 */
334 @Override
335 public void setReadOnly(boolean readOnly) {
336 super.setReadOnly(readOnly);
337 getFieldLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
338 typeDesignationsCollectionField.getLayout().iterator().forEachRemaining(c -> c.setReadOnly(readOnly));
339
340 }
341
342 /**
343 * @return the collectorField
344 */
345 @Override
346 public TeamOrPersonField getCollectorField() {
347 return collectorField;
348 }
349
350 /**
351 * By default AnnotationType.EDITORIAL() is enabled.
352 *
353 * @return the editableAnotationTypes
354 */
355 @Override
356 public AnnotationType[] getEditableAnotationTypes() {
357 return editableAnotationTypes;
358 }
359
360 /**
361 * By default AnnotationType.EDITORIAL() is enabled.
362 *
363 *
364 * @param editableAnotationTypes the editableAnotationTypes to set
365 */
366 @Override
367 public void setEditableAnotationTypes(AnnotationType ... editableAnotationTypes) {
368 this.editableAnotationTypes = editableAnotationTypes;
369 }
370
371 /**
372 * {@inheritDoc}
373 */
374 @Override
375 public FilterableAnnotationsField getAnnotationsField() {
376 return annotationsListField;
377 }
378
379
380
381 }