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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright 2011 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.client.ui.window;
  17. import com.google.gwt.dom.client.Element;
  18. import com.google.gwt.dom.client.NativeEvent;
  19. import com.google.gwt.dom.client.Style;
  20. import com.google.gwt.dom.client.Style.Position;
  21. import com.google.gwt.dom.client.Style.Unit;
  22. import com.google.gwt.user.client.DOM;
  23. import com.google.gwt.user.client.Event;
  24. import com.google.gwt.user.client.Window;
  25. import com.google.gwt.user.client.ui.Widget;
  26. import com.vaadin.client.ApplicationConnection;
  27. import com.vaadin.client.BrowserInfo;
  28. import com.vaadin.client.ComponentConnector;
  29. import com.vaadin.client.ConnectorHierarchyChangeEvent;
  30. import com.vaadin.client.LayoutManager;
  31. import com.vaadin.client.Paintable;
  32. import com.vaadin.client.UIDL;
  33. import com.vaadin.client.communication.RpcProxy;
  34. import com.vaadin.client.ui.AbstractComponentContainerConnector;
  35. import com.vaadin.client.ui.ClickEventHandler;
  36. import com.vaadin.client.ui.PostLayoutListener;
  37. import com.vaadin.client.ui.ShortcutActionHandler;
  38. import com.vaadin.client.ui.SimpleManagedLayout;
  39. import com.vaadin.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
  40. import com.vaadin.client.ui.layout.MayScrollChildren;
  41. import com.vaadin.shared.MouseEventDetails;
  42. import com.vaadin.shared.ui.Connect;
  43. import com.vaadin.shared.ui.window.WindowServerRpc;
  44. import com.vaadin.shared.ui.window.WindowState;
  45. @Connect(value = com.vaadin.ui.Window.class)
  46. public class WindowConnector extends AbstractComponentContainerConnector
  47. implements Paintable, BeforeShortcutActionListener,
  48. SimpleManagedLayout, PostLayoutListener, MayScrollChildren {
  49. private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
  50. @Override
  51. protected void fireClick(NativeEvent event,
  52. MouseEventDetails mouseDetails) {
  53. rpc.click(mouseDetails);
  54. }
  55. };
  56. private WindowServerRpc rpc;
  57. boolean minWidthChecked = false;
  58. @Override
  59. public boolean delegateCaptionHandling() {
  60. return false;
  61. };
  62. @Override
  63. protected void init() {
  64. super.init();
  65. rpc = RpcProxy.create(WindowServerRpc.class, this);
  66. getLayoutManager().registerDependency(this,
  67. getWidget().contentPanel.getElement());
  68. getLayoutManager().registerDependency(this, getWidget().header);
  69. getLayoutManager().registerDependency(this, getWidget().footer);
  70. }
  71. @Override
  72. public void onUnregister() {
  73. LayoutManager lm = getLayoutManager();
  74. VWindow window = getWidget();
  75. lm.unregisterDependency(this, window.contentPanel.getElement());
  76. lm.unregisterDependency(this, window.header);
  77. lm.unregisterDependency(this, window.footer);
  78. }
  79. @Override
  80. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  81. getWidget().id = getConnectorId();
  82. getWidget().client = client;
  83. // Workaround needed for Testing Tools (GWT generates window DOM
  84. // slightly different in different browsers).
  85. DOM.setElementProperty(getWidget().closeBox, "id", getConnectorId()
  86. + "_window_close");
  87. if (isRealUpdate(uidl)) {
  88. if (getState().isModal() != getWidget().vaadinModality) {
  89. getWidget().setVaadinModality(!getWidget().vaadinModality);
  90. }
  91. if (!getWidget().isAttached()) {
  92. getWidget().setVisible(false); // hide until
  93. // possible centering
  94. getWidget().show();
  95. }
  96. if (getState().isResizable() != getWidget().resizable) {
  97. getWidget().setResizable(getState().isResizable());
  98. }
  99. getWidget().resizeLazy = getState().isResizeLazy();
  100. getWidget().setDraggable(getState().isDraggable());
  101. // Caption must be set before required header size is measured. If
  102. // the caption attribute is missing the caption should be cleared.
  103. String iconURL = null;
  104. if (getIcon() != null) {
  105. iconURL = getIcon();
  106. }
  107. getWidget().setCaption(getState().getCaption(), iconURL);
  108. }
  109. getWidget().visibilityChangesDisabled = true;
  110. if (!isRealUpdate(uidl)) {
  111. return;
  112. }
  113. getWidget().visibilityChangesDisabled = false;
  114. clickEventHandler.handleEventHandlerRegistration();
  115. getWidget().immediate = getState().isImmediate();
  116. getWidget().setClosable(!isReadOnly());
  117. // Initialize the position form UIDL
  118. int positionx = getState().getPositionX();
  119. int positiony = getState().getPositionY();
  120. if (positionx >= 0 || positiony >= 0) {
  121. if (positionx < 0) {
  122. positionx = 0;
  123. }
  124. if (positiony < 0) {
  125. positiony = 0;
  126. }
  127. getWidget().setPopupPosition(positionx, positiony);
  128. }
  129. int childIndex = 0;
  130. // we may have actions
  131. for (int i = 0; i < uidl.getChildCount(); i++) {
  132. UIDL childUidl = uidl.getChildUIDL(i);
  133. if (childUidl.getTag().equals("actions")) {
  134. if (getWidget().shortcutHandler == null) {
  135. getWidget().shortcutHandler = new ShortcutActionHandler(
  136. getConnectorId(), client);
  137. }
  138. getWidget().shortcutHandler.updateActionMap(childUidl);
  139. }
  140. }
  141. // setting scrollposition must happen after children is rendered
  142. getWidget().contentPanel.setScrollPosition(getState().getScrollTop());
  143. getWidget().contentPanel.setHorizontalScrollPosition(getState()
  144. .getScrollLeft());
  145. // Center this window on screen if requested
  146. // This had to be here because we might not know the content size before
  147. // everything is painted into the window
  148. // centered is this is unset on move/resize
  149. getWidget().centered = getState().isCentered();
  150. getWidget().setVisible(true);
  151. // ensure window is not larger than browser window
  152. if (getWidget().getOffsetWidth() > Window.getClientWidth()) {
  153. getWidget().setWidth(Window.getClientWidth() + "px");
  154. }
  155. if (getWidget().getOffsetHeight() > Window.getClientHeight()) {
  156. getWidget().setHeight(Window.getClientHeight() + "px");
  157. }
  158. if (uidl.hasAttribute("bringToFront")) {
  159. /*
  160. * Focus as a side-effect. Will be overridden by
  161. * ApplicationConnection if another component was focused by the
  162. * server side.
  163. */
  164. getWidget().contentPanel.focus();
  165. getWidget().bringToFrontSequence = uidl
  166. .getIntAttribute("bringToFront");
  167. VWindow.deferOrdering();
  168. }
  169. }
  170. @Override
  171. public void updateCaption(ComponentConnector component) {
  172. // NOP, window has own caption, layout caption not rendered
  173. }
  174. @Override
  175. public void onBeforeShortcutAction(Event e) {
  176. // NOP, nothing to update just avoid workaround ( causes excess
  177. // blur/focus )
  178. }
  179. @Override
  180. public VWindow getWidget() {
  181. return (VWindow) super.getWidget();
  182. }
  183. @Override
  184. public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
  185. super.onConnectorHierarchyChange(event);
  186. // We always have 1 child, unless the child is hidden
  187. Widget newChildWidget = null;
  188. ComponentConnector newChild = null;
  189. if (getChildComponents().size() == 1) {
  190. newChild = getChildComponents().get(0);
  191. newChildWidget = newChild.getWidget();
  192. }
  193. getWidget().layout = newChild;
  194. getWidget().contentPanel.setWidget(newChildWidget);
  195. }
  196. @Override
  197. public void layout() {
  198. LayoutManager lm = getLayoutManager();
  199. VWindow window = getWidget();
  200. ComponentConnector layout = window.layout;
  201. Element contentElement = window.contentPanel.getElement();
  202. if (!minWidthChecked) {
  203. boolean needsMinWidth = !isUndefinedWidth()
  204. || layout.isRelativeWidth();
  205. int minWidth = window.getMinWidth();
  206. if (needsMinWidth && lm.getInnerWidth(contentElement) < minWidth) {
  207. minWidthChecked = true;
  208. // Use minimum width if less than a certain size
  209. window.setWidth(minWidth + "px");
  210. }
  211. minWidthChecked = true;
  212. }
  213. boolean needsMinHeight = !isUndefinedHeight()
  214. || layout.isRelativeHeight();
  215. int minHeight = window.getMinHeight();
  216. if (needsMinHeight && lm.getInnerHeight(contentElement) < minHeight) {
  217. // Use minimum height if less than a certain size
  218. window.setHeight(minHeight + "px");
  219. }
  220. Style contentStyle = window.contents.getStyle();
  221. int headerHeight = lm.getOuterHeight(window.header);
  222. contentStyle.setPaddingTop(headerHeight, Unit.PX);
  223. contentStyle.setMarginTop(-headerHeight, Unit.PX);
  224. int footerHeight = lm.getOuterHeight(window.footer);
  225. contentStyle.setPaddingBottom(footerHeight, Unit.PX);
  226. contentStyle.setMarginBottom(-footerHeight, Unit.PX);
  227. /*
  228. * Must set absolute position if the child has relative height and
  229. * there's a chance of horizontal scrolling as some browsers will
  230. * otherwise not take the scrollbar into account when calculating the
  231. * height.
  232. */
  233. Element layoutElement = layout.getWidget().getElement();
  234. Style childStyle = layoutElement.getStyle();
  235. if (layout.isRelativeHeight() && !BrowserInfo.get().isIE9()) {
  236. childStyle.setPosition(Position.ABSOLUTE);
  237. Style wrapperStyle = contentElement.getStyle();
  238. if (window.getElement().getStyle().getWidth().length() == 0
  239. && !layout.isRelativeWidth()) {
  240. /*
  241. * Need to lock width to make undefined width work even with
  242. * absolute positioning
  243. */
  244. int contentWidth = lm.getOuterWidth(layoutElement);
  245. wrapperStyle.setWidth(contentWidth, Unit.PX);
  246. } else {
  247. wrapperStyle.clearWidth();
  248. }
  249. } else {
  250. childStyle.clearPosition();
  251. }
  252. }
  253. @Override
  254. public void postLayout() {
  255. minWidthChecked = false;
  256. VWindow window = getWidget();
  257. if (window.centered) {
  258. window.center();
  259. }
  260. window.positionOrSizeUpdated();
  261. }
  262. @Override
  263. public WindowState getState() {
  264. return (WindowState) super.getState();
  265. }
  266. /**
  267. * Gives the WindowConnector an order number. As a side effect, moves the
  268. * window according to its order number so the windows are stacked. This
  269. * method should be called for each window in the order they should appear.
  270. */
  271. public void setWindowOrderAndPosition() {
  272. getWidget().setWindowOrderAndPosition();
  273. }
  274. }