001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package example.bluetooth.demo;
033:
034: import java.io.IOException;
035:
036: import java.util.Vector;
037:
038: import javax.microedition.lcdui.Alert;
039: import javax.microedition.lcdui.AlertType;
040: import javax.microedition.lcdui.Command;
041: import javax.microedition.lcdui.CommandListener;
042: import javax.microedition.lcdui.Display;
043: import javax.microedition.lcdui.Displayable;
044: import javax.microedition.lcdui.Graphics;
045: import javax.microedition.lcdui.Image;
046: import javax.microedition.lcdui.List;
047: import javax.microedition.lcdui.Ticker;
048:
049: /**
050: * Allows to customize the images list to be published,
051: * creates the corresponding service record to describe this list
052: * and send the images to clients by request.
053: *
054: * @version ,
055: */
056: final class GUIImageServer implements CommandListener {
057: /** Keeps the help message of this demo. */
058: private final String helpText = "The server is started by default.\n\n"
059: + "No images are published initially. Change this by corresponding"
060: + " commands - the changes have an effect immediately.\n\n"
061: + "If image is removed from the published list, it can't "
062: + "be downloaded.";
063:
064: /** This command goes to demo main screen. */
065: private final Command backCommand = new Command("Back",
066: Command.BACK, 2);
067:
068: /** Adds the selected image to the published list. */
069: private final Command addCommand = new Command("Publish image",
070: Command.SCREEN, 1);
071:
072: /** Removes the selected image from the published list. */
073: private final Command removeCommand = new Command("Remove image",
074: Command.SCREEN, 1);
075:
076: /** Shows the help message. */
077: private final Command helpCommand = new Command("Help",
078: Command.HELP, 1);
079:
080: /** The list control to configure images. */
081: private final List imagesList = new List("Configure Server",
082: List.IMPLICIT);
083:
084: /** The help screen for the server. */
085: private final Alert helpScreen = new Alert("Help");
086:
087: /** Keeps the parent MIDlet reference to process specific actions. */
088: private DemoMIDlet parent;
089:
090: /** The list of images file names. */
091: private Vector imagesNames;
092:
093: /** These images are used to indicate the picture is published. */
094: private Image onImage;
095:
096: /** These images are used to indicate the picture is published. */
097: private Image offImage;
098:
099: /** Keeps an information about what images are published. */
100: private boolean[] published;
101:
102: /** This object handles the real transmission. */
103: private BTImageServer bt_server;
104:
105: /** Constructs images server GUI. */
106: GUIImageServer(DemoMIDlet parent) {
107: this .parent = parent;
108: bt_server = new BTImageServer(this );
109: setupIdicatorImage();
110: setupImageList();
111: published = new boolean[imagesList.size()];
112:
113: // prepare main screen
114: imagesList.addCommand(backCommand);
115: imagesList.addCommand(addCommand);
116: imagesList.addCommand(removeCommand);
117: imagesList.addCommand(helpCommand);
118: imagesList.setCommandListener(this );
119:
120: // prepare help screen
121: helpScreen.addCommand(backCommand);
122: helpScreen.setTimeout(Alert.FOREVER);
123: helpScreen.setString(helpText);
124: helpScreen.setCommandListener(this );
125: }
126:
127: /**
128: * Process the command event.
129: *
130: * @param c - the issued command.
131: * @param d - the screen object the command was issued for.
132: */
133: public void commandAction(Command c, Displayable d) {
134: if ((c == backCommand) && (d == imagesList)) {
135: destroy();
136: parent.show();
137:
138: return;
139: }
140:
141: if ((c == backCommand) && (d == helpScreen)) {
142: Display.getDisplay(parent).setCurrent(imagesList);
143:
144: return;
145: }
146:
147: if (c == helpCommand) {
148: Display.getDisplay(parent).setCurrent(helpScreen);
149:
150: return;
151: }
152:
153: /*
154: * Changing the state of base of published images
155: */
156: int index = imagesList.getSelectedIndex();
157:
158: // nothing to do
159: if ((c == addCommand) == published[index]) {
160: return;
161: }
162:
163: // update information and view
164: published[index] = c == addCommand;
165:
166: Image stateImg = (c == addCommand) ? onImage : offImage;
167: imagesList.set(index, imagesList.getString(index), stateImg);
168:
169: // update bluetooth service information
170: if (!bt_server.changeImageInfo(imagesList.getString(index),
171: published[index])) {
172: // either a bad record or SDDB is busy
173: Alert al = new Alert("Error", "Can't update base", null,
174: AlertType.ERROR);
175: al.setTimeout(DemoMIDlet.ALERT_TIMEOUT);
176: Display.getDisplay(parent).setCurrent(al, imagesList);
177:
178: // restore internal information
179: published[index] = !published[index];
180: stateImg = published[index] ? onImage : offImage;
181: imagesList
182: .set(index, imagesList.getString(index), stateImg);
183: }
184: }
185:
186: /**
187: * We have to provide this method due to "do not do network
188: * operation in command listener method" restriction, which
189: * is caused by crooked midp design.
190: *
191: * This method is called by BTImageServer after it is done
192: * with bluetooth initialization and next screen is ready
193: * to appear.
194: */
195: void completeInitialization(boolean isBTReady) {
196: // bluetooth was initialized successfully.
197: if (isBTReady) {
198: Ticker t = new Ticker(
199: "Choose images you want to publish...");
200: imagesList.setTicker(t);
201: Display.getDisplay(parent).setCurrent(imagesList);
202:
203: return;
204: }
205:
206: // something wrong
207: Alert al = new Alert("Error", "Can't initialize bluetooth",
208: null, AlertType.ERROR);
209: al.setTimeout(DemoMIDlet.ALERT_TIMEOUT);
210: Display.getDisplay(parent).setCurrent(al,
211: parent.getDisplayable());
212: }
213:
214: /** Destroys this component. */
215: void destroy() {
216: // finalize the image server work
217: bt_server.destroy();
218: }
219:
220: /** Gets the image file name from its title (label). */
221: String getImageFileName(String imgName) {
222: if (imgName == null) {
223: return null;
224: }
225:
226: // no interface in List to get the index - should find
227: int index = -1;
228:
229: for (int i = 0; i < imagesList.size(); i++) {
230: if (imagesList.getString(i).equals(imgName)) {
231: index = i;
232:
233: break;
234: }
235: }
236:
237: // not found or not published
238: if ((index == -1) || !published[index]) {
239: return null;
240: }
241:
242: return (String) imagesNames.elementAt(index);
243: }
244:
245: /**
246: * Creates the image to indicate the base state.
247: */
248: private void setupIdicatorImage() {
249: // create "on" image
250: try {
251: onImage = Image.createImage("/images/st-on.png");
252: } catch (IOException e) {
253: // provide off-screen image then
254: onImage = createIndicatorImage(12, 12, 0, 255, 0);
255: }
256:
257: // create "off" image
258: try {
259: offImage = Image.createImage("/images/st-off.png");
260: } catch (IOException e) {
261: // provide off-screen image then
262: offImage = createIndicatorImage(12, 12, 255, 0, 0);
263: }
264: }
265:
266: /**
267: * Gets the description of images from manifest and
268: * prepares the list to control the configuration.
269: * <p>
270: * The attributes are named "ImageTitle-n" and "ImageImage-n".
271: * The value "n" must start at "1" and be incremented by 1.
272: */
273: private void setupImageList() {
274: imagesNames = new Vector();
275: imagesList.setCommandListener(this );
276:
277: for (int n = 1; n < 100; n++) {
278: String name = parent.getAppProperty("ImageName-" + n);
279:
280: // no more images available
281: if ((name == null) || (name.length() == 0)) {
282: break;
283: }
284:
285: String label = parent.getAppProperty("ImageTitle-" + n);
286:
287: // no label available - use picture name instead
288: if ((label == null) || (label.length() == 0)) {
289: label = name;
290: }
291:
292: imagesNames.addElement(name);
293: imagesList.append(label, offImage);
294: }
295: }
296:
297: /**
298: * Creates the off-screen image with specified size an color.
299: */
300: private Image createIndicatorImage(int w, int h, int r, int g, int b) {
301: Image res = Image.createImage(w, h);
302: Graphics gc = res.getGraphics();
303: gc.setColor(r, g, b);
304: gc.fillRect(0, 0, w, h);
305:
306: return res;
307: }
308: } // end of class 'GUIImageServer' definition
|