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.field;
35
36 import info.magnolia.icons.MagnoliaIcons;
37 import info.magnolia.ui.preview.ItemPreviewComponent;
38
39 import java.util.Objects;
40 import java.util.Optional;
41
42 import com.vaadin.data.HasValue;
43 import com.vaadin.ui.Button;
44 import com.vaadin.ui.Component;
45 import com.vaadin.ui.CustomField;
46 import com.vaadin.ui.HorizontalLayout;
47 import com.vaadin.ui.NativeButton;
48 import com.vaadin.ui.VerticalLayout;
49
50
51
52
53
54 public abstract class AbstractLinkField<T, P> extends CustomField<T> {
55
56 static final String REMOVE_BUTTON = "remove-button";
57 static final String MAGNOLIA_BUTTON = "magnoliabutton";
58 static final String SELECT_NEW_BUTTON = "select-new-button";
59 static final String LINK_FIELD = "linkfield";
60
61 private final VerticalLayout rootLayout = new VerticalLayout();
62 private final HorizontalLayout linkLayout = new HorizontalLayout();
63 private final Button selectButton = new NativeButton();
64 private final HasValue<T> hasValue;
65 private final Button removeButton = new Button(MagnoliaIcons.DELETE, event -> setValue(null));
66 private final Component innerComponent;
67
68 private boolean editable;
69 private Component contentPreview;
70 private String buttonCaptionNew;
71
72 AbstractLinkField(HasValue<T> innerComponent) {
73 this.hasValue = innerComponent;
74 this.innerComponent = (Component) innerComponent;
75 }
76
77 @Override
78 protected Component initContent() {
79 addStyleName(LINK_FIELD);
80
81 rootLayout.setMargin(false);
82 rootLayout.setSizeFull();
83 rootLayout.setSpacing(true);
84
85 hasValue.setRequiredIndicatorVisible(false);
86 hasValue.addValueChangeListener(event -> doSetValue((T) event.getValue()));
87 innerComponent.setCaption(null);
88 innerComponent.setWidth(100, Unit.PERCENTAGE);
89
90 linkLayout.setSizeFull();
91 linkLayout.addComponent(innerComponent);
92 linkLayout.setExpandRatio(innerComponent, 1);
93 linkLayout.setSpacing(false);
94
95 if (!isReadOnly()) {
96 removeButton.setVisible(getOptionalValue().isPresent());
97 removeButton.addStyleName(REMOVE_BUTTON);
98 linkLayout.addComponent(removeButton);
99
100 selectButton.addStyleName(MAGNOLIA_BUTTON);
101 selectButton.setCaption(buttonCaptionNew);
102 selectButton.addStyleName(SELECT_NEW_BUTTON);
103 linkLayout.addComponent(selectButton);
104 linkLayout.setExpandRatio(selectButton, 0);
105 }
106
107 rootLayout.addComponent(linkLayout);
108 updateComponents();
109
110 return rootLayout;
111 }
112
113 @Override
114 protected void doSetValue(T value) {
115 hasValue.setValue(value);
116 setRemoveButtonVisibility(value);
117 updateComponents();
118 }
119
120 @Override
121 public T getValue() {
122 return hasValue.getValue();
123 }
124
125 @Override
126 public boolean isEmpty() {
127 return Objects.equals(getValue(), getEmptyValue());
128 }
129
130 public boolean isEditable() {
131 return editable;
132 }
133
134 public void setEditable(boolean editable) {
135 this.editable = editable;
136 }
137
138 public void setButtonCaptionNew(String buttonCaptionNew) {
139 this.buttonCaptionNew = buttonCaptionNew;
140 }
141
142 public void setDisableOnClick(boolean disable) {
143 selectButton.setDisableOnClick(disable);
144 }
145
146 public void addClickListener(Button.ClickListener buttonClickListener) {
147 selectButton.addClickListener(buttonClickListener);
148 }
149
150 @Override
151 public void setEnabled(boolean enabled) {
152 super.setEnabled(enabled);
153 innerComponent.setEnabled(enabled);
154 selectButton.setEnabled(enabled);
155 }
156
157 public void setContentPreview(Component contentPreviewComponent) {
158 if (contentPreview != null) {
159 rootLayout.removeComponent(contentPreview);
160 }
161 rootLayout.addComponentAsFirst(contentPreviewComponent);
162 contentPreview = contentPreviewComponent;
163 }
164
165 public void setContentPreview(ItemPreviewComponent<P> contentPreviewComponent) {
166 hasValue.addValueChangeListener(event -> {
167 P item = getSelectedItem().orElse(null);
168 contentPreviewComponent.onValueChange(item);
169 contentPreviewComponent.setVisible(item != null);
170 });
171 setContentPreview((Component) contentPreviewComponent);
172 }
173
174 @Override
175 public void setReadOnly(boolean readOnly) {
176 super.setReadOnly(readOnly);
177 hasValue.setReadOnly(readOnly);
178 }
179
180
181
182 private void updateComponents() {
183 if (!isEditable() && !isEmpty()) {
184 setReadOnly(true);
185 if (linkLayout.getComponentIndex(selectButton) != -1) {
186 linkLayout.removeComponent(selectButton);
187 }
188 if (linkLayout.getComponentIndex(removeButton) != -1) {
189 linkLayout.removeComponent(removeButton);
190 }
191 }
192 }
193
194 private void setRemoveButtonVisibility(T value) {
195 removeButton.setVisible(!Objects.equals(value, getEmptyValue()));
196 }
197
198 @Override
199 public T getEmptyValue() {
200 return hasValue.getEmptyValue();
201 }
202
203 public abstract Optional<P> getSelectedItem();
204
205 public abstract void setSelectedItem(P item);
206 }