Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

VAbsoluteLayout.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. package com.vaadin.terminal.gwt.client.ui;
  2. import java.util.HashMap;
  3. import java.util.HashSet;
  4. import java.util.Iterator;
  5. import java.util.Map;
  6. import java.util.Set;
  7. import java.util.Map.Entry;
  8. import com.google.gwt.dom.client.DivElement;
  9. import com.google.gwt.dom.client.Document;
  10. import com.google.gwt.dom.client.Style;
  11. import com.google.gwt.user.client.DOM;
  12. import com.google.gwt.user.client.Element;
  13. import com.google.gwt.user.client.ui.ComplexPanel;
  14. import com.google.gwt.user.client.ui.SimplePanel;
  15. import com.google.gwt.user.client.ui.Widget;
  16. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  17. import com.vaadin.terminal.gwt.client.BrowserInfo;
  18. import com.vaadin.terminal.gwt.client.Container;
  19. import com.vaadin.terminal.gwt.client.VCaption;
  20. import com.vaadin.terminal.gwt.client.Paintable;
  21. import com.vaadin.terminal.gwt.client.RenderSpace;
  22. import com.vaadin.terminal.gwt.client.UIDL;
  23. public class VAbsoluteLayout extends ComplexPanel implements Container {
  24. /** Tag name for widget creation */
  25. public static final String TAGNAME = "absolutelayout";
  26. /** Class name, prefix in styling */
  27. public static final String CLASSNAME = "i-absolutelayout";
  28. private DivElement marginElement;
  29. protected final Element canvas = DOM.createDiv();
  30. private int excessPixelsHorizontal;
  31. private int excessPixelsVertical;
  32. private Object previousStyleName;
  33. private Map<String, AbsoluteWrapper> pidToComponentWrappper = new HashMap<String, AbsoluteWrapper>();
  34. protected ApplicationConnection client;
  35. private boolean rendering;
  36. public VAbsoluteLayout() {
  37. setElement(Document.get().createDivElement());
  38. setStyleName(CLASSNAME);
  39. marginElement = Document.get().createDivElement();
  40. canvas.getStyle().setProperty("position", "relative");
  41. marginElement.appendChild(canvas);
  42. getElement().appendChild(marginElement);
  43. }
  44. public RenderSpace getAllocatedSpace(Widget child) {
  45. // TODO needs some special handling for components with only on edge
  46. // horizontally or vertically defined
  47. AbsoluteWrapper wrapper = (AbsoluteWrapper) child.getParent();
  48. int w;
  49. if (wrapper.left != null && wrapper.right != null) {
  50. w = wrapper.getOffsetWidth();
  51. } else if (wrapper.right != null) {
  52. // left == null
  53. // available width == right edge == offsetleft + width
  54. w = wrapper.getOffsetWidth() + wrapper.getElement().getOffsetLeft();
  55. } else {
  56. // left != null && right == null || left == null &&
  57. // right == null
  58. // available width == canvas width - offset left
  59. w = canvas.getOffsetWidth() - wrapper.getElement().getOffsetLeft();
  60. }
  61. int h;
  62. if (wrapper.top != null && wrapper.bottom != null) {
  63. h = wrapper.getOffsetHeight();
  64. } else if (wrapper.bottom != null) {
  65. // top not defined, available space 0... bottom of wrapper
  66. h = wrapper.getElement().getOffsetTop() + wrapper.getOffsetHeight();
  67. } else {
  68. // top defined or both undefined, available space == canvas - top
  69. h = canvas.getOffsetHeight() - wrapper.getElement().getOffsetTop();
  70. }
  71. return new RenderSpace(w, h);
  72. }
  73. public boolean hasChildComponent(Widget component) {
  74. for (Iterator<Entry<String, AbsoluteWrapper>> iterator = pidToComponentWrappper
  75. .entrySet().iterator(); iterator.hasNext();) {
  76. if (iterator.next().getValue().paintable == component) {
  77. return true;
  78. }
  79. }
  80. return false;
  81. }
  82. public void replaceChildComponent(Widget oldComponent, Widget newComponent) {
  83. for (Widget wrapper : getChildren()) {
  84. AbsoluteWrapper w = (AbsoluteWrapper) wrapper;
  85. if (w.getWidget() == oldComponent) {
  86. w.setWidget(newComponent);
  87. return;
  88. }
  89. }
  90. }
  91. public boolean requestLayout(Set<Paintable> children) {
  92. // component inside an absolute panel never affects parent nor the
  93. // layout
  94. return true;
  95. }
  96. public void updateCaption(Paintable component, UIDL uidl) {
  97. AbsoluteWrapper parent2 = (AbsoluteWrapper) ((Widget) component)
  98. .getParent();
  99. parent2.updateCaption(uidl);
  100. }
  101. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  102. rendering = true;
  103. this.client = client;
  104. // TODO margin handling
  105. if (client.updateComponent(this, uidl, true)) {
  106. rendering = false;
  107. return;
  108. }
  109. HashSet<String> unrenderedPids = new HashSet<String>(
  110. pidToComponentWrappper.keySet());
  111. for (Iterator<UIDL> childIterator = uidl.getChildIterator(); childIterator
  112. .hasNext();) {
  113. UIDL cc = childIterator.next();
  114. UIDL componentUIDL = cc.getChildUIDL(0);
  115. unrenderedPids.remove(componentUIDL.getId());
  116. getWrapper(client, componentUIDL).updateFromUIDL(cc);
  117. }
  118. for (String pid : unrenderedPids) {
  119. AbsoluteWrapper absoluteWrapper = pidToComponentWrappper.get(pid);
  120. pidToComponentWrappper.remove(pid);
  121. absoluteWrapper.destroy();
  122. }
  123. rendering = false;
  124. }
  125. private AbsoluteWrapper getWrapper(ApplicationConnection client,
  126. UIDL componentUIDL) {
  127. AbsoluteWrapper wrapper = pidToComponentWrappper.get(componentUIDL
  128. .getId());
  129. if (wrapper == null) {
  130. wrapper = new AbsoluteWrapper(client.getPaintable(componentUIDL));
  131. pidToComponentWrappper.put(componentUIDL.getId(), wrapper);
  132. add(wrapper);
  133. }
  134. return wrapper;
  135. }
  136. @Override
  137. public void add(Widget child) {
  138. super.add(child, canvas);
  139. }
  140. @Override
  141. public void setStyleName(String style) {
  142. super.setStyleName(style);
  143. if (previousStyleName == null || !previousStyleName.equals(style)) {
  144. excessPixelsHorizontal = -1;
  145. excessPixelsVertical = -1;
  146. }
  147. }
  148. @Override
  149. public void setWidth(String width) {
  150. super.setWidth(width);
  151. // TODO do this so that canvas gets the sized properly (the area
  152. // inside marginals)
  153. canvas.getStyle().setProperty("width", width);
  154. if (!rendering) {
  155. if (BrowserInfo.get().isIE6()) {
  156. relayoutWrappersForIe6();
  157. }
  158. relayoutRelativeChildren();
  159. }
  160. }
  161. private void relayoutRelativeChildren() {
  162. for (Widget widget : getChildren()) {
  163. if (widget instanceof AbsoluteWrapper) {
  164. AbsoluteWrapper w = (AbsoluteWrapper) widget;
  165. client.handleComponentRelativeSize(w.getWidget());
  166. w.updateCaptionPosition();
  167. }
  168. }
  169. }
  170. @Override
  171. public void setHeight(String height) {
  172. super.setHeight(height);
  173. // TODO do this so that canvas gets the sized properly (the area
  174. // inside marginals)
  175. canvas.getStyle().setProperty("height", height);
  176. if (!rendering) {
  177. if (BrowserInfo.get().isIE6()) {
  178. relayoutWrappersForIe6();
  179. }
  180. relayoutRelativeChildren();
  181. }
  182. }
  183. private void relayoutWrappersForIe6() {
  184. for (Widget wrapper : getChildren()) {
  185. if (wrapper instanceof AbsoluteWrapper) {
  186. ((AbsoluteWrapper) wrapper).ie6Layout();
  187. }
  188. }
  189. }
  190. public class AbsoluteWrapper extends SimplePanel {
  191. private String css;
  192. private String left;
  193. private String top;
  194. private String right;
  195. private String bottom;
  196. private String zIndex;
  197. private Paintable paintable;
  198. private VCaption caption;
  199. public AbsoluteWrapper(Paintable paintable) {
  200. this.paintable = paintable;
  201. setStyleName(CLASSNAME + "-wrapper");
  202. }
  203. public void updateCaption(UIDL uidl) {
  204. boolean captionIsNeeded = VCaption.isNeeded(uidl);
  205. if (captionIsNeeded) {
  206. if (caption == null) {
  207. caption = new VCaption(paintable, client);
  208. VAbsoluteLayout.this.add(caption);
  209. }
  210. caption.updateCaption(uidl);
  211. updateCaptionPosition();
  212. } else {
  213. if (caption != null) {
  214. caption.removeFromParent();
  215. caption = null;
  216. }
  217. }
  218. }
  219. public void destroy() {
  220. if (caption != null) {
  221. caption.removeFromParent();
  222. }
  223. client.unregisterPaintable(paintable);
  224. removeFromParent();
  225. }
  226. public void updateFromUIDL(UIDL componentUIDL) {
  227. setPosition(componentUIDL.getStringAttribute("css"));
  228. if (getWidget() != paintable) {
  229. setWidget((Widget) paintable);
  230. }
  231. UIDL childUIDL = componentUIDL.getChildUIDL(0);
  232. paintable.updateFromUIDL(childUIDL, client);
  233. if (childUIDL.hasAttribute("cached")) {
  234. // child may need relative size adjustment if wrapper details
  235. // have changed this could be optimized (check if wrapper size
  236. // has changed)
  237. client.handleComponentRelativeSize((Widget) paintable);
  238. }
  239. }
  240. public void setPosition(String stringAttribute) {
  241. if (css == null || !css.equals(stringAttribute)) {
  242. css = stringAttribute;
  243. top = right = bottom = left = zIndex = null;
  244. if (!css.equals("")) {
  245. String[] properties = css.split(";");
  246. for (int i = 0; i < properties.length; i++) {
  247. String[] keyValue = properties[i].split(":");
  248. if (keyValue[0].equals("left")) {
  249. left = keyValue[1];
  250. } else if (keyValue[0].equals("top")) {
  251. top = keyValue[1];
  252. } else if (keyValue[0].equals("right")) {
  253. right = keyValue[1];
  254. } else if (keyValue[0].equals("bottom")) {
  255. bottom = keyValue[1];
  256. } else if (keyValue[0].equals("z-index")) {
  257. zIndex = keyValue[1];
  258. }
  259. }
  260. }
  261. // ensure ne values
  262. Style style = getElement().getStyle();
  263. style.setProperty("zIndex", zIndex);
  264. style.setProperty("top", top);
  265. style.setProperty("left", left);
  266. style.setProperty("right", right);
  267. style.setProperty("bottom", bottom);
  268. if (BrowserInfo.get().isIE6()) {
  269. ie6Layout();
  270. }
  271. }
  272. updateCaptionPosition();
  273. }
  274. private void updateCaptionPosition() {
  275. if (caption != null) {
  276. Style style = caption.getElement().getStyle();
  277. style.setProperty("position", "absolute");
  278. style.setPropertyPx("left", getElement().getOffsetLeft());
  279. style.setPropertyPx("top", getElement().getOffsetTop()
  280. - caption.getHeight());
  281. }
  282. }
  283. private void ie6Layout() {
  284. // special handling for IE6 is needed, it does not support
  285. // setting both left/right or top/bottom
  286. Style style = getElement().getStyle();
  287. if (bottom != null && top != null) {
  288. // define height for wrapper to simulate bottom property
  289. int bottompixels = measureForIE6(bottom);
  290. ApplicationConnection.getConsole().log("ALB" + bottompixels);
  291. int height = canvas.getOffsetHeight() - bottompixels
  292. - getElement().getOffsetTop();
  293. ApplicationConnection.getConsole().log("ALB" + height);
  294. if (height < 0) {
  295. height = 0;
  296. }
  297. style.setPropertyPx("height", height);
  298. } else {
  299. // reset possibly existing value
  300. style.setProperty("height", "");
  301. }
  302. if (left != null && right != null) {
  303. // define width for wrapper to simulate right property
  304. int rightPixels = measureForIE6(right);
  305. ApplicationConnection.getConsole().log("ALR" + rightPixels);
  306. int width = canvas.getOffsetWidth() - rightPixels
  307. - getElement().getOffsetWidth();
  308. ApplicationConnection.getConsole().log("ALR" + width);
  309. if (width < 0) {
  310. width = 0;
  311. }
  312. style.setPropertyPx("width", width);
  313. } else {
  314. // reset possibly existing value
  315. style.setProperty("width", "");
  316. }
  317. }
  318. }
  319. private Element measureElement;
  320. private int measureForIE6(String cssLength) {
  321. if (measureElement == null) {
  322. measureElement = DOM.createDiv();
  323. measureElement.getStyle().setProperty("position", "absolute");
  324. canvas.appendChild(measureElement);
  325. }
  326. measureElement.getStyle().setProperty("width", cssLength);
  327. return measureElement.getOffsetWidth();
  328. }
  329. }