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.

VWindowPaintable.java 12KB

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