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.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright 2000-2018 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. VPanel panel = getWidget();
  77. if (isRealUpdate(uidl)) {
  78. // Handle caption displaying and style names, prior generics.
  79. // Affects size calculations
  80. // Restore default stylenames
  81. panel.contentNode.setClassName(VPanel.CLASSNAME + "-content");
  82. panel.bottomDecoration.setClassName(VPanel.CLASSNAME + "-deco");
  83. panel.captionNode.setClassName(VPanel.CLASSNAME + "-caption");
  84. boolean hasCaption = hasCaption();
  85. if (hasCaption) {
  86. panel.setCaption(getState().caption,getState().captionAsHtml);
  87. } else {
  88. panel.setCaption("",false);
  89. panel.captionNode.setClassName(VPanel.CLASSNAME + "-nocaption");
  90. }
  91. // Add proper stylenames for all elements. This way we can prevent
  92. // unwanted CSS selector inheritance.
  93. final String captionBaseClass = VPanel.CLASSNAME
  94. + (hasCaption ? "-caption" : "-nocaption");
  95. final String contentBaseClass = VPanel.CLASSNAME + "-content";
  96. final String decoBaseClass = VPanel.CLASSNAME + "-deco";
  97. String captionClass = captionBaseClass;
  98. String contentClass = contentBaseClass;
  99. String decoClass = decoBaseClass;
  100. if (ComponentStateUtil.hasStyles(getState())) {
  101. for (String style : getState().styles) {
  102. captionClass += " " + captionBaseClass + "-" + style;
  103. contentClass += " " + contentBaseClass + "-" + style;
  104. decoClass += " " + decoBaseClass + "-" + style;
  105. }
  106. }
  107. panel.captionNode.setClassName(captionClass);
  108. panel.contentNode.setClassName(contentClass);
  109. panel.bottomDecoration.setClassName(decoClass);
  110. panel.makeScrollable();
  111. }
  112. if (!isRealUpdate(uidl)) {
  113. return;
  114. }
  115. clickEventHandler.handleEventHandlerRegistration();
  116. panel.client = client;
  117. panel.id = uidl.getId();
  118. if (getIconUri() != null) {
  119. panel.setIconUri(getIconUri(), client);
  120. } else {
  121. panel.setIconUri(null, client);
  122. }
  123. // We may have actions attached to this panel
  124. if (uidl.getChildCount() > 0) {
  125. final int cnt = uidl.getChildCount();
  126. for (int i = 0; i < cnt; i++) {
  127. UIDL childUidl = uidl.getChildUIDL(i);
  128. if (childUidl.getTag().equals("actions")) {
  129. if (panel.shortcutHandler == null) {
  130. panel.shortcutHandler = new ShortcutActionHandler(
  131. getConnectorId(), client);
  132. }
  133. panel.shortcutHandler.updateActionMap(childUidl);
  134. }
  135. }
  136. }
  137. if (getState().scrollTop != panel.scrollTop) {
  138. // Sizes are not yet up to date, so changing the scroll position
  139. // is deferred to after the layout phase
  140. uidlScrollTop = getState().scrollTop;
  141. }
  142. if (getState().scrollLeft != panel.scrollLeft) {
  143. // Sizes are not yet up to date, so changing the scroll position
  144. // is deferred to after the layout phase
  145. uidlScrollLeft = getState().scrollLeft;
  146. }
  147. // And apply tab index
  148. panel.contentNode.setTabIndex(getState().tabIndex);
  149. }
  150. /**
  151. * Detects if caption div should be visible.
  152. *
  153. * @return {@code true} if caption div should be shown
  154. */
  155. protected boolean hasCaption() {
  156. return getState().caption != null && !getState().caption.isEmpty();
  157. }
  158. @Override
  159. public void updateCaption(ComponentConnector component) {
  160. // NOP: layouts caption, errors etc not rendered in Panel
  161. }
  162. @Override
  163. public VPanel getWidget() {
  164. return (VPanel) super.getWidget();
  165. }
  166. @Override
  167. public void layout() {
  168. updateSizes();
  169. }
  170. void updateSizes() {
  171. VPanel panel = getWidget();
  172. LayoutManager layoutManager = getLayoutManager();
  173. Profiler.enter("PanelConnector.layout getHeights");
  174. int top = layoutManager.getOuterHeight(panel.captionNode);
  175. int bottom = layoutManager.getInnerHeight(panel.bottomDecoration);
  176. Profiler.leave("PanelConnector.layout getHeights");
  177. Profiler.enter("PanelConnector.layout modify style");
  178. Style style = panel.getElement().getStyle();
  179. panel.captionNode.getParentElement().getStyle().setMarginTop(-top,
  180. Unit.PX);
  181. panel.bottomDecoration.getStyle().setMarginBottom(-bottom, Unit.PX);
  182. style.setPaddingTop(top, Unit.PX);
  183. style.setPaddingBottom(bottom, Unit.PX);
  184. Profiler.leave("PanelConnector.layout modify style");
  185. // Update scroll positions
  186. Profiler.enter("PanelConnector.layout update scroll positions");
  187. panel.contentNode.setScrollTop(panel.scrollTop);
  188. panel.contentNode.setScrollLeft(panel.scrollLeft);
  189. Profiler.leave("PanelConnector.layout update scroll positions");
  190. // Read actual value back to ensure update logic is correct
  191. Profiler.enter("PanelConnector.layout read scroll positions");
  192. panel.scrollTop = panel.contentNode.getScrollTop();
  193. panel.scrollLeft = panel.contentNode.getScrollLeft();
  194. Profiler.leave("PanelConnector.layout read scroll positions");
  195. }
  196. @Override
  197. public void postLayout() {
  198. VPanel panel = getWidget();
  199. if (uidlScrollTop != null) {
  200. // IE / Safari fix for when scroll top is set to greater than panel
  201. // height
  202. int maxScroll = panel.getWidget().getOffsetHeight();
  203. if (uidlScrollTop > maxScroll) {
  204. uidlScrollTop = maxScroll;
  205. }
  206. panel.contentNode.setScrollTop(uidlScrollTop.intValue());
  207. // Read actual value back to ensure update logic is correct
  208. // TODO Does this trigger reflows?
  209. panel.scrollTop = panel.contentNode.getScrollTop();
  210. uidlScrollTop = null;
  211. }
  212. if (uidlScrollLeft != null) {
  213. panel.contentNode.setScrollLeft(uidlScrollLeft.intValue());
  214. // Read actual value back to ensure update logic is correct
  215. // TODO Does this trigger reflows?
  216. panel.scrollLeft = panel.contentNode.getScrollLeft();
  217. uidlScrollLeft = null;
  218. }
  219. }
  220. @Override
  221. public PanelState getState() {
  222. return (PanelState) super.getState();
  223. }
  224. @Override
  225. public void onConnectorHierarchyChange(
  226. ConnectorHierarchyChangeEvent event) {
  227. // We always have 1 child, unless the child is hidden
  228. getWidget().setWidget(getContentWidget());
  229. }
  230. }