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.magnoliashell.shell;
35
36 import info.magnolia.ui.vaadin.gwt.client.jquerywrapper.JQueryCallback;
37 import info.magnolia.ui.vaadin.gwt.client.jquerywrapper.JQueryWrapper;
38 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shellmessage.ShellMessageWidget;
39 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shellmessage.ShellMessageWidget.MessageType;
40 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shellmessage.VInfoMessage;
41 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shellmessage.VShellErrorMessage;
42 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shellmessage.VWarningMessage;
43 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.animation.JQueryAnimation;
44 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.widget.AppsViewportWidget;
45 import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.widget.ViewportWidget;
46 import info.magnolia.ui.vaadin.gwt.client.shared.magnoliashell.Fragment;
47 import info.magnolia.ui.vaadin.gwt.client.shared.magnoliashell.ShellAppType;
48 import info.magnolia.ui.vaadin.gwt.client.shared.magnoliashell.ViewportType;
49
50 import java.util.EnumMap;
51 import java.util.Map;
52
53 import com.google.gwt.core.client.Scheduler;
54 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
55 import com.google.gwt.event.dom.client.KeyCodes;
56 import com.google.gwt.event.dom.client.KeyPressEvent;
57 import com.google.gwt.event.dom.client.KeyPressHandler;
58 import com.google.gwt.user.client.DOM;
59 import com.google.gwt.user.client.Element;
60 import com.google.gwt.user.client.ui.FocusPanel;
61 import com.google.gwt.user.client.ui.RootPanel;
62 import com.google.gwt.user.client.ui.Widget;
63 import com.googlecode.mgwt.ui.client.widget.touch.TouchPanel;
64
65
66
67
68 public class MagnoliaShellViewImpl extends TouchPanel implements MagnoliaShellView {
69
70 public static final String CLASS_NAME = "v-magnolia-shell";
71
72 public static final String VIEWPORT_SLOT_CLASS_NAME = "v-shell-viewport-slot";
73
74 private final Map<ViewportType, ViewportWidget> viewports = new EnumMap<ViewportType, ViewportWidget>(ViewportType.class);
75
76 private final ShellAppLauncher mainAppLauncher;
77
78 private ShellMessageWidget lowPriorityMessage;
79
80 private ShellMessageWidget hiPriorityMessage;
81
82 private Presenter presenter;
83
84 private JQueryAnimation viewportShifter = new JQueryAnimation();
85
86 private final Element viewportSlot = DOM.createDiv();
87
88
89 private final FocusPanel blurHelper = new FocusPanel();
90
91 public MagnoliaShellViewImpl() {
92 super();
93 this.mainAppLauncher = new ShellAppLauncher();
94 getElement().setClassName(CLASS_NAME);
95 viewportSlot.setClassName(VIEWPORT_SLOT_CLASS_NAME);
96 add(mainAppLauncher, getElement());
97
98
99 getElement().appendChild(viewportSlot);
100 viewportShifter.addCallback(new JQueryCallback() {
101 @Override
102 public void execute(JQueryWrapper query) {
103 presenter.updateViewportLayout(appViewport());
104 }
105 });
106
107 initKeyboardShortcutSupport();
108 }
109
110
111
112
113
114
115 protected void initKeyboardShortcutSupport() {
116
117 add(blurHelper, getElement());
118
119 KeyPressHandler keyboardShortcutHandler = new KeyPressHandler() {
120
121 @Override
122 public void onKeyPress(KeyPressEvent event) {
123
124
125 if (isFocusedElementAnInputField()) {
126 return;
127 }
128
129
130 if (event.isAnyModifierKeyDown()) {
131 return;
132 }
133
134 char c = event.getCharCode();
135
136 switch (c) {
137
138
139 case '1':
140 mainAppLauncher.toggleShellApp(ShellAppType.APPLAUNCHER);
141 break;
142 case '2':
143 mainAppLauncher.toggleShellApp(ShellAppType.PULSE);
144 break;
145 case '3':
146 mainAppLauncher.toggleShellApp(ShellAppType.FAVORITE);
147 break;
148
149
150 case '9':
151 appViewport().goToPreviousApp();
152 break;
153 case '0':
154 appViewport().goToNextApp();
155 break;
156
157 default:
158
159 }
160 }
161 };
162 RootPanel.get().addDomHandler(keyboardShortcutHandler, KeyPressEvent.getType());
163
164
165
166
167
168
169 KeyPressHandler escapeKeyPressHandler = new KeyPressHandler() {
170 @Override
171 public void onKeyPress(KeyPressEvent event) {
172 int code = event.getNativeEvent().getKeyCode();
173 if (code == KeyCodes.KEY_ESCAPE) {
174 blurHelper.getElement().focus();
175 }
176 }
177 };
178 RootPanel.get().addDomHandler(escapeKeyPressHandler, KeyPressEvent.getType());
179 }
180
181
182
183
184
185
186 protected boolean isFocusedElementAnInputField() {
187 Element focused = elementInFocus(RootPanel.get().getElement());
188 String tagName = focused.getTagName();
189 if ("input".equalsIgnoreCase(tagName) || "select".equalsIgnoreCase(tagName) || "textarea".equalsIgnoreCase(tagName)) {
190 return true;
191 }
192 return false;
193 }
194
195 protected native Element elementInFocus(Element element)
196
197 ;
198
199
200 protected AppsViewportWidget appViewport() {
201 return (AppsViewportWidget) viewports.get(ViewportType.APP);
202 }
203
204 protected void replaceWidget(final Widget oldWidget, final Widget newWidget) {
205 if (oldWidget != newWidget) {
206 if (oldWidget != null) {
207 remove(oldWidget);
208 }
209 }
210 if (getWidgetIndex(newWidget) < 0) {
211 add(newWidget, viewportSlot);
212 }
213 }
214
215 @Override
216 public void setPresenter(Presenter presenter) {
217 this.presenter = presenter;
218 mainAppLauncher.setListener(presenter);
219 }
220
221 @Override
222 public void showMessage(MessageType type, String topic, String message, String id) {
223 final ShellMessageWidget msg;
224 switch (type) {
225 case WARNING:
226 msg = new VWarningMessage(this, topic, message, id);
227 if (lowPriorityMessage != null && getWidgetIndex(lowPriorityMessage) != -1) {
228 lowPriorityMessage.hide();
229 }
230 lowPriorityMessage = msg;
231 break;
232 case INFO:
233 msg = new VInfoMessage(this, topic, message, id);
234 if (lowPriorityMessage != null && getWidgetIndex(lowPriorityMessage) != -1) {
235 lowPriorityMessage.hide();
236 }
237 lowPriorityMessage = msg;
238 break;
239 case ERROR:
240 msg = new VShellErrorMessage(this, topic, message, id);
241 if (hiPriorityMessage != null && getWidgetIndex(hiPriorityMessage) != -1) {
242 hiPriorityMessage.hide();
243 }
244 hiPriorityMessage = msg;
245 break;
246 default:
247 msg = null;
248 }
249 Scheduler.get().scheduleDeferred(new ScheduledCommand() {
250
251 @Override
252 public void execute() {
253 if (msg != null) {
254 add(msg, getElement());
255 }
256 }
257 });
258 }
259
260 @Override
261 public void hideAllMessages() {
262 if (hiPriorityMessage != null && getWidgetIndex(hiPriorityMessage) != -1) {
263 hiPriorityMessage.hideWithoutTransition();
264 }
265 if (lowPriorityMessage != null && getWidgetIndex(lowPriorityMessage) != -1) {
266 lowPriorityMessage.hideWithoutTransition();
267 }
268
269 hiPriorityMessage = null;
270 lowPriorityMessage = null;
271 }
272
273 @Override
274 public void updateViewport(ViewportWidget viewport, ViewportType type) {
275 ViewportWidget oldViewport = viewports.get(type);
276 if (oldViewport != viewport) {
277 replaceWidget(oldViewport, viewport);
278 viewports.put(type, viewport);
279 }
280 }
281
282 @Override
283 public void shiftViewportsVertically(int shiftPx, boolean animated) {
284 viewportShifter.setProperty("top", mainAppLauncher.getOffsetHeight() + shiftPx);
285 if (shiftPx == 0 || shiftPx == 60) {
286 viewportShifter.clearTopAfterThisAnimation();
287 }
288 viewportShifter.run(animated ? 300 : 0, viewportSlot);
289 }
290
291 @Override
292 public void setShellAppIndication(ShellAppType type, int indication) {
293 mainAppLauncher.setIndication(type, indication);
294 }
295
296 @Override
297 public void closeMessageEager(final String id) {
298 presenter.removeMessage(id);
299 }
300
301 @Override
302 public void navigateToMessageDetails(String id) {
303 presenter.activateShellApp(Fragment.fromString("shell:pulse:messages/" + id));
304 }
305
306 @Override
307 public void updateShellDivet() {
308 mainAppLauncher.updateDivet();
309 }
310
311 @Override
312 public void openOverlayOnWidget(Widget overlayWidget, Widget overlayParent) {
313 add(overlayWidget, overlayParent.getElement());
314 }
315
316 @Override
317 public void onShellAppStarting(ShellAppType type) {
318 mainAppLauncher.activateControl(type);
319 }
320
321 @Override
322 public void onAppStarting() {
323 mainAppLauncher.deactivateControls();
324 }
325
326 @Override
327 public void setUserMenu(Widget widget) {
328 mainAppLauncher.setUserMenu(widget);
329 }
330
331 @Override
332 public void onLoad() {
333 super.onLoad();
334 presenter.initHistory();
335 }
336
337 @Override
338 public boolean hasOverlay(Widget widget) {
339 return getWidgetIndex(widget) != -1;
340 }
341
342
343 }