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.form.field;
35
36 import info.magnolia.icons.MagnoliaIcons;
37 import info.magnolia.ui.vaadin.gwt.client.form.field.FieldLayoutState;
38
39 import java.util.function.Consumer;
40
41 import org.apache.commons.lang3.StringUtils;
42 import org.vaadin.jonatan.contexthelp.ContextHelp;
43
44 import com.google.common.base.Preconditions;
45 import com.vaadin.shared.ui.ContentMode;
46 import com.vaadin.ui.AbstractField;
47 import com.vaadin.ui.Button;
48 import com.vaadin.ui.Component;
49 import com.vaadin.ui.HorizontalLayout;
50 import com.vaadin.ui.Label;
51 import com.vaadin.ui.TabSheet;
52 import com.vaadin.ui.UI;
53 import com.vaadin.ui.VerticalLayout;
54
55
56
57
58 public class FieldLayout extends VerticalLayout implements Component.Focusable {
59
60 private final ContextHelp contextHelp;
61 private final boolean isRequired;
62
63 private Label statusLabel;
64 private final Component field;
65 private final String description;
66
67 public static FieldLayout of(Component field, String description) {
68 return of(field, description, false);
69 }
70
71 public static FieldLayout of(Component field, String description, boolean isRequired) {
72 return new FieldLayout(field, description, isRequired);
73 }
74
75 private FieldLayout(Component field, String description, boolean isRequired) {
76 this.isRequired = isRequired;
77 Preconditions.checkNotNull(field);
78 this.field = field;
79 this.description = description;
80 this.contextHelp = UI.getCurrent().getExtensions().stream()
81 .filter(ContextHelp.class::isInstance)
82 .findFirst()
83 .map(ContextHelp.class::cast)
84 .orElse(null);
85 initContent();
86 }
87
88 private void initContent() {
89 setMargin(false);
90 setVisible(field.isVisible());
91
92 statusLabel = new Label(null, ContentMode.HTML);
93 statusLabel.setVisible(false);
94 statusLabel.addStyleName("validation-display");
95
96 Component horizontalLayout = field;
97 if (contextHelp != null && StringUtils.isNotEmpty(description)) {
98 final Button helpButton = new Button(MagnoliaIcons.HELP_MARK);
99 helpButton.addStyleName("help-button v-button-icon icon-button");
100
101 contextHelp.extend(UI.getCurrent());
102 contextHelp.addHelpForComponent(helpButton, description);
103
104 helpButton.addClickListener(event -> {
105 contextHelp.showHelpFor(helpButton);
106 });
107 HorizontalLayout descriptionLayout = new HorizontalLayout(field, helpButton);
108 descriptionLayout.addStyleName("help-button-field-layout");
109 descriptionLayout.setSizeFull();
110 descriptionLayout.setExpandRatio(field, 1);
111 descriptionLayout.setExpandRatio(helpButton, 0);
112 descriptionLayout.setSpacing(false);
113 horizontalLayout = descriptionLayout;
114 }
115
116 setCaption(field.getCaption());
117 setRequiredIndicatorVisible(isRequired);
118
119 addComponents(horizontalLayout, statusLabel);
120 }
121
122 @Override
123 public void setCaption(String caption) {
124 super.setCaption(caption);
125 }
126
127 @Override
128 public void setRequiredIndicatorVisible(boolean visible) {
129 if (field instanceof AbstractField) {
130 ((AbstractField) field).setRequiredIndicatorVisible(false);
131 }
132 getState().required = visible;
133 }
134
135 @Override
136 protected boolean isRequiredIndicatorVisible() {
137 return getState().required;
138 }
139
140 @Override
141 protected FieldLayoutState getState() {
142 return (FieldLayoutState) super.getState();
143 }
144
145 @Override
146 public void focus() {
147 performTabSelection(field);
148 if (field instanceof Focusable) {
149 ((Focusable) field).focus();
150 }
151 }
152
153 @Override
154 public int getTabIndex() {
155 return 0;
156 }
157
158 @Override
159 public void setTabIndex(int tabIndex) {
160 }
161
162 public Consumer<String> getValidationStatusHandler() {
163 return errorMessage -> {
164 statusLabel.setValue(errorMessage);
165 if (errorMessage.isEmpty()) {
166 field.removeStyleName("error");
167 statusLabel.setVisible(false);
168 } else {
169 field.addStyleName("error");
170
171 statusLabel.setVisible(true);
172 }
173 };
174 }
175
176 public Component getField() {
177 return field;
178 }
179
180
181
182
183 private void performTabSelection(Component f) {
184 Component t = f;
185 do {
186 f = t;
187 t = f.getParent();
188 } while (!(t == null || t instanceof TabSheet));
189 if (t != null) {
190 ((TabSheet) t).setSelectedTab(f);
191 }
192 }
193 }