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.

Slot.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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.orderedlayout;
  17. import java.util.List;
  18. import com.google.gwt.aria.client.Roles;
  19. import com.google.gwt.core.client.GWT;
  20. import com.google.gwt.dom.client.Document;
  21. import com.google.gwt.dom.client.Element;
  22. import com.google.gwt.user.client.DOM;
  23. import com.google.gwt.user.client.Event;
  24. import com.google.gwt.user.client.Timer;
  25. import com.google.gwt.user.client.ui.SimplePanel;
  26. import com.google.gwt.user.client.ui.Widget;
  27. import com.vaadin.client.BrowserInfo;
  28. import com.vaadin.client.LayoutManager;
  29. import com.vaadin.client.StyleConstants;
  30. import com.vaadin.client.Util;
  31. import com.vaadin.client.ui.FontIcon;
  32. import com.vaadin.client.ui.Icon;
  33. import com.vaadin.client.ui.ImageIcon;
  34. import com.vaadin.client.ui.layout.ElementResizeEvent;
  35. import com.vaadin.client.ui.layout.ElementResizeListener;
  36. import com.vaadin.shared.ui.AlignmentInfo;
  37. /**
  38. * Represents a slot which contains the actual widget in the layout.
  39. */
  40. public final class Slot extends SimplePanel {
  41. private static final String ALIGN_CLASS_PREFIX = "v-align-";
  42. private final VAbstractOrderedLayout layout;
  43. public static final String SLOT_CLASSNAME = "v-slot";
  44. private Element spacer;
  45. private Element captionWrap;
  46. private Element caption;
  47. private Element captionText;
  48. private Icon icon;
  49. private Element errorIcon;
  50. private Element requiredIcon;
  51. private ElementResizeListener captionResizeListener;
  52. private ElementResizeListener widgetResizeListener;
  53. private ElementResizeListener spacingResizeListener;
  54. /*
  55. * This listener is applied only in IE8 to workaround browser issue where
  56. * IE8 forgets to update the error indicator position when the slot gets
  57. * resized by widget resizing itself. #11693
  58. */
  59. private ElementResizeListener ie8CaptionElementResizeUpdateListener = new ElementResizeListener() {
  60. @Override
  61. public void onElementResize(ElementResizeEvent e) {
  62. Element caption = getCaptionElement();
  63. if (caption != null) {
  64. Util.forceIE8Redraw(caption);
  65. }
  66. }
  67. };
  68. // Caption is placed after component unless there is some part which
  69. // moves it above.
  70. private CaptionPosition captionPosition = CaptionPosition.RIGHT;
  71. private AlignmentInfo alignment;
  72. private double expandRatio = -1;
  73. /**
  74. * Constructs a slot.
  75. *
  76. * @param layout
  77. * The layout to which this slot belongs
  78. * @param widget
  79. * The widget to put in the slot
  80. */
  81. public Slot(VAbstractOrderedLayout layout, Widget widget) {
  82. this.layout = layout;
  83. setStyleName(SLOT_CLASSNAME);
  84. setWidget(widget);
  85. }
  86. /*
  87. * (non-Javadoc)
  88. *
  89. * @see com.google.gwt.user.client.ui.SimplePanel#remove(com.google.gwt.user
  90. * .client.ui.Widget)
  91. */
  92. @Override
  93. public boolean remove(Widget w) {
  94. detachListeners();
  95. return super.remove(w);
  96. }
  97. /*
  98. * (non-Javadoc)
  99. *
  100. * @see com.google.gwt.user.client.ui.SimplePanel#setWidget(com.google.gwt
  101. * .user.client.ui.Widget)
  102. */
  103. @Override
  104. public void setWidget(Widget w) {
  105. detachListeners();
  106. super.setWidget(w);
  107. attachListeners();
  108. }
  109. /**
  110. * Attaches resize listeners to the widget, caption and spacing elements
  111. */
  112. private void attachListeners() {
  113. if (getWidget() != null && layout.getLayoutManager() != null) {
  114. LayoutManager lm = layout.getLayoutManager();
  115. if (getCaptionElement() != null && captionResizeListener != null) {
  116. lm.addElementResizeListener(getCaptionElement(),
  117. captionResizeListener);
  118. }
  119. if (widgetResizeListener != null) {
  120. lm.addElementResizeListener(getWidget().getElement(),
  121. widgetResizeListener);
  122. }
  123. if (getSpacingElement() != null && spacingResizeListener != null) {
  124. lm.addElementResizeListener(getSpacingElement(),
  125. spacingResizeListener);
  126. }
  127. if (BrowserInfo.get().isIE8()) {
  128. lm.addElementResizeListener(getWidget().getElement(),
  129. ie8CaptionElementResizeUpdateListener);
  130. }
  131. }
  132. }
  133. /**
  134. * Detaches resize listeners from the widget, caption and spacing elements
  135. */
  136. private void detachListeners() {
  137. if (getWidget() != null && layout.getLayoutManager() != null) {
  138. LayoutManager lm = layout.getLayoutManager();
  139. if (getCaptionElement() != null && captionResizeListener != null) {
  140. lm.removeElementResizeListener(getCaptionElement(),
  141. captionResizeListener);
  142. }
  143. if (widgetResizeListener != null) {
  144. lm.removeElementResizeListener(getWidget().getElement(),
  145. widgetResizeListener);
  146. }
  147. // in many cases, the listener has already been removed by
  148. // setSpacing(false)
  149. if (getSpacingElement() != null && spacingResizeListener != null) {
  150. lm.removeElementResizeListener(getSpacingElement(),
  151. spacingResizeListener);
  152. }
  153. if (BrowserInfo.get().isIE8()) {
  154. lm.removeElementResizeListener(getWidget().getElement(),
  155. ie8CaptionElementResizeUpdateListener);
  156. }
  157. }
  158. }
  159. public ElementResizeListener getCaptionResizeListener() {
  160. return captionResizeListener;
  161. }
  162. public void setCaptionResizeListener(
  163. ElementResizeListener captionResizeListener) {
  164. detachListeners();
  165. this.captionResizeListener = captionResizeListener;
  166. attachListeners();
  167. }
  168. public ElementResizeListener getWidgetResizeListener() {
  169. return widgetResizeListener;
  170. }
  171. public void setWidgetResizeListener(
  172. ElementResizeListener widgetResizeListener) {
  173. detachListeners();
  174. this.widgetResizeListener = widgetResizeListener;
  175. attachListeners();
  176. }
  177. public ElementResizeListener getSpacingResizeListener() {
  178. return spacingResizeListener;
  179. }
  180. public void setSpacingResizeListener(
  181. ElementResizeListener spacingResizeListener) {
  182. detachListeners();
  183. this.spacingResizeListener = spacingResizeListener;
  184. attachListeners();
  185. }
  186. /**
  187. * Returns the alignment for the slot
  188. *
  189. */
  190. public AlignmentInfo getAlignment() {
  191. return alignment;
  192. }
  193. /**
  194. * Sets the style names for the slot containing the widget
  195. *
  196. * @param stylenames
  197. * The style names for the slot
  198. */
  199. protected void setStyleNames(String... stylenames) {
  200. setStyleName(SLOT_CLASSNAME);
  201. if (stylenames != null) {
  202. for (String stylename : stylenames) {
  203. addStyleDependentName(stylename);
  204. }
  205. }
  206. // Ensure alignment style names are correct
  207. setAlignment(alignment);
  208. }
  209. /**
  210. * Sets how the widget is aligned inside the slot
  211. *
  212. * @param alignment
  213. * The alignment inside the slot
  214. */
  215. public void setAlignment(AlignmentInfo alignment) {
  216. this.alignment = alignment;
  217. if (alignment != null && alignment.isHorizontalCenter()) {
  218. addStyleName(ALIGN_CLASS_PREFIX + "center");
  219. removeStyleName(ALIGN_CLASS_PREFIX + "right");
  220. } else if (alignment != null && alignment.isRight()) {
  221. addStyleName(ALIGN_CLASS_PREFIX + "right");
  222. removeStyleName(ALIGN_CLASS_PREFIX + "center");
  223. } else {
  224. removeStyleName(ALIGN_CLASS_PREFIX + "right");
  225. removeStyleName(ALIGN_CLASS_PREFIX + "center");
  226. }
  227. if (alignment != null && alignment.isVerticalCenter()) {
  228. addStyleName(ALIGN_CLASS_PREFIX + "middle");
  229. removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
  230. } else if (alignment != null && alignment.isBottom()) {
  231. addStyleName(ALIGN_CLASS_PREFIX + "bottom");
  232. removeStyleName(ALIGN_CLASS_PREFIX + "middle");
  233. } else {
  234. removeStyleName(ALIGN_CLASS_PREFIX + "middle");
  235. removeStyleName(ALIGN_CLASS_PREFIX + "bottom");
  236. }
  237. }
  238. /**
  239. * Set how the slot should be expanded relative to the other slots. 0 means
  240. * that the slot should not participate in the division of space based on
  241. * the expand ratios but instead be allocated space based on its natural
  242. * size. Other values causes the slot to get a share of the otherwise
  243. * unallocated space in proportion to the slot's expand ratio value.
  244. *
  245. * @param expandRatio
  246. * The ratio of the space the slot should occupy
  247. *
  248. */
  249. public void setExpandRatio(double expandRatio) {
  250. this.expandRatio = expandRatio;
  251. }
  252. /**
  253. * Get the expand ratio for the slot. The expand ratio describes how the
  254. * slot should be resized compared to other slots in the layout
  255. *
  256. * @return the expand ratio of the slot
  257. *
  258. * @see #setExpandRatio(double)
  259. */
  260. public double getExpandRatio() {
  261. return expandRatio;
  262. }
  263. /**
  264. * Set the spacing for the slot. The spacing determines if there should be
  265. * empty space around the slot when the slot.
  266. *
  267. * @param spacing
  268. * Should spacing be enabled
  269. */
  270. public void setSpacing(boolean spacing) {
  271. if (spacing && spacer == null) {
  272. spacer = DOM.createDiv();
  273. spacer.addClassName("v-spacing");
  274. /*
  275. * This has to be done here for the initial render. In other cases
  276. * where the spacer already exists onAttach will handle it.
  277. */
  278. getElement().getParentElement().insertBefore(spacer, getElement());
  279. } else if (!spacing && spacer != null) {
  280. // Remove listener before spacer to avoid memory leak
  281. LayoutManager lm = layout.getLayoutManager();
  282. if (lm != null && spacingResizeListener != null) {
  283. lm.removeElementResizeListener(spacer, spacingResizeListener);
  284. }
  285. spacer.removeFromParent();
  286. spacer = null;
  287. }
  288. }
  289. /**
  290. * Get the element which is added to make the spacing
  291. *
  292. * @return
  293. */
  294. public com.google.gwt.user.client.Element getSpacingElement() {
  295. return DOM.asOld(spacer);
  296. }
  297. /**
  298. * Does the slot have spacing
  299. */
  300. public boolean hasSpacing() {
  301. return getSpacingElement() != null;
  302. }
  303. /**
  304. * Get the vertical amount in pixels of the spacing
  305. */
  306. protected int getVerticalSpacing() {
  307. if (spacer == null) {
  308. return 0;
  309. } else if (layout.getLayoutManager() != null) {
  310. return layout.getLayoutManager().getOuterHeight(spacer);
  311. }
  312. return spacer.getOffsetHeight();
  313. }
  314. /**
  315. * Get the horizontal amount of pixels of the spacing
  316. *
  317. * @return
  318. */
  319. protected int getHorizontalSpacing() {
  320. if (spacer == null) {
  321. return 0;
  322. } else if (layout.getLayoutManager() != null) {
  323. return layout.getLayoutManager().getOuterWidth(spacer);
  324. }
  325. return spacer.getOffsetWidth();
  326. }
  327. /**
  328. * Set the position of the caption relative to the slot
  329. *
  330. * @param captionPosition
  331. * The position of the caption
  332. */
  333. public void setCaptionPosition(CaptionPosition captionPosition) {
  334. if (caption == null) {
  335. return;
  336. }
  337. captionWrap.removeClassName("v-caption-on-"
  338. + this.captionPosition.name().toLowerCase());
  339. this.captionPosition = captionPosition;
  340. if (captionPosition == CaptionPosition.BOTTOM
  341. || captionPosition == CaptionPosition.RIGHT) {
  342. captionWrap.appendChild(caption);
  343. } else {
  344. captionWrap.insertFirst(caption);
  345. }
  346. captionWrap.addClassName("v-caption-on-"
  347. + captionPosition.name().toLowerCase());
  348. }
  349. /**
  350. * Get the position of the caption relative to the slot
  351. */
  352. public CaptionPosition getCaptionPosition() {
  353. return captionPosition;
  354. }
  355. /**
  356. * Set the caption of the slot
  357. *
  358. * @param captionText
  359. * The text of the caption
  360. * @param iconUrl
  361. * The icon URL, must already be run trough translateVaadinUri()
  362. * @param styles
  363. * The style names
  364. * @param error
  365. * The error message
  366. * @param showError
  367. * Should the error message be shown
  368. * @param required
  369. * Is the (field) required
  370. * @param enabled
  371. * Is the component enabled
  372. *
  373. * @deprecated Use
  374. * {@link #setCaption(String, Icon, List, String, boolean, boolean, boolean)}
  375. * instead
  376. */
  377. @Deprecated
  378. public void setCaption(String captionText, String iconUrl,
  379. List<String> styles, String error, boolean showError,
  380. boolean required, boolean enabled) {
  381. Icon icon;
  382. if (FontIcon.isFontIconUri(iconUrl)) {
  383. icon = GWT.create(FontIcon.class);
  384. } else {
  385. icon = GWT.create(ImageIcon.class);
  386. }
  387. icon.setUri(iconUrl);
  388. setCaption(captionText, icon, styles, error, showError, required,
  389. enabled);
  390. }
  391. /**
  392. * Set the caption of the slot
  393. *
  394. * @param captionText
  395. * The text of the caption
  396. * @param icon
  397. * The icon
  398. * @param styles
  399. * The style names
  400. * @param error
  401. * The error message
  402. * @param showError
  403. * Should the error message be shown
  404. * @param required
  405. * Is the (field) required
  406. * @param enabled
  407. * Is the component enabled
  408. */
  409. public void setCaption(String captionText, Icon icon, List<String> styles,
  410. String error, boolean showError, boolean required, boolean enabled) {
  411. // TODO place for optimization: check if any of these have changed
  412. // since last time, and only run those changes
  413. // Caption wrappers
  414. Widget widget = getWidget();
  415. final Element focusedElement = Util.getFocusedElement();
  416. // By default focus will not be lost
  417. boolean focusLost = false;
  418. if (captionText != null || icon != null || error != null || required) {
  419. if (caption == null) {
  420. caption = DOM.createDiv();
  421. captionWrap = DOM.createDiv();
  422. captionWrap.addClassName(StyleConstants.UI_WIDGET);
  423. captionWrap.addClassName("v-has-caption");
  424. getElement().appendChild(captionWrap);
  425. orphan(widget);
  426. captionWrap.appendChild(widget.getElement());
  427. adopt(widget);
  428. // Made changes to DOM. Focus can be lost if it was in the
  429. // widget.
  430. focusLost = (focusedElement == null ? false : widget
  431. .getElement().isOrHasChild(focusedElement));
  432. }
  433. } else if (caption != null) {
  434. orphan(widget);
  435. getElement().appendChild(widget.getElement());
  436. adopt(widget);
  437. captionWrap.removeFromParent();
  438. caption = null;
  439. captionWrap = null;
  440. // Made changes to DOM. Focus can be lost if it was in the widget.
  441. focusLost = (focusedElement == null ? false : widget.getElement()
  442. .isOrHasChild(focusedElement));
  443. }
  444. // Caption text
  445. if (captionText != null) {
  446. if (this.captionText == null) {
  447. this.captionText = DOM.createSpan();
  448. this.captionText.addClassName("v-captiontext");
  449. caption.appendChild(this.captionText);
  450. }
  451. if (captionText.trim().equals("")) {
  452. this.captionText.setInnerHTML("&nbsp;");
  453. } else {
  454. this.captionText.setInnerText(captionText);
  455. }
  456. } else if (this.captionText != null) {
  457. this.captionText.removeFromParent();
  458. this.captionText = null;
  459. }
  460. // Icon
  461. if (this.icon != null) {
  462. icon.getElement().removeFromParent();
  463. }
  464. if (icon != null) {
  465. caption.insertFirst(icon.getElement());
  466. }
  467. this.icon = icon;
  468. // Required
  469. if (required) {
  470. if (requiredIcon == null) {
  471. requiredIcon = DOM.createSpan();
  472. // TODO decide something better (e.g. use CSS to insert the
  473. // character)
  474. requiredIcon.setInnerHTML("*");
  475. requiredIcon.setClassName("v-required-field-indicator");
  476. // The star should not be read by the screen reader, as it is
  477. // purely visual. Required state is set at the element level for
  478. // the screen reader.
  479. Roles.getTextboxRole().setAriaHiddenState(requiredIcon, true);
  480. }
  481. caption.appendChild(requiredIcon);
  482. } else if (requiredIcon != null) {
  483. requiredIcon.removeFromParent();
  484. requiredIcon = null;
  485. }
  486. // Error
  487. if (error != null && showError) {
  488. if (errorIcon == null) {
  489. errorIcon = DOM.createSpan();
  490. errorIcon.setClassName("v-errorindicator");
  491. }
  492. caption.appendChild(errorIcon);
  493. } else if (errorIcon != null) {
  494. errorIcon.removeFromParent();
  495. errorIcon = null;
  496. }
  497. if (caption != null) {
  498. // Styles
  499. caption.setClassName("v-caption");
  500. if (styles != null) {
  501. for (String style : styles) {
  502. caption.addClassName("v-caption-" + style);
  503. }
  504. }
  505. if (enabled) {
  506. caption.removeClassName("v-disabled");
  507. } else {
  508. caption.addClassName("v-disabled");
  509. }
  510. // Caption position
  511. if (captionText != null || icon != null) {
  512. setCaptionPosition(CaptionPosition.TOP);
  513. } else {
  514. setCaptionPosition(CaptionPosition.RIGHT);
  515. }
  516. }
  517. if (focusLost) {
  518. // Find out what element is currently focused.
  519. Element currentFocus = Util.getFocusedElement();
  520. if (currentFocus != null
  521. && currentFocus.equals(Document.get().getBody())) {
  522. // Focus has moved to BodyElement and should be moved back to
  523. // original location. This happened because of adding or
  524. // removing the captionWrap
  525. focusedElement.focus();
  526. } else if (currentFocus != focusedElement) {
  527. // Focus is either moved somewhere else on purpose or IE has
  528. // lost it. Investigate further.
  529. Timer focusTimer = new Timer() {
  530. @Override
  531. public void run() {
  532. if (Util.getFocusedElement() == null) {
  533. // This should never become an infinite loop and
  534. // even if it does it will be stopped once something
  535. // is done with the browser.
  536. schedule(25);
  537. } else if (Util.getFocusedElement().equals(
  538. Document.get().getBody())) {
  539. // Focus found it's way to BodyElement. Now it can
  540. // be restored
  541. focusedElement.focus();
  542. }
  543. }
  544. };
  545. if (BrowserInfo.get().isIE8()) {
  546. // IE8 can't fix the focus immediately. It will fail.
  547. focusTimer.schedule(25);
  548. } else {
  549. // Newer IE versions can handle things immediately.
  550. focusTimer.run();
  551. }
  552. }
  553. }
  554. }
  555. /**
  556. * Does the slot have a caption
  557. */
  558. public boolean hasCaption() {
  559. return caption != null;
  560. }
  561. /**
  562. * Get the slots caption element
  563. */
  564. public com.google.gwt.user.client.Element getCaptionElement() {
  565. return DOM.asOld(caption);
  566. }
  567. private boolean relativeWidth = false;
  568. /**
  569. * Set if the slot has a relative width
  570. *
  571. * @param relativeWidth
  572. * True if slot uses relative width, false if the slot has a
  573. * static width
  574. */
  575. public void setRelativeWidth(boolean relativeWidth) {
  576. this.relativeWidth = relativeWidth;
  577. updateRelativeSize(relativeWidth, "width");
  578. }
  579. public boolean hasRelativeWidth() {
  580. return relativeWidth;
  581. }
  582. private boolean relativeHeight = false;
  583. /**
  584. * Set if the slot has a relative height
  585. *
  586. * @param relativeHeight
  587. * True if the slot uses a relative height, false if the slot has
  588. * a static height
  589. */
  590. public void setRelativeHeight(boolean relativeHeight) {
  591. this.relativeHeight = relativeHeight;
  592. updateRelativeSize(relativeHeight, "height");
  593. }
  594. public boolean hasRelativeHeight() {
  595. return relativeHeight;
  596. }
  597. /**
  598. * Updates the captions size if the slot is relative
  599. *
  600. * @param isRelativeSize
  601. * Is the slot relatively sized
  602. * @param direction
  603. * The direction of the caption
  604. */
  605. private void updateRelativeSize(boolean isRelativeSize, String direction) {
  606. if (isRelativeSize && hasCaption()) {
  607. captionWrap.getStyle().setProperty(direction,
  608. getWidget().getElement().getStyle().getProperty(direction));
  609. captionWrap.addClassName("v-has-" + direction);
  610. } else if (hasCaption()) {
  611. if (direction.equals("height")) {
  612. captionWrap.getStyle().clearHeight();
  613. } else {
  614. captionWrap.getStyle().clearWidth();
  615. }
  616. captionWrap.removeClassName("v-has-" + direction);
  617. captionWrap.getStyle().clearPaddingTop();
  618. captionWrap.getStyle().clearPaddingRight();
  619. captionWrap.getStyle().clearPaddingBottom();
  620. captionWrap.getStyle().clearPaddingLeft();
  621. caption.getStyle().clearMarginTop();
  622. caption.getStyle().clearMarginRight();
  623. caption.getStyle().clearMarginBottom();
  624. caption.getStyle().clearMarginLeft();
  625. }
  626. }
  627. /*
  628. * (non-Javadoc)
  629. *
  630. * @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt
  631. * .user.client.Event)
  632. */
  633. @Override
  634. public void onBrowserEvent(Event event) {
  635. super.onBrowserEvent(event);
  636. if (DOM.eventGetType(event) == Event.ONLOAD
  637. && icon.getElement() == DOM.eventGetTarget(event)) {
  638. if (layout.getLayoutManager() != null) {
  639. layout.getLayoutManager().layoutLater();
  640. } else {
  641. layout.updateCaptionOffset(caption);
  642. }
  643. }
  644. }
  645. /*
  646. * (non-Javadoc)
  647. *
  648. * @see com.google.gwt.user.client.ui.SimplePanel#getContainerElement()
  649. */
  650. @Override
  651. protected com.google.gwt.user.client.Element getContainerElement() {
  652. if (captionWrap == null) {
  653. return getElement();
  654. } else {
  655. return DOM.asOld(captionWrap);
  656. }
  657. }
  658. /*
  659. * (non-Javadoc)
  660. *
  661. * @see com.google.gwt.user.client.ui.Widget#onDetach()
  662. */
  663. @Override
  664. protected void onDetach() {
  665. if (spacer != null) {
  666. spacer.removeFromParent();
  667. }
  668. super.onDetach();
  669. }
  670. /*
  671. * (non-Javadoc)
  672. *
  673. * @see com.google.gwt.user.client.ui.Widget#onAttach()
  674. */
  675. @Override
  676. protected void onAttach() {
  677. super.onAttach();
  678. if (spacer != null) {
  679. getElement().getParentElement().insertBefore(spacer, getElement());
  680. }
  681. }
  682. public boolean isRelativeInDirection(boolean vertical) {
  683. if (vertical) {
  684. return hasRelativeHeight();
  685. } else {
  686. return hasRelativeWidth();
  687. }
  688. }
  689. }