001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Darrell Meyer <darrell@mygwt.net> - derived implementation
011: *******************************************************************************/package net.mygwt.ui.client.widget;
012:
013: import net.mygwt.ui.client.Events;
014: import net.mygwt.ui.client.MyDOM;
015: import net.mygwt.ui.client.Style;
016: import net.mygwt.ui.client.event.BaseEvent;
017: import net.mygwt.ui.client.event.Listener;
018: import net.mygwt.ui.client.event.ShellListener;
019: import net.mygwt.ui.client.event.TypedListener;
020: import net.mygwt.ui.client.fx.Draggable;
021: import net.mygwt.ui.client.fx.FXStyle;
022: import net.mygwt.ui.client.fx.Resizable;
023: import net.mygwt.ui.client.util.Format;
024: import net.mygwt.ui.client.util.Markup;
025: import net.mygwt.ui.client.util.Rectangle;
026:
027: import com.google.gwt.user.client.Command;
028: import com.google.gwt.user.client.DOM;
029: import com.google.gwt.user.client.DeferredCommand;
030: import com.google.gwt.user.client.Element;
031: import com.google.gwt.user.client.Event;
032: import com.google.gwt.user.client.EventPreview;
033: import com.google.gwt.user.client.ui.Frame;
034: import com.google.gwt.user.client.ui.HasText;
035: import com.google.gwt.user.client.ui.KeyboardListener;
036: import com.google.gwt.user.client.ui.RootPanel;
037: import com.google.gwt.user.client.ui.WidgetHelper;
038:
039: /**
040: * A <code>Shell</code> is a window with a header and content area. If the
041: * shell locations is not set either by calling {@link #setPagePosition} or
042: * #setBounds it will be centered when opened.
043: *
044: * <p>
045: * Shells must have a pixel width. If a width is not set the default width will
046: * be used. Default width is 250. If a height is not specified it will be
047: * determined by the size of the content.
048: * </p>
049: *
050: * <dl>
051: * <dt><b>Styles:</b></dt>
052: * <dd>CLOSE, RESIZE, MODAL, AUTO_HIDE</dd>
053: * <p>
054: * <dt><b>Events:</b></dt>
055: *
056: * <dd><b>Activate</b> : (widget)<br>
057: * <div>Fires after a shell is activated (receives focus).</div>
058: * <ul>
059: * <li>widget : this</li>
060: * </ul>
061: * </dd>
062: *
063: * <dd><b>Deactivate</b> : (widget)<br>
064: * <div>Fires after a shell is deactivated.</div>
065: * <ul>
066: * <li>widget : this</li>
067: * </ul>
068: * </dd>
069: *
070: * <dd><b>BeforeClose</b> : (widget)<br>
071: * <div>Fires before a shell is closed. Listeners can set the <code>doit</code>
072: * field to <code>false</code> to cancel the operation.</div>
073: * <ul>
074: * <li>widget : this</li>
075: * </ul>
076: * </dd>
077: *
078: * <dd><b>Close</b> : (widget)<br>
079: * <div>Fires after a shell is closed.</div>
080: * <ul>
081: * <li>widget : this</li>
082: * </ul>
083: * </dd>
084: *
085: * <dd><b>BeforeShow</b> : (widget)<br>
086: * <div>Fires before the shell is opened. Listeners can set the
087: * <code>doit</code> field to <code>false</code> to cancel the operation.</div>
088: * <ul>
089: * <li>widget : this</li>
090: * </ul>
091: * </dd>
092: *
093: * <dd><b>Show</b> : (widget)<br>
094: * <div>Fires after the shell is opened.</div>
095: * <ul>
096: * <li>widget : this</li>
097: * </ul>
098: * </dd>
099: *
100: * <dd><b>KeyPress</b> : (widget, event)<br>
101: * <div>Fires after a key is pressed.</div>
102: * <ul>
103: * <li>widget : this</li>
104: * <li>event : event</li>
105: * </ul>
106: * </dd>
107: *
108: * <dt><b>CSS Styles:</b></dt>
109: * <dd>.my-shell { the shell itself }</dd>
110: * <dd>.my-shell-hdr { header }</dd>
111: * <dd>.my-shell-hdr-text { header text }</dd>
112: * <dd>.my-shell-body { body }</dd>
113: * <dd>.my-shell-plain { add for plain content area }</dd>
114: * </dl>
115: */
116: public class Shell extends Component implements HasText {
117:
118: protected WidgetContainer content;
119: protected Element bodyWrapper, bodyWrapperInner, bodyElem,
120: contentElem, footerElem;
121: protected Shadow shadow;
122:
123: private int minimumWidth = 200;
124: private int minimumHeight = 100;
125: private boolean animate = false;
126: private int shadowPosition = Style.SIDES;
127: private int animateDuration = 300;
128: private boolean blinkModal = true;
129: private boolean keepLastBounds = true;
130: private Item header;
131: private ModalPanel modal;
132: private ToolButton closeBtn;
133: private Draggable draggable;
134: private Resizable resizer;
135: private boolean drag = true, resize;
136: private boolean showing, resizing, created, autoHide;
137: private Listener dragListener;
138: private EventPreview eventPreview;
139: private Rectangle lastBounds;
140: private FramePanel framePanel;
141:
142: /**
143: * Creates a new window that is initialy invisible. A new shell is created
144: * with default style settings.
145: * <p>
146: * Default styles: CLOSE, RESIZE.
147: * </p>
148: */
149: public Shell() {
150: this (Style.CLOSE | Style.RESIZE);
151: }
152:
153: /**
154: * Creates a new shell instance.
155: *
156: * @param style the style information
157: */
158: public Shell(int style) {
159: this .style = style;
160: baseStyle = "my-shell";
161: header = new Item("my-shell-hdr") {
162: protected void onClick(BaseEvent be) {
163: super .onClick(be);
164: activateShell(be.event);
165: }
166: };
167: content = new WidgetContainer();
168: content.setStyleAttribute("position", "relative");
169:
170: autoHide = (style & Style.AUTO_HIDE) != 0;
171: resize = (style & Style.RESIZE) != 0;
172: }
173:
174: /**
175: * Adds a listener interface to receive shell events.
176: *
177: * @param listener the listener to be added
178: */
179: public void addShellListener(ShellListener listener) {
180: TypedListener typedListener = new TypedListener(listener);
181: addListener(Events.Activate, typedListener);
182: addListener(Events.Deactivate, typedListener);
183: addListener(Events.Close, typedListener);
184: }
185:
186: /**
187: * Centers the shell.
188: */
189: public void center() {
190: if (rendered) {
191: MyDOM.center(getElement());
192: onResize(getWidth(), getHeight());
193: }
194: }
195:
196: /**
197: * Closes the shell.
198: */
199: public void close() {
200: if (!showing) {
201: return;
202: }
203: if (!fireEvent(Events.BeforeClose)) {
204: return;
205: }
206: showing = false;
207:
208: lastBounds = getBounds();
209:
210: if (animate) {
211: FXStyle fx = new FXStyle(getElement());
212: fx.duration = animateDuration;
213: fx.addListener(Events.EffectComplete, new Listener() {
214: public void handleEvent(BaseEvent be) {
215: afterHide();
216: }
217: });
218: fx.fadeOut();
219: } else {
220: afterHide();
221: }
222:
223: ShellManager.get().unregister(this );
224: }
225:
226: /**
227: * Returns <code>true</code> if animations are enabled.
228: *
229: * @return the animate state
230: */
231: public boolean getAnimate() {
232: return animate;
233: }
234:
235: /**
236: * Returns the animation duration.
237: *
238: * @return the duration in milliseconds
239: */
240: public int getAnimateDuration() {
241: return animateDuration;
242: }
243:
244: /**
245: * Returns <code>true</code> if auto hide is enabled.
246: *
247: * @return the auto hide state
248: */
249: public boolean getAutoHide() {
250: return autoHide;
251: }
252:
253: /**
254: * Returns the blink modal state.
255: *
256: * @return <code>true</code> if blinking is enabled
257: */
258: public boolean getBlinkModal() {
259: return blinkModal;
260: }
261:
262: /**
263: * Returns the content panel of the shell.
264: *
265: * @return the panel
266: */
267: public WidgetContainer getContent() {
268: return content;
269: }
270:
271: /**
272: * Returns the shell's draggable instance. This method will cause the shell to
273: * be rendered.
274: *
275: * @return the draggable instance
276: */
277: public Draggable getDraggable() {
278: if (!isRendered()) {
279: getElement();
280: }
281: return draggable;
282: }
283:
284: /**
285: * Returns the shell's header.
286: *
287: * @return the header
288: */
289: public Item getHeader() {
290: return header;
291: }
292:
293: /**
294: * Returns <code>true</code> if the shell will remember its last postion.
295: *
296: * @return the keep last bounds state
297: */
298: public boolean getKeepLastBounds() {
299: return keepLastBounds;
300: }
301:
302: /**
303: * Returns the minimum height.
304: *
305: * @return the minimu height
306: */
307: public int getMinimumHeight() {
308: return minimumHeight;
309: }
310:
311: /**
312: * Returns the minimum width.
313: *
314: * @return the minimum width
315: */
316: public int getMinimumWidth() {
317: return minimumWidth;
318: }
319:
320: /**
321: * Returns the shadow position.
322: *
323: * @return the shadow position
324: */
325: public int getShadowPosition() {
326: return shadowPosition;
327: }
328:
329: /**
330: * Returns the shell's header text.
331: *
332: * @return the text
333: */
334: public String getText() {
335: return header.getText();
336: }
337:
338: public void hide() {
339: super .hide();
340: if (shadow != null && !isVisible()) {
341: shadow.hide();
342: }
343: }
344:
345: /**
346: * Returns <code>true</code> if dragging is enabled.
347: *
348: * @return the drag enabled state
349: */
350: public boolean isDragEnabled() {
351: return drag;
352: }
353:
354: public void onBrowserEvent(Event event) {
355: if (DOM.eventGetType(event) == Event.ONCLICK) {
356: activateShell(event);
357: }
358: }
359:
360: /**
361: * Opens the shell.
362: */
363: public void open() {
364: if (!rendered) {
365: render();
366: }
367:
368: if (showing) {
369: return;
370: }
371:
372: if (!fireEvent(Events.BeforeOpen)) {
373: return;
374: }
375:
376: // when removing from panel, position gets removed
377: setStyleAttribute("position", "absolute");
378:
379: showing = true;
380:
381: if (!created) {
382: createContent(getContent());
383: created = true;
384: }
385:
386: if (modal != null) {
387: modal.show(this );
388: } else {
389: RootPanel.get().add(this );
390: }
391:
392: int width = Math.max(minimumWidth, getOffsetWidth());
393:
394: if (width == minimumWidth) {
395: setWidth(width);
396: }
397:
398: if (resizer != null) {
399: resizer.minHeight = minimumHeight;
400: resizer.minWidth = minimumWidth;
401: }
402:
403: if (keepLastBounds && lastBounds != null) {
404: MyDOM.setLeftTop(getElement(), lastBounds.x, lastBounds.y);
405: setSize(lastBounds.width, lastBounds.height);
406: onResize(lastBounds.width, lastBounds.height);
407: } else {
408: int x = MyDOM.getLeft(getElement());
409: int y = MyDOM.getTop(getElement());
410: // not positioned then center
411: if (x < 1 || y < 1) {
412: MyDOM.center(getElement());
413: y = MyDOM.getTop(getElement());
414: if (y < 0) {
415: setPagePosition(MyDOM.getLeft(getElement()), 4);
416: }
417: }
418: }
419:
420: ShellManager.get().register(this );
421: ShellManager.get().setActive(this );
422:
423: final Shell fShell = this ;
424:
425: framePanel.onShow(getElement());
426: int z = Math.max(100, DOM.getIntStyleAttribute(getElement(),
427: "zIndex"));
428: framePanel.setZIndex(z);
429:
430: if (animate) {
431: FXStyle fx = new FXStyle(getElement());
432: if (shadow != null) {
433: fx.addListener(Events.EffectComplete, new Listener() {
434: public void handleEvent(BaseEvent be) {
435: shadow.show(fShell);
436: afterShow();
437: }
438: });
439: }
440: fx.duration = animateDuration;
441: fx.fadeIn();
442: } else {
443: if (shadow != null) {
444: shadow.setVisible(true);
445: shadow.show(this );
446: }
447: afterShow();
448: }
449:
450: }
451:
452: /**
453: * Removes a previously added listener interface.
454: *
455: * @param listener the listener interface to remove
456: */
457: public void removeShellListener(ShellListener listener) {
458: unhook(Events.Activate, listener);
459: unhook(Events.Deactivate, listener);
460: unhook(Events.Close, listener);
461: }
462:
463: /**
464: * Specifies if the the open and closing of the shell should be animated.
465: * Default value is <code>false</code>.
466: *
467: * @param animate <code>true</code> to enable animations
468: */
469: public void setAnimate(boolean animate) {
470: this .animate = animate;
471: }
472:
473: /**
474: * Specifies the length of the fade effect. Default value is 300;
475: *
476: * @param animateDuration the duration in milliseconds
477: */
478: public void setAnimateDuration(int animateDuration) {
479: this .animateDuration = animateDuration;
480: }
481:
482: /**
483: * Sets the auto hide state. Has no effect if called after the
484: *
485: * @param autoHide <code>true</code> to auto hide
486: */
487: public void setAutoHide(boolean autoHide) {
488: this .autoHide = autoHide;
489: }
490:
491: /**
492: * Specifies if the shell should blink when clicks occur outside it's
493: * boundaries. When <code>true</code>, close() should not be called within
494: * any button listeners. Default value is <code>true</code>.
495: *
496: * @param blinkModal <code>true</code> to enable blinking
497: */
498: public void setBlinkModal(boolean blinkModal) {
499: this .blinkModal = blinkModal;
500: }
501:
502: /**
503: * Enables and disables shell dragging.
504: *
505: * @param enabled the drag enabled state
506: */
507: public void setDragEnabled(boolean enabled) {
508: this .drag = enabled;
509: if (draggable != null) {
510: draggable.setEnabled(enabled);
511: String c = enabled ? "move" : "default";
512: header.setStyleAttribute("cursor", c);
513: }
514: }
515:
516: /**
517: * Sets the shell's header icon.
518: *
519: * @param style the icon style
520: */
521: public void setIconStyle(String style) {
522: header.setIconStyle(style);
523: }
524:
525: /**
526: * Specifies if the shell should be returned to the same size and location
527: * when it was last closed. Default value is <code>true</code>.
528: *
529: * @param keepLastBounds <code>true</code> to enable
530: */
531: public void setKeepLastBounds(boolean keepLastBounds) {
532: this .keepLastBounds = keepLastBounds;
533: }
534:
535: /**
536: * Sets the shell's location based on page coordinates.
537: *
538: * @param x the x coordinate
539: * @param y the y coordinate
540: */
541: public void setPagePosition(int x, int y) {
542: // will cause render
543: MyDOM.setLeftTop(getElement(), x, y);
544: if (shadow != null) {
545: shadow.sync(getBounds());
546: }
547: }
548:
549: /**
550: * Specifies the minimum height. Default value is 100;
551: *
552: * @param minimumHeight the minimum height
553: */
554: public void setMinimumHeight(int minimumHeight) {
555: this .minimumHeight = minimumHeight;
556: }
557:
558: /**
559: * Sets the shell's minimum size to the size specified by the arguments.
560: *
561: * @param width the minimum width
562: * @param height the minimum height
563: */
564: public void setMinimumSize(int width, int height) {
565: minimumWidth = width;
566: minimumHeight = height;
567: }
568:
569: /**
570: * Specifies the minimum width. Default value is 200.
571: *
572: * @param minimumWidth the minium width
573: */
574: public void setMinimumWidth(int minimumWidth) {
575: this .minimumWidth = minimumWidth;
576: }
577:
578: /**
579: * Enables and disables shell resizing. Only applies to shell's with a RESIZE
580: * style. Does nothing if called before shell is rendered.
581: *
582: * @param enabled the resize enabled state
583: */
584: public void setResizeEnabled(boolean enabled) {
585: this .resize = enabled;
586: if (resizer != null) {
587: resizer.setEnabled(enabled);
588: }
589: }
590:
591: /**
592: * Specifies the shadow position. Valid values are NONE, DROP, SIDES, FRAME.
593: * Default values is SIDES.
594: *
595: * @param shadowPosition the shadow position
596: */
597: public void setShadowPosition(int shadowPosition) {
598: this .shadowPosition = shadowPosition;
599: }
600:
601: /**
602: * Sets the shell's style. Has no effect if called after the shell has been
603: * rendered.
604: *
605: * @param style the style
606: */
607: public void setStyle(int style) {
608: if (!isRendered()) {
609: this .style = style;
610: }
611: }
612:
613: /**
614: * Sets the shell's header text.
615: *
616: * @param text the text
617: */
618: public void setText(String text) {
619: header.setText(text);
620: }
621:
622: /**
623: * Sets a url for the content area of the shell.
624: *
625: * @param url the url
626: * @return the frame widget
627: */
628: public Frame setURL(String url) {
629: Frame f = new Frame(url);
630: MyDOM.setStyleAttribute(f.getElement(), "frameborder", "0");
631: f.setSize("100%", "100%");
632: getContent().removeAll();
633: getContent().add(f);
634: return f;
635: }
636:
637: public void show() {
638: super .show();
639: if (shadow != null && isVisible()) {
640: shadow.show();
641: }
642: }
643:
644: protected void activateShell(Event event) {
645: // ignore close button
646: if (closeBtn != null) {
647: if (DOM.isOrHasChild(closeBtn.getElement(), DOM
648: .eventGetTarget(event))) {
649: return;
650: }
651: }
652: ShellManager.get().setActive(this );
653: }
654:
655: protected void afterHide() {
656: RootPanel.get().remove(this );
657: framePanel.onHide(getElement());
658: resizing = false;
659:
660: if (shadow != null) {
661: shadow.remove();
662: }
663:
664: if (modal != null) {
665: modal.hide();
666: }
667:
668: if (eventPreview != null) {
669: DOM.removeEventPreview(eventPreview);
670: }
671:
672: fireEvent(Events.Close);
673: }
674:
675: protected void afterShow() {
676: if (eventPreview != null) {
677: DOM.addEventPreview(eventPreview);
678: }
679: if (resizer != null) {
680: setBounds(getBounds());
681: }
682: content.setStyleAttribute("overflow", "auto");
683: fireEvent(Events.Open);
684: }
685:
686: /**
687: * Subclasses should override and add content to container.
688: *
689: * @param container the content container
690: */
691: protected void createContent(WidgetContainer container) {
692:
693: }
694:
695: protected void doAttachChildren() {
696: WidgetHelper.doAttach(header);
697: WidgetHelper.doAttach(content);
698: }
699:
700: protected void doDetachChildren() {
701: WidgetHelper.doDetach(header);
702: WidgetHelper.doDetach(content);
703: }
704:
705: protected void onKeyPress(Event event) {
706: int keyCode = DOM.eventGetKeyCode(event);
707: if (keyCode == KeyboardListener.KEY_ESCAPE) {
708: close();
709: }
710: }
711:
712: protected void onRender() {
713: super .onRender();
714: setElement(DOM.createDiv());
715: setStyleName(baseStyle);
716: MyDOM.setStyleAttribute(getElement(), "position", "absolute");
717:
718: if (!header.isRendered()) {
719: header.baseStyle = baseStyle + "-hdr";
720: }
721: DOM.appendChild(getElement(), header.getElement());
722:
723: String html = Format.substitute(Markup.BOTTOM_BOX, baseStyle
724: + "-body");
725: bodyWrapper = MyDOM.create("<div>" + html + "</div>");
726: bodyWrapperInner = DOM.getFirstChild(bodyWrapper);
727: bodyElem = DOM.getFirstChild(bodyWrapperInner);
728: contentElem = MyDOM.findChild(baseStyle + "-body-mc", bodyElem);
729: footerElem = MyDOM.findChild(baseStyle + "-body-bc", bodyElem);
730: DOM.appendChild(getElement(), bodyWrapper);
731:
732: DOM.appendChild(contentElem, content.getElement());
733:
734: // close button
735: if ((style & Style.CLOSE) != 0) {
736: closeBtn = new ToolButton("my-tool-close");
737: closeBtn.addListener(Events.Click, new Listener() {
738: public void handleEvent(BaseEvent be) {
739: close();
740: }
741: });
742: header.addWidget(closeBtn);
743: }
744:
745: eventPreview = new EventPreview() {
746: public boolean onEventPreview(Event event) {
747: if (autoHide) {
748: Element target = DOM.eventGetTarget(event);
749: if (!DOM.isOrHasChild(getElement(), target)) {
750: if (DOM.eventGetType(event) == Event.ONCLICK) {
751: if (resizing) {
752: // ignore
753: resizing = false;
754: return false;
755: }
756: close();
757: return false;
758: }
759: }
760: }
761: int type = DOM.eventGetType(event);
762: if (type == Event.ONKEYPRESS) {
763: onKeyPress(event);
764: }
765: if (modal != null && modal.isVisible()) {
766: modal.onEventPreview(event);
767: }
768: return true;
769: }
770: };
771:
772: // resizable
773: if (resize) {
774: resizer = new Resizable(this );
775: resizer.minWidth = minimumWidth;
776: resizer.minHeight = minimumHeight;
777:
778: resizer.addListener(Events.ResizeStart, new Listener() {
779: public void handleEvent(BaseEvent be) {
780: resizing = true;
781: }
782: });
783: } else {
784: setResizeEnabled(false);
785: }
786:
787: if ((style & Style.MODAL) != 0) {
788: modal = new ModalPanel();
789: modal.setBlinkEnabled(blinkModal);
790: }
791:
792: framePanel = FramePanel.pop();
793:
794: dragListener = new Listener() {
795: public void handleEvent(BaseEvent be) {
796: switch (be.type) {
797: case Events.DragStart:
798: MyDOM.addStyleName(bodyWrapper, baseStyle
799: + "-body-wrapper");
800: MyDOM.addStyleName(bodyWrapperInner, baseStyle
801: + "-body-wrapper-inner");
802: MyDOM.setVisible(bodyElem, false);
803: if (shadow != null) {
804: shadow.setVisible(false);
805: }
806: break;
807: case Events.DragMove:
808: framePanel.sync(getElement());
809: break;
810: case Events.DragEnd:
811: MyDOM.removeStyleName(bodyWrapper, baseStyle
812: + "-body-wrapper");
813: MyDOM.removeStyleName(bodyWrapperInner, baseStyle
814: + "-body-wrapper-inner");
815: MyDOM.setVisible(bodyElem, true);
816:
817: int z = Math.max(100, DOM.getIntStyleAttribute(
818: getElement(), "zIndex"));
819: framePanel.setZIndex(z);
820:
821: if (shadow != null) {
822: shadow.setVisible(true);
823: shadow.sync(getBounds());
824: }
825: // split bars are added to rootpanel and will not get updated when
826: // shell is moved.
827: SplitBar.updateHandles();
828:
829: framePanel.sync(getElement());
830: break;
831: }
832: }
833:
834: };
835:
836: draggable = new Draggable(this , header);
837: draggable.useProxy = false;
838: draggable.addListener(Events.DragStart, dragListener);
839: draggable.addListener(Events.DragMove, dragListener);
840: draggable.addListener(Events.DragEnd, dragListener);
841:
842: if (!drag) {
843: setDragEnabled(false);
844: }
845:
846: if (shadowPosition != Style.NONE) {
847: shadow = new Shadow(shadowPosition);
848: }
849:
850: if (attachBounds.width == Style.DEFAULT) {
851: setWidth(250);
852: }
853:
854: sinkEvents(Event.ONCLICK | Event.KEYEVENTS | Event.MOUSEEVENTS);
855: }
856:
857: protected void onResize(int width, int height) {
858: int h = height;
859: int w = width;
860:
861: if (h == Style.DEFAULT) {
862: h = getOffsetHeight();
863: }
864:
865: if (getOffsetHeight() < minimumHeight) {
866: MyDOM.setHeight(getElement(), minimumHeight);
867: h = minimumHeight;
868: }
869:
870: w -= 12;
871: h -= header.getHeight();
872: MyDOM.setHeight(bodyWrapper, h);
873: MyDOM.setHeight(bodyWrapperInner, h);
874:
875: h -= MyDOM.getHeight(footerElem);
876:
877: // adjust for borders of center content
878: w -= MyDOM
879: .getBorderWidth(contentElem, Style.LEFT | Style.RIGHT);
880: h -= MyDOM
881: .getBorderWidth(contentElem, Style.TOP | Style.BOTTOM);
882:
883: if (width != Style.DEFAULT) {
884: MyDOM.setWidth(content.getElement(), w);
885: }
886:
887: if (h > 10) {
888: MyDOM.setHeight(content.getElement(), h);
889: }
890:
891: content.layout(true);
892:
893: if (shadow != null) {
894: shadow.sync(getBounds());
895: }
896:
897: int ow = getOffsetWidth();
898: ow = Math.max(ow, MyDOM.getWidth(bodyElem));
899:
900: if (ow > width) {
901: setWidth(ow);
902: return;
903: }
904:
905: DeferredCommand.addCommand(new Command() {
906: public void execute() {
907: SplitBar.updateHandles();
908: }
909: });
910: }
911: }
|