Project

General

Profile

Download (8.84 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.HashSet;
12
import java.util.Set;
13

    
14
import com.vaadin.data.Validator.InvalidValueException;
15
import com.vaadin.data.fieldgroup.BeanFieldGroup;
16
import com.vaadin.data.fieldgroup.FieldGroup.CommitException;
17
import com.vaadin.data.util.BeanItem;
18
import com.vaadin.event.FieldEvents.TextChangeEvent;
19
import com.vaadin.server.FontAwesome;
20
import com.vaadin.ui.Alignment;
21
import com.vaadin.ui.Button;
22
import com.vaadin.ui.Component;
23
import com.vaadin.ui.CssLayout;
24
import com.vaadin.ui.CustomField;
25
import com.vaadin.ui.GridLayout;
26
import com.vaadin.ui.Label;
27
import com.vaadin.ui.TextField;
28
import com.vaadin.ui.themes.ValoTheme;
29

    
30
import eu.etaxonomy.cdm.model.common.TimePeriod;
31
import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
32
import eu.etaxonomy.cdm.vaadin.component.PartialDateField;
33
import eu.etaxonomy.cdm.vaadin.component.TextFieldNFix;
34
import eu.etaxonomy.cdm.vaadin.component.registration.RegistrationStyles;
35
import eu.etaxonomy.cdm.vaadin.util.formatter.DateTimeFormat;
36
import eu.etaxonomy.cdm.vaadin.util.formatter.TimePeriodFormatter;
37

    
38
/**
39
 * @author a.kohlbecker
40
 * @since Apr 6, 2017
41
 *
42
 */
43
public abstract class AbstractTimePeriodField<T extends TimePeriod> extends CustomField<T> {
44

    
45
    private static final long serialVersionUID = -7377778547595966252L;
46

    
47
    private static final String PRIMARY_STYLE = "v-time-period-field";
48

    
49
    private BeanFieldGroup<TimePeriod> fieldGroup = new BeanFieldGroup<>(TimePeriod.class);
50

    
51
    TextField parseField = null;
52

    
53
    TextField freeText = null;
54

    
55
    Label toLabel = null;
56

    
57
    GridLayout detailsViewGrid = new GridLayout(3, 4);
58

    
59
    CssLayout detailsView = new CssLayout();
60

    
61
    //TODO implement custom button textfield which does not require a gridLayout
62
    GridLayout buttonTextField = new GridLayout(2, 1);
63
    GridLayout simpleView = new GridLayout(2, 1);
64

    
65
    TextField cacheField = new TextFieldNFix();
66

    
67
    Set<Component> styledComponents = new HashSet<>();
68

    
69
    private TimePeriodFormatter timePeriodFormatter = new TimePeriodFormatter(DateTimeFormat.ISO8601_DATE);
70

    
71
    /**
72
     *
73
     */
74
    public AbstractTimePeriodField() {
75
        super();
76

    
77
    }
78

    
79
    /**
80
     * @param string
81
     */
82
    public AbstractTimePeriodField(String string) {
83
        this();
84
        setCaption(string);
85
    }
86

    
87
    /**
88
     * {@inheritDoc}
89
     */
90
    @Override
91
    protected Component initContent() {
92

    
93
        super.setPrimaryStyleName(PRIMARY_STYLE);
94

    
95
        CssLayout root = new CssLayout();
96

    
97
        initSimpleView();
98
        initDetailsView();
99

    
100

    
101
        detailsView.setWidth(100, Unit.PERCENTAGE);
102
        simpleView.setWidth(100, Unit.PERCENTAGE);
103
        root.addComponent(simpleView);
104
        root.addComponent(detailsView);
105

    
106
        applyDefaultStyles();
107

    
108
        showSimple();
109

    
110
        root.setWidth(100, Unit.PERCENTAGE);
111

    
112
        // fixed size to avoid layout and component expansion problems in the nested grid layouts
113
        this.setWidth(300, Unit.PIXELS);
114

    
115
        return root;
116
    }
117

    
118
    /**
119
     *
120
     */
121
    private void initSimpleView() {
122

    
123
        Button showDetailsButton = new Button(FontAwesome.CALENDAR);
124
        showDetailsButton.addClickListener(e -> showDetails());
125
        cacheField.setWidth(100, Unit.PERCENTAGE);
126
        // showDetailsButton.setWidth(100, Unit.PERCENTAGE);
127

    
128
        simpleView.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
129
        simpleView.addComponent(showDetailsButton, 0, 0);
130
        simpleView.addComponent(cacheField, 1, 0);
131
        simpleView.setColumnExpandRatio(1, 0.9f);
132
    }
133

    
134
    /**
135
     *
136
     */
137
    private void initDetailsView() {
138

    
139
        parseField = new TextFieldNFix();
140
        // parseField.setWidth(100, Unit.PERCENTAGE);
141
        parseField.setInputPrompt("This field will parse the entered time period");
142
        parseField.addTextChangeListener(e -> parseInput(e));
143
        parseField.setWidth(100, Unit.PERCENTAGE);
144

    
145
        Button closeDetailsButton = new Button(FontAwesome.CLOSE);
146
        closeDetailsButton.addClickListener(e -> {
147
            try {
148
                fieldGroup.commit();
149
            } catch (CommitException e1) {
150
                // TODO Auto-generated catch block
151
                e1.printStackTrace();
152
            }
153
            updateCacheField();
154
            showSimple();
155
        });
156

    
157
        buttonTextField.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
158
        buttonTextField.setWidth(100, Unit.PERCENTAGE);
159
        buttonTextField.addComponent(closeDetailsButton, 0, 0);
160
        buttonTextField.addComponent(parseField, 1, 0);
161
        buttonTextField.setColumnExpandRatio(1, 1.0f);
162

    
163
        PartialDateField startDate = new PartialDateField("Start");
164
        startDate.setInputPrompt("dd.mm.yyyy");
165
        PartialDateField endDate = new PartialDateField("End");
166
        endDate.setInputPrompt("dd.mm.yyyy");
167
        freeText = new TextFieldNFix("FreeText");
168
        freeText.setWidth(100, Unit.PERCENTAGE);
169

    
170
        fieldGroup.bind(startDate, "start");
171
        fieldGroup.bind(endDate, "end");
172
        fieldGroup.bind(freeText, "freeText");
173

    
174
        toLabel = new Label("\u2014"); // EM DASH : 0x2014
175
        startDate.setWidth(100, Unit.PERCENTAGE);
176
        endDate.setWidth(100, Unit.PERCENTAGE);
177
        toLabel.setWidthUndefined();
178

    
179
        int row = 0;
180
        detailsViewGrid.addComponent(buttonTextField, 0, row, 2, row);
181
        row++;
182
        detailsViewGrid.addComponent(startDate, 0, row, 0, row);
183
        detailsViewGrid.addComponent(toLabel, 1, row);
184
        detailsViewGrid.setComponentAlignment(toLabel, Alignment.BOTTOM_CENTER);
185
        detailsViewGrid.addComponent(endDate, 2, row, 2, row);
186
        row++;
187
        detailsViewGrid.addComponent(freeText, 0, row, 2, row);
188
        detailsViewGrid.setWidth(100, Unit.PERCENTAGE);
189
        detailsViewGrid.setColumnExpandRatio(0,  5);
190
        detailsViewGrid.setColumnExpandRatio(1,  1);
191
        detailsViewGrid.setColumnExpandRatio(2,  5);
192

    
193

    
194
        // apply the style of the container to all child components. E.g. make all tiny
195
        addStyleName((getStyleName()));
196

    
197
        detailsView.setStyleName("margin-wrapper");
198
        detailsView.addComponent(detailsViewGrid);
199

    
200
    }
201

    
202

    
203
    /**
204
     * @return
205
     */
206
    private void showSimple() {
207
        detailsView.setVisible(false);
208
        simpleView.setVisible(true);
209
    }
210

    
211
    /**
212
     * @return
213
     */
214
    private void showDetails() {
215
        detailsView.setVisible(true);
216
        simpleView.setVisible(false);
217
    }
218

    
219
    /**
220
     * @param e
221
     * @return
222
     */
223
    private void parseInput(TextChangeEvent e) {
224
        if(!e.getText().isEmpty()){
225
            TimePeriod parsedPeriod = TimePeriodParser.parseString(e.getText());
226
            fieldGroup.setItemDataSource(new BeanItem<TimePeriod>(parsedPeriod));
227
        }
228
    }
229

    
230
    /**
231
     *
232
     */
233
    private void applyDefaultStyles() {
234
        if(parseField != null) {
235
            parseField.addStyleName(RegistrationStyles.HELPER_FIELD);
236
            toLabel.addStyleName("to-label");
237
            buttonTextField.addStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
238
        }
239

    
240
    }
241

    
242
    @Override
243
    protected void setInternalValue(T newValue) {
244
        if(newValue == null){
245
            newValue = newModelInstance();
246
        }
247
        super.setInternalValue(newValue);
248
            fieldGroup.setItemDataSource(new BeanItem<TimePeriod>(newValue));
249
        updateCacheField();
250
    }
251

    
252
    /**
253
     * @return
254
     */
255
    protected abstract T newModelInstance();
256

    
257
    /**
258
     * @param newValue
259
     */
260
    private void updateCacheField() {
261
        TimePeriod newValue = fieldGroup.getItemDataSource().getBean();
262
        cacheField.setReadOnly(false);
263
        cacheField.setValue(timePeriodFormatter.print(newValue));
264
        cacheField.setReadOnly(true);
265
    }
266

    
267
    @Override
268
    public void setStyleName(String style) {
269
        super.setStyleName(style);
270
        detailsViewGrid.iterator().forEachRemaining(c -> c.setStyleName(style));
271
        buttonTextField.iterator().forEachRemaining(c -> c.setStyleName(style));
272
        simpleView.iterator().forEachRemaining(c -> c.setStyleName(style));
273
        applyDefaultStyles();
274
    }
275

    
276
    @Override
277
    public void addStyleName(String style) {
278
        super.addStyleName(style);
279
        detailsViewGrid.iterator().forEachRemaining(c -> c.addStyleName(style));
280
        simpleView.iterator().forEachRemaining(c -> {
281
            c.addStyleName(style);
282
        });
283

    
284
        buttonTextField.iterator().forEachRemaining(c -> c.addStyleName(style));
285
    }
286

    
287
    /**
288
     * {@inheritDoc}
289
     */
290
    @Override
291
    public void commit() throws SourceException, InvalidValueException {
292
        super.commit();
293
        try {
294
            fieldGroup.commit();
295
        } catch (CommitException e) {
296
            throw new RuntimeException(e);
297
        }
298
    }
299

    
300

    
301

    
302

    
303

    
304
}
(1-1/8)