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.framework.layout;
35
36 import info.magnolia.ui.field.EditorPropertyDefinition;
37 import info.magnolia.ui.field.NamedFieldDefinition;
38 import info.magnolia.ui.field.ValueBoundProperty;
39 import info.magnolia.ui.vaadin.extension.FocusFieldCaption;
40 import info.magnolia.ui.vaadin.form.field.FieldLayout;
41
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Map.Entry;
45 import java.util.stream.Collectors;
46 import java.util.stream.StreamSupport;
47
48 import org.apache.commons.lang3.StringUtils;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
51
52 import com.vaadin.ui.Component;
53 import com.vaadin.ui.FormLayout;
54 import com.vaadin.ui.TabSheet;
55 import com.vaadin.ui.themes.ValoTheme;
56
57
58
59
60
61
62 public class TabbedLayoutProducer implements FieldLayoutProducer<TabbedLayoutDefinition> {
63
64 private static final Logger log = LoggerFactory.getLogger(TabbedLayoutProducer.class);
65
66 @Override
67 public Component createLayout(TabbedLayoutDefinition definition, Map<EditorPropertyDefinition, Component> mappings) {
68 TabSheet tabSheet = new TabSheet();
69
70 tabSheet.addStyleNames(ValoTheme.TABSHEET_FRAMED);
71
72 List<TabDefinition> tabs = definition.getTabs();
73 Map<String, Entry<EditorPropertyDefinition, Component>> fieldNameMappings = mappings.entrySet().stream()
74 .collect(Collectors.toMap(def -> def.getKey().getName(), entry -> entry));
75
76 if (tabs.size() == 1) {
77 tabSheet.addStyleName("single-tab");
78 }
79
80 for (TabDefinition tabDefinition : tabs) {
81 FormLayout formSection = new FormLayout();
82 formSection.setWidth("100%");
83 formSection.setMargin(true);
84
85 for (NamedFieldDefinition tabField : tabDefinition.getFields()) {
86 String fieldName = tabField.getName();
87 if (fieldNameMappings.containsKey(fieldName)) {
88 Entry<EditorPropertyDefinition, Component> tabFieldMapping = fieldNameMappings.get(fieldName);
89 EditorPropertyDefinition propertyDefinition = tabFieldMapping.getKey();
90 Component component = tabFieldMapping.getValue();
91 String description = propertyDefinition.getDescription();
92 FieldLayout wrappedField = FieldLayout.of(component, description, isRequired(propertyDefinition));
93 formSection.addComponent(wrappedField);
94 continue;
95 }
96 log.warn(String.format("Could not retrieve component field named %s from mappings", fieldName));
97 }
98
99 tabSheet.addTab(formSection, StringUtils.defaultIfBlank(tabDefinition.getLabel(), tabDefinition.getName()));
100 FocusFieldCaption.focusCaptionOf(formSection);
101 }
102
103 tabSheet.addAttachListener(event -> focusFirstField(tabSheet));
104 tabSheet.addSelectedTabChangeListener(event -> focusFirstField(tabSheet));
105
106 return tabSheet;
107 }
108
109 private void focusFirstField(TabSheet tabSheet) {
110 if (tabSheet.getSelectedTab() instanceof FormLayout) {
111 StreamSupport.stream(((FormLayout) tabSheet.getSelectedTab()).spliterator(), false)
112 .map(formEntry -> ((FieldLayout) formEntry).getField())
113 .filter(field -> field instanceof Component.Focusable)
114 .findFirst()
115 .ifPresent(field -> ((Component.Focusable) field).focus());
116 }
117 }
118
119 public boolean isRequired(EditorPropertyDefinition definition) {
120 return definition instanceof ValueBoundProperty && ((ValueBoundProperty<?>) definition).isRequired();
121 }
122 }