Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

VAbsoluteLayout.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.HashMap;
  6. import java.util.Iterator;
  7. import java.util.Map;
  8. import java.util.Map.Entry;
  9. import java.util.Set;
  10. import com.google.gwt.dom.client.DivElement;
  11. import com.google.gwt.dom.client.Document;
  12. import com.google.gwt.dom.client.Style;
  13. import com.google.gwt.user.client.DOM;
  14. import com.google.gwt.user.client.Element;
  15. import com.google.gwt.user.client.ui.ComplexPanel;
  16. import com.google.gwt.user.client.ui.SimplePanel;
  17. import com.google.gwt.user.client.ui.Widget;
  18. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  19. import com.vaadin.terminal.gwt.client.Container;
  20. import com.vaadin.terminal.gwt.client.RenderSpace;
  21. import com.vaadin.terminal.gwt.client.UIDL;
  22. import com.vaadin.terminal.gwt.client.Util;
  23. import com.vaadin.terminal.gwt.client.VCaption;
  24. import com.vaadin.terminal.gwt.client.VPaintableMap;
  25. import com.vaadin.terminal.gwt.client.VPaintableWidget;
  26. public class VAbsoluteLayout extends ComplexPanel implements Container {
  27. /** Tag name for widget creation */
  28. public static final String TAGNAME = "absolutelayout";
  29. /** Class name, prefix in styling */
  30. public static final String CLASSNAME = "v-absolutelayout";
  31. private DivElement marginElement;
  32. protected final Element canvas = DOM.createDiv();
  33. // private int excessPixelsHorizontal;
  34. //
  35. // private int excessPixelsVertical;
  36. private Object previousStyleName;
  37. Map<String, AbsoluteWrapper> pidToComponentWrappper = new HashMap<String, AbsoluteWrapper>();
  38. protected ApplicationConnection client;
  39. boolean rendering;
  40. public VAbsoluteLayout() {
  41. setElement(Document.get().createDivElement());
  42. setStyleName(CLASSNAME);
  43. marginElement = Document.get().createDivElement();
  44. canvas.getStyle().setProperty("position", "relative");
  45. canvas.getStyle().setProperty("overflow", "hidden");
  46. marginElement.appendChild(canvas);
  47. getElement().appendChild(marginElement);
  48. }
  49. public RenderSpace getAllocatedSpace(Widget child) {
  50. // TODO needs some special handling for components with only on edge
  51. // horizontally or vertically defined
  52. AbsoluteWrapper wrapper = (AbsoluteWrapper) child.getParent();
  53. int w;
  54. if (wrapper.left != null && wrapper.right != null) {
  55. w = wrapper.getOffsetWidth();
  56. } else if (wrapper.right != null) {
  57. // left == null
  58. // available width == right edge == offsetleft + width
  59. w = wrapper.getOffsetWidth() + wrapper.getElement().getOffsetLeft();
  60. } else {
  61. // left != null && right == null || left == null &&
  62. // right == null
  63. // available width == canvas width - offset left
  64. w = canvas.getOffsetWidth() - wrapper.getElement().getOffsetLeft();
  65. }
  66. int h;
  67. if (wrapper.top != null && wrapper.bottom != null) {
  68. h = wrapper.getOffsetHeight();
  69. } else if (wrapper.bottom != null) {
  70. // top not defined, available space 0... bottom of wrapper
  71. h = wrapper.getElement().getOffsetTop() + wrapper.getOffsetHeight();
  72. } else {
  73. // top defined or both undefined, available space == canvas - top
  74. h = canvas.getOffsetHeight() - wrapper.getElement().getOffsetTop();
  75. }
  76. return new RenderSpace(w, h);
  77. }
  78. public boolean hasChildComponent(Widget component) {
  79. for (Iterator<Entry<String, AbsoluteWrapper>> iterator = pidToComponentWrappper
  80. .entrySet().iterator(); iterator.hasNext();) {
  81. if (iterator.next().getValue().paintable == component) {
  82. return true;
  83. }
  84. }
  85. return false;
  86. }
  87. public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
  88. for (Widget wrapper : getChildren()) {
  89. AbsoluteWrapper w = (AbsoluteWrapper) wrapper;
  90. if (w.getWidget() == oldComponent) {
  91. w.setWidget(newComponent);
  92. return;
  93. }
  94. }
  95. }
  96. public boolean requestLayout(Set<Widget> children) {
  97. // component inside an absolute panel never affects parent nor the
  98. // layout
  99. return true;
  100. }
  101. AbsoluteWrapper getWrapper(ApplicationConnection client, UIDL componentUIDL) {
  102. AbsoluteWrapper wrapper = pidToComponentWrappper.get(componentUIDL
  103. .getId());
  104. if (wrapper == null) {
  105. wrapper = new AbsoluteWrapper(client.getPaintable(componentUIDL));
  106. pidToComponentWrappper.put(componentUIDL.getId(), wrapper);
  107. add(wrapper);
  108. }
  109. return wrapper;
  110. }
  111. @Override
  112. public void add(Widget child) {
  113. super.add(child, canvas);
  114. }
  115. @Override
  116. public void setStyleName(String style) {
  117. super.setStyleName(style);
  118. if (previousStyleName == null || !previousStyleName.equals(style)) {
  119. // excessPixelsHorizontal = -1;
  120. // excessPixelsVertical = -1;
  121. }
  122. }
  123. @Override
  124. public void setWidth(String width) {
  125. super.setWidth(width);
  126. // TODO do this so that canvas gets the sized properly (the area
  127. // inside marginals)
  128. canvas.getStyle().setProperty("width", width);
  129. if (!rendering) {
  130. relayoutRelativeChildren();
  131. }
  132. }
  133. private void relayoutRelativeChildren() {
  134. for (Widget widget : getChildren()) {
  135. if (widget instanceof AbsoluteWrapper) {
  136. AbsoluteWrapper w = (AbsoluteWrapper) widget;
  137. client.handleComponentRelativeSize(w.getWidget());
  138. w.updateCaptionPosition();
  139. }
  140. }
  141. }
  142. @Override
  143. public void setHeight(String height) {
  144. super.setHeight(height);
  145. // TODO do this so that canvas gets the sized properly (the area
  146. // inside marginals)
  147. canvas.getStyle().setProperty("height", height);
  148. if (!rendering) {
  149. relayoutRelativeChildren();
  150. }
  151. }
  152. public class AbsoluteWrapper extends SimplePanel {
  153. private String css;
  154. private String left;
  155. private String top;
  156. private String right;
  157. private String bottom;
  158. private String zIndex;
  159. private VPaintableWidget paintable;
  160. private VCaption caption;
  161. public AbsoluteWrapper(VPaintableWidget paintable) {
  162. this.paintable = paintable;
  163. setStyleName(CLASSNAME + "-wrapper");
  164. }
  165. public void updateCaption(UIDL uidl) {
  166. boolean captionIsNeeded = VCaption.isNeeded(uidl,
  167. paintable.getState());
  168. if (captionIsNeeded) {
  169. if (caption == null) {
  170. caption = new VCaption(paintable, client);
  171. VAbsoluteLayout.this.add(caption);
  172. }
  173. caption.updateCaption(uidl);
  174. updateCaptionPosition();
  175. } else {
  176. if (caption != null) {
  177. caption.removeFromParent();
  178. caption = null;
  179. }
  180. }
  181. }
  182. @Override
  183. public void setWidget(Widget w) {
  184. // this fixes #5457 (Widget implementation can change on-the-fly)
  185. paintable = VPaintableMap.get(client).getPaintable(w);
  186. super.setWidget(w);
  187. }
  188. public void destroy() {
  189. if (caption != null) {
  190. caption.removeFromParent();
  191. }
  192. client.unregisterPaintable(paintable);
  193. removeFromParent();
  194. }
  195. public void updateFromUIDL(UIDL componentUIDL) {
  196. setPosition(componentUIDL.getStringAttribute("css"));
  197. if (getWidget() != paintable.getWidgetForPaintable()) {
  198. setWidget(paintable.getWidgetForPaintable());
  199. }
  200. UIDL childUIDL = componentUIDL.getChildUIDL(0);
  201. paintable.updateFromUIDL(childUIDL, client);
  202. if (childUIDL.hasAttribute("cached")) {
  203. // child may need relative size adjustment if wrapper details
  204. // have changed this could be optimized (check if wrapper size
  205. // has changed)
  206. client.handleComponentRelativeSize(paintable
  207. .getWidgetForPaintable());
  208. }
  209. }
  210. public void setPosition(String stringAttribute) {
  211. if (css == null || !css.equals(stringAttribute)) {
  212. css = stringAttribute;
  213. top = right = bottom = left = zIndex = null;
  214. if (!css.equals("")) {
  215. String[] properties = css.split(";");
  216. for (int i = 0; i < properties.length; i++) {
  217. String[] keyValue = properties[i].split(":");
  218. if (keyValue[0].equals("left")) {
  219. left = keyValue[1];
  220. } else if (keyValue[0].equals("top")) {
  221. top = keyValue[1];
  222. } else if (keyValue[0].equals("right")) {
  223. right = keyValue[1];
  224. } else if (keyValue[0].equals("bottom")) {
  225. bottom = keyValue[1];
  226. } else if (keyValue[0].equals("z-index")) {
  227. zIndex = keyValue[1];
  228. }
  229. }
  230. }
  231. // ensure ne values
  232. Style style = getElement().getStyle();
  233. /*
  234. * IE8 dies when nulling zIndex, even in IE7 mode. All other css
  235. * properties (and even in older IE's) accept null values just
  236. * fine. Assign empty string instead of null.
  237. */
  238. if (zIndex != null) {
  239. style.setProperty("zIndex", zIndex);
  240. } else {
  241. style.setProperty("zIndex", "");
  242. }
  243. style.setProperty("top", top);
  244. style.setProperty("left", left);
  245. style.setProperty("right", right);
  246. style.setProperty("bottom", bottom);
  247. }
  248. updateCaptionPosition();
  249. }
  250. private void updateCaptionPosition() {
  251. if (caption != null) {
  252. Style style = caption.getElement().getStyle();
  253. style.setProperty("position", "absolute");
  254. style.setPropertyPx("left", getElement().getOffsetLeft());
  255. style.setPropertyPx("top", getElement().getOffsetTop()
  256. - caption.getHeight());
  257. }
  258. }
  259. }
  260. /**
  261. * Returns the deepest nested child component which contains "element". The
  262. * child component is also returned if "element" is part of its caption.
  263. *
  264. * @param element
  265. * An element that is a nested sub element of the root element in
  266. * this layout
  267. * @return The Paintable which the element is a part of. Null if the element
  268. * belongs to the layout and not to a child.
  269. */
  270. VPaintableWidget getComponent(Element element) {
  271. return Util.getPaintableForElement(client, this, element);
  272. }
  273. }