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.workbench;
35
36 import info.magnolia.cms.i18n.MessagesUtil;
37 import info.magnolia.ui.vaadin.icon.Icon;
38 import info.magnolia.ui.workbench.ContentView.ViewType;
39 import info.magnolia.ui.workbench.definition.ContentPresenterDefinition;
40
41 import java.io.Serializable;
42 import java.util.EnumMap;
43 import java.util.Map;
44
45 import org.apache.commons.lang.StringUtils;
46
47 import com.vaadin.data.Property;
48 import com.vaadin.event.FieldEvents;
49 import com.vaadin.shared.ui.MarginInfo;
50 import com.vaadin.ui.Button;
51 import com.vaadin.ui.Button.ClickEvent;
52 import com.vaadin.ui.Component;
53 import com.vaadin.ui.CssLayout;
54 import com.vaadin.ui.NativeButton;
55 import com.vaadin.ui.TextField;
56 import com.vaadin.ui.VerticalLayout;
57 import com.vaadin.ui.themes.BaseTheme;
58
59
60
61
62 public class WorkbenchViewImpl extends VerticalLayout implements WorkbenchView, Serializable {
63
64 private final CssLayout toolBar = new CssLayout();
65
66 private final CssLayout viewModes = new CssLayout();
67
68 private final CssLayout searchBox = new CssLayout();
69
70 private TextField searchField;
71
72 private Button clearSearchBoxButton;
73
74 private Icon searchIcon;
75
76 private Icon searchArrow;
77
78 private StatusBarView statusBar;
79
80 private Map<ViewType, ContentView> contentViews = new EnumMap<ViewType, ContentView>(ViewType.class);
81
82 private Map<ViewType, Button> contentViewsButton = new EnumMap<ViewType, Button>(ViewType.class);
83
84 private ViewType currentViewType = ViewType.TREE;
85
86
87
88
89 private ViewType previousViewType = currentViewType;
90
91 private final Property.ValueChangeListener searchFieldListener = new Property.ValueChangeListener() {
92
93 @Override
94 public void valueChange(Property.ValueChangeEvent event) {
95 listener.onSearch(searchField.getValue().toString());
96
97 boolean hasSearchContent = !searchField.getValue().isEmpty();
98 if (hasSearchContent) {
99 searchBox.addStyleName("has-content");
100 } else {
101 searchBox.removeStyleName("has-content");
102 }
103 searchField.focus();
104 }
105 };
106
107 private WorkbenchView.Listener listener;
108
109 public WorkbenchViewImpl(){
110
111 setSizeFull();
112 setMargin(new MarginInfo(true, false, false, true));
113 addStyleName("workbench");
114
115 viewModes.setStyleName("view-modes");
116
117 clearSearchBoxButton = new Button();
118 clearSearchBoxButton.setStyleName("m-closebutton");
119 clearSearchBoxButton.addStyleName("icon-delete-search");
120 clearSearchBoxButton.addStyleName("searchbox-clearbutton");
121 clearSearchBoxButton.addClickListener(new Button.ClickListener() {
122
123 @Override
124 public void buttonClick(ClickEvent event) {
125 searchField.setValue("");
126 }
127 });
128
129 searchIcon = new Icon("search");
130 searchIcon.addStyleName("searchbox-icon");
131
132 searchArrow = new Icon("arrow2_s");
133 searchArrow.addStyleName("searchbox-arrow");
134
135 searchField = buildSearchField();
136
137 searchBox.setVisible(false);
138 searchBox.addComponent(searchField);
139 searchBox.addComponent(clearSearchBoxButton);
140 searchBox.addComponent(searchIcon);
141 searchBox.addComponent(searchArrow);
142 searchBox.setStyleName("searchbox");
143
144 toolBar.addStyleName("toolbar");
145 toolBar.setWidth(100, Unit.PERCENTAGE);
146 toolBar.addComponent(viewModes);
147 toolBar.addComponent(searchBox);
148
149 addComponent(toolBar);
150 setExpandRatio(toolBar, 0);
151
152
153 }
154
155 @Override
156 public void setSearchQuery(String query) {
157 if (searchField == null) {
158 return;
159 }
160
161 searchField.removeValueChangeListener(searchFieldListener);
162 if (StringUtils.isNotBlank(query)) {
163 searchField.setValue(query);
164 searchField.focus();
165 } else {
166 searchField.setValue("");
167 searchBox.removeStyleName("has-content");
168 }
169 searchField.addValueChangeListener(searchFieldListener);
170
171 }
172
173 @Override
174 public void addContentView(ViewType viewType, ContentView view, ContentPresenterDefinition contentViewDefintion) {
175 contentViews.put(viewType, view);
176
177 if (viewType.equals(ViewType.SEARCH)) {
178
179 return;
180 }
181 if (viewType.equals(ViewType.LIST)) {
182 searchBox.setVisible(true);
183 }
184
185
186 Button button = buildButton(viewType, contentViewDefintion.getIcon(), contentViewDefintion.isActive());
187 contentViewsButton.put(viewType, button);
188 viewModes.addComponent(button);
189
190 if (contentViewDefintion.isActive()) {
191 currentViewType = previousViewType = viewType;
192 }
193 }
194
195 @Override
196 public void setViewType(ViewType type) {
197 removeComponent(getSelectedView().asVaadinComponent());
198 final Component c = contentViews.get(type).asVaadinComponent();
199 addComponent(c, 1);
200 setExpandRatio(c, 1);
201
202 if (type != ViewType.SEARCH) {
203 previousViewType = type;
204 setSearchQuery(null);
205 }
206 setViewTypeStyling(type);
207
208 currentViewType = type;
209 }
210
211 private void fireViewTypeChangedEvent(ViewType viewType) {
212 this.listener.onViewTypeChanged(viewType);
213 }
214
215 @Override
216 public void setStatusBarView(StatusBarView statusBar) {
217 Component c = statusBar.asVaadinComponent();
218 if (this.statusBar == null) {
219 addComponent(c, getComponentCount());
220 } else {
221 replaceComponent(this.statusBar.asVaadinComponent(), c);
222 }
223 setExpandRatio(c, 0);
224 this.statusBar = statusBar;
225 }
226
227 @Override
228 public ContentView getSelectedView() {
229 return contentViews.get(currentViewType);
230 }
231
232 @Override
233 public Component asVaadinComponent() {
234 return this;
235 }
236
237 @Override
238 public void setListener(WorkbenchView.Listener listener) {
239 this.listener = listener;
240 }
241
242 private Button buildButton(final ViewType viewType, final String icon, final boolean active) {
243 NativeButton button = new NativeButton(null, new Button.ClickListener() {
244 @Override
245 public void buttonClick(Button.ClickEvent event) {
246 fireViewTypeChangedEvent(viewType);
247 }
248 });
249 button.setStyleName(BaseTheme.BUTTON_LINK);
250
251 button.setHtmlContentAllowed(true);
252 button.setCaption("<span class=\"" + icon + "\"></span><span class=\"view-type-arrow view-type-arrow-" + viewType.getText() + " icon-arrow2_n\"></span>");
253
254 if (active) {
255 button.addStyleName("active");
256 }
257 return button;
258 }
259
260 private void setViewTypeStyling(final ViewType viewType) {
261 for (Map.Entry<ViewType, Button> entry : contentViewsButton.entrySet()) {
262 entry.getValue().removeStyleName("active");
263 if (entry.getKey().equals(viewType)) {
264 entry.getValue().addStyleName("active");
265 }
266 }
267
268 if (viewType.equals(ContentView.ViewType.SEARCH) && contentViewsButton.containsKey(ContentView.ViewType.LIST)) {
269 contentViewsButton.get(ContentView.ViewType.LIST).addStyleName("active");
270 }
271 }
272
273 private TextField buildSearchField() {
274 final TextField field = new TextField();
275 final String inputPrompt = MessagesUtil.getWithDefault("toolbar.search.prompt", "Search");
276
277 field.setInputPrompt(inputPrompt);
278 field.setSizeUndefined();
279 field.addStyleName("searchfield");
280
281
282 field.setImmediate(true);
283 field.addListener(searchFieldListener);
284
285 field.addFocusListener(new FieldEvents.FocusListener() {
286 @Override
287 public void focus(FieldEvents.FocusEvent event) {
288
289 TextField tf = (TextField) event.getSource();
290 tf.setCursorPosition(tf.getValue().length());
291 }
292 });
293
294
295
296 return field;
297 }
298
299 @Override
300 public void setMultiselect(boolean multiselect) {
301 for (ViewType type : contentViews.keySet()) {
302 contentViews.get(type).setMultiselect(multiselect);
303 }
304 }
305 }