View Javadoc

1   /**
2    * This file Copyright (c) 2010-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.vaadin.gwt.client.magnoliashell.shell;
35  
36  import info.magnolia.ui.vaadin.gwt.client.dialog.connector.OverlayConnector;
37  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.ActivateAppEvent;
38  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.AppRequestedEvent;
39  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.CurrentAppCloseEvent;
40  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.FullScreenEvent;
41  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.HideShellAppsEvent;
42  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.HideShellAppsRequestedEvent;
43  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.ShellAppRequestedEvent;
44  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.ShellAppStartedEvent;
45  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.ShellAppStartingEvent;
46  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.event.ShellAppsHiddenEvent;
47  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shell.rpc.ShellClientRpc;
48  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shell.rpc.ShellServerRpc;
49  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.shellmessage.ShellMessageWidget.MessageType;
50  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.connector.ViewportConnector;
51  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.widget.AppsViewportWidget;
52  import info.magnolia.ui.vaadin.gwt.client.magnoliashell.viewport.widget.ViewportWidget;
53  import info.magnolia.ui.vaadin.gwt.client.shared.magnoliashell.Fragment;
54  import info.magnolia.ui.vaadin.gwt.client.shared.magnoliashell.ShellAppType;
55  import info.magnolia.ui.vaadin.gwt.client.shared.magnoliashell.ViewportType;
56  import info.magnolia.ui.vaadin.magnoliashell.MagnoliaShell;
57  
58  import java.util.Iterator;
59  import java.util.List;
60  import java.util.Map.Entry;
61  
62  import com.google.gwt.core.client.Scheduler;
63  import com.google.gwt.event.logical.shared.ValueChangeEvent;
64  import com.google.gwt.event.logical.shared.ValueChangeHandler;
65  import com.google.gwt.user.client.History;
66  import com.google.gwt.user.client.ui.Widget;
67  import com.google.web.bindery.event.shared.EventBus;
68  import com.google.web.bindery.event.shared.SimpleEventBus;
69  import com.vaadin.client.ComponentConnector;
70  import com.vaadin.client.ConnectorHierarchyChangeEvent;
71  import com.vaadin.client.Util;
72  import com.vaadin.client.communication.RpcProxy;
73  import com.vaadin.client.communication.StateChangeEvent;
74  import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler;
75  import com.vaadin.client.ui.AbstractLayoutConnector;
76  import com.vaadin.client.ui.layout.ElementResizeEvent;
77  import com.vaadin.client.ui.layout.ElementResizeListener;
78  import com.vaadin.client.ui.nativebutton.NativeButtonConnector;
79  import com.vaadin.shared.ui.Connect;
80  
81  /**
82   * MagnoliaShellConnector.
83   */
84  @Connect(MagnoliaShell.class)
85  public class MagnoliaShellConnector extends AbstractLayoutConnector implements MagnoliaShellView.Presenter {
86  
87      private ShellServerRpc rpc = RpcProxy.create(ShellServerRpc.class, this);
88      private MagnoliaShellView view;
89      private EventBus eventBus = new SimpleEventBus();
90      private Fragment lastHandledFragment;
91      private boolean isHistoryInitialized = false;
92  
93      @Override
94      protected void init() {
95          super.init();
96          addStateChangeHandler(new StateChangeHandler() {
97              @Override
98              public void onStateChanged(StateChangeEvent event) {
99                  MagnoliaShellState state = getState();
100                 Iterator<Entry<ShellAppType, Integer>> it = state.indications.entrySet().iterator();
101                 while (it.hasNext()) {
102                     final Entry<ShellAppType, Integer> entry = it.next();
103                     view.setShellAppIndication(entry.getKey(), entry.getValue());
104                 }
105             }
106         });
107 
108         addStateChangeHandler("uriFragment", new StateChangeHandler() {
109             @Override
110             public void onStateChanged(StateChangeEvent stateChangeEvent) {
111                 Fragment f = getState().uriFragment;
112                 if (f != null) {
113                     History.newItem(f.toFragment(), !f.isSameApp(lastHandledFragment));
114                 }
115             }
116         });
117 
118         registerRpc(ShellClientRpc.class, new ShellClientRpc() {
119             @Override
120             public void showMessage(String type, String topic, String msg, String id) {
121                 view.showMessage(MessageType.valueOf(type), topic, msg, id);
122             }
123 
124             @Override
125             public void hideAllMessages() {
126                 view.hideAllMessages();
127             }
128 
129             @Override
130             public void setFullScreen(boolean isFullScreen) {
131                 MagnoliaShellConnector.this.doFullScreen(isFullScreen);
132             }
133         });
134 
135         getLayoutManager().addElementResizeListener(getWidget().getElement(), new ElementResizeListener() {
136             @Override
137             public void onElementResize(ElementResizeEvent e) {
138                 view.updateShellDivet();
139             }
140         });
141 
142         eventBus.addHandler(CurrentAppCloseEvent.TYPE, new CurrentAppCloseEvent.Handler() {
143             @Override
144             public void onViewportClose(CurrentAppCloseEvent event) {
145                 closeCurrentApp();
146             }
147         });
148 
149         eventBus.addHandler(ShellAppStartingEvent.TYPE, new ShellAppStartingEvent.Handler() {
150             @Override
151             public void onShellAppStarting(ShellAppStartingEvent event) {
152                 view.onShellAppStarting(event.getType());
153             }
154         });
155 
156         eventBus.addHandler(ShellAppStartedEvent.TYPE, new ShellAppStartedEvent.Handler() {
157             @Override
158             public void onShellAppStarted(ShellAppStartedEvent event) {
159                 lastHandledFragment = Fragment.fromString("shell:" + event.getType().name().toLowerCase() + ":" + "");
160                 activateShellApp(lastHandledFragment);
161             }
162         });
163 
164         eventBus.addHandler(HideShellAppsRequestedEvent.TYPE, new HideShellAppsRequestedEvent.Handler() {
165             @Override
166             public void onHideShellAppsRequest(HideShellAppsRequestedEvent event) {
167                 onHideShellAppsRequested();
168             }
169         });
170 
171         eventBus.addHandler(ShellAppsHiddenEvent.TYPE, new ShellAppsHiddenEvent.Handler() {
172             @Override
173             public void onShellAppsHidden(ShellAppsHiddenEvent event) {
174                 rpc.stopCurrentShellApp();
175             }
176         });
177 
178         eventBus.addHandler(ActivateAppEvent.TYPE, new ActivateAppEvent.Handler() {
179             @Override
180             public void onActivateApp(ActivateAppEvent event) {
181                 rpc.activateApp(Fragment.fromString("app:" + event.getName()));
182             }
183         });
184 
185         History.addValueChangeHandler(new ValueChangeHandler<String>() {
186             @Override
187             public void onValueChange(ValueChangeEvent<String> event) {
188                 Fragment newFragment = Fragment.fromString(event.getValue());
189                 if (newFragment.isShellApp()) {
190                     showShellApp(newFragment.resolveShellAppType());
191                 } else {
192                     loadApp(newFragment.getAppName());
193                     rpc.activateApp(newFragment);
194                 }
195                 lastHandledFragment = newFragment;
196             }
197         });
198     }
199 
200     @Override
201     public void activateShellApp(Fragment f) {
202         rpc.activateShellApp(f);
203     }
204 
205     @Override
206     public void closeCurrentApp() {
207         rpc.stopCurrentApp();
208     }
209 
210     @Override
211     public void removeMessage(String id) {
212         rpc.removeMessage(id);
213     }
214 
215     @Override
216     public void loadApp(String appName) {
217         view.onAppStarting();
218         eventBus.fireEvent(new AppRequestedEvent(appName));
219     }
220 
221     @Override
222     public void showShellApp(ShellAppType shellAppType) {
223         eventBus.fireEvent(new ShellAppRequestedEvent(shellAppType));
224     }
225 
226     private void doFullScreen(boolean isFullScreen) {
227         eventBus.fireEvent(new FullScreenEvent(isFullScreen));
228     }
229 
230     @Override
231     public void onHideShellAppsRequested() {
232         ViewportWidget viewportWidget =
233                 (ViewportWidget) ((ComponentConnector)getState().viewports.get(ViewportType.APP)).getWidget();
234         AppsViewportWidget appViewportWidget =
235                 (AppsViewportWidget) ((ComponentConnector)getState().viewports.get(ViewportType.APP)).getWidget();
236 
237         // If no app is active, then show or keep the applauncher.
238         Widget currentApp = appViewportWidget.getCurrentApp();
239         if (currentApp != null) {
240             view.onAppStarting();
241             eventBus.fireEvent(new HideShellAppsEvent());
242         } else {
243             showShellApp(ShellAppType.APPLAUNCHER);
244         }
245     }
246 
247     @Override
248     public void updateCaption(ComponentConnector connector) {}
249 
250     @Override
251     public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
252         List<ComponentConnector> children = getChildComponents();
253         for (ComponentConnector connector : children) {
254             if (connector instanceof ViewportConnector) {
255                 final ViewportConnector vc = (ViewportConnector) connector;
256                 view.updateViewport(vc.getWidget(), vc.getType());
257                 vc.setEventBus(eventBus);
258             } else if (connector instanceof OverlayConnector) {
259                 if (!view.hasOverlay(connector.getWidget())) {
260                     final OverlayConnector oc = (OverlayConnector) connector;
261                     ComponentConnector overlayParent = (ComponentConnector) oc.getState().overlayParent;
262                     Widget parentWidget = overlayParent.getWidget();
263                     view.openOverlayOnWidget(oc.getWidget(), parentWidget);
264                 }
265             } else if (connector instanceof NativeButtonConnector) {
266                 view.setUserMenu(connector.getWidget());
267             }
268         }
269 
270         List<ComponentConnector> oldChildren = event.getOldChildren();
271         oldChildren.removeAll(children);
272         for (ComponentConnector cc : oldChildren) {
273             cc.getWidget().removeFromParent();
274         }
275     }
276 
277     @Override
278     protected Widget createWidget() {
279         this.view = new MagnoliaShellViewImpl();
280         this.view.setPresenter(this);
281         return view.asWidget();
282     }
283 
284     @Override
285     public MagnoliaShellState getState() {
286         return (MagnoliaShellState) super.getState();
287     }
288 
289     @Override
290     public void updateViewportLayout(ViewportWidget activeViewport) {
291         getLayoutManager().setNeedsMeasure(Util.findConnectorFor(activeViewport));
292         getLayoutManager().layoutNow();
293     }
294 
295 
296     @Override
297     public void initHistory() {
298         Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
299             @Override
300             public void execute() {
301                 if (!isHistoryInitialized) {
302                     isHistoryInitialized = true;
303                     History.fireCurrentHistoryState();
304                 }
305             }
306         });
307     }
308 
309 }