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 if (definition.isReadOnly()) {
87 fieldDefinition.setReadOnly(true);
88 }
89 }
90
91
92
93
94 @Deprecated
95 public MultiField(MultiValueFieldDefinition definition, FieldFactoryFactory fieldFactoryFactory, I18nContentSupport i18nContentSupport, ComponentProvider componentProvider, Item relatedFieldItem) {
96 this(definition, fieldFactoryFactory, componentProvider, relatedFieldItem, null);
97 }
98
99 @Override
100 protected Component initContent() {
101
102 addStyleName("linkfield");
103 root = new VerticalLayout();
104 root.setSpacing(true);
105 root.setWidth(100, Unit.PERCENTAGE);
106 root.setHeight(-1, Unit.PIXELS);
107
108
109 addButton.setCaption(buttonCaptionAdd);
110 addButton.addStyleName("magnoliabutton");
111 addButton.addClickListener(new Button.ClickListener() {
112 @Override
113 public void buttonClick(ClickEvent event) {
114
115 int newPropertyId = -1;
116 Property<?> property = null;
117
118 Transformer<?> transformer = ((TransformedProperty<?>) getPropertyDataSource()).getTransformer();
119 PropertysetItem item = (PropertysetItem) getPropertyDataSource().getValue();
120
121 if (transformer instanceof MultiTransformer) {
122
123 property = ((MultiTransformer) transformer).createProperty();
124 newPropertyId = findPropertyId(item, property);
125 } else {
126
127 newPropertyId = item.getItemPropertyIds().size();
128 }
129
130 if (newPropertyId == -1) {
131 log.warn("Could not resolve new propertyId; cannot add new multifield entry to item '{}'.", item);
132 return;
133 }
134
135 root.addComponent(createEntryComponent(newPropertyId, property), root.getComponentCount() - 1);
136 };
137 });
138
139
140 initFields();
141
142 return root;
143 }
144
145
146
147
148
149 @Override
150 protected void initFields(PropertysetItem newValue) {
151 root.removeAllComponents();
152 Iterator<?> it = newValue.getItemPropertyIds().iterator();
153 while (it.hasNext()) {
154 Object propertyId = it.next();
155 Property<?> property = newValue.getItemProperty(propertyId);
156 root.addComponent(createEntryComponent(propertyId, property));
157 }
158 if (!this.definition.isReadOnly()) {
159 root.addComponent(addButton);
160 }
161 }
162
163
164
165
166
167
168
169 private Component createEntryComponent(Object propertyId, Property<?> property) {
170
171 HorizontalLayout layout = new HorizontalLayout();
172 layout.setWidth(100, Unit.PERCENTAGE);
173 layout.setHeight(-1, Unit.PIXELS);
174
175 Field<?> field = createLocalField(fieldDefinition, property, true);
176 layout.addComponent(field);
177
178
179 if (property == null) {
180 property = field.getPropertyDataSource();
181 ((PropertysetItem) getPropertyDataSource().getValue()).addItemProperty(propertyId, property);
182 }
183 final Property<?> propertyReference = property;
184
185 layout.setWidth(100, Unit.PERCENTAGE);
186
187
188 layout.setExpandRatio(field, 1);
189 if (definition.isReadOnly()) {
190 return layout;
191 }
192
193
194 Button deleteButton = new Button();
195 deleteButton.setHtmlContentAllowed(true);
196 deleteButton.setCaption("<span class=\"" + "icon-trash" + "\"></span>");
197 deleteButton.addStyleName("inline");
198 deleteButton.setDescription(buttonCaptionRemove);
199 deleteButton.addClickListener(new ClickListener() {
200
201 @Override
202 public void buttonClick(ClickEvent event) {
203 Component layout = event.getComponent().getParent();
204 root.removeComponent(layout);
205 Transformer<?> transformer = ((TransformedProperty<?>) getPropertyDataSource()).getTransformer();
206
207
208 Object propertyId = findPropertyId(getValue(), propertyReference);
209
210 if (transformer instanceof MultiTransformer) {
211 ((MultiTransformer) transformer).removeProperty(propertyId);
212 } else {
213 if (propertyId != null && propertyId.getClass().isAssignableFrom(Integer.class)) {
214 removeValueProperty((Integer) propertyId);
215 } else {
216 log.error("Property id {} is not an integer and as such property can't be removed", propertyId);
217 }
218 getPropertyDataSource().setValue(getValue());
219 }
220 }
221 });
222 layout.addComponent(deleteButton);
223 layout.setExpandRatio(deleteButton, 0);
224
225
226 layout.setComponentAlignment(deleteButton, Alignment.BOTTOM_RIGHT);
227
228 return layout;
229 }
230
231
232 @Override
233 public Class<? extends PropertysetItem> getType() {
234 return PropertysetItem.class;
235 }
236
237
238
239
240 public void setButtonCaptionAdd(String buttonCaptionAdd) {
241 this.buttonCaptionAdd = buttonCaptionAdd;
242 }
243
244 public void setButtonCaptionRemove(String buttonCaptionRemove) {
245 this.buttonCaptionRemove = buttonCaptionRemove;
246 }
247
248
249
250
251
252
253
254 private void removeValueProperty(int fromIndex) {
255 getValue().removeItemProperty(fromIndex);
256 int toIndex = fromIndex;
257 int valuesSize = getValue().getItemPropertyIds().size();
258 if (fromIndex == valuesSize) {
259 return;
260 }
261 while (fromIndex < valuesSize) {
262 toIndex = fromIndex;
263 fromIndex +=1;
264 getValue().addItemProperty(toIndex, getValue().getItemProperty(fromIndex));
265 getValue().removeItemProperty(fromIndex);
266 }
267 }
268
269 }