1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.form.field;
35
36 import info.magnolia.cms.i18n.I18nContentSupport;
37 import info.magnolia.objectfactory.ComponentProvider;
38 import info.magnolia.ui.api.i18n.I18NAuthoringSupport;
39 import info.magnolia.ui.form.field.definition.ConfiguredFieldDefinition;
40 import info.magnolia.ui.form.field.definition.MultiValueFieldDefinition;
41 import info.magnolia.ui.form.field.factory.FieldFactoryFactory;
42 import info.magnolia.ui.form.field.transformer.TransformedProperty;
43 import info.magnolia.ui.form.field.transformer.Transformer;
44 import info.magnolia.ui.form.field.transformer.multi.MultiTransformer;
45
46 import java.util.Iterator;
47
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import com.vaadin.data.Item;
52 import com.vaadin.data.Property;
53 import com.vaadin.data.util.PropertysetItem;
54 import com.vaadin.ui.Alignment;
55 import com.vaadin.ui.Button;
56 import com.vaadin.ui.Button.ClickEvent;
57 import com.vaadin.ui.Button.ClickListener;
58 import com.vaadin.ui.Component;
59 import com.vaadin.ui.Field;
60 import com.vaadin.ui.HorizontalLayout;
61 import com.vaadin.ui.NativeButton;
62 import com.vaadin.ui.VerticalLayout;
63
64
65
66
67
68
69
70
71
72 public class MultiField extends AbstractCustomMultiField<MultiValueFieldDefinition, PropertysetItem> {
73
74 private static final Logger log = LoggerFactory.getLogger(MultiField.class);
75
76 private final ConfiguredFieldDefinition fieldDefinition;
77
78 private final Button addButton = new NativeButton();
79 private String buttonCaptionAdd;
80 private String buttonCaptionRemove;
81
82 public MultiField(MultiValueFieldDefinition definition, FieldFactoryFactory fieldFactoryFactory, ComponentProvider componentProvider, Item relatedFieldItem, I18NAuthoringSupport i18nAuthoringSupport) {
83 super(definition, fieldFactoryFactory, componentProvider, relatedFieldItem, i18nAuthoringSupport);
84 this.fieldDefinition = definition.getField();
85 }
86
87
88
89
90 @Deprecated
91 public MultiField(MultiValueFieldDefinition definition, FieldFactoryFactory fieldFactoryFactory, I18nContentSupport i18nContentSupport, ComponentProvider componentProvider, Item relatedFieldItem) {
92 this(definition, fieldFactoryFactory, componentProvider, relatedFieldItem, null);
93 }
94
95 @Override
96 protected Component initContent() {
97
98 addStyleName("linkfield");
99 root = new VerticalLayout();
100 root.setSpacing(true);
101 root.setWidth(100, Unit.PERCENTAGE);
102 root.setHeight(-1, Unit.PIXELS);
103
104
105 addButton.setCaption(buttonCaptionAdd);
106 addButton.addStyleName("magnoliabutton");
107 addButton.addClickListener(new Button.ClickListener() {
108 @Override
109 public void buttonClick(ClickEvent event) {
110
111 int newPropertyId = -1;
112 Property<?> property = null;
113
114 Transformer<?> transformer = ((TransformedProperty<?>) getPropertyDataSource()).getTransformer();
115 PropertysetItem item = (PropertysetItem) getPropertyDataSource().getValue();
116
117 if (transformer instanceof MultiTransformer) {
118
119 property = ((MultiTransformer) transformer).createProperty();
120 newPropertyId = findPropertyId(item, property);
121 } else {
122
123 newPropertyId = item.getItemPropertyIds().size();
124 }
125
126 if (newPropertyId == -1) {
127 log.warn("Could not resolve new propertyId; cannot add new multifield entry to item '{}'.", item);
128 return;
129 }
130
131 root.addComponent(createEntryComponent(newPropertyId, property), root.getComponentCount() - 1);
132 };
133 });
134
135
136 initFields();
137
138 return root;
139 }
140
141
142
143
144
145 @Override
146 protected void initFields(PropertysetItem newValue) {
147 root.removeAllComponents();
148 Iterator<?> it = newValue.getItemPropertyIds().iterator();
149 while (it.hasNext()) {
150 Object propertyId = it.next();
151 Property<?> property = newValue.getItemProperty(propertyId);
152 root.addComponent(createEntryComponent(propertyId, property));
153 }
154 root.addComponent(addButton);
155 }
156
157
158
159
160
161
162
163 private Component createEntryComponent(Object propertyId, Property<?> property) {
164
165 HorizontalLayout layout = new HorizontalLayout();
166 layout.setWidth(100, Unit.PERCENTAGE);
167 layout.setHeight(-1, Unit.PIXELS);
168
169 Field<?> field = createLocalField(fieldDefinition, property, true);
170 layout.addComponent(field);
171
172
173 if (property == null) {
174 property = field.getPropertyDataSource();
175 ((PropertysetItem) getPropertyDataSource().getValue()).addItemProperty(propertyId, property);
176 }
177 final Property<?> propertyReference = property;
178
179
180 Button deleteButton = new Button();
181 deleteButton.setHtmlContentAllowed(true);
182 deleteButton.setCaption("<span class=\"" + "icon-trash" + "\"></span>");
183 deleteButton.addStyleName("inline");
184 deleteButton.setDescription(buttonCaptionRemove);
185 deleteButton.addClickListener(new ClickListener() {
186
187 @Override
188 public void buttonClick(ClickEvent event) {
189 Component layout = event.getComponent().getParent();
190 root.removeComponent(layout);
191 Transformer<?> transformer = ((TransformedProperty<?>) getPropertyDataSource()).getTransformer();
192
193
194 Object propertyId = findPropertyId(getValue(), propertyReference);
195
196 if (transformer instanceof MultiTransformer) {
197 ((MultiTransformer) transformer).removeProperty(propertyId);
198 } else {
199 if (propertyId != null && propertyId.getClass().isAssignableFrom(Integer.class)) {
200 removeValueProperty((Integer) propertyId);
201 } else {
202 log.error("Property id {} is not an integer and as such property can't be removed", propertyId);
203 }
204 getPropertyDataSource().setValue(getValue());
205 }
206 }
207 });
208 layout.addComponent(deleteButton);
209
210
211 layout.setWidth(100, Unit.PERCENTAGE);
212
213
214 layout.setExpandRatio(field, 1);
215 layout.setExpandRatio(deleteButton, 0);
216
217
218 layout.setComponentAlignment(deleteButton, Alignment.BOTTOM_RIGHT);
219
220 return layout;
221 }
222
223
224 @Override
225 public Class<? extends PropertysetItem> getType() {
226 return PropertysetItem.class;
227 }
228
229
230
231
232 public void setButtonCaptionAdd(String buttonCaptionAdd) {
233 this.buttonCaptionAdd = buttonCaptionAdd;
234 }
235
236 public void setButtonCaptionRemove(String buttonCaptionRemove) {
237 this.buttonCaptionRemove = buttonCaptionRemove;
238 }
239
240
241
242
243
244
245
246 private void removeValueProperty(int fromIndex) {
247 getValue().removeItemProperty(fromIndex);
248 int toIndex = fromIndex;
249 int valuesSize = getValue().getItemPropertyIds().size();
250 if (fromIndex == valuesSize) {
251 return;
252 }
253 while (fromIndex < valuesSize) {
254 toIndex = fromIndex;
255 fromIndex +=1;
256 getValue().addItemProperty(toIndex, getValue().getItemProperty(fromIndex));
257 getValue().removeItemProperty(fromIndex);
258 }
259 }
260
261 }