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.

WindowConnector.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import com.google.gwt.core.client.GWT;
  6. import com.google.gwt.event.dom.client.DomEvent.Type;
  7. import com.google.gwt.event.shared.EventHandler;
  8. import com.google.gwt.event.shared.HandlerRegistration;
  9. import com.google.gwt.user.client.DOM;
  10. import com.google.gwt.user.client.Event;
  11. import com.google.gwt.user.client.Window;
  12. import com.google.gwt.user.client.ui.Frame;
  13. import com.google.gwt.user.client.ui.Widget;
  14. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  15. import com.vaadin.terminal.gwt.client.ComponentConnector;
  16. import com.vaadin.terminal.gwt.client.UIDL;
  17. import com.vaadin.terminal.gwt.client.Util;
  18. import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
  19. public class WindowConnector extends AbstractComponentContainerConnector
  20. implements BeforeShortcutActionListener, SimpleManagedLayout,
  21. PostLayoutListener {
  22. private static final String CLICK_EVENT_IDENTIFIER = PanelConnector.CLICK_EVENT_IDENTIFIER;
  23. private ClickEventHandler clickEventHandler = new ClickEventHandler(this,
  24. CLICK_EVENT_IDENTIFIER) {
  25. @Override
  26. protected <H extends EventHandler> HandlerRegistration registerHandler(
  27. H handler, Type<H> type) {
  28. return getWidget().addDomHandler(handler, type);
  29. }
  30. };
  31. @Override
  32. protected boolean delegateCaptionHandling() {
  33. return false;
  34. };
  35. @Override
  36. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  37. getWidget().id = uidl.getId();
  38. getWidget().client = client;
  39. // Workaround needed for Testing Tools (GWT generates window DOM
  40. // slightly different in different browsers).
  41. DOM.setElementProperty(getWidget().closeBox, "id", getWidget().id
  42. + "_window_close");
  43. if (uidl.hasAttribute("invisible")) {
  44. getWidget().hide();
  45. return;
  46. }
  47. if (isRealUpdate(uidl)) {
  48. if (uidl.getBooleanAttribute("modal") != getWidget().vaadinModality) {
  49. getWidget().setVaadinModality(!getWidget().vaadinModality);
  50. }
  51. if (!getWidget().isAttached()) {
  52. getWidget().setVisible(false); // hide until
  53. // possible centering
  54. getWidget().show();
  55. }
  56. if (uidl.getBooleanAttribute("resizable") != getWidget().resizable) {
  57. getWidget().setResizable(!getWidget().resizable);
  58. }
  59. getWidget().resizeLazy = uidl.hasAttribute(VView.RESIZE_LAZY);
  60. getWidget().setDraggable(!uidl.hasAttribute("fixedposition"));
  61. // Caption must be set before required header size is measured. If
  62. // the caption attribute is missing the caption should be cleared.
  63. getWidget()
  64. .setCaption(
  65. getState().getCaption(),
  66. uidl.getStringAttribute(AbstractComponentConnector.ATTRIBUTE_ICON));
  67. }
  68. getWidget().visibilityChangesDisabled = true;
  69. super.updateFromUIDL(uidl, client);
  70. if (!isRealUpdate(uidl)) {
  71. return;
  72. }
  73. getWidget().visibilityChangesDisabled = false;
  74. clickEventHandler.handleEventHandlerRegistration(client);
  75. getWidget().immediate = getState().isImmediate();
  76. getWidget().setClosable(!getState().isReadOnly());
  77. // Initialize the position form UIDL
  78. int positionx = uidl.getIntVariable("positionx");
  79. int positiony = uidl.getIntVariable("positiony");
  80. if (positionx >= 0 || positiony >= 0) {
  81. if (positionx < 0) {
  82. positionx = 0;
  83. }
  84. if (positiony < 0) {
  85. positiony = 0;
  86. }
  87. getWidget().setPopupPosition(positionx, positiony);
  88. }
  89. boolean showingUrl = false;
  90. int childIndex = 0;
  91. UIDL childUidl = uidl.getChildUIDL(childIndex++);
  92. while ("open".equals(childUidl.getTag())) {
  93. // TODO multiple opens with the same target will in practice just
  94. // open the last one - should we fix that somehow?
  95. final String parsedUri = client.translateVaadinUri(childUidl
  96. .getStringAttribute("src"));
  97. if (!childUidl.hasAttribute("name")) {
  98. final Frame frame = new Frame();
  99. DOM.setStyleAttribute(frame.getElement(), "width", "100%");
  100. DOM.setStyleAttribute(frame.getElement(), "height", "100%");
  101. DOM.setStyleAttribute(frame.getElement(), "border", "0px");
  102. frame.setUrl(parsedUri);
  103. getWidget().contentPanel.setWidget(frame);
  104. showingUrl = true;
  105. } else {
  106. final String target = childUidl.getStringAttribute("name");
  107. Window.open(parsedUri, target, "");
  108. }
  109. childUidl = uidl.getChildUIDL(childIndex++);
  110. }
  111. final ComponentConnector lo = client.getPaintable(childUidl);
  112. if (getWidget().layout != null) {
  113. if (getWidget().layout != lo) {
  114. // remove old
  115. client.unregisterPaintable(getWidget().layout);
  116. getWidget().contentPanel.remove(getWidget().layout.getWidget());
  117. // add new
  118. if (!showingUrl) {
  119. getWidget().contentPanel.setWidget(lo.getWidget());
  120. }
  121. getWidget().layout = lo;
  122. }
  123. } else if (!showingUrl) {
  124. getWidget().contentPanel.setWidget(lo.getWidget());
  125. getWidget().layout = lo;
  126. }
  127. getWidget().dynamicWidth = getState().isUndefinedWidth();
  128. getWidget().dynamicHeight = getState().isUndefinedHeight();
  129. getWidget().layoutRelativeWidth = uidl
  130. .hasAttribute("layoutRelativeWidth");
  131. getWidget().layoutRelativeHeight = uidl
  132. .hasAttribute("layoutRelativeHeight");
  133. if (getWidget().dynamicWidth && getWidget().layoutRelativeWidth) {
  134. /*
  135. * Relative layout width, fix window width before rendering (width
  136. * according to caption)
  137. */
  138. getWidget().setNaturalWidth();
  139. }
  140. getWidget().layout.updateFromUIDL(childUidl, client);
  141. if (!getWidget().dynamicHeight && getWidget().layoutRelativeWidth) {
  142. /*
  143. * Relative layout width, and fixed height. Must update the size to
  144. * be able to take scrollbars into account (layout gets narrower
  145. * space if it is higher than the window) -> only vertical scrollbar
  146. */
  147. client.runDescendentsLayout(getWidget());
  148. }
  149. /*
  150. * No explicit width is set and the layout does not have relative width
  151. * so fix the size according to the layout.
  152. */
  153. if (getWidget().dynamicWidth && !getWidget().layoutRelativeWidth) {
  154. getWidget().setNaturalWidth();
  155. }
  156. if (getWidget().dynamicHeight && getWidget().layoutRelativeHeight) {
  157. // Prevent resizing until height has been fixed
  158. getWidget().resizable = false;
  159. }
  160. // we may have actions and notifications
  161. if (uidl.getChildCount() > 1) {
  162. final int cnt = uidl.getChildCount();
  163. for (int i = 1; i < cnt; i++) {
  164. childUidl = uidl.getChildUIDL(i);
  165. if (childUidl.getTag().equals("actions")) {
  166. if (getWidget().shortcutHandler == null) {
  167. getWidget().shortcutHandler = new ShortcutActionHandler(
  168. getId(), client);
  169. }
  170. getWidget().shortcutHandler.updateActionMap(childUidl);
  171. }
  172. }
  173. }
  174. // setting scrollposition must happen after children is rendered
  175. getWidget().contentPanel.setScrollPosition(uidl
  176. .getIntVariable("scrollTop"));
  177. getWidget().contentPanel.setHorizontalScrollPosition(uidl
  178. .getIntVariable("scrollLeft"));
  179. // Center this window on screen if requested
  180. // This has to be here because we might not know the content size before
  181. // everything is painted into the window
  182. if (uidl.getBooleanAttribute("center")) {
  183. // mark as centered - this is unset on move/resize
  184. getWidget().centered = true;
  185. getWidget().center();
  186. } else {
  187. // don't try to center the window anymore
  188. getWidget().centered = false;
  189. }
  190. getWidget().updateShadowSizeAndPosition();
  191. getWidget().setVisible(true);
  192. boolean sizeReduced = false;
  193. // ensure window is not larger than browser window
  194. if (getWidget().getOffsetWidth() > Window.getClientWidth()) {
  195. getWidget().setWidth(Window.getClientWidth() + "px");
  196. sizeReduced = true;
  197. }
  198. if (getWidget().getOffsetHeight() > Window.getClientHeight()) {
  199. getWidget().setHeight(Window.getClientHeight() + "px");
  200. sizeReduced = true;
  201. }
  202. if (getWidget().dynamicHeight && getWidget().layoutRelativeHeight) {
  203. /*
  204. * Window height is undefined, layout is 100% high so the layout
  205. * should define the initial window height but on resize the layout
  206. * should be as high as the window. We fix the height to deal with
  207. * this.
  208. */
  209. int h = getWidget().contents.getOffsetHeight()
  210. + getWidget().getExtraHeight();
  211. int w = getWidget().getElement().getOffsetWidth();
  212. client.updateVariable(getId(), "height", h, false);
  213. client.updateVariable(getId(), "width", w, true);
  214. }
  215. if (sizeReduced) {
  216. // If we changed the size we need to update the size of the child
  217. // component if it is relative (#3407)
  218. client.runDescendentsLayout(getWidget());
  219. }
  220. Util.runWebkitOverflowAutoFix(getWidget().contentPanel.getElement());
  221. client.getView().getWidget().scrollIntoView(uidl);
  222. if (uidl.hasAttribute("bringToFront")) {
  223. /*
  224. * Focus as a side-efect. Will be overridden by
  225. * ApplicationConnection if another component was focused by the
  226. * server side.
  227. */
  228. getWidget().contentPanel.focus();
  229. getWidget().bringToFrontSequence = uidl
  230. .getIntAttribute("bringToFront");
  231. VWindow.deferOrdering();
  232. }
  233. }
  234. public void updateCaption(ComponentConnector component, UIDL uidl) {
  235. // NOP, window has own caption, layout captio not rendered
  236. }
  237. public void onBeforeShortcutAction(Event e) {
  238. // NOP, nothing to update just avoid workaround ( causes excess
  239. // blur/focus )
  240. }
  241. @Override
  242. public VWindow getWidget() {
  243. return (VWindow) super.getWidget();
  244. }
  245. @Override
  246. protected Widget createWidget() {
  247. return GWT.create(VWindow.class);
  248. }
  249. public void layout() {
  250. getWidget().requestLayout();
  251. }
  252. public void postLayout() {
  253. VWindow window = getWidget();
  254. if (window.centered) {
  255. window.center();
  256. window.updateShadowSizeAndPosition();
  257. }
  258. }
  259. }