001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package javax.microedition.lcdui;
028:
029: import java.util.TimerTask;
030: import java.util.Timer;
031:
032: /**
033: * An object that has the capability of being placed on the display. A
034: * <code>Displayable</code> object may have a title, a ticker,
035: * zero or more commands and a listener associated with it. The
036: * contents displayed and their interaction with the user are defined by
037: * subclasses.
038: *
039: * <p>The title string may contain
040: * <A HREF="Form.html#linebreak">line breaks</a>.
041: * The display of the title string must break accordingly.
042: * For example, if only a single line is available for a
043: * title and the string contains a line break then only the characters
044: * up to the line break are displayed.</p>
045: *
046: * <p>Unless otherwise specified by a subclass, the default state of newly
047: * created <code>Displayable</code> objects is as follows:</p>
048: *
049: * <ul>
050: * <li>it is not visible on the <code>Display</code>;</li>
051: * <li>there is no <code>Ticker</code> associated with this
052: * <code>Displayable</code>;</li>
053: * <li>the title is <code>null</code>;</li>
054: * <li>there are no <code>Commands</code> present; and</li>
055: * <li>there is no <code>CommandListener</code> present.</li>
056: * </ul>
057: *
058: * @since MIDP 1.0
059: */
060:
061: public abstract class Displayable {
062:
063: // ************************************************************
064: // public member variables
065: // ************************************************************
066:
067: // ************************************************************
068: // protected member variables
069: // ************************************************************
070:
071: /**
072: * Create a new Displayable
073: */
074: Displayable() {
075: }
076:
077: /**
078: * Create a new Displayable with a passed in title
079: *
080: * @param title the Displayable's title, or null for no title
081: */
082: Displayable(String title) {
083: synchronized (Display.LCDUILock) {
084: this .title = title;
085: }
086: }
087:
088: // ************************************************************
089: // public methods
090: // ************************************************************
091:
092: /**
093: * Gets the title of the <code>Displayable</code>. Returns
094: * <code>null</code> if there is no title.
095: * @return the title of the instance, or <code>null</code> if no title
096: * @see #setTitle
097: */
098: public String getTitle() {
099: synchronized (Display.LCDUILock) {
100: return title;
101: }
102: }
103:
104: /**
105: * Sets the title of the <code>Displayable</code>. If
106: * <code>null</code> is given,
107: * removes the title.
108: *
109: * <P>If the <code>Displayable</code> is actually visible on
110: * the display,
111: * the implementation should update
112: * the display as soon as it is feasible to do so.</P>
113: *
114: * <P>The existence of a title may affect the size
115: * of the area available for <code>Displayable</code> content.
116: * Addition, removal, or the setting of the title text at runtime
117: * may dynamically change the size of the content area.
118: * This is most important to be aware of when using the
119: * <code>Canvas</code> class.
120: * If the available area does change, the application will be notified
121: * via a call to {@link #sizeChanged(int, int) sizeChanged()}. </p>
122: *
123: * @param s the new title, or <code>null</code> for no title
124: * @see #getTitle
125: */
126: public void setTitle(String s) {
127: synchronized (Display.LCDUILock) {
128:
129: if (title == s || (title != null && title.equals(s))) {
130: return;
131: }
132: String oldTitle = title;
133: this .title = s;
134: displayableLF.lSetTitle(oldTitle, title);
135: }
136: }
137:
138: /**
139: * Gets the ticker used by this <code>Displayable</code>.
140: * @return ticker object used, or <code>null</code> if no
141: * ticker is present
142: * @see #setTicker
143: */
144: public Ticker getTicker() {
145: synchronized (Display.LCDUILock) {
146: return ticker;
147: }
148: }
149:
150: /**
151: * Sets a ticker for use with this <code>Displayable</code>,
152: * replacing any
153: * previous ticker.
154: * If <code>null</code>, removes the ticker object
155: * from this <code>Displayable</code>. The same ticker may be shared by
156: * several <code>Displayable</code>
157: * objects within an application. This is done by calling
158: * <code>setTicker()</code>
159: * with the same <code>Ticker</code> object on several
160: * different <code>Displayable</code> objects.
161: * If the <code>Displayable</code> is actually visible on the display,
162: * the implementation should update
163: * the display as soon as it is feasible to do so.
164: *
165: * <p>The existence of a ticker may affect the size
166: * of the area available for <code>Displayable's</code> contents.
167: * Addition, removal, or the setting of the ticker at runtime
168: * may dynamically change the size of the content area.
169: * This is most important to be aware of when using the
170: * <code>Canvas</code> class.
171: * If the available area does change, the application will be notified
172: * via a call to {@link #sizeChanged(int, int) sizeChanged()}. </p>
173: *
174: * @param ticker the ticker object used on this screen
175: * @see #getTicker
176: */
177: public void setTicker(Ticker ticker) {
178: synchronized (Display.LCDUILock) {
179:
180: // Return early if there's nothing to do :
181: // ticker is the same or (old and new tickers are null)
182: if (this .ticker == ticker) {
183: return;
184: }
185: Ticker oldTicker = this .ticker;
186:
187: this .ticker = ticker;
188:
189: displayableLF.lSetTicker(oldTicker, ticker);
190: }
191: }
192:
193: /**
194: * Checks if the <code>Displayable</code> is actually visible
195: * on the display. In order
196: * for a <code>Displayable</code> to be visible, all of the
197: * following must be true:
198: * the <code>Display's</code> <code>MIDlet</code> must be
199: * running in the foreground, the <code>Displayable</code>
200: * must be the <code>Display's</code> current screen, and the
201: * <code>Displayable</code> must not be
202: * obscured by a <a href="Display.html#systemscreens">
203: * system screen</a>.
204: *
205: * @return <code>true</code> if the
206: * <code>Displayable</code> is currently visible
207: */
208: public boolean isShown() {
209: synchronized (Display.LCDUILock) {
210: return displayableLF.lIsShown();
211: }
212: }
213:
214: /**
215: * Adds a command to the <code>Displayable</code>. The
216: * implementation may choose,
217: * for example,
218: * to add the command to any of the available soft buttons or place it
219: * in a menu.
220: * If the added command is already in the screen (tested by comparing the
221: * object references), the method has no effect.
222: * If the <code>Displayable</code> is actually visible on the
223: * display, and this call
224: * affects the set of visible commands, the implementation should update
225: * the display as soon as it is feasible to do so.
226: *
227: * @param cmd the command to be added
228: *
229: * @throws NullPointerException if <code>cmd</code> is
230: * <code>null</code>
231: */
232: public void addCommand(Command cmd) {
233: if (cmd == null) {
234: throw new NullPointerException();
235: }
236:
237: synchronized (Display.LCDUILock) {
238: addCommandImpl(cmd);
239: displayableLF.lAddCommand(cmd, numCommands - 1);
240: }
241: }
242:
243: /**
244: * Removes a command from the <code>Displayable</code>.
245: * If the command is not in the <code>Displayable</code>
246: * (tested by comparing the
247: * object references), the method has no effect.
248: * If the <code>Displayable</code> is actually visible on the
249: * display, and this call
250: * affects the set of visible commands, the implementation should update
251: * the display as soon as it is feasible to do so.
252: * If <code>cmd</code> is <code>null</code>, this method
253: * does nothing.
254: *
255: * @param cmd the command to be removed
256: */
257: public void removeCommand(Command cmd) {
258: synchronized (Display.LCDUILock) {
259: int i = removeCommandImpl(cmd);
260: if (i != -1) {
261: displayableLF.lRemoveCommand(cmd, i);
262: }
263: }
264: }
265:
266: /**
267: * Sets a listener for {@link Command Commands} to this
268: * <code>Displayable</code>,
269: * replacing any previous <code>CommandListener</code>. A
270: * <code>null</code> reference is
271: * allowed and has the effect of removing any existing listener.
272: *
273: * @param l the new listener, or <code>null</code>.
274: */
275: public void setCommandListener(CommandListener l) {
276: synchronized (Display.LCDUILock) {
277: listener = l;
278: }
279: displayableLF.updateCommandSet();
280: }
281:
282: /**
283: * Gets the width in pixels of the displayable area available to the
284: * application. The value returned is appropriate for the particular
285: * <code>Displayable</code> subclass. This value may depend
286: * on how the device uses the
287: * display and may be affected by the presence of a title, a ticker, or
288: * commands.
289: * This method returns the proper result at all times, even if the
290: * <code>Displayable</code> object has not yet been shown.
291: *
292: * @return width of the area available to the application
293: */
294: public int getWidth() {
295: synchronized (Display.LCDUILock) {
296: return displayableLF.lGetWidth();
297: }
298: }
299:
300: /**
301: * Gets the height in pixels of the displayable area available to the
302: * application. The value returned is appropriate for the particular
303: * <code>Displayable</code> subclass. This value may depend
304: * on how the device uses the
305: * display and may be affected by the presence of a title, a ticker, or
306: * commands.
307: * This method returns the proper result at all times, even if the
308: * <code>Displayable</code> object has not yet been shown.
309: *
310: * @return height of the area available to the application
311: */
312: public int getHeight() {
313: synchronized (Display.LCDUILock) {
314: return displayableLF.lGetHeight();
315: }
316: }
317:
318: // ************************************************************
319: // protected methods
320: // ************************************************************
321:
322: /**
323: * The implementation calls this method when the available area of the
324: * <code>Displayable</code> has been changed.
325: * The "available area" is the area of the display that
326: * may be occupied by
327: * the application's contents, such as <code>Items</code> in a
328: * <code>Form</code> or graphics within
329: * a <code>Canvas</code>. It does not include space occupied
330: * by a title, a ticker,
331: * command labels, scroll bars, system status area, etc. A size change
332: * can occur as a result of the addition, removal, or changed contents of
333: * any of these display features.
334: *
335: * <p> This method is called at least once before the
336: * <code>Displayable</code> is shown for the first time.
337: * If the size of a <code>Displayable</code> changes while
338: * it is visible,
339: * <CODE>sizeChanged</CODE> will be called. If the size of a
340: * <code>Displayable</code>
341: * changes while it is <em>not</em> visible, calls to
342: * <CODE>sizeChanged</CODE> may be deferred. If the size had changed
343: * while the <code>Displayable</code> was not visible,
344: * <CODE>sizeChanged</CODE> will be
345: * called at least once at the time the
346: * <code>Displayable</code> becomes visible once
347: * again.</p>
348: *
349: * <p>The default implementation of this method in <code>Displayable</code>
350: * and its
351: * subclasses defined in this specification must be empty.
352: * This method is intended solely for being overridden by the
353: * application. This method is defined on <code>Displayable</code>
354: * even though applications are prohibited from creating
355: * direct subclasses of <code>Displayable</code>.
356: * It is defined here so that applications can override it in
357: * subclasses of <code>Canvas</code> and <code>Form</code>.
358: * This is useful for <code>Canvas</code> subclasses to tailor
359: * their graphics and for <code>Forms</code> to modify
360: * <code>Item</code> sizes and layout
361: * directives in order to fit their contents within the the available
362: * display area.</p>
363: *
364: * @param w the new width in pixels of the available area
365: * @param h the new height in pixels of the available area
366: */
367: protected void sizeChanged(int w, int h) {
368: // this method is intended to be overridden by the application
369: }
370:
371: // ************************************************************
372: // package private methods
373: // ************************************************************
374:
375: /**
376: * Gets look&feel for this Displayable object
377: * This method is implemented in the subclasses.
378: * @return - DisplayableLF for this Displayable object
379: */
380: DisplayableLF getLF() {
381: return displayableLF;
382: }
383:
384: /**
385: * Called to schedule a call to itemStateChanged() due to
386: * a change in the given Item.
387: *
388: * @param src the Item which has changed
389: */
390: void itemStateChanged(Item src) {
391: /*
392: * This call could happen on a Displayable that is not currently
393: * visible (either not current, or the Display instance is not
394: * foreground).
395: */
396: Display.itemStateChanged(src);
397: }
398:
399: /**
400: * Called by the event handler to notify any ItemStateListener
401: * of a change in the given Item.
402: * The default implementation of this function does nothing.
403: *
404: * @param src The Item which has changed
405: */
406: void uCallItemStateChanged(Item src) {
407: }
408:
409: /**
410: * Add a Command to this Displayable
411: *
412: * @param cmd The Command to add to this Displayable
413: * @return command index
414: */
415: int addCommandImpl(Command cmd) {
416: for (int i = 0; i < numCommands; ++i) {
417: if (commands[i] == cmd) {
418: return -1;
419: }
420: }
421:
422: if ((commands == null) || (numCommands == commands.length)) {
423: Command[] newCommands = new Command[numCommands + 4];
424: if (commands != null) {
425: System.arraycopy(commands, 0, newCommands, 0,
426: numCommands);
427: }
428: commands = newCommands;
429: }
430:
431: commands[numCommands] = cmd;
432: ++numCommands;
433:
434: return numCommands - 1;
435: }
436:
437: /**
438: * Remove a Command from this Displayable
439: *
440: * @param cmd The Command to remove from this Displayable
441: * @return command index
442: */
443: int removeCommandImpl(Command cmd) {
444: for (int i = 0; i < numCommands; ++i) {
445: if (commands[i] == cmd) {
446: commands[i] = commands[--numCommands];
447: commands[numCommands] = null;
448: return i;
449: }
450: }
451:
452: return -1;
453: }
454:
455: // ************************************************************
456: // private methods
457: // ************************************************************
458:
459: // ************************************************************
460: // package private member variables
461: // ************************************************************
462:
463: /** An array of Commands added to this Displayable */
464: Command commands[];
465:
466: /** The number of Commands added to this Displayable */
467: int numCommands;
468:
469: /** The CommandListener for Commands added to this Displayable */
470: CommandListener listener;
471:
472: /** True, if this Displayable is in full screen mode */
473: boolean isInFullScreenMode; // = false
474:
475: /** True, if this Displayable is rotated */
476: boolean isRotated; // = false
477:
478: /** The title for this Displayable */
479: String title;
480:
481: /** The ticker that may be set for this Displayable */
482: Ticker ticker;
483:
484: /** The Look &s; Feel object associated with this Displayable */
485: DisplayableLF displayableLF;
486:
487: // ************************************************************
488: // private member variables
489: // ************************************************************
490:
491: // ************************************************************
492: // Static initializer, constructor
493: // ************************************************************
494:
495: } // Displayable
|