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.

VMeasuringOrderedLayoutPaintable.java 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.HashSet;
  6. import java.util.Iterator;
  7. import com.google.gwt.dom.client.Node;
  8. import com.google.gwt.dom.client.Style;
  9. import com.google.gwt.user.client.Element;
  10. import com.google.gwt.user.client.ui.Widget;
  11. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  12. import com.vaadin.terminal.gwt.client.DirectionalManagedLayout;
  13. import com.vaadin.terminal.gwt.client.LayoutManager;
  14. import com.vaadin.terminal.gwt.client.UIDL;
  15. import com.vaadin.terminal.gwt.client.VCaption;
  16. import com.vaadin.terminal.gwt.client.ConnectorMap;
  17. import com.vaadin.terminal.gwt.client.ComponentConnector;
  18. import com.vaadin.terminal.gwt.client.ValueMap;
  19. import com.vaadin.terminal.gwt.client.ui.layout.VLayoutSlot;
  20. import com.vaadin.terminal.gwt.client.ui.layout.VPaintableLayoutSlot;
  21. public abstract class VMeasuringOrderedLayoutPaintable extends
  22. AbstractComponentContainerConnector implements DirectionalManagedLayout {
  23. @Override
  24. public void init() {
  25. getLayoutManager().registerDependency(this,
  26. getWidget().spacingMeasureElement);
  27. }
  28. public void updateCaption(ComponentConnector component, UIDL uidl) {
  29. VMeasuringOrderedLayout layout = getWidget();
  30. if (VCaption.isNeeded(uidl, component.getState())) {
  31. VLayoutSlot layoutSlot = layout.getSlotForChild(component
  32. .getWidget());
  33. VCaption caption = layoutSlot.getCaption();
  34. if (caption == null) {
  35. caption = new VCaption(component, getConnection());
  36. Widget widget = component.getWidget();
  37. layout.setCaption(widget, caption);
  38. }
  39. caption.updateCaption(uidl);
  40. } else {
  41. layout.setCaption(component.getWidget(), null);
  42. }
  43. }
  44. @Override
  45. public VMeasuringOrderedLayout getWidget() {
  46. return (VMeasuringOrderedLayout) super.getWidget();
  47. }
  48. @Override
  49. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  50. super.updateFromUIDL(uidl, client);
  51. if (!isRealUpdate(uidl)) {
  52. return;
  53. }
  54. HashSet<ComponentConnector> previousChildren = new HashSet<ComponentConnector>(
  55. getChildren());
  56. VMeasuringOrderedLayout layout = getWidget();
  57. ValueMap expandRatios = uidl.getMapAttribute("expandRatios");
  58. ValueMap alignments = uidl.getMapAttribute("alignments");
  59. int currentIndex = 0;
  60. // TODO Support reordering elements!
  61. for (final Iterator<Object> it = uidl.getChildIterator(); it.hasNext();) {
  62. final UIDL childUIDL = (UIDL) it.next();
  63. final ComponentConnector child = client.getPaintable(childUIDL);
  64. Widget widget = child.getWidget();
  65. VLayoutSlot slot = layout.getSlotForChild(widget);
  66. if (widget.getParent() != layout) {
  67. slot = new VPaintableLayoutSlot(getWidget()
  68. .getStylePrimaryName(), child);
  69. }
  70. layout.addOrMove(slot, currentIndex++);
  71. String pid = child.getId();
  72. AlignmentInfo alignment;
  73. if (alignments.containsKey(pid)) {
  74. alignment = new AlignmentInfo(alignments.getInt(pid));
  75. } else {
  76. alignment = AlignmentInfo.TOP_LEFT;
  77. }
  78. slot.setAlignment(alignment);
  79. double expandRatio;
  80. if (expandRatios.containsKey(pid)) {
  81. expandRatio = expandRatios.getRawNumber(pid);
  82. } else {
  83. expandRatio = 0;
  84. }
  85. slot.setExpandRatio(expandRatio);
  86. if (!childUIDL.getBooleanAttribute("cached")) {
  87. child.updateFromUIDL(childUIDL, client);
  88. }
  89. previousChildren.remove(child);
  90. }
  91. for (ComponentConnector child : previousChildren) {
  92. Widget widget = child.getWidget();
  93. // Don't remove and unregister if it has been moved to a different
  94. // parent. Slot element will be left behind, but that is taken care
  95. // of later
  96. if (widget.getParent() == getWidget()) {
  97. layout.removeSlot(layout.getSlotForChild(widget));
  98. ConnectorMap vPaintableMap = ConnectorMap.get(client);
  99. vPaintableMap.unregisterConnector(child);
  100. }
  101. }
  102. // Remove empty layout slots left behind after children have moved to
  103. // other paintables
  104. while (true) {
  105. int childCount = layout.getElement().getChildCount();
  106. if (childCount <= 1) {
  107. // Stop if no more slots (spacing element is always present)
  108. break;
  109. }
  110. Node lastSlot = layout.getElement().getChild(childCount - 2);
  111. if (lastSlot.getChildCount() == 0) {
  112. // Remove if empty
  113. lastSlot.removeFromParent();
  114. } else {
  115. // Stop searching when last slot is not empty
  116. break;
  117. }
  118. }
  119. int bitMask = uidl.getIntAttribute("margins");
  120. layout.updateMarginStyleNames(new VMarginInfo(bitMask));
  121. layout.updateSpacingStyleName(uidl.getBooleanAttribute("spacing"));
  122. getLayoutManager().setNeedsUpdate(this);
  123. }
  124. private int getSizeForInnerSize(int size, boolean isVertical) {
  125. LayoutManager layoutManager = getLayoutManager();
  126. Element element = getWidget().getElement();
  127. if (isVertical) {
  128. return size + layoutManager.getBorderHeight(element)
  129. + layoutManager.getPaddingHeight(element);
  130. } else {
  131. return size + layoutManager.getBorderWidth(element)
  132. + layoutManager.getPaddingWidth(element);
  133. }
  134. }
  135. private static String getSizeProperty(boolean isVertical) {
  136. return isVertical ? "height" : "width";
  137. }
  138. private boolean isUndefinedInDirection(boolean isVertical) {
  139. if (isVertical) {
  140. return isUndefinedHeight();
  141. } else {
  142. return isUndefinedWidth();
  143. }
  144. }
  145. private int getInnerSizeInDirection(boolean isVertical) {
  146. if (isVertical) {
  147. return getLayoutManager().getInnerHeight(
  148. getWidget().getElement());
  149. } else {
  150. return getLayoutManager().getInnerWidth(
  151. getWidget().getElement());
  152. }
  153. }
  154. private void layoutPrimaryDirection() {
  155. VMeasuringOrderedLayout layout = getWidget();
  156. boolean isVertical = layout.isVertical;
  157. boolean isUndefined = isUndefinedInDirection(isVertical);
  158. int startPadding = getStartPadding(isVertical);
  159. int spacingSize = getSpacingInDirection(isVertical);
  160. int allocatedSize;
  161. if (isUndefined) {
  162. allocatedSize = -1;
  163. } else {
  164. allocatedSize = getInnerSizeInDirection(isVertical);
  165. }
  166. allocatedSize = layout.layoutPrimaryDirection(spacingSize,
  167. allocatedSize, startPadding);
  168. Style ownStyle = getWidget().getElement().getStyle();
  169. if (isUndefined) {
  170. ownStyle.setPropertyPx(getSizeProperty(isVertical),
  171. getSizeForInnerSize(allocatedSize, isVertical));
  172. } else {
  173. ownStyle.setProperty(getSizeProperty(isVertical),
  174. getDefinedSize(isVertical));
  175. }
  176. }
  177. private int getSpacingInDirection(boolean isVertical) {
  178. if (isVertical) {
  179. return getLayoutManager().getOuterHeight(
  180. getWidget().spacingMeasureElement);
  181. } else {
  182. return getLayoutManager().getOuterWidth(
  183. getWidget().spacingMeasureElement);
  184. }
  185. }
  186. private void layoutSecondaryDirection() {
  187. VMeasuringOrderedLayout layout = getWidget();
  188. boolean isVertical = layout.isVertical;
  189. boolean isUndefined = isUndefinedInDirection(!isVertical);
  190. int startPadding = getStartPadding(!isVertical);
  191. int allocatedSize;
  192. if (isUndefined) {
  193. allocatedSize = -1;
  194. } else {
  195. allocatedSize = getInnerSizeInDirection(!isVertical);
  196. }
  197. allocatedSize = layout.layoutSecondaryDirection(allocatedSize,
  198. startPadding);
  199. Style ownStyle = getWidget().getElement().getStyle();
  200. if (isUndefined) {
  201. ownStyle.setPropertyPx(
  202. getSizeProperty(!getWidget().isVertical),
  203. getSizeForInnerSize(allocatedSize,
  204. !getWidget().isVertical));
  205. } else {
  206. ownStyle.setProperty(
  207. getSizeProperty(!getWidget().isVertical),
  208. getDefinedSize(!getWidget().isVertical));
  209. }
  210. }
  211. private String getDefinedSize(boolean isVertical) {
  212. if (isVertical) {
  213. return getDeclaredHeight();
  214. } else {
  215. return getDeclaredWidth();
  216. }
  217. }
  218. private int getStartPadding(boolean isVertical) {
  219. if (isVertical) {
  220. return getLayoutManager().getPaddingTop(
  221. getWidget().getElement());
  222. } else {
  223. return getLayoutManager().getPaddingLeft(
  224. getWidget().getElement());
  225. }
  226. }
  227. public void layoutHorizontally() {
  228. if (getWidget().isVertical) {
  229. layoutSecondaryDirection();
  230. } else {
  231. layoutPrimaryDirection();
  232. }
  233. }
  234. public void layoutVertically() {
  235. if (getWidget().isVertical) {
  236. layoutPrimaryDirection();
  237. } else {
  238. layoutSecondaryDirection();
  239. }
  240. }
  241. }