001: /*
002: * GWT-Ext Widget Library
003: * Copyright(c) 2007-2008, GWT-Ext.
004: * licensing@gwt-ext.com
005: *
006: * http://www.gwt-ext.com/license
007: */
008: package com.gwtext.client.widgets;
009:
010: import com.google.gwt.core.client.JavaScriptObject;
011: import com.google.gwt.user.client.Element;
012: import com.google.gwt.user.client.Timer;
013: import com.gwtext.client.core.Box;
014: import com.gwtext.client.core.Function;
015: import com.gwtext.client.core.Size;
016: import com.gwtext.client.widgets.event.BoxComponentListener;
017:
018: /**
019: * Base class for any visual {@link Component} that uses a box container. BoxComponent provides automatic box model adjustments
020: * for sizing and positioning and will work correctly withnin the Component rendering model. All container classes should subclass
021: * BoxComponent so that they will work consistently when nested within other Ext layout containers.
022: */
023: public class BoxComponent extends Component {
024:
025: private static JavaScriptObject configPrototype;
026:
027: static {
028: init();
029: }
030:
031: private static native void init()/*-{
032: var c = new $wnd.Ext.BoxComponent();
033: @com.gwtext.client.widgets.BoxComponent::configPrototype = c.initialConfig;
034: }-*/;
035:
036: protected JavaScriptObject getConfigPrototype() {
037: return configPrototype;
038: }
039:
040: public String getXType() {
041: return "box";
042: }
043:
044: public BoxComponent() {
045: }
046:
047: public BoxComponent(JavaScriptObject jsObj) {
048: super (jsObj);
049: }
050:
051: public BoxComponent(Element element) {
052: super (element);
053: }
054:
055: protected native JavaScriptObject create(JavaScriptObject config) /*-{
056: return new $wnd.Ext.BoxComponent(config);
057: }-*/;
058:
059: /**
060: * Gets the current box measurements of the component's.
061: *
062: * @return the box measurements
063: */
064: public native Box getBox()/*-{
065: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
066: var boxJS = component.getBox();
067: return @com.gwtext.client.core.Box::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(boxJS);
068: }-*/;
069:
070: /**
071: * Gets the current box measurements of the component's.
072: *
073: * @param local if true the element's left and top are returned instead of page XY (defaults to false)
074: * @return the box measurements
075: */
076: public native Box getBox(boolean local)/*-{
077: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
078: var boxJS = component.getBox(local);
079: return @com.gwtext.client.core.Box::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(boxJS);
080: }-*/;
081:
082: /**
083: * Gets the current XY position of the component's underlying element.
084: *
085: * @return the XY position
086: */
087: public native int[] getPosition() /*-{
088: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
089: var arrJS = component.getPosition();
090: return @com.gwtext.client.util.JavaScriptObjectHelper::convertToJavaIntArray(Lcom/google/gwt/core/client/JavaScriptObject;)(arrJS);
091: }-*/;
092:
093: /**
094: * Gets the current XY position of the component's underlying element.
095: *
096: * @return the XY position
097: * @param local if true the element's left and top are returned instead of page XY (defaults to false)
098: */
099: public native int[] getPosition(boolean local) /*-{
100: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
101: var arrJS = component.getPosition();
102: return @com.gwtext.client.util.JavaScriptObjectHelper::convertToJavaIntArray(Lcom/google/gwt/core/client/JavaScriptObject;)(arrJS);
103: }-*/;
104:
105: /**
106: * Gets the current size of the component's underlying element.
107: *
108: * @return the components Size
109: */
110: public native Size getSize()/*-{
111: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
112: var sizeJS = component.getSize();
113: return @com.gwtext.client.core.Size::instance(Lcom/google/gwt/core/client/JavaScriptObject;)(sizeJS);
114: }-*/;
115:
116: /**
117: * Sets the page XY position of the component. To set the left and top instead, use setPosition.
118: * This method fires the move event.
119: *
120: * @param x the new X position
121: * @param y the new Y opsition
122: */
123: public native void setPagePosition(int x, int y) /*-{
124: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
125: component.setPagePosition(x, y);
126: }-*/;
127:
128: /**
129: * Sets the left and top of the component. To set the page XY position instead, use setPagePosition.
130: * This method fires the move event.
131: *
132: * @param left the new left
133: * @param top the new right
134: */
135: public native void setPosition(int left, int top) /*-{
136: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
137: component.setPosition(left, top);
138: }-*/;
139:
140: /**
141: * Sets the width and height of the component. This method fires the resize event.
142: *
143: * @param width the new width
144: * @param height the new height
145: */
146: private void setSize(int width, int height) {
147: if (!isRendered()) {
148: setWidth(width);
149: setHeight(height);
150: } else {
151: setSizeRendered(width, height);
152: }
153: }
154:
155: private native void setSizeRendered(int width, int height) /*-{
156: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
157: component.setSize(width, height);
158: }-*/;
159:
160: /**
161: * Force the component's size to recalculate based on the underlying element's current height and width.
162: */
163: public native void syncSize()/*-{
164: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
165: component.syncSize();
166: }-*/;
167:
168: /**
169: * Sets the current box measurements of the component's underlying element.
170: *
171: * @param box the new box measurements
172: */
173: public native void updateBox(Box box)/*-{
174: var component = this.@com.gwtext.client.widgets.Component::getOrCreateJsObj()();
175: var boxJS = box.@com.gwtext.client.core.JsObject::getJsObj()();
176: component.updateBox(boxJS);
177: }-*/;
178:
179: /**
180: * Add a Component listener.
181: *
182: * @param listener the listener
183: */
184: protected native void addListener(BoxComponentListener listener) /*-{
185: this.@com.gwtext.client.widgets.Component::addListener(Lcom/gwtext/client/widgets/event/ComponentListener;)(listener);
186: var componentJ = this;
187:
188: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('move',
189: function(source, x, y) {
190: listener.@com.gwtext.client.widgets.event.BoxComponentListener::onMove(Lcom/gwtext/client/widgets/BoxComponent;II)(componentJ, x, y)
191: }
192: );
193:
194: this.@com.gwtext.client.widgets.Component::addListener(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)('resize',
195: function(source, adjWidth, adjHeight, rawWidth, rawHeight) {
196:
197: if(adjWidth == null || adjWidth === undefined) adjWidth = 0;
198: if(adjHeight == null || adjHeight === undefined) adjHeight = 0;
199: if(rawWidth == null || rawWidth === undefined) rawWidth = 0;
200: if(rawHeight == null || rawHeight === undefined) rawHeight = 0;
201: if(typeof adjWidth == 'string') adjWidth = -1;
202: if(typeof adjHeight == 'string') adjHeight = -1;
203: if(typeof rawWidth == 'string') rawWidth = -1;
204: if(typeof rawHeight == 'string') rawHeight = -1;
205: listener.@com.gwtext.client.widgets.event.BoxComponentListener::onResize(Lcom/gwtext/client/widgets/BoxComponent;IIII)(componentJ, adjWidth, adjHeight, rawWidth, rawHeight);
206: }
207: );
208: }-*/;
209:
210: /**
211: * Runs the specified function when the Component is rendered.
212: *
213: * @param function the function to execute on render
214: */
215: public void doOnRender(Function function) {
216: if (!isRendered()) {
217: addListener("render", function);
218: } else {
219: throw new IllegalStateException(
220: "The component is already rendered");
221: }
222: }
223:
224: /**
225: * Runs the specified function when the Component is rendered.
226: *
227: * @param function the function to execute on render
228: * @param delayMillis a delay in milliseconds
229: */
230: public void doOnRender(final Function function,
231: final int delayMillis) {
232: if (!isRendered()) {
233: addListener("render", new Function() {
234: public void execute() {
235: new Timer() {
236: public void run() {
237: function.execute();
238: }
239: }.schedule(delayMillis);
240: }
241: });
242: } else {
243: throw new IllegalStateException(
244: "The component is already rendered");
245: }
246: }
247:
248: // --- config properties ---
249:
250: /**
251: * True to use height:'auto', false to use fixed height (defaults to false).
252: *
253: * <br><br>
254: * <b>Note:</b> This property cannot be changed after the Component has been rendered.
255: *
256: * @param autoHeight true to use auto height
257: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
258: */
259: public void setAutoHeight(boolean autoHeight)
260: throws IllegalStateException {
261: setAttribute("autoHeight", autoHeight, true);
262: }
263:
264: /**
265: *
266: * @return true if using auto height, else false
267: */
268: public boolean getAutoHeight() {
269: return getAttributeAsBoolean("autoHeight");
270: }
271:
272: /**
273: * True to use width:'auto', false to use fixed width (defaults to false).
274: *
275: * @param autoWidth true for auto width
276: * @throws IllegalStateException this property cannot be changed after the Component has been rendered
277: */
278: public void setAutoWidth(boolean autoWidth)
279: throws IllegalStateException {
280: setAttribute("autoWidth", autoWidth, true);
281: }
282:
283: /**
284: * @return true if using auto width, else false
285: */
286: public boolean getAutoWidth() {
287: return getAttributeAsBoolean("autoWidth");
288: }
289:
290: /**
291: * The height of this component in pixels (defaults to auto).
292: *
293: * @param height the component height
294: */
295: public void setHeight(int height) {
296: if (!isRendered()) {
297: if (height == -1) {
298: setAttribute("height", "auto", true);
299: } else {
300: setAttribute("height", height, true);
301: }
302: } else {
303: super .setHeight(height + "px");
304: }
305: }
306:
307: /**
308: * Set the height in pixels or auto. Note that setting percentage based heights will lead to unpredictable
309: * display behavior. You should use the various layouts like {@link com.gwtext.client.widgets.layout.AnchorLayout}
310: * to control percentage based rendering of components.
311: *
312: * @param height the component height
313: */
314: public void setHeight(String height) {
315: if (!isRendered()) {
316: if (height.indexOf("px") != -1) {
317: height = height.replaceAll("px", "").trim();
318: setHeight(Integer.parseInt(height));
319: } else if (height.trim().equalsIgnoreCase("auto")) {
320: setAutoHeight(true);
321: } else {
322: setAttribute("height", height, true);
323: }
324: } else {
325: super .setHeight(height);
326: }
327: }
328:
329: /**
330: * The height of this component in pixels.
331: *
332: * @return the hieght of the component in pixels
333: */
334: public int getHeight() {
335: if (!isRendered()) {
336: String height = getAttribute("height");
337: if (height.equals("auto")) {
338: return -1;
339: } else {
340: return Integer.parseInt(height);
341: }
342: } else {
343: return getEl().getHeight();
344: }
345: }
346:
347: /**
348: * The component width. (defaults to auto)
349: *
350: * @param width the width, -1 for auto
351: */
352: public void setWidth(int width) {
353: if (!isRendered()) {
354: if (width == -1) {
355: setAttribute("width", "auto", true);
356: } else {
357: setAttribute("width", width, true);
358: }
359: } else {
360: super .setWidth(width + "px");
361: }
362: }
363:
364: /**
365: * Set the width in pixels or auto. Note that setting percentage based widths will lead to unpredictable
366: * display behavior. You should use the various layouts like {@link com.gwtext.client.widgets.layout.AnchorLayout}
367: * to control percentage based rendering of components.
368: *
369: * @param width the component height
370: */
371: public void setWidth(String width) {
372: if (!isRendered()) {
373: if (width.indexOf("px") != -1) {
374: width = width.replaceAll("px", "").trim();
375: setWidth(Integer.parseInt(width));
376: } else if (width.trim().equalsIgnoreCase("auto")) {
377: setAutoWidth(true);
378: } else {
379: setAttribute("width", width, true);
380: }
381: } else {
382: super .setWidth(width);
383: }
384: }
385:
386: /**
387: * The component width.
388: *
389: * @return the component width, -1 for auto
390: */
391: public int getWidth() {
392: if (isRendered()) {
393: return getEl().getWidth();
394: } else {
395: String width = getAttribute("width");
396: if (width.equals("auto")) {
397: return -1;
398: } else {
399: return Integer.parseInt(width);
400: }
401: }
402: }
403: }
|