Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

WindowConnector.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. * Copyright 2000-2013 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.event.dom.client.ClickEvent;
  23. import com.google.gwt.event.dom.client.ClickHandler;
  24. import com.google.gwt.event.dom.client.DoubleClickEvent;
  25. import com.google.gwt.event.dom.client.DoubleClickHandler;
  26. import com.google.gwt.user.client.Event;
  27. import com.google.gwt.user.client.Window;
  28. import com.vaadin.client.ApplicationConnection;
  29. import com.vaadin.client.BrowserInfo;
  30. import com.vaadin.client.ComponentConnector;
  31. import com.vaadin.client.ConnectorHierarchyChangeEvent;
  32. import com.vaadin.client.LayoutManager;
  33. import com.vaadin.client.Paintable;
  34. import com.vaadin.client.UIDL;
  35. import com.vaadin.client.Util;
  36. import com.vaadin.client.communication.RpcProxy;
  37. import com.vaadin.client.communication.StateChangeEvent;
  38. import com.vaadin.client.ui.AbstractSingleComponentContainerConnector;
  39. import com.vaadin.client.ui.ClickEventHandler;
  40. import com.vaadin.client.ui.PostLayoutListener;
  41. import com.vaadin.client.ui.ShortcutActionHandler;
  42. import com.vaadin.client.ui.ShortcutActionHandler.BeforeShortcutActionListener;
  43. import com.vaadin.client.ui.SimpleManagedLayout;
  44. import com.vaadin.client.ui.VWindow;
  45. import com.vaadin.client.ui.layout.MayScrollChildren;
  46. import com.vaadin.shared.MouseEventDetails;
  47. import com.vaadin.shared.ui.Connect;
  48. import com.vaadin.shared.ui.window.WindowMode;
  49. import com.vaadin.shared.ui.window.WindowServerRpc;
  50. import com.vaadin.shared.ui.window.WindowState;
  51. @Connect(value = com.vaadin.ui.Window.class)
  52. public class WindowConnector extends AbstractSingleComponentContainerConnector
  53. implements Paintable, BeforeShortcutActionListener,
  54. SimpleManagedLayout, PostLayoutListener, MayScrollChildren,
  55. WindowMoveHandler {
  56. private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
  57. @Override
  58. protected void fireClick(NativeEvent event,
  59. MouseEventDetails mouseDetails) {
  60. getRpcProxy(WindowServerRpc.class).click(mouseDetails);
  61. }
  62. };
  63. abstract class WindowEventHandler implements ClickHandler,
  64. DoubleClickHandler {
  65. }
  66. private WindowEventHandler maximizeRestoreClickHandler = new WindowEventHandler() {
  67. @Override
  68. public void onClick(ClickEvent event) {
  69. final Element target = event.getNativeEvent().getEventTarget()
  70. .cast();
  71. if (target == getWidget().maximizeRestoreBox) {
  72. // Click on maximize/restore box
  73. onMaximizeRestore();
  74. }
  75. }
  76. @Override
  77. public void onDoubleClick(DoubleClickEvent event) {
  78. final Element target = event.getNativeEvent().getEventTarget()
  79. .cast();
  80. if (getWidget().header.isOrHasChild(target)) {
  81. // Double click on header
  82. onMaximizeRestore();
  83. }
  84. }
  85. };
  86. @Override
  87. public boolean delegateCaptionHandling() {
  88. return false;
  89. }
  90. @Override
  91. protected void init() {
  92. super.init();
  93. VWindow window = getWidget();
  94. window.id = getConnectorId();
  95. window.client = getConnection();
  96. getLayoutManager().registerDependency(this,
  97. window.contentPanel.getElement());
  98. getLayoutManager().registerDependency(this, window.header);
  99. getLayoutManager().registerDependency(this, window.footer);
  100. window.addHandler(maximizeRestoreClickHandler, ClickEvent.getType());
  101. window.addHandler(maximizeRestoreClickHandler,
  102. DoubleClickEvent.getType());
  103. window.setOwner(getConnection().getUIConnector().getWidget());
  104. window.addMoveHandler(this);
  105. }
  106. @Override
  107. public void onUnregister() {
  108. LayoutManager lm = getLayoutManager();
  109. VWindow window = getWidget();
  110. lm.unregisterDependency(this, window.contentPanel.getElement());
  111. lm.unregisterDependency(this, window.header);
  112. lm.unregisterDependency(this, window.footer);
  113. }
  114. @Override
  115. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  116. VWindow window = getWidget();
  117. String connectorId = getConnectorId();
  118. // Workaround needed for Testing Tools (GWT generates window DOM
  119. // slightly different in different browsers).
  120. window.closeBox.setId(connectorId + "_window_close");
  121. window.maximizeRestoreBox
  122. .setId(connectorId + "_window_maximizerestore");
  123. window.visibilityChangesDisabled = true;
  124. if (!isRealUpdate(uidl)) {
  125. return;
  126. }
  127. window.visibilityChangesDisabled = false;
  128. // we may have actions
  129. for (int i = 0; i < uidl.getChildCount(); i++) {
  130. UIDL childUidl = uidl.getChildUIDL(i);
  131. if (childUidl.getTag().equals("actions")) {
  132. if (window.shortcutHandler == null) {
  133. window.shortcutHandler = new ShortcutActionHandler(
  134. connectorId, client);
  135. }
  136. window.shortcutHandler.updateActionMap(childUidl);
  137. }
  138. }
  139. if (uidl.hasAttribute("bringToFront")) {
  140. /*
  141. * Focus as a side-effect. Will be overridden by
  142. * ApplicationConnection if another component was focused by the
  143. * server side.
  144. */
  145. window.contentPanel.focus();
  146. window.bringToFrontSequence = uidl.getIntAttribute("bringToFront");
  147. VWindow.deferOrdering();
  148. }
  149. }
  150. @Override
  151. public void updateCaption(ComponentConnector component) {
  152. // NOP, window has own caption, layout caption not rendered
  153. }
  154. @Override
  155. public void onBeforeShortcutAction(Event e) {
  156. // NOP, nothing to update just avoid workaround ( causes excess
  157. // blur/focus )
  158. }
  159. @Override
  160. public VWindow getWidget() {
  161. return (VWindow) super.getWidget();
  162. }
  163. @Override
  164. public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
  165. // We always have 1 child, unless the child is hidden
  166. getWidget().contentPanel.setWidget(getContentWidget());
  167. }
  168. @Override
  169. public void layout() {
  170. LayoutManager lm = getLayoutManager();
  171. VWindow window = getWidget();
  172. ComponentConnector content = getContent();
  173. boolean hasContent = (content != null);
  174. Element contentElement = window.contentPanel.getElement();
  175. Style contentStyle = window.contents.getStyle();
  176. int headerHeight = lm.getOuterHeight(window.header);
  177. contentStyle.setPaddingTop(headerHeight, Unit.PX);
  178. contentStyle.setMarginTop(-headerHeight, Unit.PX);
  179. int footerHeight = lm.getOuterHeight(window.footer);
  180. contentStyle.setPaddingBottom(footerHeight, Unit.PX);
  181. contentStyle.setMarginBottom(-footerHeight, Unit.PX);
  182. int minWidth = lm.getOuterWidth(window.header)
  183. - lm.getInnerWidth(window.header);
  184. int minHeight = footerHeight + headerHeight;
  185. getWidget().getElement().getStyle().setPropertyPx("minWidth", minWidth);
  186. getWidget().getElement().getStyle()
  187. .setPropertyPx("minHeight", minHeight);
  188. /*
  189. * Must set absolute position if the child has relative height and
  190. * there's a chance of horizontal scrolling as some browsers will
  191. * otherwise not take the scrollbar into account when calculating the
  192. * height.
  193. */
  194. if (hasContent) {
  195. Element layoutElement = content.getWidget().getElement();
  196. Style childStyle = layoutElement.getStyle();
  197. // IE8 needs some hackery to measure its content correctly
  198. Util.forceIE8Redraw(layoutElement);
  199. if (content.isRelativeHeight() && !BrowserInfo.get().isIE9()) {
  200. childStyle.setPosition(Position.ABSOLUTE);
  201. Style wrapperStyle = contentElement.getStyle();
  202. if (window.getElement().getStyle().getWidth().length() == 0
  203. && !content.isRelativeWidth()) {
  204. /*
  205. * Need to lock width to make undefined width work even with
  206. * absolute positioning
  207. */
  208. int contentWidth = lm.getOuterWidth(layoutElement);
  209. wrapperStyle.setWidth(contentWidth, Unit.PX);
  210. } else {
  211. wrapperStyle.clearWidth();
  212. }
  213. } else {
  214. childStyle.clearPosition();
  215. }
  216. }
  217. }
  218. @Override
  219. public void postLayout() {
  220. VWindow window = getWidget();
  221. if (window.centered && getState().windowMode != WindowMode.MAXIMIZED) {
  222. window.center();
  223. }
  224. window.positionOrSizeUpdated();
  225. }
  226. @Override
  227. public WindowState getState() {
  228. return (WindowState) super.getState();
  229. }
  230. @Override
  231. public void onStateChanged(StateChangeEvent stateChangeEvent) {
  232. super.onStateChanged(stateChangeEvent);
  233. VWindow window = getWidget();
  234. WindowState state = getState();
  235. if (state.modal != window.vaadinModality) {
  236. window.setVaadinModality(!window.vaadinModality);
  237. }
  238. if (!window.isAttached()) {
  239. window.setVisible(false); // hide until possible centering
  240. window.show();
  241. }
  242. boolean resizeable = state.resizable
  243. && state.windowMode == WindowMode.NORMAL;
  244. window.setResizable(resizeable);
  245. window.resizeLazy = state.resizeLazy;
  246. window.setDraggable(state.draggable
  247. && state.windowMode == WindowMode.NORMAL);
  248. window.updateMaximizeRestoreClassName(state.resizable, state.windowMode);
  249. // Caption must be set before required header size is measured. If
  250. // the caption attribute is missing the caption should be cleared.
  251. String iconURL = null;
  252. if (getIconUri() != null) {
  253. iconURL = getIconUri();
  254. }
  255. window.setAssistivePrefix(state.assistivePrefix);
  256. window.setAssistivePostfix(state.assistivePostfix);
  257. window.setCaption(state.caption, iconURL);
  258. window.setWaiAriaRole(getState().role);
  259. window.setAssistiveDescription(state.contentDescription);
  260. window.setTabStopEnabled(getState().assistiveTabStop);
  261. window.setTabStopTopAssistiveText(getState().assistiveTabStopTopText);
  262. window.setTabStopBottomAssistiveText(getState().assistiveTabStopBottomText);
  263. clickEventHandler.handleEventHandlerRegistration();
  264. window.immediate = state.immediate;
  265. window.setClosable(!isReadOnly());
  266. // initialize position from state
  267. updateWindowPosition();
  268. // setting scrollposition must happen after children is rendered
  269. window.contentPanel.setScrollPosition(state.scrollTop);
  270. window.contentPanel.setHorizontalScrollPosition(state.scrollLeft);
  271. // Center this window on screen if requested
  272. // This had to be here because we might not know the content size before
  273. // everything is painted into the window
  274. // centered is this is unset on move/resize
  275. window.centered = state.centered;
  276. window.setVisible(true);
  277. // ensure window is not larger than browser window
  278. if (window.getOffsetWidth() > Window.getClientWidth()) {
  279. window.setWidth(Window.getClientWidth() + "px");
  280. }
  281. if (window.getOffsetHeight() > Window.getClientHeight()) {
  282. window.setHeight(Window.getClientHeight() + "px");
  283. }
  284. }
  285. // Need to override default because of window mode
  286. @Override
  287. protected void updateComponentSize() {
  288. if (getState().windowMode == WindowMode.NORMAL) {
  289. super.updateComponentSize();
  290. } else if (getState().windowMode == WindowMode.MAXIMIZED) {
  291. super.updateComponentSize("100%", "100%");
  292. }
  293. }
  294. protected void updateWindowPosition() {
  295. VWindow window = getWidget();
  296. WindowState state = getState();
  297. if (state.windowMode == WindowMode.NORMAL) {
  298. // if centered, position handled in postLayout()
  299. if (!state.centered
  300. && (state.positionX >= 0 || state.positionY >= 0)) {
  301. // If both positions are negative, then
  302. // setWindowOrderAndPosition has already taken care of
  303. // positioning the window so it stacks with other windows
  304. window.setPopupPosition(state.positionX, state.positionY);
  305. }
  306. } else if (state.windowMode == WindowMode.MAXIMIZED) {
  307. window.setPopupPositionNoUpdate(0, 0);
  308. window.bringToFront();
  309. }
  310. }
  311. protected void updateWindowMode() {
  312. VWindow window = getWidget();
  313. WindowState state = getState();
  314. // update draggable on widget
  315. window.setDraggable(state.draggable
  316. && state.windowMode == WindowMode.NORMAL);
  317. // update resizable on widget
  318. window.setResizable(state.resizable
  319. && state.windowMode == WindowMode.NORMAL);
  320. updateComponentSize();
  321. updateWindowPosition();
  322. window.updateMaximizeRestoreClassName(state.resizable, state.windowMode);
  323. window.updateContentsSize();
  324. }
  325. protected void onMaximizeRestore() {
  326. WindowState state = getState();
  327. if (state.resizable) {
  328. if (state.windowMode == WindowMode.MAXIMIZED) {
  329. state.windowMode = WindowMode.NORMAL;
  330. } else {
  331. state.windowMode = WindowMode.MAXIMIZED;
  332. }
  333. updateWindowMode();
  334. getRpcProxy(WindowServerRpc.class).windowModeChanged(
  335. state.windowMode);
  336. }
  337. }
  338. /**
  339. * Gives the WindowConnector an order number. As a side effect, moves the
  340. * window according to its order number so the windows are stacked. This
  341. * method should be called for each window in the order they should appear.
  342. */
  343. public void setWindowOrderAndPosition() {
  344. getWidget().setWindowOrderAndPosition();
  345. }
  346. @Override
  347. public boolean hasTooltip() {
  348. /*
  349. * Tooltip event handler always needed on the window widget to make sure
  350. * tooltips are properly hidden. (#11448)
  351. */
  352. return true;
  353. }
  354. @Override
  355. public void onWindowMove(WindowMoveEvent event) {
  356. RpcProxy.create(WindowServerRpc.class, this).windowMoved(
  357. event.getNewX(), event.getNewY());
  358. }
  359. }