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

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