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.gwt.client.actionbar.widget;
35
36 import info.magnolia.ui.vaadin.gwt.client.actionbar.event.ActionTriggerEvent;
37 import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem;
38 import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarSection;
39
40 import java.util.Collection;
41 import java.util.LinkedHashMap;
42 import java.util.Map;
43 import java.util.logging.Logger;
44
45 import com.google.gwt.dom.client.MediaElement;
46 import com.google.gwt.event.logical.shared.ResizeEvent;
47 import com.google.gwt.event.logical.shared.ResizeHandler;
48 import com.google.gwt.event.shared.HandlerRegistration;
49 import com.google.gwt.media.client.Audio;
50 import com.google.gwt.media.client.Video;
51 import com.google.gwt.user.client.DOM;
52 import com.google.gwt.user.client.Element;
53 import com.google.gwt.user.client.Event;
54 import com.google.gwt.user.client.Window;
55 import com.google.gwt.user.client.ui.ComplexPanel;
56 import com.google.gwt.user.client.ui.FlowPanel;
57 import com.google.gwt.user.client.ui.Image;
58 import com.google.gwt.user.client.ui.Widget;
59 import com.google.web.bindery.event.shared.EventBus;
60 import com.googlecode.mgwt.dom.client.event.touch.TouchStartEvent;
61 import com.googlecode.mgwt.dom.client.event.touch.TouchStartHandler;
62 import com.googlecode.mgwt.ui.client.widget.touch.TouchDelegate;
63
64
65
66
67 public class ActionbarWidgetViewImpl extends ComplexPanel implements ActionbarWidgetView, ActionTriggerEvent.Handler, ResizeHandler {
68
69 private static final Logger log = Logger.getLogger(ActionbarWidgetViewImpl.class.getName());
70
71 private static final int BREAK_POINT_1 = 1200;
72 private static final int BREAK_POINT_2 = 1600;
73
74 public static final String CLASSNAME = "v-actionbar";
75
76 public static final String CLASSNAME_TOGGLE = "v-actionbar-toggle";
77
78 private final Element root = DOM.createElement("section");
79
80 private final FlowPanel toggleButton = new FlowPanel();
81
82 private final Element toggleButtonIcon = DOM.createElement("span");
83
84 private final EventBus eventBus;
85
86 private final HandlerRegistration registration;
87
88 private Presenter presenter;
89
90 private int tabletRow = -1;
91
92 private int tabletColumn = 0;
93
94 private boolean isToggledOpen = false;
95
96 private final TouchDelegateient/widget/touch/TouchDelegate.html#TouchDelegate">TouchDelegate delegate = new TouchDelegate(toggleButton);
97
98 private final Map<String, ActionbarSectionWidget> sections = new LinkedHashMap<String, ActionbarSectionWidget>();
99
100 public ActionbarWidgetViewImpl(final EventBus eventBus, Presenter presenter) {
101 setElement(root);
102 addStyleName(CLASSNAME);
103
104 this.presenter = presenter;
105 this.eventBus = eventBus;
106 this.eventBus.addHandler(ActionTriggerEvent.TYPE, this);
107
108 createToggleControl();
109
110 isToggledOpen = !presenter.isDeviceTablet();
111 actualizeToggleState(isToggledOpen);
112
113 this.registration = Window.addResizeHandler(this);
114 }
115
116
117 private void createToggleControl() {
118
119 toggleButton.addStyleName(CLASSNAME_TOGGLE);
120 add(toggleButton, root);
121
122 toggleButtonIcon.addClassName("v-actionbar-toggle-icon");
123 toggleButton.getElement().appendChild(toggleButtonIcon);
124
125 DOM.sinkEvents(toggleButton.getElement(), Event.TOUCHEVENTS);
126 delegate.addTouchStartHandler(new TouchStartHandler() {
127 @Override
128 public void onTouchStart(TouchStartEvent event) {
129 isToggledOpen = !isToggledOpen;
130 presenter.setOpened(isToggledOpen);
131 }
132 });
133 }
134
135 @Override
136 protected void onDetach() {
137 super.onDetach();
138 this.registration.removeHandler();
139 }
140
141
142
143
144
145 @Override
146 public void refreshActionsPositionsTablet() {
147
148 if (!presenter.isDeviceTablet()) {
149 return;
150 }
151
152 tabletRow = -1;
153 tabletColumn = 0;
154
155 for (final ActionbarSectionWidget section : sections.values()) {
156
157
158 if (section.isVisible()) {
159
160 for (final VActionbarGroup group : section.getGroups().values()) {
161
162 tabletColumn = 0;
163 tabletRow++;
164
165 for (ActionbarItemWidget action : group.getActions()) {
166
167
168 if (group.getNumActions() > 1) {
169 if (tabletColumn == 0) {
170 action.addStyleName("flyout");
171 }
172 } else {
173 action.removeStyleName("flyout");
174 }
175 ((VActionbarItemTablet) action).setRow(tabletRow);
176 ((VActionbarItemTablet) action).setColumn(tabletColumn);
177 tabletColumn++;
178 }
179 }
180 }
181 }
182 setToggleButtonHeights(tabletRow);
183 }
184
185
186
187
188 private void actualizeToggleState(boolean isOpen) {
189 if (isOpen) {
190 toggleButtonIcon.addClassName("open");
191 } else {
192 toggleButtonIcon.removeClassName("open");
193 }
194 if (presenter.isDeviceTablet()) {
195 for (final ActionbarSectionWidget section : sections.values()) {
196 for (final VActionbarGroup group : section.getGroups().values()) {
197 group.setOpenHorizontally(isOpen);
198 }
199 }
200 }
201 }
202
203 @Override
204 public Map<String, ActionbarSectionWidget> getSections() {
205 return sections;
206 }
207
208 @Override
209 public void setPresenter(final Presenter presenter) {
210 this.presenter = presenter;
211 }
212
213 public void addSection(ActionbarSection sectionParams) {
214 ActionbarSectionWidgett/actionbar/widget/ActionbarSectionWidget.html#ActionbarSectionWidget">ActionbarSectionWidget section = new ActionbarSectionWidget(sectionParams);
215 sections.put(sectionParams.getName(), section);
216 add(section, root);
217 }
218
219 public void addAction(ActionbarItem actionParams, String sectionName) {
220 ActionbarSectionWidget section = sections.get(sectionName);
221 if (section != null) {
222 VActionbarGroup group = section.getGroups().get(actionParams.getGroupName());
223 if (group == null) {
224 tabletColumn = 0;
225 tabletRow++;
226 group = new VActionbarGroup(actionParams.getGroupName());
227 section.addGroup(group);
228 setToggleButtonHeights(tabletRow);
229 }
230
231 ActionbarItemWidget action;
232 if (presenter.isDeviceTablet()) {
233 action = new VActionbarItemTablet(actionParams, group, eventBus);
234 ((VActionbarItemTablet) action).setRow(tabletRow);
235 ((VActionbarItemTablet) action).setColumn(tabletColumn);
236 tabletColumn++;
237 } else {
238 action = new ActionbarItemWidget(actionParams, group, eventBus);
239 }
240 group.addAction(action);
241 }
242 }
243
244
245
246
247 private void setToggleButtonHeights(int tabletRow) {
248
249 toggleButton.setStyleName(CLASSNAME_TOGGLE + " row-" + (tabletRow + 1));
250 }
251
252 @Override
253 public void onActionTriggered(ActionTriggerEvent event) {
254 ActionbarItemWidget action = event.getSource();
255 ActionbarSectionWidget/../../info/magnolia/ui/vaadin/gwt/client/actionbar/widget/ActionbarSectionWidget.html#ActionbarSectionWidget">ActionbarSectionWidget section = (ActionbarSectionWidget) action.getParent().getParent();
256 presenter.triggerAction(section.getName() + ":" + action.getName());
257 }
258
259 @Override
260 public void setSections(Collection<ActionbarSection> newSections) {
261 for (final ActionbarSectionWidget section : this.sections.values()) {
262 remove(section);
263 }
264 sections.clear();
265 for (final ActionbarSection section : newSections) {
266 addSection(section);
267 for (final String actionName : section.getActionOrder()) {
268 ActionbarItem action = section.getActions().get(actionName);
269 if (action.getIconFontId() == null) {
270 action.setResourceUrl(presenter.getIconResourceURL(action.getName()));
271 }
272 addAction(action, section.getName());
273 }
274 }
275 updateLayout();
276 refreshActionsPositionsTablet();
277 }
278
279 @Override
280 public void setVisibleSections(Collection<ActionbarSection> visibleSections) {
281 for (final ActionbarSectionWidget section : sections.values()) {
282 section.setVisible(visibleSections.contains(section.getData()));
283 }
284 updateLayout();
285 refreshActionsPositionsTablet();
286 }
287
288 @Override
289 public void setDisabledActions(Collection<ActionbarItem> disabledActions) {
290 for (final ActionbarSectionWidget section : sections.values()) {
291 for (final VActionbarGroup group : section.getGroups().values()) {
292 for (final ActionbarItemWidget action : group.getActions()) {
293 action.setEnabled(!disabledActions.contains(action.getData()));
294 }
295 }
296 }
297 }
298
299 @Override
300 public boolean isOpen() {
301 return isToggledOpen;
302 }
303
304 @Override
305 public void setOpen(boolean isOpen) {
306 actualizeToggleState(isToggledOpen);
307 if (isToggledOpen != isOpen) {
308 presenter.forceLayout();
309 updateLayout();
310 }
311 }
312
313 @Override
314 public void setSectionPreview(String sectionName, String previewUrl) {
315 ActionbarSectionWidget sectionWidget = sections.get(sectionName);
316 if (sectionWidget != null) {
317 sectionWidget.addStyleName("preview");
318
319 if (previewUrl != null) {
320 Widget widget;
321 Video video = Video.createIfSupported();
322 String mediaType = getMediaType(previewUrl);
323 if (video != null && mediaType != null && !MediaElement.CANNOT_PLAY.equals(video.canPlayType("video/" + mediaType))) {
324 video.addSource(previewUrl);
325 video.setControls(true);
326 widget = video;
327 } else {
328 Audio audio = Audio.createIfSupported();
329 if (audio != null && mediaType != null && !MediaElement.CANNOT_PLAY.equals(audio.canPlayType("audio/" + mediaType))) {
330 audio.addSource(previewUrl);
331 audio.setControls(true);
332 widget = audio;
333 } else {
334 widget = new Image(previewUrl);
335 }
336 }
337 sectionWidget.setPreview(widget);
338 }
339 }
340 }
341
342 private String getMediaType(String previewUrl) {
343 String[] splitPreviewUrl = previewUrl.split("\\?");
344
345 return splitPreviewUrl[0].substring(splitPreviewUrl[0].lastIndexOf(".") + 1);
346 }
347
348 @Override
349 public void updateLayout() {
350 int windowWidth = Window.getClientWidth();
351
352
353 final int MARGIN_TOP = windowWidth < BREAK_POINT_1 ? 55 : (windowWidth >= BREAK_POINT_2 ? 125 : 100) ;
354 final int MARGIN_BOTTOM = 20;
355
356 int availableHeight = getOffsetHeight();
357 if (sections.containsKey("preview") && sections.get("preview").isVisible() && isToggledOpen) {
358 availableHeight -= 215 - MARGIN_BOTTOM;
359 }
360
361 int actualHeight = 0;
362 for (ActionbarSectionWidget section : sections.values()) {
363 if (!section.getName().equals("preview") && section.isVisible()) {
364 section.getElement().getStyle().clearProperty("maxHeight");
365 actualHeight += section.getOffsetHeight() + MARGIN_TOP + MARGIN_BOTTOM;
366 }
367 }
368 log.fine("actualHeight/availableHeight: " + actualHeight + "/" + availableHeight);
369
370
371 int i = getWidgetCount() - 1;
372 int minimumHeight = 75;
373 while (actualHeight > availableHeight && i >= 0) {
374 log.fine("rewinding widget list, current height diff: " + (actualHeight - availableHeight) + " (i=" + i + ")");
375 Widget widget = getWidget(i);
376 if (widget instanceof ActionbarSectionWidget && widget.isVisible()) {
377 String sectionName = ((ActionbarSectionWidget) widget).getName();
378 if (!sectionName.equals("preview")) {
379 int currentHeight = widget.getOffsetHeight() + MARGIN_TOP;
380 if (currentHeight > minimumHeight) {
381 int newHeight = (actualHeight - availableHeight > currentHeight - minimumHeight) ? minimumHeight : currentHeight + availableHeight - actualHeight;
382 log.fine(sectionName + " currentHeight => newHeight: " + currentHeight + "=>" + (newHeight - MARGIN_TOP));
383 widget.getElement().getStyle().setPropertyPx("maxHeight", newHeight - MARGIN_TOP);
384 actualHeight -= (currentHeight - newHeight);
385 }
386 }
387 }
388 i--;
389 }
390 }
391
392 @Override
393 public void onResize(ResizeEvent event) {
394 updateLayout();
395 }
396 }