You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
преди 12 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.HashSet;
  6. import java.util.Iterator;
  7. import com.google.gwt.core.client.GWT;
  8. import com.google.gwt.core.client.Scheduler;
  9. import com.google.gwt.event.dom.client.DomEvent.Type;
  10. import com.google.gwt.event.shared.EventHandler;
  11. import com.google.gwt.event.shared.HandlerRegistration;
  12. import com.google.gwt.user.client.Command;
  13. import com.google.gwt.user.client.DOM;
  14. import com.google.gwt.user.client.Event;
  15. import com.google.gwt.user.client.History;
  16. import com.google.gwt.user.client.Window;
  17. import com.google.gwt.user.client.ui.RootPanel;
  18. import com.google.gwt.user.client.ui.Widget;
  19. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  20. import com.vaadin.terminal.gwt.client.BrowserInfo;
  21. import com.vaadin.terminal.gwt.client.Focusable;
  22. import com.vaadin.terminal.gwt.client.UIDL;
  23. import com.vaadin.terminal.gwt.client.Util;
  24. import com.vaadin.terminal.gwt.client.VConsole;
  25. import com.vaadin.terminal.gwt.client.ConnectorMap;
  26. import com.vaadin.terminal.gwt.client.ComponentConnector;
  27. public class VViewPaintable extends AbstractComponentContainerConnector {
  28. private static final String CLICK_EVENT_IDENTIFIER = VPanelPaintable.CLICK_EVENT_IDENTIFIER;
  29. @Override
  30. public void updateFromUIDL(final UIDL uidl, ApplicationConnection client) {
  31. getWidget().rendering = true;
  32. // As VView is not created in the same way as all other paintables we
  33. // have to set the id here
  34. setId(uidl.getId());
  35. getWidget().id = uidl.getId();
  36. boolean firstPaint = getWidget().connection == null;
  37. getWidget().connection = client;
  38. getWidget().immediate = getState().isImmediate();
  39. getWidget().resizeLazy = uidl
  40. .hasAttribute(VView.RESIZE_LAZY);
  41. String newTheme = uidl.getStringAttribute("theme");
  42. if (getWidget().theme != null
  43. && !newTheme.equals(getWidget().theme)) {
  44. // Complete page refresh is needed due css can affect layout
  45. // calculations etc
  46. getWidget().reloadHostPage();
  47. } else {
  48. getWidget().theme = newTheme;
  49. }
  50. // this also implicitly removes old styles
  51. getWidget().setStyleName(
  52. getWidget().getStylePrimaryName() + " "
  53. + getState().getStyle());
  54. clickEventHandler.handleEventHandlerRegistration(client);
  55. if (!getWidget().isEmbedded()
  56. && getState().getCaption() != null) {
  57. // only change window title if we're in charge of the whole page
  58. com.google.gwt.user.client.Window.setTitle(getState().getCaption());
  59. }
  60. // Process children
  61. int childIndex = 0;
  62. // Open URL:s
  63. boolean isClosed = false; // was this window closed?
  64. while (childIndex < uidl.getChildCount()
  65. && "open".equals(uidl.getChildUIDL(childIndex).getTag())) {
  66. final UIDL open = uidl.getChildUIDL(childIndex);
  67. final String url = client.translateVaadinUri(open
  68. .getStringAttribute("src"));
  69. final String target = open.getStringAttribute("name");
  70. if (target == null) {
  71. // source will be opened to this browser window, but we may have
  72. // to finish rendering this window in case this is a download
  73. // (and window stays open).
  74. Scheduler.get().scheduleDeferred(new Command() {
  75. public void execute() {
  76. VView.goTo(url);
  77. }
  78. });
  79. } else if ("_self".equals(target)) {
  80. // This window is closing (for sure). Only other opens are
  81. // relevant in this change. See #3558, #2144
  82. isClosed = true;
  83. VView.goTo(url);
  84. } else {
  85. String options;
  86. if (open.hasAttribute("border")) {
  87. if (open.getStringAttribute("border").equals("minimal")) {
  88. options = "menubar=yes,location=no,status=no";
  89. } else {
  90. options = "menubar=no,location=no,status=no";
  91. }
  92. } else {
  93. options = "resizable=yes,menubar=yes,toolbar=yes,directories=yes,location=yes,scrollbars=yes,status=yes";
  94. }
  95. if (open.hasAttribute("width")) {
  96. int w = open.getIntAttribute("width");
  97. options += ",width=" + w;
  98. }
  99. if (open.hasAttribute("height")) {
  100. int h = open.getIntAttribute("height");
  101. options += ",height=" + h;
  102. }
  103. Window.open(url, target, options);
  104. }
  105. childIndex++;
  106. }
  107. if (isClosed) {
  108. // don't render the content, something else will be opened to this
  109. // browser view
  110. getWidget().rendering = false;
  111. return;
  112. }
  113. // Draw this application level window
  114. UIDL childUidl = uidl.getChildUIDL(childIndex);
  115. final ComponentConnector lo = client.getPaintable(childUidl);
  116. if (getWidget().layout != null) {
  117. if (getWidget().layout != lo) {
  118. // remove old
  119. client.unregisterPaintable(getWidget().layout);
  120. // add new
  121. getWidget().setWidget(lo.getWidget());
  122. getWidget().layout = lo;
  123. }
  124. } else {
  125. getWidget().setWidget(lo.getWidget());
  126. getWidget().layout = lo;
  127. }
  128. getWidget().layout.updateFromUIDL(childUidl, client);
  129. // Save currently open subwindows to track which will need to be closed
  130. final HashSet<VWindow> removedSubWindows = new HashSet<VWindow>(
  131. getWidget().subWindows);
  132. // Handle other UIDL children
  133. while ((childUidl = uidl.getChildUIDL(++childIndex)) != null) {
  134. String tag = childUidl.getTag().intern();
  135. if (tag == "actions") {
  136. if (getWidget().actionHandler == null) {
  137. getWidget().actionHandler = new ShortcutActionHandler(
  138. getWidget().id, client);
  139. }
  140. getWidget().actionHandler
  141. .updateActionMap(childUidl);
  142. } else if (tag == "execJS") {
  143. String script = childUidl.getStringAttribute("script");
  144. VView.eval(script);
  145. } else if (tag == "notifications") {
  146. for (final Iterator<?> it = childUidl.getChildIterator(); it
  147. .hasNext();) {
  148. final UIDL notification = (UIDL) it.next();
  149. VNotification.showNotification(client, notification);
  150. }
  151. } else {
  152. // subwindows
  153. final VWindowPaintable w = (VWindowPaintable) client
  154. .getPaintable(childUidl);
  155. VWindow windowWidget = w.getWidget();
  156. if (getWidget().subWindows.contains(windowWidget)) {
  157. removedSubWindows.remove(windowWidget);
  158. } else {
  159. getWidget().subWindows.add(windowWidget);
  160. }
  161. w.updateFromUIDL(childUidl, client);
  162. }
  163. }
  164. // Close old windows which where not in UIDL anymore
  165. for (final Iterator<VWindow> rem = removedSubWindows.iterator(); rem
  166. .hasNext();) {
  167. final VWindow w = rem.next();
  168. client.unregisterPaintable(ConnectorMap.get(getConnection())
  169. .getConnector(w));
  170. getWidget().subWindows.remove(w);
  171. w.hide();
  172. }
  173. if (uidl.hasAttribute("focused")) {
  174. // set focused component when render phase is finished
  175. Scheduler.get().scheduleDeferred(new Command() {
  176. public void execute() {
  177. ComponentConnector paintable = (ComponentConnector) uidl
  178. .getPaintableAttribute("focused", getConnection());
  179. final Widget toBeFocused = paintable
  180. .getWidget();
  181. /*
  182. * Two types of Widgets can be focused, either implementing
  183. * GWT HasFocus of a thinner Vaadin specific Focusable
  184. * interface.
  185. */
  186. if (toBeFocused instanceof com.google.gwt.user.client.ui.Focusable) {
  187. final com.google.gwt.user.client.ui.Focusable toBeFocusedWidget = (com.google.gwt.user.client.ui.Focusable) toBeFocused;
  188. toBeFocusedWidget.setFocus(true);
  189. } else if (toBeFocused instanceof Focusable) {
  190. ((Focusable) toBeFocused).focus();
  191. } else {
  192. VConsole.log("Could not focus component");
  193. }
  194. }
  195. });
  196. }
  197. // Add window listeners on first paint, to prevent premature
  198. // variablechanges
  199. if (firstPaint) {
  200. Window.addWindowClosingHandler(getWidget());
  201. Window.addResizeHandler(getWidget());
  202. }
  203. getWidget().onResize();
  204. // finally set scroll position from UIDL
  205. if (uidl.hasVariable("scrollTop")) {
  206. getWidget().scrollable = true;
  207. getWidget().scrollTop = uidl
  208. .getIntVariable("scrollTop");
  209. DOM.setElementPropertyInt(getWidget().getElement(),
  210. "scrollTop", getWidget().scrollTop);
  211. getWidget().scrollLeft = uidl
  212. .getIntVariable("scrollLeft");
  213. DOM.setElementPropertyInt(getWidget().getElement(),
  214. "scrollLeft", getWidget().scrollLeft);
  215. } else {
  216. getWidget().scrollable = false;
  217. }
  218. // Safari workaround must be run after scrollTop is updated as it sets
  219. // scrollTop using a deferred command.
  220. if (BrowserInfo.get().isSafari()) {
  221. Util.runWebkitOverflowAutoFix(getWidget().getElement());
  222. }
  223. getWidget().scrollIntoView(uidl);
  224. if (uidl.hasAttribute(VView.FRAGMENT_VARIABLE)) {
  225. getWidget().currentFragment = uidl
  226. .getStringAttribute(VView.FRAGMENT_VARIABLE);
  227. if (!getWidget().currentFragment.equals(History
  228. .getToken())) {
  229. History.newItem(getWidget().currentFragment, true);
  230. }
  231. } else {
  232. // Initial request for which the server doesn't yet have a fragment
  233. // (and haven't shown any interest in getting one)
  234. getWidget().currentFragment = History.getToken();
  235. // Include current fragment in the next request
  236. client.updateVariable(getWidget().id,
  237. VView.FRAGMENT_VARIABLE,
  238. getWidget().currentFragment, false);
  239. }
  240. getWidget().rendering = false;
  241. }
  242. public void init(String rootPanelId,
  243. ApplicationConnection applicationConnection) {
  244. DOM.sinkEvents(getWidget().getElement(), Event.ONKEYDOWN
  245. | Event.ONSCROLL);
  246. // iview is focused when created so element needs tabIndex
  247. // 1 due 0 is at the end of natural tabbing order
  248. DOM.setElementProperty(getWidget().getElement(),
  249. "tabIndex", "1");
  250. RootPanel root = RootPanel.get(rootPanelId);
  251. // Remove the v-app-loading or any splash screen added inside the div by
  252. // the user
  253. root.getElement().setInnerHTML("");
  254. // For backwards compatibility with static index pages only.
  255. // No longer added by AbstractApplicationServlet/Portlet
  256. root.removeStyleName("v-app-loading");
  257. String themeUri = applicationConnection.getConfiguration()
  258. .getThemeUri();
  259. String themeName = themeUri.substring(themeUri.lastIndexOf('/'));
  260. themeName = themeName.replaceAll("[^a-zA-Z0-9]", "");
  261. root.addStyleName("v-theme-" + themeName);
  262. root.add(getWidget());
  263. if (applicationConnection.getConfiguration().isStandalone()) {
  264. // set focus to iview element by default to listen possible keyboard
  265. // shortcuts. For embedded applications this is unacceptable as we
  266. // don't want to steal focus from the main page nor we don't want
  267. // side-effects from focusing (scrollIntoView).
  268. getWidget().getElement().focus();
  269. }
  270. }
  271. private ClickEventHandler clickEventHandler = new ClickEventHandler(this,
  272. CLICK_EVENT_IDENTIFIER) {
  273. @Override
  274. protected <H extends EventHandler> HandlerRegistration registerHandler(
  275. H handler, Type<H> type) {
  276. return getWidget().addDomHandler(handler, type);
  277. }
  278. };
  279. public void updateCaption(ComponentConnector component, UIDL uidl) {
  280. // NOP The main view never draws caption for its layout
  281. }
  282. @Override
  283. public VView getWidget() {
  284. return (VView) super.getWidget();
  285. }
  286. @Override
  287. protected Widget createWidget() {
  288. return GWT.create(VView.class);
  289. }
  290. }