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.vaadin.switcher;
35
36 import java.util.Collection;
37 import java.util.Iterator;
38
39 import org.apache.commons.lang3.StringUtils;
40
41 import com.vaadin.ui.Button;
42 import com.vaadin.ui.Component;
43 import com.vaadin.ui.CssLayout;
44 import com.vaadin.v7.data.Container;
45 import com.vaadin.v7.data.Item;
46 import com.vaadin.v7.data.Property;
47 import com.vaadin.v7.data.util.ContainerOrderedWrapper;
48 import com.vaadin.v7.data.util.IndexedContainer;
49 import com.vaadin.v7.data.util.converter.Converter;
50 import com.vaadin.v7.ui.ComboBox;
51 import com.vaadin.v7.ui.CustomField;
52 import com.vaadin.v7.ui.HorizontalLayout;
53 import com.vaadin.v7.ui.Label;
54
55
56
57
58
59
60
61
62
63
64
65 public class Switcher extends CustomField<Object> implements Container.Viewer {
66
67
68
69
70 public static final String VARIATION_GREEN = "green";
71
72
73
74
75 public static final String VARIATION_BLACK = "black";
76
77 private static final String cssGreenVariationClassname = "greenSwitcher";
78
79 private static final String cssBlackVariationClassname = "blackSwitcher";
80
81 private static final String cssSwitcherArrowClassname = "switcherArrow";
82
83 private static final String cssSwitcherBorderClassname = "switcherBorder";
84
85 private CssLayout comboLayout = new CssLayout();
86
87 private HorizontalLayout mainLayout = new HorizontalLayout();
88
89 private String descriptionPropertyName;
90
91 private String colorVariation;
92
93 private Button back, forward;
94
95 private ComboBox combobox;
96
97 private Label descriptionLabel;
98
99
100
101
102
103 public Switcher(Collection<?> options) {
104 this(createContainer(options), VARIATION_GREEN);
105 }
106
107
108
109
110
111
112
113
114 public Switcher(Collection<?> options, String colorVariation) {
115 this(createContainer(options), colorVariation);
116 }
117
118
119
120
121
122 public Switcher(Container container) {
123 this(container, VARIATION_GREEN);
124 }
125
126
127
128
129
130
131
132 public Switcher(Container container, String colorVariation) {
133 this.colorVariation = colorVariation;
134
135
136 if (!(container instanceof Container.Ordered)) {
137 container = new ContainerOrderedWrapper(container);
138 }
139
140 combobox = new ComboBox("", container);
141 combobox.setTextInputAllowed(false);
142
143 }
144
145
146
147
148
149
150
151
152 public void setDescriptionPropertyName(String descriptionPropertyName) {
153 this.descriptionPropertyName = descriptionPropertyName;
154 }
155
156
157
158
159
160
161 public void withBorder(boolean withBorder){
162 if(withBorder){
163 mainLayout.addStyleName(cssSwitcherBorderClassname);
164 }else{
165 mainLayout.removeStyleName(cssSwitcherBorderClassname);
166 }
167 }
168
169
170 @Override
171 protected Component initContent() {
172 construct();
173 addHandlers();
174 mainLayout.setSizeFull();
175
176 return mainLayout;
177 }
178
179
180
181
182
183 public void setNullSelectionAllowed(boolean nullSelectionAllowed) {
184 combobox.setNullSelectionAllowed(nullSelectionAllowed);
185 }
186
187
188
189
190
191
192
193 public void setNullSelectionItemId(Object item) {
194 combobox.setNullSelectionItemId(item);
195 }
196
197
198
199
200
201
202 public void setItemCaptionPropertyId(String propertyId) {
203 combobox.setItemCaptionPropertyId(propertyId);
204 }
205
206
207
208
209
210
211 @Override
212 public void setValue(Object newValue) {
213 if (newValue == null) {
214 return;
215 }
216 combobox.setValue(newValue);
217 }
218
219
220
221
222 public void goForward() {
223 Object currentItemId = combobox.getValue();
224 if (getContainerDataSource().isLastId(currentItemId)) {
225 return;
226 }
227 setValue(getContainerDataSource().nextItemId(currentItemId));
228 }
229
230
231
232
233
234 public void goBack() {
235 Object currentItemId = combobox.getValue();
236 if (getContainerDataSource().isFirstId(currentItemId)) {
237 return;
238 }
239 setValue(getContainerDataSource().prevItemId(currentItemId));
240 }
241
242
243
244
245
246
247 @Override
248 public void addValueChangeListener(Property.ValueChangeListener valueChangeListener) {
249 combobox.addValueChangeListener(valueChangeListener);
250 }
251
252
253
254
255
256
257 @Override
258 public Property getPropertyDataSource() {
259 return combobox.getPropertyDataSource();
260 }
261
262
263
264
265
266
267
268 @Override
269 public void setPropertyDataSource(Property newDataSource) {
270 combobox.setPropertyDataSource(newDataSource);
271 }
272
273
274
275
276
277
278
279
280 @Override
281 public void setConverter(Converter<Object, ?> converter) {
282 combobox.setConverter(converter);
283 }
284
285
286
287
288
289
290 @Override
291 protected Object getInternalValue() {
292 return combobox.getValue();
293 }
294
295 @Override
296 public Class<?> getType() {
297 return Object.class;
298 }
299
300
301
302
303
304 @Override
305 public void setContainerDataSource(Container newDataSource) {
306 combobox.setContainerDataSource(newDataSource);
307 }
308
309
310
311
312
313
314 @Override
315 public Container.Ordered getContainerDataSource() {
316 return (Container.Ordered) combobox.getContainerDataSource();
317 }
318
319
320 private static Container createContainer(Collection<?> options) {
321 final Container container = new IndexedContainer();
322 if (options != null) {
323 for (final Iterator<?> i = options.iterator(); i.hasNext(); ) {
324 container.addItem(i.next());
325 }
326 }
327 return container;
328 }
329
330
331 private void construct() {
332 mainLayout.setPrimaryStyleName("switcher");
333 mainLayout.addStyleName(VARIATION_GREEN.equals(colorVariation) ? cssGreenVariationClassname : cssBlackVariationClassname);
334
335
336 back = new Button("");
337 back.setPrimaryStyleName(cssSwitcherArrowClassname);
338 back.addStyleName("icon-arrow2_w");
339 mainLayout.addComponent(back);
340
341
342
343 comboLayout.setWidth(100, Unit.PERCENTAGE);
344 combobox.setWidth(100, Unit.PERCENTAGE);
345 comboLayout.addComponent(combobox);
346
347 descriptionLabel = new Label("");
348 descriptionLabel.setPrimaryStyleName("switcherItemDescription");
349 descriptionLabel.addStyleName("descriptionLabel");
350 comboLayout.addComponent(descriptionLabel);
351
352 mainLayout.addComponent(comboLayout);
353 mainLayout.setExpandRatio(comboLayout, 1.0f);
354
355
356 forward = new Button("");
357 forward.setPrimaryStyleName(cssSwitcherArrowClassname);
358 forward.addStyleName("icon-arrow2_e");
359 mainLayout.addComponent(forward);
360
361 updateButtonState(getValue());
362 updateItemDescription();
363 }
364
365
366 private void setButtonEnabled(Button button, boolean isEnabled) {
367 if (isEnabled) {
368 button.removeStyleName("disabled");
369 button.removeStyleName("v-button-disabled");
370 button.removeStyleName("switcher-back-disabled");
371 } else {
372 button.addStyleName("disabled");
373 }
374 }
375
376 private void addHandlers() {
377 back.addClickListener(new Button.ClickListener() {
378 @Override
379 public void buttonClick(Button.ClickEvent event) {
380 goBack();
381 }
382 });
383
384 forward.addClickListener(new Button.ClickListener() {
385 @Override
386 public void buttonClick(Button.ClickEvent event) {
387 goForward();
388 }
389 });
390
391 combobox.addValueChangeListener(new Property.ValueChangeListener() {
392 @Override
393 public void valueChange(Property.ValueChangeEvent event) {
394 updateButtonState(event.getProperty().getValue());
395 updateItemDescription();
396 fireValueChange(true);
397 }
398 });
399 }
400
401 private void updateButtonState(Object newValue) {
402 if (newValue == null) {
403 setButtonEnabled(back, false);
404 setButtonEnabled(forward, false);
405 return;
406 }
407
408 Object first = getContainerDataSource().firstItemId();
409 Object last = getContainerDataSource().lastItemId();
410 if (!newValue.equals(first) && !newValue.equals(last)) {
411 setButtonEnabled(back, true);
412 setButtonEnabled(forward, true);
413 } else if (newValue.equals(first)) {
414 setButtonEnabled(back, false);
415 setButtonEnabled(forward, true);
416 } else {
417 setButtonEnabled(back, true);
418 setButtonEnabled(forward, false);
419 }
420 }
421
422 private void updateItemDescription() {
423 String description = null;
424 final Object itemId = getValue();
425 final Item item = getContainerDataSource().getItem(itemId);
426
427 boolean isDescriptionBlank = true;
428 if (item != null) {
429 Property property = item.getItemProperty(descriptionPropertyName);
430
431 if (property != null && property.getValue() != null) {
432 description = property.getValue().toString();
433 }
434 isDescriptionBlank = StringUtils.isBlank(description);
435 descriptionLabel.setValue(isDescriptionBlank ? "" : description);
436 }
437
438 if (isDescriptionBlank) {
439 mainLayout.removeStyleName("has-description");
440 } else {
441 mainLayout.addStyleName("has-description");
442 }
443
444 descriptionLabel.setVisible(!isDescriptionBlank);
445 }
446 }