25bc54584e88f3a7d822fbe2ed6b04a227e46127
[cdm-vaadin.git] / src / main / java / eu / etaxonomy / cdm / vaadin / component / common / FilterableAnnotationsField.java
1 /**
2 * Copyright (C) 2018 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.ArrayList;
12 import java.util.Arrays;
13 import java.util.Collection;
14 import java.util.List;
15 import java.util.Optional;
16
17 import org.vaadin.viritin.FilterableListContainer;
18
19 import com.vaadin.data.Container;
20 import com.vaadin.data.Container.Filter;
21 import com.vaadin.data.Item;
22 import com.vaadin.data.Validator.InvalidValueException;
23 import com.vaadin.data.fieldgroup.FieldGroup;
24 import com.vaadin.data.util.BeanItemContainer;
25 import com.vaadin.ui.Button;
26 import com.vaadin.ui.Component;
27 import com.vaadin.ui.CssLayout;
28 import com.vaadin.ui.DefaultFieldFactory;
29 import com.vaadin.ui.Field;
30 import com.vaadin.ui.NativeSelect;
31 import com.vaadin.ui.Table;
32 import com.vaadin.ui.Table.ColumnHeaderMode;
33 import com.vaadin.ui.TextArea;
34
35 import eu.etaxonomy.cdm.model.common.Annotation;
36 import eu.etaxonomy.cdm.model.common.AnnotationType;
37 import eu.etaxonomy.cdm.model.common.Language;
38 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
39 import eu.etaxonomy.cdm.vaadin.component.ButtonFactory;
40 import eu.etaxonomy.cdm.vaadin.util.converter.SetToListConverter;
41 import eu.etaxonomy.cdm.vaadin.util.filter.CdmTermFilter;
42 import eu.etaxonomy.vaadin.component.CompositeCustomField;
43
44 /**
45 * @author a.kohlbecker
46 * @since Jun 20, 2018
47 *
48 */
49 public class FilterableAnnotationsField extends CompositeCustomField<List<Annotation>> {
50
51 private static final long serialVersionUID = -8258550787601028813L;
52
53 private CssLayout root = new CssLayout();
54
55 private Table table = new Table();
56
57 private Button newButton = ButtonFactory.CREATE_NEW.createButton();
58
59 private List<AnnotationType> typesFilter = null;
60
61 private BeanItemContainer<DefinedTermBase> typeSelectItemContainer;
62
63 private FilterableListContainer<Annotation> container;
64
65 private boolean withNewButton;
66
67 public FilterableAnnotationsField() {
68 this(null);
69 }
70
71 public FilterableAnnotationsField(String caption) {
72
73 setCaption(caption);
74 // annotations are always sets
75 setConverter(new SetToListConverter<Annotation>());
76
77 root.setWidth(100, Unit.PERCENTAGE);
78
79 // setup table
80 table.setPageLength(1);
81 table.setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
82 table.setWidth(100, Unit.PERCENTAGE);
83 table.setTableFieldFactory(new DefaultFieldFactory() {
84
85 private static final long serialVersionUID = 5437750882205859178L;
86
87 @Override
88 public Field<?> createField(Item item, Object propertyId, Component uiContext) {
89
90 Field<?> field = createField(propertyId);
91 if(field == null) {
92 field = super.createField(item, propertyId, uiContext);
93 }
94 return field;
95
96 }
97
98 @Override
99 public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) {
100
101 Field<?> field = createField(propertyId);
102
103 if(field == null) {
104 field = super.createField(container, itemId, propertyId, uiContext);
105 }
106 return field;
107 }
108
109 protected Field<?> createField(Object propertyId) {
110 Field<?> field = null;
111 if(propertyId.equals("text")){
112 TextArea ta = new TextArea();
113 ta.setNullRepresentation("");
114 ta.setWidth(100, Unit.PERCENTAGE);
115 field = ta;
116 } else if(propertyId.equals("annotationType")) {
117 NativeSelect select = new NativeSelect();
118 select.setContainerDataSource(typeSelectItemContainer);
119 select.setWidth(100, Unit.PIXELS);
120 field = select;
121 }
122 field.setStyleName(table.getStyleName());
123 return field;
124 }
125 });
126
127 addStyledComponent(table);
128
129 }
130
131 public void setAnnotationTypesVisible(AnnotationType ... types){
132 typesFilter = Arrays.asList(types);
133 }
134
135 /**
136 * {@inheritDoc}
137 */
138 @Override
139 protected void addDefaultStyles() {
140 // no default styles here
141 }
142
143 /**
144 * {@inheritDoc}
145 */
146 @Override
147 public Optional<FieldGroup> getFieldGroup() {
148 // holds a Container instead
149 return Optional.empty();
150 }
151
152 @Override
153 public void commit() throws SourceException, InvalidValueException {
154 table.commit();
155 Collection<Filter> filters = container.getContainerFilters();
156 super.commit();
157 for(Filter filter : filters){
158 container.addContainerFilter(filter);
159 }
160 System.err.println(container.size());
161 }
162
163
164
165 /**
166 * {@inheritDoc}
167 */
168 @Override
169 protected List<Annotation> getInternalValue() {
170 if(container == null || container.getItemIds() == null){
171 return null;
172 }
173 return new ArrayList<>(container.getItemIds());
174 }
175
176
177 @Override
178 protected void setInternalValue(List<Annotation> newValue) {
179
180 boolean hasIncludeFilter = typesFilter != null && !typesFilter.isEmpty();
181 boolean onlyOneType = hasIncludeFilter && typesFilter.size() == 1;
182
183 if(newValue.isEmpty()){
184 Annotation emptyDefaultAnnotation = newInstance();
185 newValue.add(emptyDefaultAnnotation );
186 if(onlyOneType){
187 emptyDefaultAnnotation.setAnnotationType(typesFilter.get(0));
188 }
189 }
190 container = new FilterableListContainer<Annotation>(newValue);
191 if(hasIncludeFilter){
192 container.addContainerFilter(new CdmTermFilter<AnnotationType>("annotationType", typesFilter));
193 }
194 table.setContainerDataSource(container);
195 if(onlyOneType){
196 table.setVisibleColumns("text");
197 } else {
198 table.setVisibleColumns("text", "annotationType");
199 }
200 table.setEditable(true);
201 if(newValue.size() > 1){
202 table.setPageLength(2);
203 }
204 }
205
206 /**
207 * {@inheritDoc}
208 */
209 @Override
210 protected Component initContent() {
211 root.addComponentAsFirst(table);
212
213 newButton.addClickListener(e -> addAnnotation());
214 withNewButton(true);
215 return root;
216 }
217
218
219 /**
220 * @return
221 */
222 private void addAnnotation() {
223 container.addItem(newInstance());
224 if(container.size() > 1){
225 table.setPageLength(2);
226 }
227 }
228
229 /**
230 * @return
231 */
232 private Annotation newInstance() {
233 return Annotation.NewInstance(null, Language.DEFAULT());
234 }
235
236 /**
237 * {@inheritDoc}
238 */
239 @Override
240 public Class<? extends List<Annotation>> getType() {
241 return (Class<? extends List<Annotation>>) new ArrayList<Annotation>().getClass();
242 }
243
244 /**
245 * @param buildTermItemContainer
246 */
247 public void setAnnotationTypeItemContainer(BeanItemContainer<DefinedTermBase> typeSelectItemContainer) {
248 this.typeSelectItemContainer = typeSelectItemContainer;
249 }
250
251 /**
252 * {@inheritDoc}
253 */
254 @Override
255 public void setReadOnly(boolean readOnly) {
256 super.setReadOnly(readOnly);
257 setDeepReadOnly(readOnly, table, null);
258 }
259
260 public void withNewButton(boolean withNewButton) {
261 if(this.withNewButton != withNewButton){
262 if(!this.withNewButton){
263 root.addComponent(newButton);
264 } else {
265 root.removeComponent(newButton);
266 }
267 this.withNewButton = withNewButton;
268 }
269 }
270
271
272
273
274
275
276 }