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 com.sun.midp.events.EventQueue;
030:
031: import com.sun.midp.lcdui.DisplayContainer;
032: import com.sun.midp.lcdui.DisplayAccess;
033: import com.sun.midp.lcdui.DisplayEventHandler;
034: import com.sun.midp.lcdui.DisplayEventProducer;
035: import com.sun.midp.lcdui.ForegroundController;
036: import com.sun.midp.lcdui.RepaintEventProducer;
037: import com.sun.midp.lcdui.ItemEventConsumer;
038:
039: /**
040: * This class has dual functiopnality:
041: *
042: * First, it implements DisplayEventHandler I/F and thus provides access
043: * to display objects (creation, preemption, set/get IDs and other properties).
044: *
045: * Second, it implements ItemEventConsumer I/F and thus processes
046: * LCDUI events that due to different reasons can't be associated with
047: * Display instance specific DisplayEventConsumer objects,
048: * but need to be processed by isolate-wide handler.
049: * TBD: These are subjects for futher investigation to move them
050: * to DisplayEventConsumer.
051: *
052: * In addition, it implements a number of package private methods that work
053: * with Display and are called locally by display/DisplayAccessor.
054: * TBD: These are subjects for further investination to move them closer
055: * to end users: Display & displayAccessor classes.
056: *
057: */
058: class DisplayEventHandlerImpl implements DisplayEventHandler,
059: ItemEventConsumer {
060:
061: /** Cached reference to Active Displays Container. */
062: private DisplayContainer displayContainer;
063:
064: /** Cached reference to the ForegroundController. */
065: private ForegroundController foregroundController;
066:
067: /** The preempting display. */
068: private DisplayAccess preemptingDisplay;
069:
070: /** If request to end preemption was called */
071: private boolean preemptionDoneCalled = false;
072:
073: /** Package private constructor restrict creation to LCDUI package. */
074: DisplayEventHandlerImpl() {
075: }
076:
077: /**
078: * Initialize Display Event Handler.
079: * DisplayEventHandler I/F method.
080: *
081: * @param theDisplayEventProducer producer for display events
082: * @param theForegroundController controls which display has the foreground
083: * @param theRepaintEventProducer producer for repaint events events
084: * @param theDisplayContainer container for display objects
085: */
086: public void initDisplayEventHandler(
087: DisplayEventProducer theDisplayEventProducer,
088: ForegroundController theForegroundController,
089: RepaintEventProducer theRepaintEventProducer,
090: DisplayContainer theDisplayContainer) {
091:
092: foregroundController = theForegroundController;
093:
094: displayContainer = theDisplayContainer;
095:
096: /*
097: * TBD: not a good idea to call static initializer
098: * from non-static method ...
099: * Maybe to create a separate method:
100: * DisplayEventHandler.initDisplayClass(token,...)
101: * for these purposes and call it from Suite Loader's main() ?
102: * displayEventHandlerImpl I/F miplementor will call
103: * Display.initClass() from itsinitDisplayClass() method ?
104: */
105: Display.initClass(theForegroundController,
106: theDisplayEventProducer, theRepaintEventProducer,
107: theDisplayContainer);
108: }
109:
110: /**
111: * Initialize per suite data of the display event handler.
112: * DisplayEventHandler I/F method.
113: *
114: * @param drawTrustedIcon true, to draw the trusted icon in the upper
115: * status bar for every display of this suite
116: */
117: public void initSuiteData(boolean drawTrustedIcon) {
118: Display.initSuiteData(drawTrustedIcon);
119: }
120:
121: /**
122: * Preempt the current displayable with
123: * the given displayable until donePreempting is called.
124: * To avoid dead locking the event thread his method
125: * MUST NOT be called in the event thread.
126: * DisplayEventHandler I/F method.
127: *
128: * @param d displayable to show the user
129: * @param waitForDisplay if true this method will wait if the
130: * screen is being preempted by another thread, however
131: * if this is called in the event dispatch thread this
132: * method will return null regardless of the value
133: * of <code>waitForDisplay</code>
134: *
135: * @return an preempt token object to pass to donePreempting done if
136: * prempt will happen, else null
137: *
138: * @exception InterruptedException if another thread interrupts the
139: * calling thread while this method is waiting to preempt the
140: * display.
141: */
142: public Object preemptDisplay(Displayable d, boolean waitForDisplay)
143: throws InterruptedException {
144: Display tempDisplay;
145: String title;
146:
147: if (d == null) {
148: throw new NullPointerException(
149: "The displayable can't be null");
150: }
151:
152: title = d.getTitle();
153: if (title == null) {
154: throw new NullPointerException(
155: "The title of the displayable can't be null");
156: }
157:
158: if (EventQueue.isDispatchThread()) {
159: // Developer programming error
160: throw new RuntimeException(
161: "Blocking call performed in the event thread");
162: }
163:
164: /**
165: * This sync protects preempt related local fields:
166: * preemptingDisplay and destroyPreemptingDisplay.
167: */
168: synchronized (this ) {
169: if (preemptingDisplay != null) {
170:
171: if (!waitForDisplay) {
172: return null;
173: }
174:
175: this .wait();
176: }
177:
178: // This class will own the display.
179: tempDisplay = new Display(
180: "com.sun.midp.lcdui.DisplayEventHandlerImpl");
181:
182: foregroundController.startPreempting(tempDisplay.displayId);
183:
184: tempDisplay.setCurrent(d);
185:
186: preemptingDisplay = tempDisplay.accessor;
187:
188: return preemptingDisplay;
189: }
190: }
191:
192: /**
193: * Display the displayable that was being displayed before
194: * preemptDisplay was called.
195: * DisplayEventHandler I/F method.
196: *
197: * @param preemptToken the token returned from preemptDisplay
198: */
199: public void donePreempting(Object preemptToken) {
200: /**
201: * This sync protects preempt related local fields:
202: * preemptingDisplay and destroyPreemptingDisplay.
203: */
204: synchronized (this ) {
205: if (preemptingDisplay != null
206: && (preemptToken == preemptingDisplay || preemptToken == null)) {
207:
208: preemptionDoneCalled = true;
209:
210: foregroundController.stopPreempting(preemptingDisplay
211: .getDisplayId());
212:
213: }
214: }
215: }
216:
217: /**
218: * Called by Display to notify DisplayEventHandler that
219: * Display has been sent to the background to finish
220: * preempt process if any.
221: *
222: * @param displayId id of Display
223: */
224: public void onDisplayBackgroundProcessed(int displayId) {
225:
226: synchronized (this ) {
227: if (preemptionDoneCalled && preemptingDisplay != null
228: && preemptingDisplay.getDisplayId() == displayId) {
229:
230: displayContainer.removeDisplay(preemptingDisplay
231: .getNameOfOwner());
232:
233: preemptingDisplay = null;
234:
235: preemptionDoneCalled = false;
236:
237: // A midlet may be waiting to preempt
238: this .notify();
239: }
240: }
241: }
242:
243: /**
244: * Called by event delivery to process an Item state change.
245: * ItemEventConsumer I/F method.
246: *
247: * @param item the Item which has changed state
248: */
249: public void handleItemStateChangeEvent(Item item) {
250: if (item.owner != null) {
251: item.owner.uCallItemStateChanged(item);
252: }
253: }
254:
255: /**
256: * Called by event delivery to refresh a CustomItem's size information.
257: * ItemEventConsumer I/F method.
258: *
259: * @param ci the custom item whose size information has to be changed
260: */
261: public void handleItemSizeRefreshEvent(CustomItem ci) {
262: ci.customItemLF.uCallSizeRefresh();
263: }
264:
265: /*
266: * private methods
267: */
268: static {
269: // Instantiate link with MMAPI video player for repaint hooks
270: new MMHelperImpl();
271: }
272: }
|