Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

VAbsoluteLayout.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. /*
  2. * Copyright 2000-2013 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;
  17. import com.google.gwt.dom.client.DivElement;
  18. import com.google.gwt.dom.client.Document;
  19. import com.google.gwt.dom.client.Style;
  20. import com.google.gwt.user.client.DOM;
  21. import com.google.gwt.user.client.ui.ComplexPanel;
  22. import com.google.gwt.user.client.ui.SimplePanel;
  23. import com.google.gwt.user.client.ui.Widget;
  24. import com.vaadin.client.StyleConstants;
  25. import com.vaadin.client.VCaption;
  26. public class VAbsoluteLayout extends ComplexPanel {
  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 com.google.gwt.user.client.Element canvas = DOM.createDiv();
  33. /**
  34. * Default constructor
  35. */
  36. public VAbsoluteLayout() {
  37. setElement(Document.get().createDivElement());
  38. marginElement = Document.get().createDivElement();
  39. canvas.getStyle().setProperty("position", "relative");
  40. canvas.getStyle().setProperty("overflow", "hidden");
  41. marginElement.appendChild(canvas);
  42. getElement().appendChild(marginElement);
  43. setStyleName(CLASSNAME);
  44. }
  45. /*
  46. * (non-Javadoc)
  47. *
  48. * @see
  49. * com.google.gwt.user.client.ui.Panel#add(com.google.gwt.user.client.ui
  50. * .Widget)
  51. */
  52. @Override
  53. public void add(Widget child) {
  54. AbsoluteWrapper wrapper = new AbsoluteWrapper(child);
  55. wrapper.updateStyleNames();
  56. super.add(wrapper, canvas);
  57. }
  58. /*
  59. * (non-Javadoc)
  60. *
  61. * @see
  62. * com.google.gwt.user.client.ui.ComplexPanel#remove(com.google.gwt.user
  63. * .client.ui.Widget)
  64. */
  65. @Override
  66. public boolean remove(Widget w) {
  67. AbsoluteWrapper wrapper = getChildWrapper(w);
  68. if (wrapper != null) {
  69. wrapper.destroy();
  70. return super.remove(wrapper);
  71. }
  72. return super.remove(w);
  73. }
  74. /**
  75. * Does this layout contain a widget
  76. *
  77. * @param widget
  78. * The widget to check
  79. * @return Returns true if the widget is in this layout, false if not
  80. */
  81. public boolean contains(Widget widget) {
  82. return getChildWrapper(widget) != null;
  83. }
  84. /*
  85. * (non-Javadoc)
  86. *
  87. * @see com.google.gwt.user.client.ui.ComplexPanel#getWidget(int)
  88. */
  89. @Override
  90. public Widget getWidget(int index) {
  91. for (int i = 0, j = 0; i < super.getWidgetCount(); i++) {
  92. Widget w = super.getWidget(i);
  93. if (w instanceof AbsoluteWrapper) {
  94. if (j == index) {
  95. return w;
  96. } else {
  97. j++;
  98. }
  99. }
  100. }
  101. return null;
  102. }
  103. /*
  104. * (non-Javadoc)
  105. *
  106. * @see com.google.gwt.user.client.ui.ComplexPanel#getWidgetCount()
  107. */
  108. @Override
  109. public int getWidgetCount() {
  110. int counter = 0;
  111. for (int i = 0; i < super.getWidgetCount(); i++) {
  112. if (super.getWidget(i) instanceof AbsoluteWrapper) {
  113. counter++;
  114. }
  115. }
  116. return counter;
  117. }
  118. /*
  119. * (non-Javadoc)
  120. *
  121. * @see
  122. * com.google.gwt.user.client.ui.ComplexPanel#getWidgetIndex(com.google.
  123. * gwt.user.client.ui.Widget)
  124. */
  125. @Override
  126. public int getWidgetIndex(Widget child) {
  127. for (int i = 0, j = 0; i < super.getWidgetCount(); i++) {
  128. Widget w = super.getWidget(i);
  129. if (w instanceof AbsoluteWrapper) {
  130. if (child == w) {
  131. return j;
  132. } else {
  133. j++;
  134. }
  135. }
  136. }
  137. return -1;
  138. }
  139. /**
  140. * Sets a caption for a contained widget
  141. *
  142. * @param child
  143. * The child widget to set the caption for
  144. * @param caption
  145. * The caption of the widget
  146. */
  147. public void setWidgetCaption(Widget child, VCaption caption) {
  148. AbsoluteWrapper wrapper = getChildWrapper(child);
  149. if (wrapper != null) {
  150. if (caption != null) {
  151. if (!getChildren().contains(caption)) {
  152. super.add(caption, canvas);
  153. }
  154. wrapper.setCaption(caption);
  155. caption.updateCaption();
  156. wrapper.updateCaptionPosition();
  157. } else if (wrapper.getCaption() != null) {
  158. wrapper.setCaption(null);
  159. }
  160. }
  161. }
  162. /**
  163. * Set the position of the widget in the layout. The position is a CSS
  164. * property string using properties such as top,left,right,top
  165. *
  166. * @param child
  167. * The child widget to set the position for
  168. * @param position
  169. * The position string
  170. */
  171. public void setWidgetPosition(Widget child, String position) {
  172. AbsoluteWrapper wrapper = getChildWrapper(child);
  173. if (wrapper != null) {
  174. wrapper.setPosition(position);
  175. }
  176. }
  177. /**
  178. * Get the caption for a widget
  179. *
  180. * @param child
  181. * The child widget to get the caption of
  182. */
  183. public VCaption getWidgetCaption(Widget child) {
  184. AbsoluteWrapper wrapper = getChildWrapper(child);
  185. if (wrapper != null) {
  186. return wrapper.getCaption();
  187. }
  188. return null;
  189. }
  190. /**
  191. * Get the pixel width of an slot in the layout
  192. *
  193. * @param child
  194. * The widget in the layout.
  195. * @return Returns the size in pixels, or 0 if child is not in the layout
  196. */
  197. public int getWidgetSlotWidth(Widget child) {
  198. AbsoluteWrapper wrapper = getChildWrapper(child);
  199. if (wrapper != null) {
  200. return wrapper.getOffsetWidth();
  201. }
  202. return 0;
  203. }
  204. /**
  205. * Get the pixel height of an slot in the layout
  206. *
  207. * @param child
  208. * The widget in the layout
  209. * @return Returns the size in pixels, or 0 if the child is not in the
  210. * layout
  211. */
  212. public int getWidgetSlotHeight(Widget child) {
  213. AbsoluteWrapper wrapper = getChildWrapper(child);
  214. if (wrapper != null) {
  215. return wrapper.getOffsetHeight();
  216. }
  217. return 0;
  218. }
  219. /**
  220. * Get the wrapper for a widget
  221. *
  222. * @param child
  223. * The child to get the wrapper for
  224. * @return
  225. */
  226. protected AbsoluteWrapper getChildWrapper(Widget child) {
  227. for (Widget w : getChildren()) {
  228. if (w instanceof AbsoluteWrapper) {
  229. AbsoluteWrapper wrapper = (AbsoluteWrapper) w;
  230. if (wrapper.getWidget() == child) {
  231. return wrapper;
  232. }
  233. }
  234. }
  235. return null;
  236. }
  237. /*
  238. * (non-Javadoc)
  239. *
  240. * @see
  241. * com.google.gwt.user.client.ui.UIObject#setStylePrimaryName(java.lang.
  242. * String)
  243. */
  244. @Override
  245. public void setStylePrimaryName(String style) {
  246. updateStylenames(style);
  247. }
  248. /*
  249. * (non-Javadoc)
  250. *
  251. * @see
  252. * com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String)
  253. */
  254. @Override
  255. public void setStyleName(String style) {
  256. super.setStyleName(style);
  257. updateStylenames(style);
  258. addStyleName(StyleConstants.UI_LAYOUT);
  259. }
  260. /**
  261. * Updates all style names contained in the layout
  262. *
  263. * @param primaryStyleName
  264. * The style name to use as primary
  265. */
  266. protected void updateStylenames(String primaryStyleName) {
  267. super.setStylePrimaryName(primaryStyleName);
  268. canvas.setClassName(getStylePrimaryName() + "-canvas");
  269. canvas.setClassName(getStylePrimaryName() + "-margin");
  270. for (Widget w : getChildren()) {
  271. if (w instanceof AbsoluteWrapper) {
  272. AbsoluteWrapper wrapper = (AbsoluteWrapper) w;
  273. wrapper.updateStyleNames();
  274. }
  275. }
  276. }
  277. /**
  278. * Performs a vertical layout of the layout. Should be called when a widget
  279. * is added or removed
  280. */
  281. public void layoutVertically() {
  282. layout();
  283. }
  284. /**
  285. * Performs an horizontal layout. Should be called when a widget is add or
  286. * removed
  287. */
  288. public void layoutHorizontally() {
  289. layout();
  290. }
  291. private void layout() {
  292. for (Widget widget : getChildren()) {
  293. if (widget instanceof AbsoluteWrapper) {
  294. AbsoluteWrapper wrapper = (AbsoluteWrapper) widget;
  295. wrapper.updateCaptionPosition();
  296. }
  297. }
  298. }
  299. /**
  300. * Cleanup old wrappers which have been left empty by other inner layouts
  301. * moving the widget from the wrapper into their own hierarchy. This usually
  302. * happens when a call to setWidget(widget) is done in an inner layout which
  303. * automatically detaches the widget from the parent, in this case the
  304. * wrapper, and re-attaches it somewhere else. This has to be done in the
  305. * layout phase since the order of the hierarchy events are not defined.
  306. */
  307. public void cleanupWrappers() {
  308. for (Widget widget : getChildren()) {
  309. if (widget instanceof AbsoluteWrapper) {
  310. AbsoluteWrapper wrapper = (AbsoluteWrapper) widget;
  311. if (wrapper.getWidget() == null) {
  312. wrapper.destroy();
  313. super.remove(wrapper);
  314. continue;
  315. }
  316. }
  317. }
  318. }
  319. /**
  320. * Sets style names for the wrapper wrapping the widget in the layout. The
  321. * style names will be prefixed with v-absolutelayout-wrapper.
  322. *
  323. * @param widget
  324. * The widget which wrapper we want to add the stylenames to
  325. * @param stylenames
  326. * The style names that should be added to the wrapper
  327. */
  328. public void setWidgetWrapperStyleNames(Widget widget, String... stylenames) {
  329. AbsoluteWrapper wrapper = getChildWrapper(widget);
  330. if (wrapper == null) {
  331. throw new IllegalArgumentException(
  332. "No wrapper for widget found, has the widget been added to the layout?");
  333. }
  334. wrapper.setWrapperStyleNames(stylenames);
  335. }
  336. /**
  337. * Internal wrapper for wrapping widgets in the Absolute layout
  338. */
  339. protected class AbsoluteWrapper extends SimplePanel {
  340. private String css;
  341. private String left;
  342. private String top;
  343. private String right;
  344. private String bottom;
  345. private String zIndex;
  346. private VCaption caption;
  347. private String[] extraStyleNames;
  348. /**
  349. * Constructor
  350. *
  351. * @param child
  352. * The child to wrap
  353. */
  354. public AbsoluteWrapper(Widget child) {
  355. setWidget(child);
  356. }
  357. /**
  358. * Get the caption of the wrapper
  359. */
  360. public VCaption getCaption() {
  361. return caption;
  362. }
  363. /**
  364. * Set the caption for the wrapper
  365. *
  366. * @param caption
  367. * The caption for the wrapper
  368. */
  369. public void setCaption(VCaption caption) {
  370. if (caption != null) {
  371. this.caption = caption;
  372. } else if (this.caption != null) {
  373. this.caption.removeFromParent();
  374. this.caption = caption;
  375. }
  376. }
  377. /**
  378. * Removes the wrapper caption and itself from the layout
  379. */
  380. public void destroy() {
  381. if (caption != null) {
  382. caption.removeFromParent();
  383. }
  384. removeFromParent();
  385. }
  386. /**
  387. * Set the position for the wrapper in the layout
  388. *
  389. * @param position
  390. * The position string
  391. */
  392. public void setPosition(String position) {
  393. if (css == null || !css.equals(position)) {
  394. css = position;
  395. top = right = bottom = left = zIndex = null;
  396. if (!css.equals("")) {
  397. String[] properties = css.split(";");
  398. for (int i = 0; i < properties.length; i++) {
  399. String[] keyValue = properties[i].split(":");
  400. if (keyValue[0].equals("left")) {
  401. left = keyValue[1];
  402. } else if (keyValue[0].equals("top")) {
  403. top = keyValue[1];
  404. } else if (keyValue[0].equals("right")) {
  405. right = keyValue[1];
  406. } else if (keyValue[0].equals("bottom")) {
  407. bottom = keyValue[1];
  408. } else if (keyValue[0].equals("z-index")) {
  409. zIndex = keyValue[1];
  410. }
  411. }
  412. }
  413. // ensure ne values
  414. Style style = getElement().getStyle();
  415. /*
  416. * IE8 dies when nulling zIndex, even in IE7 mode. All other css
  417. * properties (and even in older IE's) accept null values just
  418. * fine. Assign empty string instead of null.
  419. */
  420. if (zIndex != null) {
  421. style.setProperty("zIndex", zIndex);
  422. } else {
  423. style.setProperty("zIndex", "");
  424. }
  425. style.setProperty("top", top);
  426. style.setProperty("left", left);
  427. style.setProperty("right", right);
  428. style.setProperty("bottom", bottom);
  429. }
  430. updateCaptionPosition();
  431. }
  432. /**
  433. * Updates the caption position by using element offset left and top
  434. */
  435. private void updateCaptionPosition() {
  436. if (caption != null) {
  437. Style style = caption.getElement().getStyle();
  438. style.setProperty("position", "absolute");
  439. style.setPropertyPx("left", getElement().getOffsetLeft());
  440. style.setPropertyPx("top", getElement().getOffsetTop()
  441. - caption.getHeight());
  442. }
  443. }
  444. /**
  445. * Sets the style names of the wrapper. Will be prefixed with the
  446. * v-absolutelayout-wrapper prefix
  447. *
  448. * @param stylenames
  449. * The wrapper style names
  450. */
  451. public void setWrapperStyleNames(String... stylenames) {
  452. extraStyleNames = stylenames;
  453. updateStyleNames();
  454. }
  455. /**
  456. * Updates the style names using the primary style name as prefix
  457. */
  458. protected void updateStyleNames() {
  459. setStyleName(VAbsoluteLayout.this.getStylePrimaryName()
  460. + "-wrapper");
  461. if (extraStyleNames != null) {
  462. for (String stylename : extraStyleNames) {
  463. addStyleDependentName(stylename);
  464. }
  465. }
  466. }
  467. }
  468. }