KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > user > client > ui > Widget


1 /*
2  * Copyright 2007 Google Inc.
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.google.gwt.user.client.ui;
17
18 import com.google.gwt.core.client.GWT;
19 import com.google.gwt.user.client.DOM;
20 import com.google.gwt.user.client.Event;
21 import com.google.gwt.user.client.EventListener;
22 import com.google.gwt.user.client.Element;
23
24 /**
25  * The base class for the majority of user-interface objects. Widget adds
26  * support for receiving events from the browser and being added directly to
27  * {@link com.google.gwt.user.client.ui.Panel panels}.
28  */

29 public class Widget extends UIObject implements EventListener {
30
31   private boolean attached;
32   private Object JavaDoc layoutData;
33   private Widget parent;
34
35   /**
36    * Gets this widget's parent panel.
37    *
38    * @return the widget's parent panel
39    */

40   public Widget getParent() {
41     return parent;
42   }
43
44   /**
45    * Determines whether this widget is currently attached to the browser's
46    * document (i.e., there is an unbroken chain of widgets between this widget
47    * and the underlying browser document).
48    *
49    * @return <code>true</code> if the widget is attached
50    */

51   public boolean isAttached() {
52     return attached;
53   }
54
55   public void onBrowserEvent(Event event) {
56   }
57
58   /**
59    * Removes this widget from its parent widget. If it has no parent, this
60    * method does nothing.
61    *
62    * @throws IllegalStateException if this widget's parent does not support
63    * removal (e.g. {@link Composite})
64    */

65   public void removeFromParent() {
66     if (parent instanceof HasWidgets) {
67       ((HasWidgets) parent).remove(this);
68     } else if (parent != null) {
69       throw new IllegalStateException JavaDoc(
70           "This widget's parent does not implement HasWidgets");
71     }
72   }
73
74   /**
75    * This method is called when a widget is attached to the browser's document.
76    * To receive notification after a Widget has been added from the
77    * document, override the {@link #onLoad} method.
78    *
79    * <p>
80    * Subclasses that override this method must call
81    * <code>super.onAttach()</code> to ensure that the Widget has been
82    * attached to the underlying Element.
83    * </p>
84    *
85    * @throws IllegalStateException if this widget is already attached
86    */

87   protected void onAttach() {
88     if (attached) {
89       throw new IllegalStateException JavaDoc(
90           "Should only call onAttach when the widget is detached from the browser's document");
91     }
92
93     attached = true;
94
95     // Set the main element's event listener. This should only be set
96
// while the widget is attached, because it creates a circular
97
// reference between JavaScript and the DOM.
98
DOM.setEventListener(getElement(), this);
99
100     // Now that the widget is attached, call onLoad().
101
onLoad();
102   }
103
104   /**
105    * This method is called when a widget is detached from the browser's
106    * document. To receive notification before a Widget is removed from the
107    * document, override the {@link #onUnload} method.
108    *
109    * <p>
110    * Subclasses that override this method must call
111    * <code>super.onDetach()</code> to ensure that the Widget has been
112    * detached from the underlying Element. Failure to do so will result
113    * in application memeroy leaks due to circular references between DOM
114    * Elements and JavaScript objects.
115    * </p>
116    *
117    * @throws IllegalStateException if this widget is already detached
118    */

119   protected void onDetach() {
120     if (!attached) {
121       throw new IllegalStateException JavaDoc(
122           "Should only call onDetach when the widget is attached to the browser's document");
123     }
124     
125     // Give the user a chance to clean up, but don't trust the code to not throw
126
try {
127       onUnload();
128     } finally {
129       attached = false;
130   
131       // Clear out the element's event listener (breaking the circular
132
// reference between it and the widget).
133
DOM.setEventListener(getElement(), null);
134     }
135   }
136
137   /**
138    * This method is called immediately after a widget becomes attached to the
139    * browser's document.
140    */

141   protected void onLoad() {
142   }
143   
144   /**
145    * This method is called immediately before a widget will be detached from the
146    * browser's document.
147    */

148   protected void onUnload() {
149   }
150
151   /**
152    * Sets this object's browser element. Widget subclasses must call this method
153    * before attempting to call any other methods.
154    *
155    * If a browser element has already been attached, then it is replaced with
156    * the new element. The old event listeners are removed from the old browser
157    * element, and the event listeners are set up on the new browser element.
158    *
159    * @param elem the object's new element
160    */

161   protected void setElement(Element elem) {
162     if (attached) {
163       // Remove old event listener to avoid leaking. onDetach will not do this
164
// for us, because it is only called when the widget itself is detached from
165
// the document.
166
DOM.setEventListener(getElement(), null);
167     }
168
169     super.setElement(elem);
170     if (attached) {
171       // Hook the event listener back up on the new element. onAttach will not
172
// do this for us, because it is only called when the widget itself is
173
// attached to the document.
174
DOM.setEventListener(elem, this);
175     }
176   }
177
178   /**
179    * Gets the panel-defined layout data associated with this widget.
180    *
181    * @return the widget's layout data
182    * @see #setLayoutData
183    */

184   Object JavaDoc getLayoutData() {
185     return layoutData;
186   }
187
188   /**
189    * Sets the panel-defined layout data associated with this widget. Only the
190    * panel that currently contains a widget should ever set this value. It
191    * serves as a place to store layout bookkeeping data associated with a
192    * widget.
193    *
194    * @param layoutData the widget's layout data
195    */

196   void setLayoutData(Object JavaDoc layoutData) {
197     this.layoutData = layoutData;
198   }
199
200   /**
201    * Sets this widget's parent. This method should only be called by
202    * {@link Panel} and {@link Composite}.
203    *
204    * @param parent the widget's new parent
205    */

206   void setParent(Widget parent) {
207     Widget oldParent = this.parent;
208     this.parent = parent;
209     if (parent == null) {
210       if (oldParent != null && oldParent.isAttached()) {
211         onDetach();
212         assert !isAttached() :
213             "Failure of " + GWT.getTypeName(this) + " to call super.onDetach()";
214       }
215     } else if (parent.isAttached()) {
216       onAttach();
217         assert isAttached() :
218             "Failure of " + GWT.getTypeName(this) + " to call super.onAttach()";
219     }
220   }
221 }
222
Popular Tags