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.

AbstractOrderedLayoutConnector.java 9.7KB

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