Project

General

Profile

Download (12.3 KB) Statistics
| Branch: | Tag: | Revision:
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.component.common;
10

    
11
import java.util.EnumSet;
12
import java.util.List;
13

    
14
import org.vaadin.teemu.switchui.Switch;
15
import org.vaadin.viritin.fields.LazyComboBox;
16

    
17
import com.vaadin.data.Validator.InvalidValueException;
18
import com.vaadin.data.fieldgroup.BeanFieldGroup;
19
import com.vaadin.data.fieldgroup.FieldGroup;
20
import com.vaadin.server.FontAwesome;
21
import com.vaadin.ui.Button;
22
import com.vaadin.ui.Component;
23
import com.vaadin.ui.CssLayout;
24
import com.vaadin.ui.Field;
25
import com.vaadin.ui.TextField;
26
import com.vaadin.ui.themes.ValoTheme;
27

    
28
import eu.etaxonomy.cdm.model.agent.Person;
29
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
30
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
31
import eu.etaxonomy.cdm.vaadin.security.UserHelper;
32
import eu.etaxonomy.vaadin.component.CompositeCustomField;
33
import eu.etaxonomy.vaadin.component.SwitchButton;
34

    
35
/**
36
 * @author a.kohlbecker
37
 * @since May 11, 2017
38
 *
39
 */
40
public class PersonField extends CompositeCustomField<Person> {
41

    
42
    private static final long serialVersionUID = 8346575511284469356L;
43

    
44
    private static final String PRIMARY_STYLE = "v-person-field";
45

    
46
    /**
47
     * do not allow entities which are having only <code>null</code> values in all fields
48
     * {@link #getValue()} would return <code>null</code> in this case.
49
     */
50
    boolean allowNewEmptyEntity = true;
51

    
52
    private LazyComboBox<Person> personSelect = new LazyComboBox<Person>(Person.class);
53

    
54
    private Button personSelectConfirmButton = new Button("OK");
55
    private Button newPersonButton = new Button("New");
56

    
57
    private BeanFieldGroup<Person> fieldGroup = new BeanFieldGroup<>(Person.class);
58

    
59
    enum Mode {
60
        CACHE_MODE, DETAILS_MODE;
61

    
62
        public String toCssClass() {
63
            return name().toLowerCase().replace("_", "-");
64
        }
65
    }
66

    
67
    private Mode currentMode = null;
68

    
69
    private float baseWidth = 100 / 9;
70

    
71
    private CssLayout root = new CssLayout();
72
    private CssLayout selectOrNewContainer = new CssLayout();
73

    
74
    private TextField titleCacheField = new TextFieldNFix();
75
    private TextField nomenclaturalTitleField = new TextFieldNFix();
76
    private Button nomenclaturalTitleButton = new Button();
77
    private CssLayout detailsContainer = new CssLayout();
78
    private TextField initialsField = new TextFieldNFix();
79
    private TextField firstNameField = new TextFieldNFix();
80
    private TextField lastNameField = new TextFieldNFix();
81
    private TextField prefixField = new TextFieldNFix();
82
    private TextField suffixField = new TextFieldNFix();
83
    private SwitchButton unlockSwitch = new SwitchButton();
84

    
85
    private boolean onCommit = false;
86

    
87

    
88

    
89
    /**
90
     * @param caption
91
     */
92
    public PersonField(String caption) {
93

    
94
        this();
95
        setCaption(caption);
96
    }
97

    
98
    /**
99
     * @param caption
100
     */
101
    public PersonField() {
102

    
103
        root.setPrimaryStyleName(PRIMARY_STYLE);
104

    
105
        // select existing or create new person
106
        addStyledComponents(personSelect, personSelectConfirmButton, newPersonButton);
107
        personSelect.addValueChangeListener(e -> {
108
            if(personSelect.getValue() != null){
109
                personSelectConfirmButton.setEnabled(true);
110
            }
111
        });
112
        personSelectConfirmButton.setEnabled(false);
113
        personSelectConfirmButton.addClickListener(e -> {
114
            setValue(personSelect.getValue());
115
            personSelect.clear();
116
        });
117
        selectOrNewContainer.addComponents(personSelect, personSelectConfirmButton, newPersonButton);
118
        newPersonButton.addClickListener(e -> createNewPerson());
119

    
120
        // edit person
121
        addStyledComponent(titleCacheField);
122
        addStyledComponents(initialsField);
123
        addStyledComponent(firstNameField);
124
        addStyledComponent(lastNameField);
125
        addStyledComponent(prefixField);
126
        addStyledComponent(suffixField);
127
        addStyledComponent(unlockSwitch);
128
        addStyledComponent(nomenclaturalTitleField);
129
        addStyledComponent(nomenclaturalTitleButton);
130

    
131
        addSizedComponent(root);
132
    }
133

    
134
    /**
135
     *
136
     */
137
    private void checkUserPermissions(Person newValue) {
138
        boolean userCanEdit = UserHelper.fromSession().userHasPermission(newValue, "DELETE", "UPDATE");
139
        boolean isUnsavedEnitity = newValue.getId() == 0;
140
        setEnabled(isUnsavedEnitity || userCanEdit);
141
    }
142

    
143
    private void setMode(Mode mode){
144
        if(mode.equals(currentMode)){
145
            return;
146
        }
147
        if(currentMode != null){
148
            String removeMode = currentMode.toCssClass();
149
            root.removeStyleName(removeMode);
150
        }
151
        String newMode = mode.toCssClass();
152
        root.addStyleName(newMode);
153
        currentMode = mode;
154
    }
155

    
156

    
157
    /**
158
     * {@inheritDoc}
159
     */
160
    @Override
161
    protected Component initContent() {
162

    
163
        selectOrNewContainer.setWidth(100, Unit.PERCENTAGE);
164
        personSelect.setWidthUndefined();
165

    
166
        root.addComponent(titleCacheField);
167
        root.addComponent(unlockSwitch);
168
        root.addComponent(selectOrNewContainer);
169

    
170
        titleCacheField.setWidth(100, Unit.PERCENTAGE);
171

    
172
        prefixField.setWidth(baseWidth, Unit.PERCENTAGE);
173
        prefixField.setInputPrompt("Prefix");
174

    
175
        initialsField.setWidth(baseWidth, Unit.PERCENTAGE);
176
        initialsField.setInputPrompt("Initials");
177

    
178
        firstNameField.setWidth(baseWidth * 3, Unit.PERCENTAGE);
179
        firstNameField.setInputPrompt("Other/given names");
180

    
181
        lastNameField.setWidth(baseWidth * 3, Unit.PERCENTAGE);
182
        lastNameField.setInputPrompt("Family name");
183

    
184
        suffixField.setWidth(baseWidth, Unit.PERCENTAGE);
185
        suffixField.setInputPrompt("Suffix");
186

    
187
        detailsContainer.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
188
        detailsContainer.addComponent(prefixField);
189
        detailsContainer.addComponent(initialsField);
190
        detailsContainer.addComponent(firstNameField);
191
        detailsContainer.addComponent(lastNameField);
192
        detailsContainer.addComponent(suffixField);
193
        root.addComponent(detailsContainer);
194

    
195
        nomenclaturalTitleButton.setHeight(22, Unit.PIXELS);
196
        nomenclaturalTitleButton.setDescription("Show the nomenclatural title cache.");
197
        nomenclaturalTitleButton.addClickListener( e -> {
198
            nomenclaturalTitleField.setVisible(!nomenclaturalTitleField.isVisible());
199
            nomenclaturalTitleButtonChooseIcon();
200
            if(nomenclaturalTitleField.isVisible()){
201
                nomenclaturalTitleField.focus();
202
            }
203
        });
204
        // nomenclaturalTitleField.setCaption("Nomenclatural title");
205
        nomenclaturalTitleField.setWidth(100, Unit.PERCENTAGE);
206

    
207
        root.addComponent(nomenclaturalTitleField);
208
        root.addComponent(nomenclaturalTitleButton);
209

    
210
        unlockSwitch.addValueChangeListener(e -> {
211
            if(refreshMode()){
212
                switch (currentMode) {
213
                    case CACHE_MODE:
214
                        titleCacheField.focus();
215
                        break;
216
                    case DETAILS_MODE:
217
                        firstNameField.focus();
218
                        break;
219
                    default:
220
                        break;
221

    
222
                }
223
            }
224
        });
225
        unlockSwitch.setValueSetLister(e -> {
226
            refreshMode();
227
        });
228

    
229
        addDefaultStyles();
230
        setMode(Mode.DETAILS_MODE);
231

    
232
        fieldGroup.bind(titleCacheField, "titleCache");
233
        fieldGroup.bind(prefixField, "prefix");
234
        fieldGroup.bind(initialsField, "initials");
235
        fieldGroup.bind(firstNameField, "firstname");
236
        fieldGroup.bind(lastNameField, "lastname");
237
        fieldGroup.bind(suffixField, "suffix");
238
        fieldGroup.bind(unlockSwitch, "protectedTitleCache");
239
        fieldGroup.bind(nomenclaturalTitleField, "nomenclaturalTitle");
240
        fieldGroup.setBuffered(false);
241

    
242
        updateVisibilities(getValue());
243

    
244
        return root;
245
    }
246

    
247
    /**
248
     *
249
     */
250
    protected void nomenclaturalTitleButtonChooseIcon() {
251
        nomenclaturalTitleButton.setIcon(nomenclaturalTitleField.isVisible() ? FontAwesome.ANGLE_UP : FontAwesome.ELLIPSIS_H);
252
    }
253

    
254
    /**
255
     *
256
     * @return true if the mode has changed
257
     */
258
    protected boolean refreshMode() {
259
        Mode lastMode = currentMode;
260
        setMode(unlockSwitch.getValue() ? Mode.CACHE_MODE: Mode.DETAILS_MODE);
261
        return !lastMode.equals(currentMode);
262
    }
263

    
264
    /**
265
     * {@inheritDoc}
266
     */
267
    @Override
268
    public Class<? extends Person> getType() {
269
        return Person.class;
270
    }
271

    
272
    private void createNewPerson(){
273
        Person p = Person.NewInstance();
274
        setValue(p);
275
    }
276

    
277
    @Override
278
    public void setValue(Person person){
279
        super.setValue(person);
280
        if(person != null && person.getId() != 0){
281
            personSelect.setValue(person);
282
        }
283
    }
284

    
285
    /**
286
     * {@inheritDoc}
287
     */
288
    @Override
289
    protected void setInternalValue(Person newValue) {
290

    
291
        super.setInternalValue(newValue);
292
        fieldGroup.setItemDataSource(newValue);
293
        checkUserPermissions(newValue);
294
        updateVisibilities(newValue);
295
    }
296

    
297
    /**
298
     *
299
     */
300
    private void updateVisibilities(Person person) {
301

    
302
        selectOrNewContainer.setVisible(person == null);
303

    
304
        detailsContainer.setVisible(person != null);
305
        unlockSwitch.setVisible(person != null);
306
        titleCacheField.setVisible(person != null);
307
        nomenclaturalTitleField.setVisible(nomenclaturalTitleField.getValue().equals(titleCacheField.getValue()));
308
        nomenclaturalTitleButtonChooseIcon();
309

    
310
    }
311

    
312
    @Override
313
    protected void addDefaultStyles(){
314
        titleCacheField.addStyleName("cache-field");
315
        detailsContainer.addStyleName("details-fields");
316
        unlockSwitch.addStyleName(Switch.DOM_STYLE);
317
        nomenclaturalTitleButton.addStyleName(ValoTheme.BUTTON_BORDERLESS_COLORED + " center-h");
318
    }
319

    
320
    /**
321
     * {@inheritDoc}
322
     */
323
    @Override
324
    public FieldGroup getFieldGroup() {
325
        return fieldGroup;
326
    }
327

    
328

    
329
    /**
330
     * {@inheritDoc}
331
     */
332
    @Override
333
    protected List<Field> nullValueCheckIgnoreFields() {
334

    
335
        List<Field>ignoreFields = super.nullValueCheckIgnoreFields();
336
        ignoreFields.add(unlockSwitch);
337

    
338
        if(unlockSwitch.getValue().booleanValue() == false){
339
            Person value = getValue();
340
            if(value != null && value.getId() == 0){
341
                // only if the entity is unsaved!
342
                ignoreFields.add(titleCacheField);
343
                titleCacheField.setValue(null);
344
            }
345
        }
346
        return ignoreFields;
347
    }
348

    
349
    /**
350
     * {@inheritDoc}
351
     */
352
    @Override
353
    public void commit() throws SourceException, InvalidValueException {
354

    
355
        super.commit();
356

    
357
        Person bean =  getValue();
358
        if(bean != null){
359
            boolean isUnsaved = bean.getId() == 0;
360
            if(isUnsaved && !(hasNullContent() && !allowNewEmptyEntity)){
361
                UserHelper.fromSession().createAuthorityForCurrentUser(bean, EnumSet.of(CRUD.UPDATE, CRUD.DELETE), null);
362
            }
363
        }
364
    }
365

    
366
    /**
367
     * {@inheritDoc}
368
     *
369
     * @return returns <code>null</code> in case the edited entity is unsaved and if
370
     * it only has null values.
371
     */
372
    @Override
373
    public Person getValue() {
374
        Person bean = super.getValue();
375
        if(bean == null){
376
            return null;
377
        }
378
       // boolean isUnsaved = bean.getId() == 0;
379
//        if(isUnsaved && hasNullContent() && !allowNewEmptyEntity) {
380
//            return null;
381
//        }
382
        return bean;
383
    }
384

    
385
    /**
386
     * @return the personSelect
387
     */
388
    public LazyComboBox<Person> getPersonSelect() {
389
        return personSelect;
390
    }
391

    
392
    /**
393
     * @param personSelect the personSelect to set
394
     */
395
    public void setPersonSelect(LazyComboBox<Person> personSelect) {
396
        this.personSelect = personSelect;
397
    }
398

    
399
    /**
400
     * @return the allowNewEmptyEntity
401
     */
402
    public boolean isAllowNewEmptyEntity() {
403
        return allowNewEmptyEntity;
404
    }
405

    
406
    /**
407
     * @param allowNewEmptyEntity the allowNewEmptyEntity to set
408
     */
409
    public void setAllowNewEmptyEntity(boolean allowNewEmptyEntity) {
410
        this.allowNewEmptyEntity = allowNewEmptyEntity;
411
    }
412

    
413

    
414

    
415
}
(3-3/5)