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.

PanelConnector.java 9.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * Copyright 2000-2016 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.panel;
  17. import com.google.gwt.dom.client.NativeEvent;
  18. import com.google.gwt.dom.client.Style;
  19. import com.google.gwt.dom.client.Style.Unit;
  20. import com.vaadin.client.ApplicationConnection;
  21. import com.vaadin.client.ComponentConnector;
  22. import com.vaadin.client.ConnectorHierarchyChangeEvent;
  23. import com.vaadin.client.LayoutManager;
  24. import com.vaadin.client.Paintable;
  25. import com.vaadin.client.Profiler;
  26. import com.vaadin.client.UIDL;
  27. import com.vaadin.client.ui.AbstractSingleComponentContainerConnector;
  28. import com.vaadin.client.ui.ClickEventHandler;
  29. import com.vaadin.client.ui.PostLayoutListener;
  30. import com.vaadin.client.ui.ShortcutActionHandler;
  31. import com.vaadin.client.ui.SimpleManagedLayout;
  32. import com.vaadin.client.ui.VPanel;
  33. import com.vaadin.client.ui.layout.MayScrollChildren;
  34. import com.vaadin.shared.MouseEventDetails;
  35. import com.vaadin.shared.ui.ComponentStateUtil;
  36. import com.vaadin.shared.ui.Connect;
  37. import com.vaadin.shared.ui.panel.PanelServerRpc;
  38. import com.vaadin.shared.ui.panel.PanelState;
  39. import com.vaadin.ui.Panel;
  40. @Connect(Panel.class)
  41. public class PanelConnector extends AbstractSingleComponentContainerConnector
  42. implements Paintable, SimpleManagedLayout, PostLayoutListener,
  43. MayScrollChildren {
  44. private Integer uidlScrollTop;
  45. private ClickEventHandler clickEventHandler = new ClickEventHandler(this) {
  46. @Override
  47. protected void fireClick(NativeEvent event,
  48. MouseEventDetails mouseDetails) {
  49. getRpcProxy(PanelServerRpc.class).click(mouseDetails);
  50. }
  51. };
  52. private Integer uidlScrollLeft;
  53. @Override
  54. public void init() {
  55. super.init();
  56. VPanel panel = getWidget();
  57. LayoutManager layoutManager = getLayoutManager();
  58. layoutManager.registerDependency(this, panel.captionNode);
  59. layoutManager.registerDependency(this, panel.bottomDecoration);
  60. layoutManager.registerDependency(this, panel.contentNode);
  61. }
  62. @Override
  63. public void onUnregister() {
  64. VPanel panel = getWidget();
  65. LayoutManager layoutManager = getLayoutManager();
  66. layoutManager.unregisterDependency(this, panel.captionNode);
  67. layoutManager.unregisterDependency(this, panel.bottomDecoration);
  68. layoutManager.unregisterDependency(this, panel.contentNode);
  69. }
  70. @Override
  71. public boolean delegateCaptionHandling() {
  72. return false;
  73. }
  74. @Override
  75. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  76. if (isRealUpdate(uidl)) {
  77. // Handle caption displaying and style names, prior generics.
  78. // Affects size calculations
  79. // Restore default stylenames
  80. getWidget().contentNode.setClassName(VPanel.CLASSNAME + "-content");
  81. getWidget().bottomDecoration
  82. .setClassName(VPanel.CLASSNAME + "-deco");
  83. getWidget().captionNode.setClassName(VPanel.CLASSNAME + "-caption");
  84. boolean hasCaption = false;
  85. if (getState().caption != null && !getState().caption.isEmpty()) {
  86. getWidget().setCaption(getState().caption);
  87. hasCaption = true;
  88. } else {
  89. getWidget().setCaption("");
  90. getWidget().captionNode
  91. .setClassName(VPanel.CLASSNAME + "-nocaption");
  92. }
  93. // Add proper stylenames for all elements. This way we can prevent
  94. // unwanted CSS selector inheritance.
  95. final String captionBaseClass = VPanel.CLASSNAME
  96. + (hasCaption ? "-caption" : "-nocaption");
  97. final String contentBaseClass = VPanel.CLASSNAME + "-content";
  98. final String decoBaseClass = VPanel.CLASSNAME + "-deco";
  99. String captionClass = captionBaseClass;
  100. String contentClass = contentBaseClass;
  101. String decoClass = decoBaseClass;
  102. if (ComponentStateUtil.hasStyles(getState())) {
  103. for (String style : getState().styles) {
  104. captionClass += " " + captionBaseClass + "-" + style;
  105. contentClass += " " + contentBaseClass + "-" + style;
  106. decoClass += " " + decoBaseClass + "-" + style;
  107. }
  108. }
  109. getWidget().captionNode.setClassName(captionClass);
  110. getWidget().contentNode.setClassName(contentClass);
  111. getWidget().bottomDecoration.setClassName(decoClass);
  112. getWidget().makeScrollable();
  113. }
  114. if (!isRealUpdate(uidl)) {
  115. return;
  116. }
  117. clickEventHandler.handleEventHandlerRegistration();
  118. getWidget().client = client;
  119. getWidget().id = uidl.getId();
  120. if (getIconUri() != null) {
  121. getWidget().setIconUri(getIconUri(), client);
  122. } else {
  123. getWidget().setIconUri(null, client);
  124. }
  125. // We may have actions attached to this panel
  126. if (uidl.getChildCount() > 0) {
  127. final int cnt = uidl.getChildCount();
  128. for (int i = 0; i < cnt; i++) {
  129. UIDL childUidl = uidl.getChildUIDL(i);
  130. if (childUidl.getTag().equals("actions")) {
  131. if (getWidget().shortcutHandler == null) {
  132. getWidget().shortcutHandler = new ShortcutActionHandler(
  133. getConnectorId(), client);
  134. }
  135. getWidget().shortcutHandler.updateActionMap(childUidl);
  136. }
  137. }
  138. }
  139. if (getState().scrollTop != getWidget().scrollTop) {
  140. // Sizes are not yet up to date, so changing the scroll position
  141. // is deferred to after the layout phase
  142. uidlScrollTop = getState().scrollTop;
  143. }
  144. if (getState().scrollLeft != getWidget().scrollLeft) {
  145. // Sizes are not yet up to date, so changing the scroll position
  146. // is deferred to after the layout phase
  147. uidlScrollLeft = getState().scrollLeft;
  148. }
  149. // And apply tab index
  150. getWidget().contentNode.setTabIndex(getState().tabIndex);
  151. }
  152. @Override
  153. public void updateCaption(ComponentConnector component) {
  154. // NOP: layouts caption, errors etc not rendered in Panel
  155. }
  156. @Override
  157. public VPanel getWidget() {
  158. return (VPanel) super.getWidget();
  159. }
  160. @Override
  161. public void layout() {
  162. updateSizes();
  163. }
  164. void updateSizes() {
  165. VPanel panel = getWidget();
  166. LayoutManager layoutManager = getLayoutManager();
  167. Profiler.enter("PanelConnector.layout getHeights");
  168. int top = layoutManager.getOuterHeight(panel.captionNode);
  169. int bottom = layoutManager.getInnerHeight(panel.bottomDecoration);
  170. Profiler.leave("PanelConnector.layout getHeights");
  171. Profiler.enter("PanelConnector.layout modify style");
  172. Style style = panel.getElement().getStyle();
  173. panel.captionNode.getParentElement().getStyle().setMarginTop(-top,
  174. Unit.PX);
  175. panel.bottomDecoration.getStyle().setMarginBottom(-bottom, Unit.PX);
  176. style.setPaddingTop(top, Unit.PX);
  177. style.setPaddingBottom(bottom, Unit.PX);
  178. Profiler.leave("PanelConnector.layout modify style");
  179. // Update scroll positions
  180. Profiler.enter("PanelConnector.layout update scroll positions");
  181. panel.contentNode.setScrollTop(panel.scrollTop);
  182. panel.contentNode.setScrollLeft(panel.scrollLeft);
  183. Profiler.leave("PanelConnector.layout update scroll positions");
  184. // Read actual value back to ensure update logic is correct
  185. Profiler.enter("PanelConnector.layout read scroll positions");
  186. panel.scrollTop = panel.contentNode.getScrollTop();
  187. panel.scrollLeft = panel.contentNode.getScrollLeft();
  188. Profiler.leave("PanelConnector.layout read scroll positions");
  189. }
  190. @Override
  191. public void postLayout() {
  192. VPanel panel = getWidget();
  193. if (uidlScrollTop != null) {
  194. // IE / Safari fix for when scroll top is set to greater than panel
  195. // height
  196. int maxScroll = panel.getWidget().getOffsetHeight();
  197. if (uidlScrollTop > maxScroll) {
  198. uidlScrollTop = maxScroll;
  199. }
  200. panel.contentNode.setScrollTop(uidlScrollTop.intValue());
  201. // Read actual value back to ensure update logic is correct
  202. // TODO Does this trigger reflows?
  203. panel.scrollTop = panel.contentNode.getScrollTop();
  204. uidlScrollTop = null;
  205. }
  206. if (uidlScrollLeft != null) {
  207. panel.contentNode.setScrollLeft(uidlScrollLeft.intValue());
  208. // Read actual value back to ensure update logic is correct
  209. // TODO Does this trigger reflows?
  210. panel.scrollLeft = panel.contentNode.getScrollLeft();
  211. uidlScrollLeft = null;
  212. }
  213. }
  214. @Override
  215. public PanelState getState() {
  216. return (PanelState) super.getState();
  217. }
  218. @Override
  219. public void onConnectorHierarchyChange(
  220. ConnectorHierarchyChangeEvent event) {
  221. // We always have 1 child, unless the child is hidden
  222. getWidget().setWidget(getContentWidget());
  223. }
  224. }