diff --git a/4168.pdf b/4168.pdf new file mode 100644 index 0000000..f99f1fd Binary files /dev/null and b/4168.pdf differ diff --git a/4169.pdf b/4169.pdf new file mode 100644 index 0000000..43671c0 Binary files /dev/null and b/4169.pdf differ diff --git a/9781430210610.jpg b/9781430210610.jpg new file mode 100644 index 0000000..733b16e Binary files /dev/null and b/9781430210610.jpg differ diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..2a14f3c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,27 @@ +Freeware License, some rights reserved + +Copyright (c) 2009 Ray Rischpater + +Permission is hereby granted, free of charge, to anyone obtaining a copy +of this software and associated documentation files (the "Software"), +to work with the Software within the limits of freeware distribution and fair use. +This includes the rights to use, copy, and modify the Software for personal use. +Users are also allowed and encouraged to submit corrections and modifications +to the Software for the benefit of other users. + +It is not allowed to reuse, modify, or redistribute the Software for +commercial use in any way, or for a user’s educational materials such as books +or blog articles without prior permission from the copyright holder. + +The above copyright notice and this permission notice need to be included +in all copies or substantial portions of the software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS OR APRESS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..c2e82cd --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +#Apress Source Code + +This repository accompanies [*Beginning Java ME Platform*](http://www.apress.com/9781430210610) by Ray Rischpater (Apress, 2009). + +![Cover image](9781430210610.jpg) + +Download the files as a zip using the green button, or clone the repository to your machine using Git. + +##Releases + +Release v1.0 corresponds to the code in the published book, without corrections or updates. + +##Contributions + +See the file Contributing.md for more information on how you can contribute to this repository. diff --git a/Sample Code/chapter03/code/WeatherApplet/build.xml b/Sample Code/chapter03/code/WeatherApplet/build.xml new file mode 100644 index 0000000..cd151f7 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/build.xml @@ -0,0 +1,69 @@ + + + + + + Builds, tests, and runs the project WeatherApplet. + + + diff --git a/Sample Code/chapter03/code/WeatherApplet/manifest.mf b/Sample Code/chapter03/code/WeatherApplet/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/Sample Code/chapter03/code/WeatherApplet/nbproject/build-impl.xml b/Sample Code/chapter03/code/WeatherApplet/nbproject/build-impl.xml new file mode 100644 index 0000000..2bc4f4f --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/nbproject/build-impl.xml @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set platform.home + Must set platform.bootcp + Must set platform.java + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter03/code/WeatherApplet/nbproject/genfiles.properties b/Sample Code/chapter03/code/WeatherApplet/nbproject/genfiles.properties new file mode 100644 index 0000000..0318740 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/nbproject/genfiles.properties @@ -0,0 +1,11 @@ +build.xml.data.CRC32=100831e2 +build.xml.script.CRC32=de46eb58 +build.xml.stylesheet.CRC32=e44f9c28 +nbproject/build-impl.xml.data.CRC32=100831e2 +nbproject/build-impl.xml.script.CRC32=c4554643 +nbproject/build-impl.xml.stylesheet.CRC32=c607b9ec +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-target-impl.xml.data.CRC32=100831e2 +nbproject/build-target-impl.xml.script.CRC32=8db5c960 +nbproject/build-target-impl.xml.stylesheet.CRC32=cf6e38a1 diff --git a/Sample Code/chapter03/code/WeatherApplet/nbproject/private/private.properties b/Sample Code/chapter03/code/WeatherApplet/nbproject/private/private.properties new file mode 100644 index 0000000..3d14d5a --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/nbproject/private/private.properties @@ -0,0 +1,7 @@ +#Sat Dec 01 21:59:01 PST 2007 +application.version.counter=000006 +javac.debug=true +application.args= +javadoc.preview=true +application.version=0.0.5 +user.properties.file=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\build.properties diff --git a/Sample Code/chapter03/code/WeatherApplet/nbproject/private/private.xml b/Sample Code/chapter03/code/WeatherApplet/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter03/code/WeatherApplet/nbproject/project.properties b/Sample Code/chapter03/code/WeatherApplet/nbproject/project.properties new file mode 100644 index 0000000..e78fcca --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/nbproject/project.properties @@ -0,0 +1,76 @@ +application.args= +application.description= +application.description.detail= +application.name=WeatherApplet +application.vendor=Ray Rischpater +application.version.autoincrement=true +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form,**/*.mbm +# This directory is removed when the project is cleaned: +build.dir=build +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/${dist.jar.name} +dist.jar.name=WeatherApplet.jar +dist.javadoc.dir=${dist.dir}/javadoc +# Put all native components to this directory: +dll.dir=dll +jar.compress=false +javac.classpath=\ + ${libs.cdc-agui-swing-layout.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.4 +javac.target=1.4 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.cdc-junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=com.apress.rischpater.weatherxlet.WeatherXlet +main.class.applet=false +main.class.xlet=true +manifest.file=manifest.mf +platform.active=Sun_Java_Toolkit_1.0_for_Connected_Device_Configuration +platform.bootclasspath=${platform.home}\\lib\\agui-1.0.jar;${platform.home}\\lib\\rt.jar;${platform.home}\\lib\\jce.jar;${platform.home}\\lib\\jaas.jar;${platform.home}\\lib\\jsse-cdc.jar +platform.device=DefaultColorPhone +platform.fat.jar=true +platform.profile=AGUI-1.0 +# Put all resources which should not be in jar file here. They will be handled per target platform +resources.dir=resources +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +savaje.bundle.base=c: +savaje.bundle.debug=false +src.dir=src +# This directory is removed when the project is cleaned: +target.dir=target +test.src.dir=test diff --git a/Sample Code/chapter03/code/WeatherApplet/nbproject/project.xml b/Sample Code/chapter03/code/WeatherApplet/nbproject/project.xml new file mode 100644 index 0000000..a09519c --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/nbproject/project.xml @@ -0,0 +1,17 @@ + + + org.netbeans.modules.j2me.cdc.nbproject + + + WeatherApplet + 1.6 + + + + + + + + + + diff --git a/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/SettingPanel.form b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/SettingPanel.form new file mode 100644 index 0000000..9bc4604 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/SettingPanel.form @@ -0,0 +1,76 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/SettingPanel.java b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/SettingPanel.java new file mode 100644 index 0000000..bc31f93 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/SettingPanel.java @@ -0,0 +1,92 @@ +/* + * SettingPanel.java + * + * Created on November 24, 2007, 7:55 AM + */ + +package com.apress.rischpater.weatherxlet; + +/** + * + * @author Ray Rischpater + */ +public class SettingPanel extends javax.swing.JPanel { + + /** Creates new form SettingPanel */ + public SettingPanel( WeatherController c ) { + controller = c; + initComponents(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + jLabel1 = new javax.swing.JLabel(); + jTextField1 = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + jTextField2 = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + + jLabel1.setText("City"); + + jTextField1.setText("Berkeley"); + + jLabel2.setText("State"); + + jTextField2.setText("CA"); + + jButton1.setText("Back"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jLabel1) + .add(jLabel2)) + .addContainerGap(199, Short.MAX_VALUE)) + .add(jTextField1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 229, Short.MAX_VALUE) + .add(jTextField2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 229, Short.MAX_VALUE) + .add(layout.createSequentialGroup() + .add(jButton1) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(layout.createSequentialGroup() + .add(jLabel1) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jTextField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jLabel2) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jTextField2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 139, Short.MAX_VALUE) + .add(jButton1)) + ); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + controller.showMainPanel(); + }//GEN-LAST:event_jButton1ActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JTextField jTextField1; + private javax.swing.JTextField jTextField2; + // End of variables declaration//GEN-END:variables + WeatherController controller; +} diff --git a/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherController.java b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherController.java new file mode 100644 index 0000000..c0d12de --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherController.java @@ -0,0 +1,47 @@ +/* + * WeatherController.java + * + * Created on November 24, 2007, 8:03 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherxlet; +import javax.swing.JPanel; +import org.jdesktop.layout.GroupLayout; + +/** + * + * @author kf6gpe + */ +public class WeatherController { + private JPanel mainPanel, settingPanel; + WeatherXlet xlet; + + GroupLayout layout; + + /** Creates a new instance of WeatherController */ + public WeatherController( WeatherXlet x) { + xlet = x; + layout = (org.jdesktop.layout.GroupLayout)xlet.getContentPane().getLayout(); + } + + public void setMainPanel( JPanel m ) { + mainPanel = m; + } + + public void setSettingPanel( JPanel s ) { + settingPanel = s; + } + + public void showMainPanel() { + layout.replace( settingPanel, mainPanel ); + xlet.pack(); + } + + public void showSettingPanel() { + layout.replace( mainPanel, settingPanel ); + xlet.pack(); + } +} diff --git a/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherXlet.form b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherXlet.form new file mode 100644 index 0000000..ef5f2e3 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherXlet.form @@ -0,0 +1,129 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherXlet.java b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherXlet.java new file mode 100644 index 0000000..92d99f8 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherApplet/src/com/apress/rischpater/weatherxlet/WeatherXlet.java @@ -0,0 +1,236 @@ +/* + * WeatherXlet.java + * + * Created on November 24, 2007, 6:57 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherxlet; + +import java.awt.Container; +import java.awt.EventQueue; +import javax.microedition.xlet.UnavailableContainerException; +import javax.microedition.xlet.XletContext; +import javax.microedition.xlet.XletStateChangeException; + +/** + * + * @author Ray Rischpater + */ +public class WeatherXlet extends javax.swing.JInternalFrame implements javax.microedition.xlet.Xlet { + + private XletContext context; // our Xlet application context. + private Container rootContainer; // the root container of our screen. + + + /** Creates new form WeatherXlet */ + public WeatherXlet() { + initComponents(); + controller = new WeatherController( this ); + jPanel2 = new SettingPanel( controller ); + + controller.setMainPanel( jPanel1 ); + controller.setSettingPanel( jPanel2 ); + + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // //GEN-BEGIN:initComponents + private void initComponents() { + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + location = new javax.swing.JTextField(); + jLabel2 = new javax.swing.JLabel(); + forecast = new javax.swing.JTextField(); + jButton1 = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); + + setFocusable(false); + jLabel1.setText("Location"); + + location.setEditable(false); + location.setText("Berkeley, CA"); + location.setFocusable(false); + location.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + locationActionPerformed(evt); + } + }); + + jLabel2.setText("Forecast"); + + forecast.setEditable(false); + forecast.setText("Partly cloudy"); + forecast.setFocusable(false); + forecast.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + forecastActionPerformed(evt); + } + }); + + jButton1.setText("Exit"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + jButton2.setText("Settings"); + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + + org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jPanel1Layout.createSequentialGroup() + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jLabel1) + .add(jLabel2)) + .addContainerGap(179, Short.MAX_VALUE)) + .add(forecast, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 228, Short.MAX_VALUE) + .add(jPanel1Layout.createSequentialGroup() + .add(jButton1) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 96, Short.MAX_VALUE) + .add(jButton2)) + .add(location, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 228, Short.MAX_VALUE) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(jPanel1Layout.createSequentialGroup() + .add(jLabel1) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(location, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(jLabel2) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED) + .add(forecast, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 151, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 10, Short.MAX_VALUE) + .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE) + .add(jButton1) + .add(jButton2))) + ); + + org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING) + .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup() + .addContainerGap() + .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addContainerGap()) + ); + pack(); + }// //GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + exit(); + }//GEN-LAST:event_jButton1ActionPerformed + + private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton2ActionPerformed + controller.showSettingPanel(); + }//GEN-LAST:event_jButton2ActionPerformed + + private void forecastActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_forecastActionPerformed +// TODO add your handling code here: + }//GEN-LAST:event_forecastActionPerformed + + private void locationActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_locationActionPerformed +// TODO add your handling code here: + }//GEN-LAST:event_locationActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JTextField forecast; + private javax.swing.JButton jButton1; + private javax.swing.JButton jButton2; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JPanel jPanel1; + private javax.swing.JTextField location; + // End of variables declaration//GEN-END:variables + private WeatherController controller; + private javax.swing.JPanel jPanel2; + + public void initXlet(final XletContext xletContext) throws XletStateChangeException { + context = xletContext; + if(rootContainer == null) { + try { + //This call to getContainer() tells the OS we want to be a graphical app. + rootContainer = context.getContainer(); + } catch (UnavailableContainerException e) { + System.out.println("Ouch ! could not get our container!"); + // If we can't get the root container, + // abort the initialization + throw new XletStateChangeException( "Start aborted -- no container: " + + e.getMessage() ); + } + } + } + + public void startXlet() throws XletStateChangeException { + // Note: Swing thread constraints still apply in an Xlet... most operations + // need to be on the event thread, and this invokeLater does that. + try { + // using invokeAndWait to avoid writing synchornization code. + // invokeLater would work just as well in most cases. + EventQueue.invokeAndWait(new Runnable() { + public void run() { + WeatherXlet.this.setVisible(true); + rootContainer.add(WeatherXlet.this); + // This is needed - or nothing will be displayed. + rootContainer.setVisible(true); + } + }); + } catch (Exception e) { + System.out.println("Ouch - exception in invokeAndWait()"); + e.printStackTrace(); + exit(); + } + } + + public void pauseXlet() { + //This is pure overkill for this application, but is done to demonstrate the point. + //We are freeing up our only resources (the screen), and we will rebuild it when + //we get started again. If you took out this block - the application should still + //run perfectly, and the screen should only be created once. + try { + // using invokeAndWait to avoid writing synchornization code. + // invokeLater would work just as well in most cases. + EventQueue.invokeAndWait(new Runnable() { + public void run() { + rootContainer.remove(WeatherXlet.this); + } + }); + } catch (Exception e) { + System.out.println("Ouch - exception in invokeAndWait()"); + e.printStackTrace(); + exit(); + } + } + + public void destroyXlet(boolean b) throws XletStateChangeException { + System.out.println("HelloXet.destroylet() - goodbye"); + } + + public void exit(){ + rootContainer.setVisible( false ); + context.notifyDestroyed(); + } +} diff --git a/Sample Code/chapter03/code/WeatherWidget/build.xml b/Sample Code/chapter03/code/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter03/code/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter03/code/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter03/code/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter03/code/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter03/code/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter03/code/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..692b09a --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,7 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active= +deployment.number=0.0.2 diff --git a/Sample Code/chapter03/code/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter03/code/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter03/code/WeatherWidget/nbproject/project.properties b/Sample Code/chapter03/code/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..0b38c91 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/nbproject/project.properties @@ -0,0 +1,81 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter03/code/WeatherWidget/nbproject/project.xml b/Sample Code/chapter03/code/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter03/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java b/Sample Code/chapter03/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java new file mode 100644 index 0000000..7ba3f83 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java @@ -0,0 +1,299 @@ +/* + * WeatherWidget.java + * + * Created on November 19, 2007, 7:58 PM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +/** + * + * @author kf6gpe + */ +public class WeatherWidget extends MIDlet implements CommandListener { + + /** + * Creates a new instance of WeatherWidget + */ + public WeatherWidget() { + } + + private Form wxForm;//GEN-BEGIN:MVDFields + private StringItem locationItem; + private Command exitCommand; + private Command okCommand; + private Command backCommand; + private Spacer spacer1; + private StringItem wxItem; + private List locationList; + private Command okCommand1; + private Command backCommand1; + private TextBox locationEntry; + private Command itemCommand1; + private Command okCommand2; + private Command backCommand2;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_wxForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == wxForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction3 + // Insert post-action code here + } else if (command == okCommand) {//GEN-LINE:MVDCACase3 + // Insert pre-action code here + getDisplay().setCurrent(get_locationList());//GEN-LINE:MVDCAAction30 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase30 + } else if (displayable == locationList) { + if (command == backCommand1) {//GEN-END:MVDCACase30 + // Insert pre-action code here + getDisplay().setCurrent(get_wxForm());//GEN-LINE:MVDCAAction32 + // Insert post-action code here + } else if (command == itemCommand1) {//GEN-LINE:MVDCACase32 + // Insert pre-action code here + getDisplay().setCurrent(get_wxForm());//GEN-LINE:MVDCAAction35 + // Insert post-action code here + } else if (command == okCommand2) {//GEN-LINE:MVDCACase35 + // Insert pre-action code here + getDisplay().setCurrent(get_locationEntry());//GEN-LINE:MVDCAAction37 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase37 + } else if (displayable == locationEntry) { + if (command == backCommand2) {//GEN-END:MVDCACase37 + // Insert pre-action code here + getDisplay().setCurrent(get_locationList());//GEN-LINE:MVDCAAction39 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase39 + }//GEN-END:MVDCACase39 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() {//GEN-FIRST:MVDGetDisplay + return Display.getDisplay(this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() {//GEN-FIRST:MVDExitMidlet + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + }//GEN-LAST:MVDExitMidlet + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + wxForm = new Form(null, new Item[] {//GEN-BEGIN:MVDGetInit2 + get_locationItem(), + get_spacer1(), + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_okCommand()); + wxForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return wxForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for locationItem component and should be called instead of accessing locationItem field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for locationItem component + */ + public StringItem get_locationItem() { + if (locationItem == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + locationItem = new StringItem("Location", "Berkeley, CA");//GEN-LINE:MVDGetInit4 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return locationItem; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return exitCommand; + }//GEN-END:MVDGetEnd5 + /** This method returns instance for okCommand component and should be called instead of accessing okCommand field directly.//GEN-BEGIN:MVDGetBegin11 + * @return Instance for okCommand component + */ + public Command get_okCommand() { + if (okCommand == null) {//GEN-END:MVDGetBegin11 + // Insert pre-init code here + okCommand = new Command("Settings", Command.OK, 1);//GEN-LINE:MVDGetInit11 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd11 + return okCommand; + }//GEN-END:MVDGetEnd11 + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly.//GEN-BEGIN:MVDGetBegin13 + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) {//GEN-END:MVDGetBegin13 + // Insert pre-init code here + backCommand = new Command("Back", Command.BACK, 1);//GEN-LINE:MVDGetInit13 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd13 + return backCommand; + }//GEN-END:MVDGetEnd13 + + /** This method returns instance for spacer1 component and should be called instead of accessing spacer1 field directly.//GEN-BEGIN:MVDGetBegin15 + * @return Instance for spacer1 component + */ + public Spacer get_spacer1() { + if (spacer1 == null) {//GEN-END:MVDGetBegin15 + // Insert pre-init code here + spacer1 = new Spacer(1000, 10);//GEN-LINE:MVDGetInit15 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd15 + return spacer1; + }//GEN-END:MVDGetEnd15 + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly.//GEN-BEGIN:MVDGetBegin16 + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) {//GEN-END:MVDGetBegin16 + // Insert pre-init code here + wxItem = new StringItem("Forecast", "Sunny.");//GEN-LINE:MVDGetInit16 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd16 + return wxItem; + }//GEN-END:MVDGetEnd16 + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly.//GEN-BEGIN:MVDGetBegin27 + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) {//GEN-END:MVDGetBegin27 + // Insert pre-init code here + locationList = new List("Weather", Choice.EXCLUSIVE, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit27 + locationList.addCommand(get_backCommand1()); + locationList.addCommand(get_itemCommand1()); + locationList.addCommand(get_okCommand2()); + locationList.setCommandListener(this); + locationList.setSelectedFlags(new boolean[0]); + locationList.setSelectCommand(get_itemCommand1()); + locationList.setFitPolicy(Choice.TEXT_WRAP_OFF);//GEN-END:MVDGetInit27 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd27 + return locationList; + }//GEN-END:MVDGetEnd27 + + /** This method returns instance for okCommand1 component and should be called instead of accessing okCommand1 field directly.//GEN-BEGIN:MVDGetBegin29 + * @return Instance for okCommand1 component + */ + public Command get_okCommand1() { + if (okCommand1 == null) {//GEN-END:MVDGetBegin29 + // Insert pre-init code here + okCommand1 = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit29 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd29 + return okCommand1; + }//GEN-END:MVDGetEnd29 + + /** This method returns instance for backCommand1 component and should be called instead of accessing backCommand1 field directly.//GEN-BEGIN:MVDGetBegin31 + * @return Instance for backCommand1 component + */ + public Command get_backCommand1() { + if (backCommand1 == null) {//GEN-END:MVDGetBegin31 + // Insert pre-init code here + backCommand1 = new Command("Back", Command.BACK, 1);//GEN-LINE:MVDGetInit31 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd31 + return backCommand1; + }//GEN-END:MVDGetEnd31 + + /** This method returns instance for locationEntry component and should be called instead of accessing locationEntry field directly.//GEN-BEGIN:MVDGetBegin33 + * @return Instance for locationEntry component + */ + public TextBox get_locationEntry() { + if (locationEntry == null) {//GEN-END:MVDGetBegin33 + // Insert pre-init code here + locationEntry = new TextBox("Add Location", "", 120, TextField.ANY);//GEN-BEGIN:MVDGetInit33 + locationEntry.addCommand(get_backCommand2()); + locationEntry.setCommandListener(this);//GEN-END:MVDGetInit33 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd33 + return locationEntry; + }//GEN-END:MVDGetEnd33 + + /** This method returns instance for itemCommand1 component and should be called instead of accessing itemCommand1 field directly.//GEN-BEGIN:MVDGetBegin34 + * @return Instance for itemCommand1 component + */ + public Command get_itemCommand1() { + if (itemCommand1 == null) {//GEN-END:MVDGetBegin34 + // Insert pre-init code here + itemCommand1 = new Command("Item", Command.ITEM, 1);//GEN-LINE:MVDGetInit34 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd34 + return itemCommand1; + }//GEN-END:MVDGetEnd34 + + /** This method returns instance for okCommand2 component and should be called instead of accessing okCommand2 field directly.//GEN-BEGIN:MVDGetBegin36 + * @return Instance for okCommand2 component + */ + public Command get_okCommand2() { + if (okCommand2 == null) {//GEN-END:MVDGetBegin36 + // Insert pre-init code here + okCommand2 = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit36 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd36 + return okCommand2; + }//GEN-END:MVDGetEnd36 + + /** This method returns instance for backCommand2 component and should be called instead of accessing backCommand2 field directly.//GEN-BEGIN:MVDGetBegin38 + * @return Instance for backCommand2 component + */ + public Command get_backCommand2() { + if (backCommand2 == null) {//GEN-END:MVDGetBegin38 + // Insert pre-init code here + backCommand2 = new Command("Back", Command.BACK, 1);//GEN-LINE:MVDGetInit38 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd38 + return backCommand2; + }//GEN-END:MVDGetEnd38 + + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter03/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.mvd b/Sample Code/chapter03/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.mvd new file mode 100644 index 0000000..b6714b5 --- /dev/null +++ b/Sample Code/chapter03/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.mvd @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter04/code/AlarmTimer/build.xml b/Sample Code/chapter04/code/AlarmTimer/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter04/code/AlarmTimer/nbproject/build-impl.xml b/Sample Code/chapter04/code/AlarmTimer/nbproject/build-impl.xml new file mode 100644 index 0000000..a2a8c8a --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/nbproject/build-impl.xml @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter04/code/AlarmTimer/nbproject/genfiles.properties b/Sample Code/chapter04/code/AlarmTimer/nbproject/genfiles.properties new file mode 100644 index 0000000..5329460 --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=a66d0cac +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=a66d0cac +nbproject/build-impl.xml.script.CRC32=036a5e16 +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter04/code/AlarmTimer/nbproject/private/private.properties b/Sample Code/chapter04/code/AlarmTimer/nbproject/private/private.properties new file mode 100644 index 0000000..3c0f356 --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/nbproject/private/private.properties @@ -0,0 +1,4 @@ +config.active= +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +javadoc.preview=true +netbeans.user=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 diff --git a/Sample Code/chapter04/code/AlarmTimer/nbproject/project.properties b/Sample Code/chapter04/code/AlarmTimer/nbproject/project.properties new file mode 100644 index 0000000..e8d8b99 --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/nbproject/project.properties @@ -0,0 +1,68 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=AlarmTimer.jad +dist.jar=AlarmTimer.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: HelloMidlet, ,com.apress.rischpater.alarmtimer.AlarmTimerMidlet\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: AlarmTimer\n +manifest.pushregistry= +name=AlarmTimer +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=true +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter04/code/AlarmTimer/nbproject/project.xml b/Sample Code/chapter04/code/AlarmTimer/nbproject/project.xml new file mode 100644 index 0000000..bff84ff --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + AlarmTimer + 1.6 + + + diff --git a/Sample Code/chapter04/code/AlarmTimer/src/com/apress/rischpater/alarmtimer/AlarmTimerMidlet.java b/Sample Code/chapter04/code/AlarmTimer/src/com/apress/rischpater/alarmtimer/AlarmTimerMidlet.java new file mode 100644 index 0000000..8299631 --- /dev/null +++ b/Sample Code/chapter04/code/AlarmTimer/src/com/apress/rischpater/alarmtimer/AlarmTimerMidlet.java @@ -0,0 +1,197 @@ +/* + * AlarmTimerMidlet.java + * + * Created on December 18, 2007, 3:23 AM + */ + +package com.apress.rischpater.alarmtimer; + +import java.io.*; +import java.util.*; +import java.lang.*; +import javax.microedition.io.*; +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import javax.microedition.rms.*; + +/** + * + * @author Ray Rischpater + */ +public class AlarmTimerMidlet extends MIDlet implements CommandListener { + + /** + * Creates a new instance of AlarmTimerMidlet + */ + public AlarmTimerMidlet() { + } + + class MyTask extends TimerTask { + private AlarmTimerMidlet owner; + void setOwner( AlarmTimerMidlet o ) { + owner = o; + } + public void run() { + owner.alarmFired(); + } + } + + private Form infoForm; + private StringItem helloStringItem; + private Command exitCommand; + private Alert alarmAlert; + private long DELAY = 15 * 1000; + private Timer timer; + private MyTask task; + private long whenLaunched = new Date().getTime(); + private String storeName = "AlarmTimerStore"; + private RecordStore store; + + /** This method initializes UI of the application. + */ + private void initialize() { + try { + Date d = new Date(); + long whenToFire = d.getTime() + DELAY; + store = RecordStore.openRecordStore(storeName, true); + + if (store.getNumRecords()>0){ + byte b[] = store.getRecord(1); + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + whenToFire = dis.readLong(); + if (whenToFire < whenLaunched) { + getDisplay().setCurrent(get_alarmAlert()); + } + store.deleteRecord(1); + store.closeRecordStore(); + return; + } + store.closeRecordStore(); + + String me = this.getClass().getName(); + PushRegistry.registerAlarm(me, 0); + timer = new Timer(); + task = new MyTask(); + task.setOwner(this); + timer.schedule(task, whenToFire - d.getTime() ); + + getDisplay().setCurrent(get_infoForm()); + } + catch( Exception e) {}; + } + + /** Called by the system to indicate that a command has been invoked on a particular displayable. + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) { + if (displayable == infoForm) { + if (command == exitCommand) { + exitMIDlet(); + } + } + } + + private void scheduleMIDlet( ) { + try { + String me = this.getClass().getName(); + Date when = new Date(); + if (when.getTime() < whenLaunched + DELAY) { + PushRegistry.registerAlarm(me, whenLaunched + DELAY); + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream( baos ); + dos.writeLong(whenLaunched + DELAY); + byte b[] = baos.toByteArray(); + store = RecordStore.openRecordStore(storeName, true); + store.addRecord(b, 0, b.length); + store.closeRecordStore(); + } + catch (Exception e) {} + } + + private void alarmFired() { + getDisplay().setCurrent(get_alarmAlert(), get_infoForm()); + } + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + try { + if ( getDisplay().getCurrent() != get_infoForm() ) + scheduleMIDlet(); + } + catch(Exception e) {}; + destroyApp(true); + notifyDestroyed(); + } + + /** This method returns instance for infoForm component and should be called instead of accessing infoForm field directly. + * @return Instance for infoForm component + */ + public Form get_infoForm() { + if (infoForm == null) { + infoForm = new Form(null, new Item[] {get_helloStringItem()}); + infoForm.addCommand(get_exitCommand()); + infoForm.setCommandListener(this); + } + return infoForm; + } + + /** This method returns instance for helloStringItem component and should be called instead of accessing helloStringItem field directly. + * @return Instance for helloStringItem component + */ + public StringItem get_helloStringItem() { + if (helloStringItem == null) { + // Insert pre-init code here + helloStringItem = new StringItem("", "An alarm has been set for fifteen seconds from now."); + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return helloStringItem; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + /** This method returns instance for alarmAlert component and should be called instead of accessing alarmAlert field directly. + * @return Instance for alarmAlert component + */ + public Alert get_alarmAlert() { + if (alarmAlert == null) { + alarmAlert = new Alert(null, "The alarm has fired.\n", null, null); + alarmAlert.setTimeout(-2); + } + return alarmAlert; + } + + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + timer = null; + task = null; + } + +} diff --git a/Sample Code/chapter04/code/HelloWorld/build.xml b/Sample Code/chapter04/code/HelloWorld/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter04/code/HelloWorld/nbproject/build-impl.xml b/Sample Code/chapter04/code/HelloWorld/nbproject/build-impl.xml new file mode 100644 index 0000000..a2a8c8a --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/nbproject/build-impl.xml @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter04/code/HelloWorld/nbproject/genfiles.properties b/Sample Code/chapter04/code/HelloWorld/nbproject/genfiles.properties new file mode 100644 index 0000000..e813b83 --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=37988ec2 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=37988ec2 +nbproject/build-impl.xml.script.CRC32=036a5e16 +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter04/code/HelloWorld/nbproject/private/private.properties b/Sample Code/chapter04/code/HelloWorld/nbproject/private/private.properties new file mode 100644 index 0000000..7b953e2 --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/nbproject/private/private.properties @@ -0,0 +1,3 @@ +config.active= +javadoc.preview=true +netbeans.user=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 diff --git a/Sample Code/chapter04/code/HelloWorld/nbproject/private/private.xml b/Sample Code/chapter04/code/HelloWorld/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter04/code/HelloWorld/nbproject/project.properties b/Sample Code/chapter04/code/HelloWorld/nbproject/project.properties new file mode 100644 index 0000000..88f3db2 --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/nbproject/project.properties @@ -0,0 +1,67 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=HelloWorld.jad +dist.jar=HelloWorld.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: HelloMidlet, , hello.HelloMidlet\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: HelloWorld\n +manifest.pushregistry= +name=HelloWorld +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=manufacturer +run.use.security.domain=false +sign.alias= +sign.enabled=false +sign.keystore= +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter04/code/HelloWorld/nbproject/project.xml b/Sample Code/chapter04/code/HelloWorld/nbproject/project.xml new file mode 100644 index 0000000..ef93396 --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + HelloWorld + 1.6 + + + diff --git a/Sample Code/chapter04/code/HelloWorld/src/hello/HelloMidlet.java b/Sample Code/chapter04/code/HelloWorld/src/hello/HelloMidlet.java new file mode 100644 index 0000000..56b5979 --- /dev/null +++ b/Sample Code/chapter04/code/HelloWorld/src/hello/HelloMidlet.java @@ -0,0 +1,24 @@ + +package hello; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class HelloMidlet extends MIDlet { + + public HelloMidlet() { + } + + public void startApp() { + Display.getDisplay(this).setCurrent( + new TextBox("", "Hello World", 20, 0) ); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } +} + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/REMOVE THIS SAMPLE CODE BFEORE DISTRIBUTION.txt b/Sample Code/chapter05/code/UIWidgetExample/REMOVE THIS SAMPLE CODE BFEORE DISTRIBUTION.txt new file mode 100644 index 0000000..e69de29 diff --git a/Sample Code/chapter05/code/UIWidgetExample/build.xml b/Sample Code/chapter05/code/UIWidgetExample/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/nbproject/build-impl.xml b/Sample Code/chapter05/code/UIWidgetExample/nbproject/build-impl.xml new file mode 100644 index 0000000..a2a8c8a --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/nbproject/build-impl.xml @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/nbproject/genfiles.properties b/Sample Code/chapter05/code/UIWidgetExample/nbproject/genfiles.properties new file mode 100644 index 0000000..dda9b6f --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=f66c600f +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=f66c600f +nbproject/build-impl.xml.script.CRC32=036a5e16 +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter05/code/UIWidgetExample/nbproject/private/private.properties b/Sample Code/chapter05/code/UIWidgetExample/nbproject/private/private.properties new file mode 100644 index 0000000..7b953e2 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/nbproject/private/private.properties @@ -0,0 +1,3 @@ +config.active= +javadoc.preview=true +netbeans.user=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 diff --git a/Sample Code/chapter05/code/UIWidgetExample/nbproject/private/private.xml b/Sample Code/chapter05/code/UIWidgetExample/nbproject/private/private.xml new file mode 100644 index 0000000..d4f3431 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/nbproject/private/private.xml @@ -0,0 +1,10 @@ + + + + + file:/C:/book/Chapters/chapter05/code/UIWidgetExample/src/example/canvas/CanvasExample.java + file:/C:/book/Chapters/chapter05/code/UIWidgetExample/src/example/canvas/MyCanvas.java + file:/C:/book/Chapters/chapter05/code/UIWidgetExample/src/example/gauge/NonInteractiveGaugeRunnable.java + file:/C:/book/Chapters/chapter05/code/UIWidgetExample/src/example/list/ListExample.java + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/nbproject/project.properties b/Sample Code/chapter05/code/UIWidgetExample/nbproject/project.properties new file mode 100644 index 0000000..34a6c44 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/nbproject/project.properties @@ -0,0 +1,67 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=UIWidgetExample.jad +dist.jar=UIWidgetExample.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-8: CommandExample,/icons/Icon.png,CommandExample\nMIDlet-3: Gauge, /icons/Icon.png, example.gauge.GaugeDemo\nMIDlet-7: TextField, /icons/Icon.png, example.textfield.TextFieldDemo\nMIDlet-5: ChoiceGroup, /icons/Icon.png, example.choicegroup.ChoiceGroupDemo\nMIDlet-2: StringItem, /icons/Icon.png, example.stringitem.StringItemDemo\nMIDlet-10: CanvasExample,/icons/Icon.png,example.canvas.CanvasExample\nMIDlet-11: WxItemDemo,/icons/Icon.png,example.wxitem.WeatherItemExample\nMIDlet-9: ListExample,/icons/Icon.png,ListExample\nMIDlet-6: TextBox, /icons/Icon.png, example.textbox.TextBoxDemo\nMIDlet-1: CustomItem, /icons/Icon.png, example.customitem.CustomItemDemo\nMIDlet-4: Alert, /icons/Icon.png, example.alert.AlertDemo\n +manifest.others=MIDlet-Vendor: Sun Microsystems\nMIDlet-Name: UIDemo\nMIDlet-Version: 1.0\n +manifest.pushregistry= +name=UIWidgetExample +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/cldcapi10.jar:${platform.home}/lib/midpapi20.jar +platform.configuration=CLDC-1.0 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.0 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=manufacturer +run.use.security.domain=false +sign.alias= +sign.enabled=false +sign.keystore= +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter05/code/UIWidgetExample/nbproject/project.xml b/Sample Code/chapter05/code/UIWidgetExample/nbproject/project.xml new file mode 100644 index 0000000..0bd9e56 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + UIWidgetExample + 1.6 + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/alert/AlertDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/alert/AlertDemo.java new file mode 100644 index 0000000..73bbb61 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/alert/AlertDemo.java @@ -0,0 +1,264 @@ +/* + * AlertDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.alert; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + + +public class AlertDemo extends MIDlet implements javax.microedition.lcdui.CommandListener { + + private final String[] typeStrings = {"Alarm", "Confirmation", "Error", "Info", "Warning"}; + private final String[] timeoutStrings = {"2 Seconds", "4 Seconds", "8 Seconds", "Forever"}; + private final AlertType[] alertTypes = { + AlertType.ALARM, AlertType.CONFIRMATION, AlertType.ERROR, + AlertType.INFO, AlertType.WARNING + }; + private final int[] timeouts = { 2 * SECOND, 4 * SECOND, 8 * SECOND, Alert.FOREVER }; + private final static int SECOND = 1000; + + /** Creates a new instance of AlertDemo */ + public AlertDemo() { + } + + private Form mainForm;//GEN-BEGIN:MVDFields + private ChoiceGroup typeGroup; + private ChoiceGroup timeoutGroup; + private ChoiceGroup optionsGroup; + private Alert alert; + private Command showCommand; + private Command exitCommand;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == showCommand) {//GEN-END:MVDCABody + setUpAlert(); + getDisplay().setCurrent(get_alert(), get_mainForm());//GEN-LINE:MVDCAAction8 + // Insert post-action code here + } else if (command == exitCommand) {//GEN-LINE:MVDCACase8 + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction10 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase10 + }//GEN-END:MVDCACase10 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + mainForm = new Form("Alert Options", new Item[] {//GEN-BEGIN:MVDGetInit2 + get_typeGroup(), + get_timeoutGroup(), + get_optionsGroup() + }); + mainForm.addCommand(get_showCommand()); + mainForm.addCommand(get_exitCommand()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for typeGroup component and should be called instead of accessing typeGroup field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for typeGroup component + */ + public ChoiceGroup get_typeGroup() { + if (typeGroup == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + typeGroup = new ChoiceGroup("Type", Choice.POPUP, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit3 + typeGroup.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit3 + fillTypeGroup(); + }//GEN-BEGIN:MVDGetEnd3 + return typeGroup; + }//GEN-END:MVDGetEnd3 + + /** This method returns instance for timeoutGroup component and should be called instead of accessing timeoutGroup field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for timeoutGroup component + */ + public ChoiceGroup get_timeoutGroup() { + if (timeoutGroup == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + timeoutGroup = new ChoiceGroup("Timeout", Choice.POPUP, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit4 + timeoutGroup.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit4 + fillTimeoutGroup(); + }//GEN-BEGIN:MVDGetEnd4 + return timeoutGroup; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for optionsGroup component and should be called instead of accessing optionsGroup field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for optionsGroup component + */ + public ChoiceGroup get_optionsGroup() { + if (optionsGroup == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + optionsGroup = new ChoiceGroup("Options", Choice.MULTIPLE, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit5 + optionsGroup.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit5 + this.get_optionsGroup().append("Show Indicator",null); + }//GEN-BEGIN:MVDGetEnd5 + return optionsGroup; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for alert component and should be called instead of accessing alert field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for alert component + */ + public Alert get_alert() { + if (alert == null) {//GEN-END:MVDGetBegin6 + // Insert pre-init code here + alert = new Alert("Alert", null, null, AlertType.INFO);//GEN-BEGIN:MVDGetInit6 + alert.setTimeout(-2);//GEN-END:MVDGetInit6 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd6 + return alert; + }//GEN-END:MVDGetEnd6 + + /** This method returns instance for showCommand component and should be called instead of accessing showCommand field directly.//GEN-BEGIN:MVDGetBegin7 + * @return Instance for showCommand component + */ + public Command get_showCommand() { + if (showCommand == null) {//GEN-END:MVDGetBegin7 + // Insert pre-init code here + showCommand = new Command("Show", Command.OK, 1);//GEN-LINE:MVDGetInit7 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd7 + return showCommand; + }//GEN-END:MVDGetEnd7 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin9 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin9 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit9 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd9 + return exitCommand; + }//GEN-END:MVDGetEnd9 + + private void fillTypeGroup() { + for (int i=0;i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/canvas/CanvasExample.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/canvas/CanvasExample.java new file mode 100644 index 0000000..2014d26 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/canvas/CanvasExample.java @@ -0,0 +1,14 @@ +package example.canvas; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class CanvasExample extends MIDlet { + public void startApp() { + MyCanvas c = new MyCanvas(); + + Display.getDisplay(this).setCurrent(c); + } + public void pauseApp() { } + public void destroyApp(boolean unconditional) { } +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/canvas/MyCanvas.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/canvas/MyCanvas.java new file mode 100644 index 0000000..bf977f8 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/canvas/MyCanvas.java @@ -0,0 +1,37 @@ +package example.canvas; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + + +public class MyCanvas extends Canvas { + protected void paint( Graphics g) { + System.out.println( "Paint!"); + } + protected void keyPressed( int code ) { + System.out.println( "pressed!"); + System.out.println( KEY_NUM9 ); + System.out.println( code ); + + } + protected void keyReleased( int code ) { + System.out.println( "released!"); + + } + protected void keyRepeated( int code ) { + System.out.println( "repeated!"); + } + + protected void pointerPressed(int x, int y) { + System.out.println("Press at " + Integer.toString(x) + "," + Integer.toString(y)); + } + + protected void pointerDragged( int x, int y) { + System.out.println("Drag to " + Integer.toString(x) + "," + Integer.toString(y)); + } + + protected void pointerReleased( int x, int y ) { + System.out.println("Release at " + Integer.toString(x) + "," + Integer.toString(y)); + + } +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/choicegroup/ChoiceGroupDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/choicegroup/ChoiceGroupDemo.java new file mode 100644 index 0000000..72e7369 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/choicegroup/ChoiceGroupDemo.java @@ -0,0 +1,195 @@ +/* + * ChoiceGroupDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.choicegroup; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class ChoiceGroupDemo extends MIDlet implements javax.microedition.lcdui.CommandListener { + + /** Creates a new instance of ChoiceGroupDemo */ + public ChoiceGroupDemo() { + } + + private Form mainForm;//GEN-BEGIN:MVDFields + private StringItem stringItemTitle; + private ChoiceGroup cgExcl; + private ChoiceGroup cgMult; + private ChoiceGroup cgPop; + private Image icon; + private Command exitCommand;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction13 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase13 + }//GEN-END:MVDCACase13 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + String base="Option "; + for (char c='A';c<'E';c++) { + get_cgPop().append(base+c,get_icon()); + get_cgMult().append(base+c,get_icon()); + } + mainForm = new Form("Choice Group", new Item[] {//GEN-BEGIN:MVDGetInit2 + get_stringItemTitle(), + get_cgExcl(), + get_cgMult(), + get_cgPop() + }); + mainForm.addCommand(get_exitCommand()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for stringItemTitle component and should be called instead of accessing stringItemTitle field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for stringItemTitle component + */ + public StringItem get_stringItemTitle() { + if (stringItemTitle == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + stringItemTitle = new StringItem(null, "These are the available choice group types");//GEN-BEGIN:MVDGetInit3 + stringItemTitle.setLayout(Item.LAYOUT_LEFT | Item.LAYOUT_TOP | Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit3 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd3 + return stringItemTitle; + }//GEN-END:MVDGetEnd3 + + /** This method returns instance for cgExcl component and should be called instead of accessing cgExcl field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for cgExcl component + */ + public ChoiceGroup get_cgExcl() { + if (cgExcl == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + cgExcl = new ChoiceGroup("Exclusive", Choice.EXCLUSIVE, new String[] {//GEN-BEGIN:MVDGetInit4 + "Option A", + "Option B", + "Option C", + "Option D" + }, new Image[] { + get_icon(), + get_icon(), + get_icon(), + get_icon() + }); + cgExcl.setSelectedFlags(new boolean[] { + false, + false, + false, + false + });//GEN-END:MVDGetInit4 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return cgExcl; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for cgMult component and should be called instead of accessing cgMult field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for cgMult component + */ + public ChoiceGroup get_cgMult() { + if (cgMult == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + cgMult = new ChoiceGroup("Multiple", Choice.MULTIPLE, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit5 + cgMult.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return cgMult; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for cgPop component and should be called instead of accessing cgPop field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for cgPop component + */ + public ChoiceGroup get_cgPop() { + if (cgPop == null) {//GEN-END:MVDGetBegin6 + // Insert pre-init code here + cgPop = new ChoiceGroup("Pop-up", Choice.POPUP, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit6 + cgPop.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit6 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd6 + return cgPop; + }//GEN-END:MVDGetEnd6 + + /** This method returns instance for icon component and should be called instead of accessing icon field directly.//GEN-BEGIN:MVDGetBegin7 + * @return Instance for icon component + */ + public Image get_icon() { + if (icon == null) {//GEN-END:MVDGetBegin7 + // Insert pre-init code here + try {//GEN-BEGIN:MVDGetInit7 + icon = Image.createImage("/icons/Icon.png"); + } catch (java.io.IOException exception) { + }//GEN-END:MVDGetInit7 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd7 + return icon; + }//GEN-END:MVDGetEnd7 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin12 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin12 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit12 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd12 + return exitCommand; + }//GEN-END:MVDGetEnd12 + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/choicegroup/ChoiceGroupDemo.mvd b/Sample Code/chapter05/code/UIWidgetExample/src/example/choicegroup/ChoiceGroupDemo.mvd new file mode 100644 index 0000000..f538c67 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/choicegroup/ChoiceGroupDemo.mvd @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/commands/CommandExample.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/commands/CommandExample.java new file mode 100644 index 0000000..d6fcc38 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/commands/CommandExample.java @@ -0,0 +1,26 @@ +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + + +public class CommandExample extends MIDlet { + public void startApp() { + Displayable d = new TextBox("Demo", "", 20, TextField.ANY); + Command exit = new Command("Exit", Command.EXIT, 0); + Command help = new Command("Help", Command.HELP, 1); + Command stop = new Command("Stop", Command.STOP, 2); + + d.addCommand(exit); + d.addCommand(help); + d.addCommand(stop); + + d.setCommandListener(new CommandListener() { + public void commandAction(Command c, Displayable s) { + notifyDestroyed(); + } + } ); + + Display.getDisplay(this).setCurrent(d); + } + public void pauseApp() { } + public void destroyApp(boolean unconditional) { } +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/CustomItemDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/CustomItemDemo.java new file mode 100644 index 0000000..65c1c38 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/CustomItemDemo.java @@ -0,0 +1,143 @@ +/* + * CustomItemDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.customitem; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class CustomItemDemo extends MIDlet implements javax.microedition.lcdui.CommandListener { + + /** Creates a new instance of CustomItemDemo */ + public CustomItemDemo() { + } + + private Form mainForm;//GEN-BEGIN:MVDFields + private example.customitem.Table customItem1; + private Command exitCommand; + private TextField textField1; + private TextField textField2;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction5 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase5 + }//GEN-END:MVDCACase5 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + mainForm = new Form("Custom Item Demo", new Item[] {//GEN-BEGIN:MVDGetInit2 + get_textField1(), + get_customItem1(), + get_textField2() + }); + mainForm.addCommand(get_exitCommand()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for customItem1 component and should be called instead of accessing customItem1 field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for customItem1 component + */ + public example.customitem.Table get_customItem1() { + if (customItem1 == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + customItem1 = new example.customitem.Table("Table", Display.getDisplay(this));//GEN-BEGIN:MVDGetInit3 + customItem1.setLabel("Table");//GEN-END:MVDGetInit3 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd3 + return customItem1; + }//GEN-END:MVDGetEnd3 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit4 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return exitCommand; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for textField1 component and should be called instead of accessing textField1 field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for textField1 component + */ + public TextField get_textField1() { + if (textField1 == null) {//GEN-END:MVDGetBegin6 + // Insert pre-init code here + textField1 = new TextField("Upper Item", null, 10, TextField.ANY);//GEN-LINE:MVDGetInit6 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd6 + return textField1; + }//GEN-END:MVDGetEnd6 + + /** This method returns instance for textField2 component and should be called instead of accessing textField2 field directly.//GEN-BEGIN:MVDGetBegin7 + * @return Instance for textField2 component + */ + public TextField get_textField2() { + if (textField2 == null) {//GEN-END:MVDGetBegin7 + // Insert pre-init code here + textField2 = new TextField("Lower Item", null, 10, TextField.ANY);//GEN-LINE:MVDGetInit7 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd7 + return textField2; + }//GEN-END:MVDGetEnd7 + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/CustomItemDemo.mvd b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/CustomItemDemo.mvd new file mode 100644 index 0000000..60b1814 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/CustomItemDemo.mvd @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/Table.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/Table.java new file mode 100644 index 0000000..e7c5571 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/Table.java @@ -0,0 +1,182 @@ +/* + * %W% %E% + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms + */ +package example.customitem; + +import javax.microedition.lcdui.*; + +/** + * + * @version 2.0 + */ +public class Table + extends CustomItem + implements ItemCommandListener { + + private final static Command CMD_EDIT = new Command("Edit", Command.ITEM, + 1); + private Display display; + private int rows = 5; + private int cols = 3; + private int dx = 50; + private int dy = 20; + private final static int UPPER = 0; + private final static int IN = 1; + private final static int LOWER = 2; + private int location = UPPER; + private int currentX = 0; + private int currentY = 0; + private String[][] data = new String[rows][cols]; + + public Table(String title, Display d) { + super(title); + display = d; + setDefaultCommand(CMD_EDIT); + setItemCommandListener(this); + } + + protected int getMinContentHeight() { + + return (rows * dy) + 1; + } + + protected int getMinContentWidth() { + + return (cols * dx) + 1; + } + + protected int getPrefContentHeight(int width) { + + return (rows * dy) + 1; + } + + protected int getPrefContentWidth(int height) { + + return (cols * dx) + 1; + } + + protected void paint(Graphics g, int w, int h) { + + for (int i = 0; i <= rows; i++) { + g.drawLine(0, i * dy, cols * dx, i * dy); + } + + for (int i = 0; i <= cols; i++) { + g.drawLine(i * dx, 0, i * dx, rows * dy); + } + + int oldColor = g.getColor(); + g.setColor(0x00D0D0D0); + g.fillRect((currentX * dx) + 1, (currentY * dy) + 1, dx - 1, dy - 1); + g.setColor(oldColor); + + for (int i = 0; i < rows; i++) { + + for (int j = 0; j < cols; j++) { + + if (data[i][j] != null) { + + // store clipping properties + int oldClipX = g.getClipX(); + int oldClipY = g.getClipY(); + int oldClipWidth = g.getClipWidth(); + int oldClipHeight = g.getClipHeight(); + g.setClip((j * dx) + 1, i * dy, dx - 1, dy - 1); + g.drawString(data[i][j], (j * dx) + 2, ((i + 1) * dy) - 2, + Graphics.BOTTOM | Graphics.LEFT); + + // restore clipping properties + g.setClip(oldClipX, oldClipY, oldClipWidth, oldClipHeight); + } + } + } + } + + protected boolean traverse(int dir, int viewportWidth, int viewportHeight, + int[] visRect_inout) { + + switch (dir) { + + case Canvas.DOWN: + + if (location == UPPER) { + location = IN; + } else { + + if (currentY < (rows - 1)) { + currentY++; + repaint(currentX * dx, (currentY - 1) * dy, dx, dy); + repaint(currentX * dx, currentY * dy, dx, dy); + } else { + location = LOWER; + + return false; + } + } + + break; + + case Canvas.UP: + + if (location == LOWER) { + location = IN; + } else { + + if (currentY > 0) { + currentY--; + repaint(currentX * dx, (currentY + 1) * dy, dx, dy); + repaint(currentX * dx, currentY * dy, dx, dy); + } else { + location = UPPER; + + return false; + } + } + + break; + + case Canvas.LEFT: + + if (currentX > 0) { + currentX--; + repaint((currentX + 1) * dx, currentY * dy, dx, dy); + repaint(currentX * dx, currentY * dy, dx, dy); + } + + break; + + case Canvas.RIGHT: + + if (currentX < (cols - 1)) { + currentX++; + repaint((currentX - 1) * dx, currentY * dy, dx, dy); + repaint(currentX * dx, currentY * dy, dx, dy); + } + } + + visRect_inout[0] = currentX; + visRect_inout[1] = currentY; + visRect_inout[2] = dx; + visRect_inout[3] = dy; + + return true; + } + + public void setText(String text) { + data[currentY][currentX] = text; + repaint(currentY * dx, currentX * dy, dx, dy); + } + + public void commandAction(Command c, Item i) { + + if (c == CMD_EDIT) { + + TextInput textInput = new TextInput(data[currentY][currentX], this, + display); + display.setCurrent(textInput); + } + } +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/TextInput.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/TextInput.java new file mode 100644 index 0000000..b406882 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/customitem/TextInput.java @@ -0,0 +1,47 @@ +/* + * %W% %E% + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms + */ +package example.customitem; + +import javax.microedition.lcdui.*; +import javax.microedition.midlet.MIDlet; + + +/** + * + * @version 2.0 + */ +public class TextInput extends TextBox implements CommandListener { + + private final static Command CMD_OK = new Command("OK", Command.OK, + 1); + private final static Command CMD_CANCEL = new Command("Cancel", Command.CANCEL, + 1); + + private Table parent; + private Display display; + + public TextInput(String text, Table parent, Display display) { + super("Enter Text", text, 50, TextField.ANY); + this.parent = parent; + this.display = display; + addCommand(CMD_OK); + addCommand(CMD_CANCEL); + setCommandListener(this); + } + + public void commandAction(Command c, Displayable d) { + if (c == CMD_OK) { + // update the table's cell and return + parent.setText(getString()); + display.setCurrentItem(parent); + } else if (c == CMD_CANCEL) { + // return without updating the table's cell + display.setCurrentItem(parent); + } + } + +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/GaugeDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/GaugeDemo.java new file mode 100644 index 0000000..f17c8e0 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/GaugeDemo.java @@ -0,0 +1,175 @@ +/* + * GaugeDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.gauge; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class GaugeDemo extends MIDlet implements javax.microedition.lcdui.CommandListener { + + /** Creates a new instance of GaugeDemo */ + public GaugeDemo() { + System.out.println(Gauge.INDEFINITE); + System.out.println(Gauge.CONTINUOUS_RUNNING); + System.out.println(Gauge.INCREMENTAL_IDLE); + } + + private javax.microedition.lcdui.Form mainForm;//GEN-BEGIN:MVDFields + private javax.microedition.lcdui.Gauge indefiniteGauge; + private javax.microedition.lcdui.Gauge interactiveGauge; + private javax.microedition.lcdui.Command exitCommand; + private example.gauge.IncrementalIndefiniteGaugeRunnable gauge1; + private example.gauge.NonInteractiveGaugeRunnable gauge2;//GEN-END:MVDFields + + /** This method initializes UI of the application.//GEN-BEGIN:MVDMethods + */ + private void initialize() { + getDisplay().setCurrent(get_mainForm()); + }//GEN-END:MVDMethods + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(javax.microedition.lcdui.Command command, javax.microedition.lcdui.Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction6 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase6 + }//GEN-END:MVDCACase6 + // Insert global post-action code here + }//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public javax.microedition.lcdui.Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + mainForm = new javax.microedition.lcdui.Form("Gauge Demo", new javax.microedition.lcdui.Item[] {//GEN-BEGIN:MVDGetInit2 + get_interactiveGauge(), + get_indefiniteGauge(), + get_gauge1(), + get_gauge2() + }); + mainForm.addCommand(get_exitCommand()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + new Thread(get_gauge1()).start(); + new Thread(get_gauge2()).start(); + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for indefiniteGauge component and should be called instead of accessing indefiniteGauge field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for indefiniteGauge component + */ + public javax.microedition.lcdui.Gauge get_indefiniteGauge() { + if (indefiniteGauge == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + indefiniteGauge = new javax.microedition.lcdui.Gauge("Indefinite - Running", false, -1, 2);//GEN-BEGIN:MVDGetInit3 + indefiniteGauge.setLayout(0x4211);//GEN-END:MVDGetInit3 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd3 + return indefiniteGauge; + }//GEN-END:MVDGetEnd3 + + /** This method returns instance for interactiveGauge component and should be called instead of accessing interactiveGauge field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for interactiveGauge component + */ + public javax.microedition.lcdui.Gauge get_interactiveGauge() { + if (interactiveGauge == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + interactiveGauge = new javax.microedition.lcdui.Gauge("Interactive", true, 10, 0);//GEN-BEGIN:MVDGetInit4 + interactiveGauge.setLayout(0x4211);//GEN-END:MVDGetInit4 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return interactiveGauge; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for exitCommand component + */ + public javax.microedition.lcdui.Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + exitCommand = new javax.microedition.lcdui.Command("Exit", javax.microedition.lcdui.Command.EXIT, 1);//GEN-LINE:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return exitCommand; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for gauge1 component and should be called instead of accessing gauge1 field directly.//GEN-BEGIN:MVDGetBegin7 + * @return Instance for gauge1 component + */ + public example.gauge.IncrementalIndefiniteGaugeRunnable get_gauge1() { + if (gauge1 == null) {//GEN-END:MVDGetBegin7 + // Insert pre-init code here + gauge1 = new example.gauge.IncrementalIndefiniteGaugeRunnable();//GEN-BEGIN:MVDGetInit7 + gauge1.setLabel("Non Interactive"); + gauge1.setLayout(0x4201); + gauge1.setValue(1); + gauge1.setMaxValue(-1);//GEN-END:MVDGetInit7 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd7 + return gauge1; + }//GEN-END:MVDGetEnd7 + + /** This method returns instance for gauge2 component and should be called instead of accessing gauge2 field directly.//GEN-BEGIN:MVDGetBegin8 + * @return Instance for gauge2 component + */ + public example.gauge.NonInteractiveGaugeRunnable get_gauge2() { + if (gauge2 == null) {//GEN-END:MVDGetBegin8 + // Insert pre-init code here + gauge2 = new example.gauge.NonInteractiveGaugeRunnable();//GEN-BEGIN:MVDGetInit8 + gauge2.setLabel("Indefinite - Incremental"); + gauge2.setValue(0); + gauge2.setMaxValue(10);//GEN-END:MVDGetInit8 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd8 + return gauge2; + }//GEN-END:MVDGetEnd8 + + private void addCustomComponents() { + NonInteractiveGaugeRunnable nonInteractive = new NonInteractiveGaugeRunnable(); + new Thread(nonInteractive).start(); + get_mainForm().append(nonInteractive); + + IncrementalIndefiniteGaugeRunnable indefinite = new IncrementalIndefiniteGaugeRunnable(); + new Thread(indefinite).start(); + get_mainForm().append(indefinite); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/GaugeDemo.mvd b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/GaugeDemo.mvd new file mode 100644 index 0000000..9e6bb45 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/GaugeDemo.mvd @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/IncrementalIndefiniteGaugeRunnable.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/IncrementalIndefiniteGaugeRunnable.java new file mode 100644 index 0000000..6aa10b7 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/IncrementalIndefiniteGaugeRunnable.java @@ -0,0 +1,46 @@ +/* + * %W% %E% + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms + */ +package example.gauge; + +import javax.microedition.lcdui.*; + + +/** + * This class implements a non-interactive gague control + * that moves automatically with indifinite range. + * + * @version 2.0 + */ +public class IncrementalIndefiniteGaugeRunnable extends Gauge implements Runnable { + private boolean done = false; + + /** + * The constructor initializes the gauge. + */ + public IncrementalIndefiniteGaugeRunnable() { + super("Indefinite - Incremental", false, Gauge.INDEFINITE, Gauge.INCREMENTAL_IDLE); + new Thread(this).start(); + } + + /** + * This method moves the gauge left and right. + */ + public void run() { + + while (!done) { + setValue(Gauge.INCREMENTAL_UPDATING); + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException err) { + } + } + } + + void setDone() { + done = true; + } +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/NonInteractiveGaugeRunnable.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/NonInteractiveGaugeRunnable.java new file mode 100644 index 0000000..29ff02e --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/gauge/NonInteractiveGaugeRunnable.java @@ -0,0 +1,69 @@ +/* + * %W% %E% + * + * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms + */ +package example.gauge; + +import javax.microedition.lcdui.*; + + +/** + * This class implements a non-interactive gague control + * that moves automatically, between the min and max values. + * + * @version 2.0 + */ +public class NonInteractiveGaugeRunnable extends Gauge implements Runnable { + + private int maxValue = 10; + + /** + * This member indicates the number of units to move per + * iteration. It is set to -1 when we reach a 100 and 1 + * when we reach 0. + */ + private int delta = 1; + + private boolean done = false; + + /** + * The constructor initializes the gauge. + */ + public NonInteractiveGaugeRunnable() { + super("Non Interactive", false, 10, 0); + this.maxValue = maxValue; + new Thread(this).start(); + } + + + /** + * This method moves the gauge left and right. + */ + public void run() { + + while (!done) { + + // decide whether the gauge should start moving + // backwards or forwards. + int newValue = getValue() + delta; + + if (newValue == maxValue) { + delta = -1; + } else if (newValue == 0) { + delta = 1; + } + + setValue(newValue); + try { + Thread.currentThread().sleep(1000); + } catch (InterruptedException err) { + } + } + } + + void setDone() { + done = true; + } +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/list/ListExample.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/list/ListExample.java new file mode 100644 index 0000000..b884c90 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/list/ListExample.java @@ -0,0 +1,35 @@ +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + + +public class ListExample extends MIDlet { + public void startApp() { + final List l = new List("Pizza Toppings", Choice.MULTIPLE); + l.append( "Anchovies", null ); + l.append( "Cheese", null ); + l.append( "Olives", null ); + l.append( "Onions", null ); + l.append( "Pepperoni", null ); + l.append( "Sausage", null ); + + l.addCommand( new Command( "Order", "Order Pizza", Command.ITEM, 0)); + l.setCommandListener( new CommandListener() { + public void commandAction(Command c, Displayable s) { + boolean isSelected[] = new boolean[ l.size() ]; + int i; + l.getSelectedFlags( isSelected ); + + for ( i = 0; i < l.size(); i++ ) { + if ( isSelected[ i ] ) { + System.out.println( l.getString( i )); + } + } + } + } ); + + + Display.getDisplay(this).setCurrent(l); + } + public void pauseApp() { } + public void destroyApp(boolean unconditional) { } +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/stringitem/StringItemDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/stringitem/StringItemDemo.java new file mode 100644 index 0000000..52200f1 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/stringitem/StringItemDemo.java @@ -0,0 +1,272 @@ +/* + * StringItemDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.stringitem; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class StringItemDemo extends MIDlet implements javax.microedition.lcdui.CommandListener, javax.microedition.lcdui.ItemCommandListener { + + /** Creates a new instance of StringItemDemo */ + public StringItemDemo() { + } + + private Form mainForm;//GEN-BEGIN:MVDFields + private Command exitCommand; + private StringItem stringItem1; + private StringItem stringItem2; + private StringItem stringItem4; + private StringItem stringItem5; + private Command goCommand; + private Command pressCommand; + private Command okCommand1; + private Command okCommand2; + private Command helpCommand1; + private Command stopCommand1;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular item.//GEN-BEGIN:MVDICABegin + * @param command the Command that ws invoked + * @param item the Item on which the command was invoked + */ + public void commandAction(Command command, Item item) {//GEN-END:MVDICABegin + // Insert global pre-action code here + if (item == stringItem5) {//GEN-BEGIN:MVDICABody + if (command == pressCommand) {//GEN-END:MVDICABody + Display.getDisplay(this).setCurrent(new Alert("Action", "Do an action...", null, AlertType.INFO), get_mainForm()); + // Do nothing//GEN-LINE:MVDICAAction13 + // Insert post-action code here + }//GEN-BEGIN:MVDICACase13 + } else if (item == stringItem4) { + if (command == goCommand) {//GEN-END:MVDICACase13 + Display.getDisplay(this).setCurrent(new Alert("URL", "Go to the URL...", null, AlertType.INFO), get_mainForm()); + // Do nothing//GEN-LINE:MVDICAAction11 + // Insert post-action code here + }//GEN-BEGIN:MVDICACase11 + }//GEN-END:MVDICACase11 + // Insert global post-action code here +}//GEN-LINE:MVDICAEnd + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction4 + // Insert post-action code here + } else if (command == helpCommand1) {//GEN-LINE:MVDCACase4 + // Insert pre-action code here + // Do nothing//GEN-LINE:MVDCAAction20 + // Insert post-action code here + } else if (command == stopCommand1) {//GEN-LINE:MVDCACase20 + // Insert pre-action code here + // Do nothing//GEN-LINE:MVDCAAction22 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase22 + }//GEN-END:MVDCACase22 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + mainForm = new Form("StringItems", new Item[] {//GEN-BEGIN:MVDGetInit2 + get_stringItem1(), + get_stringItem2(), + get_stringItem4(), + get_stringItem5() + }); + mainForm.addCommand(get_exitCommand()); + mainForm.addCommand(get_helpCommand1()); + mainForm.addCommand(get_stopCommand1()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 0);//GEN-LINE:MVDGetInit3 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd3 + return exitCommand; + }//GEN-END:MVDGetEnd3 + + /** This method returns instance for stringItem1 component and should be called instead of accessing stringItem1 field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for stringItem1 component + */ + public StringItem get_stringItem1() { + if (stringItem1 == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + stringItem1 = new StringItem(null, "This is a simple StringItem");//GEN-LINE:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return stringItem1; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for stringItem2 component and should be called instead of accessing stringItem2 field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for stringItem2 component + */ + public StringItem get_stringItem2() { + if (stringItem2 == null) {//GEN-END:MVDGetBegin6 + // Insert pre-init code here + stringItem2 = new StringItem("This is the StringItem label:", "This is the StringItem text");//GEN-BEGIN:MVDGetInit6 + stringItem2.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit6 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd6 + return stringItem2; + }//GEN-END:MVDGetEnd6 + /** This method returns instance for stringItem4 component and should be called instead of accessing stringItem4 field directly.//GEN-BEGIN:MVDGetBegin8 + * @return Instance for stringItem4 component + */ + public StringItem get_stringItem4() { + if (stringItem4 == null) {//GEN-END:MVDGetBegin8 + // Insert pre-init code here + stringItem4 = new StringItem("Hyper-Link", "hyperlink", javax.microedition.lcdui.Item.HYPERLINK);//GEN-BEGIN:MVDGetInit8 + stringItem4.addCommand(get_goCommand()); + stringItem4.setItemCommandListener(this); + stringItem4.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit8 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd8 + return stringItem4; + }//GEN-END:MVDGetEnd8 + + /** This method returns instance for stringItem5 component and should be called instead of accessing stringItem5 field directly.//GEN-BEGIN:MVDGetBegin9 + * @return Instance for stringItem5 component + */ + public StringItem get_stringItem5() { + if (stringItem5 == null) {//GEN-END:MVDGetBegin9 + // Insert pre-init code here + stringItem5 = new StringItem("Button", "Button", javax.microedition.lcdui.Item.BUTTON);//GEN-BEGIN:MVDGetInit9 + stringItem5.addCommand(get_pressCommand()); + stringItem5.setItemCommandListener(this); + stringItem5.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit9 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd9 + return stringItem5; + }//GEN-END:MVDGetEnd9 + + /** This method returns instance for goCommand component and should be called instead of accessing goCommand field directly.//GEN-BEGIN:MVDGetBegin10 + * @return Instance for goCommand component + */ + public Command get_goCommand() { + if (goCommand == null) {//GEN-END:MVDGetBegin10 + // Insert pre-init code here + goCommand = new Command("Go", Command.OK, 1);//GEN-LINE:MVDGetInit10 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd10 + return goCommand; + }//GEN-END:MVDGetEnd10 + + /** This method returns instance for pressCommand component and should be called instead of accessing pressCommand field directly.//GEN-BEGIN:MVDGetBegin12 + * @return Instance for pressCommand component + */ + public Command get_pressCommand() { + if (pressCommand == null) {//GEN-END:MVDGetBegin12 + // Insert pre-init code here + pressCommand = new Command("Press", Command.SCREEN, 1);//GEN-LINE:MVDGetInit12 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd12 + return pressCommand; + }//GEN-END:MVDGetEnd12 + + /** This method returns instance for okCommand1 component and should be called instead of accessing okCommand1 field directly.//GEN-BEGIN:MVDGetBegin15 + * @return Instance for okCommand1 component + */ + public Command get_okCommand1() { + if (okCommand1 == null) {//GEN-END:MVDGetBegin15 + // Insert pre-init code here + okCommand1 = new Command("Okay", Command.OK, 1);//GEN-LINE:MVDGetInit15 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd15 + return okCommand1; + }//GEN-END:MVDGetEnd15 + + /** This method returns instance for okCommand2 component and should be called instead of accessing okCommand2 field directly.//GEN-BEGIN:MVDGetBegin17 + * @return Instance for okCommand2 component + */ + public Command get_okCommand2() { + if (okCommand2 == null) {//GEN-END:MVDGetBegin17 + // Insert pre-init code here + okCommand2 = new Command("Do Nothing", Command.SCREEN, 2);//GEN-LINE:MVDGetInit17 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd17 + return okCommand2; + }//GEN-END:MVDGetEnd17 + + /** This method returns instance for helpCommand1 component and should be called instead of accessing helpCommand1 field directly.//GEN-BEGIN:MVDGetBegin19 + * @return Instance for helpCommand1 component + */ + public Command get_helpCommand1() { + if (helpCommand1 == null) {//GEN-END:MVDGetBegin19 + // Insert pre-init code here + helpCommand1 = new Command("Help", Command.HELP, 1);//GEN-LINE:MVDGetInit19 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd19 + return helpCommand1; + }//GEN-END:MVDGetEnd19 + + /** This method returns instance for stopCommand1 component and should be called instead of accessing stopCommand1 field directly.//GEN-BEGIN:MVDGetBegin21 + * @return Instance for stopCommand1 component + */ + public Command get_stopCommand1() { + if (stopCommand1 == null) {//GEN-END:MVDGetBegin21 + // Insert pre-init code here + stopCommand1 = new Command("Stop", Command.STOP, 1);//GEN-LINE:MVDGetInit21 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd21 + return stopCommand1; + }//GEN-END:MVDGetEnd21 + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/stringitem/StringItemDemo.mvd b/Sample Code/chapter05/code/UIWidgetExample/src/example/stringitem/StringItemDemo.mvd new file mode 100644 index 0000000..baf74ff --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/stringitem/StringItemDemo.mvd @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/textbox/TextBoxDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/textbox/TextBoxDemo.java new file mode 100644 index 0000000..4b0e31d --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/textbox/TextBoxDemo.java @@ -0,0 +1,243 @@ +/* + * TextBoxDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.textbox; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class TextBoxDemo extends MIDlet implements javax.microedition.lcdui.CommandListener { + + /** + * The labels for the supported textboxs. + */ + static final String[] textBoxLabels = { + "Any Character", "E-Mail", "Number", "Decimal", "Phone", "Url" + }; + + /** + * The supported example.textbox types. + */ + static final int[] textBoxTypes = { + TextField.ANY, TextField.EMAILADDR, TextField.NUMERIC, + TextField.DECIMAL, TextField.PHONENUMBER, TextField.URL + }; + + private void setUpTypeList() { + for (int i=0;textBoxLabels.length>i;i++) { + this.get_typeCG().append(textBoxLabels[i], null); + } + } + + private void setUpTextBox() { + this.textBox=null; + int i=get_typeCG().getSelectedIndex(); + String title=textBoxLabels[i]; + int t=textBoxTypes[i]; + boolean[] flags = new boolean[2]; + this.get_optionsCG().getSelectedFlags(flags); + if (flags[0]) { + t |= TextField.PASSWORD; + } + if (flags[1]) { + this.get_textBox().setTicker(new Ticker("TextBox: " + title)); + } + this.get_textBox().setTitle(title); + this.get_textBox().setConstraints(t); + } + + /** Creates a new instance of TextBoxDemo */ + public TextBoxDemo() { + } + + private Form mainForm;//GEN-BEGIN:MVDFields + private StringItem stringItem1; + private ChoiceGroup typeCG; + private ChoiceGroup optionsCG; + private Command showCommand; + private Command exitCommand; + private TextBox textBox; + private Command backCommand;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == showCommand) {//GEN-END:MVDCABody + setUpTextBox(); + getDisplay().setCurrent(get_textBox());//GEN-LINE:MVDCAAction7 + // Insert post-action code here + } else if (command == exitCommand) {//GEN-LINE:MVDCACase7 + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction11 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase11 + } else if (displayable == textBox) { + if (command == backCommand) {//GEN-END:MVDCACase11 + // Insert pre-action code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDCAAction14 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase14 + }//GEN-END:MVDCACase14 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + setUpTypeList(); + mainForm = new Form("TextBox Demo", new Item[] {//GEN-BEGIN:MVDGetInit2 + get_stringItem1(), + get_typeCG(), + get_optionsCG() + }); + mainForm.addCommand(get_showCommand()); + mainForm.addCommand(get_exitCommand()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for stringItem1 component and should be called instead of accessing stringItem1 field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for stringItem1 component + */ + public StringItem get_stringItem1() { + if (stringItem1 == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + stringItem1 = new StringItem(null, "Select a TextBox type");//GEN-LINE:MVDGetInit3 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd3 + return stringItem1; + }//GEN-END:MVDGetEnd3 + + /** This method returns instance for typeCG component and should be called instead of accessing typeCG field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for typeCG component + */ + public ChoiceGroup get_typeCG() { + if (typeCG == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + typeCG = new ChoiceGroup("Choose Type", Choice.EXCLUSIVE, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit4 + typeCG.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit4 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return typeCG; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for optionsCG component and should be called instead of accessing optionsCG field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for optionsCG component + */ + public ChoiceGroup get_optionsCG() { + if (optionsCG == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + optionsCG = new ChoiceGroup("Options", Choice.MULTIPLE, new String[] {//GEN-BEGIN:MVDGetInit5 + "As Password", + "Show Ticker" + }, new Image[] { + null, + null + }); + optionsCG.setSelectedFlags(new boolean[] { + false, + false + });//GEN-END:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return optionsCG; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for showCommand component and should be called instead of accessing showCommand field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for showCommand component + */ + public Command get_showCommand() { + if (showCommand == null) {//GEN-END:MVDGetBegin6 + // Insert pre-init code here + showCommand = new Command("Show", Command.SCREEN, 1);//GEN-LINE:MVDGetInit6 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd6 + return showCommand; + }//GEN-END:MVDGetEnd6 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin10 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin10 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit10 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd10 + return exitCommand; + }//GEN-END:MVDGetEnd10 + + /** This method returns instance for textBox component and should be called instead of accessing textBox field directly.//GEN-BEGIN:MVDGetBegin12 + * @return Instance for textBox component + */ + public TextBox get_textBox() { + if (textBox == null) {//GEN-END:MVDGetBegin12 + // Insert pre-init code here + textBox = new TextBox(null, null, 10240, TextField.ANY);//GEN-BEGIN:MVDGetInit12 + textBox.addCommand(get_backCommand()); + textBox.setCommandListener(this);//GEN-END:MVDGetInit12 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd12 + return textBox; + }//GEN-END:MVDGetEnd12 + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly.//GEN-BEGIN:MVDGetBegin13 + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) {//GEN-END:MVDGetBegin13 + // Insert pre-init code here + backCommand = new Command("Back", Command.BACK, 1);//GEN-LINE:MVDGetInit13 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd13 + return backCommand; + }//GEN-END:MVDGetEnd13 + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/textbox/TextBoxDemo.mvd b/Sample Code/chapter05/code/UIWidgetExample/src/example/textbox/TextBoxDemo.mvd new file mode 100644 index 0000000..2afebdb --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/textbox/TextBoxDemo.mvd @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/textfield/TextFieldDemo.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/textfield/TextFieldDemo.java new file mode 100644 index 0000000..c9c0954 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/textfield/TextFieldDemo.java @@ -0,0 +1,216 @@ +/* + * TextFieldDemo.java + * + * Copyright (c) 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +package example.textfield; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + +public class TextFieldDemo extends MIDlet implements javax.microedition.lcdui.CommandListener { + + /** Creates a new instance of TextFieldDemo */ + public TextFieldDemo() { + } + + private Form mainForm;//GEN-BEGIN:MVDFields + private StringItem stringItem1; + private TextField textField2; + private TextField textField3; + private TextField textField4; + private TextField textField5; + private TextField textField6; + private TextField textField7; + private Command exitCommand; + private DateField dateField1;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_mainForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** + * This method should return an instance of the display. + */ + public javax.microedition.lcdui.Display getDisplay () {//GEN-FIRST:MVDGetDisplay + return javax.microedition.lcdui.Display.getDisplay (this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet () {//GEN-FIRST:MVDExitMidlet + getDisplay ().setCurrent (null); + destroyApp (true); + notifyDestroyed (); + }//GEN-LAST:MVDExitMidlet + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == mainForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction12 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase12 + }//GEN-END:MVDCACase12 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** This method returns instance for mainForm component and should be called instead of accessing mainForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for mainForm component + */ + public Form get_mainForm() { + if (mainForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + mainForm = new Form("DateField Demo", new Item[] {//GEN-BEGIN:MVDGetInit2 + get_stringItem1(), + get_dateField1(), + get_textField2(), + get_textField3(), + get_textField4(), + get_textField5(), + get_textField6(), + get_textField7() + }); + mainForm.addCommand(get_exitCommand()); + mainForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return mainForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for stringItem1 component and should be called instead of accessing stringItem1 field directly.//GEN-BEGIN:MVDGetBegin3 + * @return Instance for stringItem1 component + */ + public StringItem get_stringItem1() { + if (stringItem1 == null) {//GEN-END:MVDGetBegin3 + // Insert pre-init code here + stringItem1 = new StringItem(null, "Here\'s a DateField");//GEN-LINE:MVDGetInit3 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd3 + return stringItem1; + }//GEN-END:MVDGetEnd3 + /** This method returns instance for textField2 component and should be called instead of accessing textField2 field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for textField2 component + */ + public TextField get_textField2() { + if (textField2 == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + textField2 = new TextField("E-mail", " ", 60, TextField.EMAILADDR);//GEN-BEGIN:MVDGetInit5 + textField2.setLayout(Item.LAYOUT_LEFT | Item.LAYOUT_TOP | Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return textField2; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for textField3 component and should be called instead of accessing textField3 field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for textField3 component + */ + public TextField get_textField3() { + if (textField3 == null) {//GEN-END:MVDGetBegin6 + // Insert pre-init code here + textField3 = new TextField("Number", null, 60, TextField.NUMERIC);//GEN-BEGIN:MVDGetInit6 + textField3.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit6 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd6 + return textField3; + }//GEN-END:MVDGetEnd6 + + /** This method returns instance for textField4 component and should be called instead of accessing textField4 field directly.//GEN-BEGIN:MVDGetBegin7 + * @return Instance for textField4 component + */ + public TextField get_textField4() { + if (textField4 == null) {//GEN-END:MVDGetBegin7 + // Insert pre-init code here + textField4 = new TextField("Decimal", null, 60, TextField.DECIMAL);//GEN-BEGIN:MVDGetInit7 + textField4.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit7 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd7 + return textField4; + }//GEN-END:MVDGetEnd7 + + /** This method returns instance for textField5 component and should be called instead of accessing textField5 field directly.//GEN-BEGIN:MVDGetBegin8 + * @return Instance for textField5 component + */ + public TextField get_textField5() { + if (textField5 == null) {//GEN-END:MVDGetBegin8 + // Insert pre-init code here + textField5 = new TextField("Phone", null, 60, TextField.PHONENUMBER);//GEN-LINE:MVDGetInit8 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd8 + return textField5; + }//GEN-END:MVDGetEnd8 + + /** This method returns instance for textField6 component and should be called instead of accessing textField6 field directly.//GEN-BEGIN:MVDGetBegin9 + * @return Instance for textField6 component + */ + public TextField get_textField6() { + if (textField6 == null) {//GEN-END:MVDGetBegin9 + // Insert pre-init code here + textField6 = new TextField("Password", null, 120, TextField.ANY | TextField.PASSWORD);//GEN-BEGIN:MVDGetInit9 + textField6.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit9 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd9 + return textField6; + }//GEN-END:MVDGetEnd9 + + /** This method returns instance for textField7 component and should be called instead of accessing textField7 field directly.//GEN-BEGIN:MVDGetBegin10 + * @return Instance for textField7 component + */ + public TextField get_textField7() { + if (textField7 == null) {//GEN-END:MVDGetBegin10 + // Insert pre-init code here + textField7 = new TextField("Url", null, 120, TextField.URL);//GEN-BEGIN:MVDGetInit10 + textField7.setLayout(Item.LAYOUT_NEWLINE_AFTER | Item.LAYOUT_2);//GEN-END:MVDGetInit10 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd10 + return textField7; + }//GEN-END:MVDGetEnd10 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin11 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin11 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit11 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd11 + return exitCommand; + }//GEN-END:MVDGetEnd11 + + /** This method returns instance for dateField1 component and should be called instead of accessing dateField1 field directly.//GEN-BEGIN:MVDGetBegin13 + * @return Instance for dateField1 component + */ + public DateField get_dateField1() { + if (dateField1 == null) {//GEN-END:MVDGetBegin13 + // Insert pre-init code here + dateField1 = new DateField("Input a Date", DateField.DATE_TIME);//GEN-LINE:MVDGetInit13 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd13 + return dateField1; + }//GEN-END:MVDGetEnd13 + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + +} diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/textfield/TextFieldDemo.mvd b/Sample Code/chapter05/code/UIWidgetExample/src/example/textfield/TextFieldDemo.mvd new file mode 100644 index 0000000..76c49a8 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/textfield/TextFieldDemo.mvd @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/wxitem/WeatherItem.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/wxitem/WeatherItem.java new file mode 100644 index 0000000..321e758 --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/wxitem/WeatherItem.java @@ -0,0 +1,146 @@ +package example.wxitem; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + + +public class WeatherItem + extends CustomItem { + private String title; + private Display display; + private int width, height; + private boolean hasFocus = false; + private int conditions; + + // States (not mutatable by caller!) + public final int SUNNY = 1; + public final int PARTLY_CLOUDY = 2; + public final int CLOUDY = 3; + public final int SHOWERS = 4; + public final int RAIN = 5; + public final int FLURRIES = 6; + public final int SNOW = 7; + public final int SLEET = 8; + + // Colors + final private int YELLOW = 0xFFFF00; + + public WeatherItem( String t, Display d ) { + super(t); + title = t; + display = d; + hasFocus = false; + width = 64; + height = 64; + conditions = 0; + } + + public void setConditions( int c ) { + conditions = c; + } + + public int getConditions( ) { + return conditions; + } + + protected int getMinContentHeight() { + return height; + } + + protected int getMinContentWidth() { + return width; + } + + protected int getPrefContentHeight(int w) { + if ( w < 0 ) + return height; + else + return height * w / width; + } + + protected int getPrefContentWidth(int h) { + if ( h < 0 ) + return width; + else + return width * h / height; + } + + protected void paint(Graphics g, int w, int h) { + // Always paint SOMETHING + g.fillRect(0, 0, w, h); + switch( conditions ) + { + case SUNNY: + drawSun(g, w, h); + break; + case PARTLY_CLOUDY: + drawSun(g, w, h); + // FALL-THRU + case CLOUDY: + drawCloud(g, w, h); + break; + case SHOWERS: + drawSun(g, w, h); + // FALL-THRU + case RAIN: + drawCloud(g, w, h); + drawRain(g, w, h); + break; + case FLURRIES: + drawSun(g, w, h); + // FALL-THRU + case SNOW: + drawCloud(g, w, h); + drawSnow(g, w, h); + break; + case SLEET: + drawCloud(g, w, h); + drawRain(g, w, h); + drawSnow(g, w, h); + break; + default: + drawUnknown(g, w, h); + break; + } + } + + protected boolean traverse(int dir, int viewportWidth, int viewportHeight, + int[] visRect) { + hasFocus = !hasFocus; + if ( hasFocus ) + { + visRect[ 0 ] = 0; + visRect[ 1 ] = 0; + visRect[ 2 ] = width; + visRect[ 3 ] = height; + } + return hasFocus; + } + + private void drawSun(Graphics g, int w, int h) { + int x, y, min, r; + min = Math.min(w, h); + r = 3 * min / 4; + x = ( w - r ) / 4; + y = ( h - r ) / 4; + + g.setColor( YELLOW ); + g.fillArc(x, y, x + r, y + r, 0, 360); + } + + private void drawCloud(Graphics g, int w, int h) { + + } + + private void drawRain(Graphics g, int w, int h) { + + } + + private void drawSnow(Graphics g, int w, int h) { + + } + + private void drawUnknown(Graphics g, int w, int h) { + + } +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/example/wxitem/WeatherItemExample.java b/Sample Code/chapter05/code/UIWidgetExample/src/example/wxitem/WeatherItemExample.java new file mode 100644 index 0000000..d310c1f --- /dev/null +++ b/Sample Code/chapter05/code/UIWidgetExample/src/example/wxitem/WeatherItemExample.java @@ -0,0 +1,27 @@ +package example.wxitem; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; + + +public class WeatherItemExample extends MIDlet { + public void startApp() { + Form f = new Form("WeatherItemTest"); + Command exit = new Command("Exit", Command.EXIT, 0); + WeatherItem item = new WeatherItem("Today", Display.getDisplay( this )); + item.setConditions(item.SUNNY); + f.append(item); + + f.addCommand(exit); + + f.setCommandListener(new CommandListener() { + public void commandAction(Command c, Displayable s) { + notifyDestroyed(); + } + } ); + + Display.getDisplay(this).setCurrent(f); + } + public void pauseApp() { } + public void destroyApp(boolean unconditional) { } +} \ No newline at end of file diff --git a/Sample Code/chapter05/code/UIWidgetExample/src/icons/Icon.png b/Sample Code/chapter05/code/UIWidgetExample/src/icons/Icon.png new file mode 100644 index 0000000..04fb580 Binary files /dev/null and b/Sample Code/chapter05/code/UIWidgetExample/src/icons/Icon.png differ diff --git a/Sample Code/chapter05/code/WeatherWidget/build.xml b/Sample Code/chapter05/code/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter05/code/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter05/code/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter05/code/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter05/code/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter05/code/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter05/code/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..692b09a --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,7 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active= +deployment.number=0.0.2 diff --git a/Sample Code/chapter05/code/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter05/code/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter05/code/WeatherWidget/nbproject/project.properties b/Sample Code/chapter05/code/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..0b38c91 --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/nbproject/project.properties @@ -0,0 +1,81 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter05/code/WeatherWidget/nbproject/project.xml b/Sample Code/chapter05/code/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter05/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java b/Sample Code/chapter05/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java new file mode 100644 index 0000000..0e3de12 --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java @@ -0,0 +1,220 @@ +/* + * WeatherWidget.java + * + * Created on March 1, 2008, 10:08 AM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.util.*; + +/** + * + * @author kf6gpe + * @version + */ +public class WeatherWidget extends MIDlet implements CommandListener { + private Form wxForm; + private StringItem locationItem; + private Command exitCommand; + private Command screenCommand; + private List locationList; + private TextBox locationTextBox; + private Command settingCommand; + private Command okCommand; + private Command backCommand; + private StringItem wxItem; + + String location; + Vector locationVector; + + /** This method initializes UI of the application. + */ + private void initialize() { + locationVector = new Vector(); + + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_location() { + if (location == null) { + location = "Berkeley, CA"; + } + return location; + } + + public void set_location( String l ) { + location = l; + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + locationVector.addElement(l); + get_locationList().append(l,null); + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", "Sunny."); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + // Insert post-init code here + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = new String[locationVector.size()]; + + locationVector.copyInto((Object[])locations); + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter05/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.txt b/Sample Code/chapter05/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.txt new file mode 100644 index 0000000..3a93f31 --- /dev/null +++ b/Sample Code/chapter05/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.txt @@ -0,0 +1,232 @@ +/* + * WeatherWidget.java + * + * Created on March 1, 2008, 10:08 AM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.util.*; + +/** + * + * @author kf6gpe + * @version + */ +public class WeatherWidget extends MIDlet implements CommandListener { + private Form wxForm; + private StringItem locationItem; + private Command exitCommand; + private Command screenCommand; + private List locationList; + private TextBox locationTextBox; + private Command settingCommand; + private Command okCommand; + private Command backCommand; + private StringItem wxItem; + + String location; + Vector locationVector; + + /** This method initializes UI of the application. + */ + private void initialize() { + locationVector = new Vector(); + + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void commandAction(Command command, Displayable displayable) { ~CCC + + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_location() { + if (location == null) { + location = "Berkeley, CA"; + } + return location; + } + + public void set_location( String l ) { + location = l; + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + locationVector.addElement(l); + get_locationList().append(l,null); + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be ca~CCC +lled instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", "Sunny."); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be ca~CCC +lled instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + // Insert post-init code here + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and sho~CCC +uld be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should~CCC + be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = new String[locationVector.size()]; + + locationVector.copyInto((Object[])locations); + locationList = new List("Where", List.IMPLICIT, locations, nul~CCC +l); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + /** This method returns instance for settingCommand component and shou~CCC +ld be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and shou~CCC +ld be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should ~CCC +be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and shoul~CCC +d be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1)~CCC +; + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should ~CCC +be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter06/code/WeatherWidget/build.xml b/Sample Code/chapter06/code/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter06/code/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter06/code/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter06/code/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter06/code/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter06/code/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter06/code/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..15c3478 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,7 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active=Debug +deployment.number=0.0.2 diff --git a/Sample Code/chapter06/code/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter06/code/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter06/code/WeatherWidget/nbproject/project.properties b/Sample Code/chapter06/code/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..0b38c91 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/nbproject/project.properties @@ -0,0 +1,81 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter06/code/WeatherWidget/nbproject/project.xml b/Sample Code/chapter06/code/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/svn-commit.tmp b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/svn-commit.tmp new file mode 100644 index 0000000..29020c9 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/svn-commit.tmp @@ -0,0 +1,5 @@ +Hack hack hack. +--This line, and those below, will be ignored-- + +M weatherwidget/WeatherWidget.java +D weatherwidget/WeatherWidget.mvd diff --git a/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/#Location.java# b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/#Location.java# new file mode 100644 index 0000000..ed6b3a9 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/#Location.java# @@ -0,0 +1,140 @@ +/* + * Location.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; + +/** + * + * @author kf6gpe + */ +public class Location { + private final static int FIELD_VERSION = 1; + private final static int FIELD_LOCATION = 2; + private final static int FIELD_FORECAST = 3; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String location; + private String forecast; + private int recordid; + + /** Creates a new instance of Location */ + public Location(String l, String f) { + location = l; + forecast = f; + recordid = NO_ID; + } + + public Location(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + + public Location(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + if (location != null) { + return location; + } else { + return ""; + } + } + + public void setLocation(String l) { + location = l; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (location != null) { + dos.writeInt(FIELD_LOCATION); + dos.writeUTF(getLocation()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + } + catch( Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_LOCATION: + setLocation(dis.readUTF()); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + } + } + } + catch (Exception e) {} + + dis = null; + bais = null; + } +} diff --git a/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java new file mode 100644 index 0000000..ed6b3a9 --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java @@ -0,0 +1,140 @@ +/* + * Location.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; + +/** + * + * @author kf6gpe + */ +public class Location { + private final static int FIELD_VERSION = 1; + private final static int FIELD_LOCATION = 2; + private final static int FIELD_FORECAST = 3; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String location; + private String forecast; + private int recordid; + + /** Creates a new instance of Location */ + public Location(String l, String f) { + location = l; + forecast = f; + recordid = NO_ID; + } + + public Location(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + + public Location(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + if (location != null) { + return location; + } else { + return ""; + } + } + + public void setLocation(String l) { + location = l; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (location != null) { + dos.writeInt(FIELD_LOCATION); + dos.writeUTF(getLocation()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + } + catch( Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_LOCATION: + setLocation(dis.readUTF()); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + } + } + } + catch (Exception e) {} + + dis = null; + bais = null; + } +} diff --git a/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java new file mode 100644 index 0000000..af9dfbd --- /dev/null +++ b/Sample Code/chapter06/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java @@ -0,0 +1,131 @@ +/* + * LocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; + +/** + * + * @author kf6gpe + */ +public class LocationStore { + private static final String storeName = "wx"; + private RecordStore store = null; + + public LocationStore() { + } + + private void openStore() throws RecordStoreException { + if (store == null) { + store = RecordStore.openRecordStore(storeName, true); + } + } + + private void closeStore() { + if (store != null) { + try { + store.closeRecordStore(); + } catch( Exception ex ) {} + store = null; + } + } + + public void addLocation(Location l) throws RecordStoreException { + Location existing = getLocation(l.getLocation()); + if (existing!=null) { + existing.setForecast(l.getForecast()); + updateLocation(existing); + } else { + byte b[] = l.toBytes(); + openStore(); + l.setId(store.getNextRecordID()); + store.addRecord(b, 0, b.length); + closeStore(); + } + } + + public String[] getLocationStrings() { + String[] result = null; + try { + openStore(); + result = new String[store.getNumRecords()]; + RecordEnumeration e = store.enumerateRecords( + null, // No filter + new RecordComparator () { + public int compare( byte[] b1, byte[] b2 ) { + Location r1 = new Location(b1); + Location r2 = new Location(b2); + if (r1.getLocation().compareTo(r2.getLocation()) == 0) { + return RecordComparator.EQUIVALENT; + } else if (r1.getLocation().compareTo(r2.getLocation()) < 0) { + return RecordComparator.PRECEDES; + } else { + return RecordComparator.FOLLOWS; + } + } + }, + false); + int i; + + for (i=0; i 0 ) location = locations[0]; + + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == cannotAddLocationAlert) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_location() { + if (location == null) { + location = ""; + } + return location; + } + + public void set_location( String l ) { + location = l; + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + String locations[]; + int i; + try { + locationStore.addLocation( new Location( l, "" )); + } catch (Exception e) { + getDisplay().setCurrent(get_cannotAddLocationAlert()); + } + // Refresh the location list lazily. + locationList = null; + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", "Sunny."); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = locationStore.getLocationStrings(); + + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + public Alert get_cannotAddLocationAlert() { + if (cannotAddLocationAlert == null) + { + cannotAddLocationAlert = new Alert("Cannot Add Location"); + cannotAddLocationAlert.setString("An error occurred adding the location you entered. It has not been added."); + cannotAddLocationAlert.addCommand(get_backCommand()); + } + return cannotAddLocationAlert; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter07/code/PIMExample/nbproject/build-impl.xml b/Sample Code/chapter07/code/PIMExample/nbproject/build-impl.xml new file mode 100644 index 0000000..a2a8c8a --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/nbproject/build-impl.xml @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter07/code/PIMExample/nbproject/genfiles.properties b/Sample Code/chapter07/code/PIMExample/nbproject/genfiles.properties new file mode 100644 index 0000000..8a2e2ea --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=aeade6af +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=aeade6af +nbproject/build-impl.xml.script.CRC32=036a5e16 +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter07/code/PIMExample/nbproject/private/private.properties b/Sample Code/chapter07/code/PIMExample/nbproject/private/private.properties new file mode 100644 index 0000000..7b953e2 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/nbproject/private/private.properties @@ -0,0 +1,3 @@ +config.active= +javadoc.preview=true +netbeans.user=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 diff --git a/Sample Code/chapter07/code/PIMExample/nbproject/private/private.xml b/Sample Code/chapter07/code/PIMExample/nbproject/private/private.xml new file mode 100644 index 0000000..edd1303 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/nbproject/private/private.xml @@ -0,0 +1,7 @@ + + + + + file:/C:/book/Chapters/chapter07/code/PIMExample/src/com/apress/rischpater/ContactLoaderThread.java + + diff --git a/Sample Code/chapter07/code/PIMExample/nbproject/project.properties b/Sample Code/chapter07/code/PIMExample/nbproject/project.properties new file mode 100644 index 0000000..92bfc7c --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/nbproject/project.properties @@ -0,0 +1,67 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=PIMExample.jad +dist.jar=PIMExample.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: ContactStuffer,,com.apress.rischpater.ContactStuffer\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: PIMExample\n +manifest.pushregistry= +name=PIMExample +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias= +sign.enabled=false +sign.keystore= +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter07/code/PIMExample/nbproject/project.xml b/Sample Code/chapter07/code/PIMExample/nbproject/project.xml new file mode 100644 index 0000000..9e63118 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + PIMExample + 1.6 + + + diff --git a/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactLoaderThread.java b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactLoaderThread.java new file mode 100644 index 0000000..2a40d18 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactLoaderThread.java @@ -0,0 +1,46 @@ +/* + * ContactLoaderThread.java + * + * Created on March 29, 2008, 8:42 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.io.*; +import java.util.*; +import javax.microedition.pim.*; + +/** + * + * @author kf6gpe + */ +public class ContactLoaderThread extends Thread { + List list; + + public ContactLoaderThread(List l) { + list = l; + } + + public void run() { + try { + PIM pim = PIM.getInstance(); + ContactList contList = (ContactList) + pim.openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY); + Enumeration contacts = contList.items(); + while(contacts.hasMoreElements()) { + Contact c = (Contact) contacts.nextElement(); + String [] nameValues = c.getStringArray( Contact.NAME, 0); + String firstName = nameValues[Contact.NAME_GIVEN]; + String lastName = nameValues[Contact.NAME_FAMILY]; + list.append(lastName + ", " + firstName, null); + } + } + catch(Exception ex) {} + } +} + diff --git a/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactStuffer.java b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactStuffer.java new file mode 100644 index 0000000..4301988 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactStuffer.java @@ -0,0 +1,215 @@ +/* + * ContactStuffer.java + * + * Created on March 28, 2008, 9:03 PM + */ + +package com.apress.rischpater; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.io.*; +import java.util.*; +import javax.microedition.pim.*; +/** + * + * @author kf6gpe + */ +public class ContactStuffer extends MIDlet implements CommandListener { + + /** + * Creates a new instance of ContactStuffer + */ + public ContactStuffer() { + try { + verifyPIMSupport(); + seed(); + } + catch (Exception ex) { + Form mForm = new Form("Exception"); + mForm.append(new StringItem(null, ex.toString())); + Command mExitCommand = new Command("Exit", Command.EXIT, 0); + mForm.addCommand(mExitCommand); + mForm.setCommandListener(this); + return; + } + } + + private Form helloForm;//GEN-BEGIN:MVDFields + private StringItem helloStringItem; + private Command exitCommand; + private List listContacts; + private Command okCommand1;//GEN-END:MVDFields + +//GEN-LINE:MVDMethods + + /** This method initializes UI of the application.//GEN-BEGIN:MVDInitBegin + */ + private void initialize() {//GEN-END:MVDInitBegin + // Insert pre-init code here + getDisplay().setCurrent(get_helloForm());//GEN-LINE:MVDInitInit + // Insert post-init code here + }//GEN-LINE:MVDInitEnd + + /** Called by the system to indicate that a command has been invoked on a particular displayable.//GEN-BEGIN:MVDCABegin + * @param command the Command that ws invoked + * @param displayable the Displayable on which the command was invoked + */ + public void commandAction(Command command, Displayable displayable) {//GEN-END:MVDCABegin + // Insert global pre-action code here + if (displayable == helloForm) {//GEN-BEGIN:MVDCABody + if (command == exitCommand) {//GEN-END:MVDCABody + // Insert pre-action code here + exitMIDlet();//GEN-LINE:MVDCAAction3 + // Insert post-action code here + } else if (command == okCommand1) {//GEN-LINE:MVDCACase3 + // Insert pre-action code here + getDisplay().setCurrent(get_listContacts());//GEN-LINE:MVDCAAction9 + // Insert post-action code here + }//GEN-BEGIN:MVDCACase9 + }//GEN-END:MVDCACase9 + // Insert global post-action code here +}//GEN-LINE:MVDCAEnd + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() {//GEN-FIRST:MVDGetDisplay + return Display.getDisplay(this); + }//GEN-LAST:MVDGetDisplay + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() {//GEN-FIRST:MVDExitMidlet + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + }//GEN-LAST:MVDExitMidlet + + /** This method returns instance for helloForm component and should be called instead of accessing helloForm field directly.//GEN-BEGIN:MVDGetBegin2 + * @return Instance for helloForm component + */ + public Form get_helloForm() { + if (helloForm == null) {//GEN-END:MVDGetBegin2 + // Insert pre-init code here + helloForm = new Form(null, new Item[] {get_helloStringItem()});//GEN-BEGIN:MVDGetInit2 + helloForm.addCommand(get_exitCommand()); + helloForm.addCommand(get_okCommand1()); + helloForm.setCommandListener(this);//GEN-END:MVDGetInit2 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd2 + return helloForm; + }//GEN-END:MVDGetEnd2 + + /** This method returns instance for helloStringItem component and should be called instead of accessing helloStringItem field directly.//GEN-BEGIN:MVDGetBegin4 + * @return Instance for helloStringItem component + */ + public StringItem get_helloStringItem() { + if (helloStringItem == null) {//GEN-END:MVDGetBegin4 + // Insert pre-init code here + helloStringItem = new StringItem("", "");//GEN-LINE:MVDGetInit4 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd4 + return helloStringItem; + }//GEN-END:MVDGetEnd4 + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly.//GEN-BEGIN:MVDGetBegin5 + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) {//GEN-END:MVDGetBegin5 + // Insert pre-init code here + exitCommand = new Command("Exit", Command.EXIT, 1);//GEN-LINE:MVDGetInit5 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd5 + return exitCommand; + }//GEN-END:MVDGetEnd5 + + /** This method returns instance for listContacts component and should be called instead of accessing listContacts field directly.//GEN-BEGIN:MVDGetBegin6 + * @return Instance for listContacts component + */ + public List get_listContacts() { + if (listContacts == null) {//GEN-END:MVDGetBegin6 + + listContacts = new List(null, Choice.IMPLICIT, new String[0], new Image[0]);//GEN-BEGIN:MVDGetInit6 + listContacts.setCommandListener(this); + listContacts.setSelectedFlags(new boolean[0]);//GEN-END:MVDGetInit6 + ContactLoaderThread t = new ContactLoaderThread( listContacts ); + t.start(); + }//GEN-BEGIN:MVDGetEnd6 + return listContacts; + }//GEN-END:MVDGetEnd6 + + /** This method returns instance for okCommand1 component and should be called instead of accessing okCommand1 field directly.//GEN-BEGIN:MVDGetBegin8 + * @return Instance for okCommand1 component + */ + public Command get_okCommand1() { + if (okCommand1 == null) {//GEN-END:MVDGetBegin8 + // Insert pre-init code here + okCommand1 = new Command("Ok", Command.OK, 1);//GEN-LINE:MVDGetInit8 + // Insert post-init code here + }//GEN-BEGIN:MVDGetEnd8 + return okCommand1; + }//GEN-END:MVDGetEnd8 + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void verifyPIMSupport() throws IOException { + String version = ""; + version = System.getProperty("microedition.pim.version"); + if (version != null) { + if (!version.equals("1.0")) + throw new IOException("Package is not version 1.0."); + } + else + throw new IOException("PIM optional package is not available."); + } + + private ContactList list = null; + + private void seed() throws PIMException { + try { + PIM pimInst = PIM.getInstance(); + list = (ContactList) + pimInst.openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE); + } + catch (PIMException ex) { + // Contact list is not supported. + } + addContact(list, "Ray", "Rischpater", "1234 High Street", + "Los Gatos", "USA", "95030"); + addContact(list, "John", "Doe", "1111 Bear Road", + "Mariposa", "USA", "9????"); + if (list != null) + list.close(); + list = null; + } + + private void addContact( ContactList list, String firstName, + String lastName, String street, String city, + String country, String postalcode) + throws PIMException { + Contact c = list.createContact(); + String [] name = new String[list.stringArraySize(Contact.NAME)]; + name[Contact.NAME_GIVEN] = firstName; + name[Contact.NAME_FAMILY] = lastName; + c.addStringArray(Contact.NAME,Contact.ATTR_NONE , name); + String [] addr = new String[list.stringArraySize(Contact.ADDR)]; + addr[Contact.ADDR_STREET] = street; + addr[Contact.ADDR_LOCALITY] = city; + addr[Contact.ADDR_COUNTRY] = country; + addr[Contact.ADDR_POSTALCODE] = street; + c.addStringArray(Contact.ADDR, Contact.ATTR_NONE , addr); + c.commit(); + } +} + diff --git a/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactStuffer.mvd b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactStuffer.mvd new file mode 100644 index 0000000..5b8c485 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/ContactStuffer.mvd @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/clt.txt b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/clt.txt new file mode 100644 index 0000000..edb6636 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/clt.txt @@ -0,0 +1,47 @@ +/* + * ContactLoaderThread.java + * + * Created on March 29, 2008, 8:42 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.io.*; +import java.util.*; +import javax.microedition.pim.*; + +/** + * + * @author kf6gpe + */ +public class ContactLoaderThread extends Thread { + List list; + + public ContactLoaderThread(List l) { + list = l; + } + + public void run() { + try { + PIM pim = PIM.getInstance(); + ContactList contList = (ContactList) + pim.openPIMList(PIM.CONTACT_LIST, PIM.READ_ONLY); + Enumeration contacts = contList.items(); + while(contacts.hasMoreElements()) { + Contact c = (Contact) contacts.nextElement(); + String [] nameValues = c.getStringArray( Contact.NAME, 0);~CCC + + String firstName = nameValues[Contact.NAME_GIVEN]; + String lastName = nameValues[Contact.NAME_FAMILY]; + list.append(lastName + ", " + firstName, null); + } + } + catch(Exception ex) {} + } +} + diff --git a/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/cs.txt b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/cs.txt new file mode 100644 index 0000000..0ad3827 --- /dev/null +++ b/Sample Code/chapter07/code/PIMExample/src/com/apress/rischpater/cs.txt @@ -0,0 +1,165 @@ +/* + * ContactStuffer.java + * + * Created on March 28, 2008, 9:03 PM + */ + +package com.apress.rischpater; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.io.*; +import java.util.*; +import javax.microedition.pim.*; +/** + * + * @author kf6gpe + */ +public class ContactStuffer extends MIDlet implements CommandListener { + + public ContactStuffer() { + try { + verifyPIMSupport(); + seed(); + } + catch (Exception ex) { + Form mForm = new Form("Exception"); + mForm.append(new StringItem(null, ex.toString())); + Command mExitCommand = new Command("Exit", Command.EXIT, 0); + mForm.addCommand(mExitCommand); + mForm.setCommandListener(this); + return; + } + } + + private Form helloForm; + private StringItem helloStringItem; + private Command exitCommand; + private List listContacts; + private Command okCommand1; + + private void initialize() { + getDisplay().setCurrent(get_helloForm()); + } + + public void commandAction(Command command, Displayable displayable) { + if (displayable == helloForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == okCommand1) { + getDisplay().setCurrent(get_listContacts()); + } + } + } + + public Display getDisplay() { + return Display.getDisplay(this); + } + + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + public Form get_helloForm() { + if (helloForm == null) { + helloForm = new Form(null, new Item[] {get_helloStringItem()}); + helloForm.addCommand(get_exitCommand()); + helloForm.addCommand(get_okCommand1()); + helloForm.setCommandListener(this); + } + return helloForm; + } + + public StringItem get_helloStringItem() { + if (helloStringItem == null) { + helloStringItem = new StringItem("", ""); + } + return helloStringItem; + } + + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + public List get_listContacts() { + if (listContacts == null) { + listContacts = new List(null, Choice.IMPLICIT, + new String[0], new Image[0]); + listContacts.setCommandListener(this); + listContacts.setSelectedFlags(new boolean[0]); + ContactLoaderThread t = new ContactLoaderThread(listContacts); + t.start(); + } + return listContacts; + } + + public Command get_okCommand1() { + if (okCommand1 == null) { + okCommand1 = new Command("Ok", Command.OK, 1); + } + return okCommand1; + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void verifyPIMSupport() throws IOException { + String version = ""; + version = System.getProperty("microedition.pim.version"); + if (version != null) { + if (!version.equals("1.0")) + throw new IOException("Package is not version 1.0."); + } + else + throw new IOException("PIM optional package is not available."); + } + + private ContactList list = null; + + private void seed() throws PIMException { + try { + PIM pimInst = PIM.getInstance(); + list = (ContactList) + pimInst.openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE); + } + catch (PIMException ex) { /* Contact list is not supported. */ } + addContact(list, "Ray", "Rischpater", "1234 High Street", + "Los Gatos", "USA", "95030"); + addContact(list, "John", "Doe", "1111 Bear Road", + "Mariposa", "USA", "9????"); + if (list != null) + list.close(); + list = null; + } + + private void addContact( ContactList list, String firstName, + String lastName, String street, String city, + String country, String postalcode) + throws PIMException { + Contact c = list.createContact(); + String [] name = new String[list.stringArraySize(Contact.NAME)]; + name[Contact.NAME_GIVEN] = firstName; + name[Contact.NAME_FAMILY] = lastName; + c.addStringArray(Contact.NAME,Contact.ATTR_NONE , name); + String [] addr = new String[list.stringArraySize(Contact.ADDR)]; + addr[Contact.ADDR_STREET] = street; + addr[Contact.ADDR_LOCALITY] = city; + addr[Contact.ADDR_COUNTRY] = country; + addr[Contact.ADDR_POSTALCODE] = street; + c.addStringArray(Contact.ADDR, Contact.ATTR_NONE , addr); + c.commit(); + } +} + diff --git a/Sample Code/chapter07/code/WeatherWidget/build.xml b/Sample Code/chapter07/code/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter07/code/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter07/code/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter07/code/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter07/code/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter07/code/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter07/code/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..15c3478 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,7 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active=Debug +deployment.number=0.0.2 diff --git a/Sample Code/chapter07/code/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter07/code/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..886e571 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,9 @@ + + + + + file:/C:/book/Chapters/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java + file:/C:/book/Chapters/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java + file:/C:/book/Chapters/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java + + diff --git a/Sample Code/chapter07/code/WeatherWidget/nbproject/project.properties b/Sample Code/chapter07/code/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..d2cc094 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/nbproject/project.properties @@ -0,0 +1,84 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Debug.sign.alias=trusted +configs.Debug.sign.enabled=true +configs.Debug.sign.keystore=${file.reference.builtin.ks} +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter07/code/WeatherWidget/nbproject/project.xml b/Sample Code/chapter07/code/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java new file mode 100644 index 0000000..ed6b3a9 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java @@ -0,0 +1,140 @@ +/* + * Location.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; + +/** + * + * @author kf6gpe + */ +public class Location { + private final static int FIELD_VERSION = 1; + private final static int FIELD_LOCATION = 2; + private final static int FIELD_FORECAST = 3; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String location; + private String forecast; + private int recordid; + + /** Creates a new instance of Location */ + public Location(String l, String f) { + location = l; + forecast = f; + recordid = NO_ID; + } + + public Location(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + + public Location(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + if (location != null) { + return location; + } else { + return ""; + } + } + + public void setLocation(String l) { + location = l; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (location != null) { + dos.writeInt(FIELD_LOCATION); + dos.writeUTF(getLocation()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + } + catch( Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_LOCATION: + setLocation(dis.readUTF()); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + } + } + } + catch (Exception e) {} + + dis = null; + bais = null; + } +} diff --git a/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java new file mode 100644 index 0000000..e98d4fd --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java @@ -0,0 +1,143 @@ +/* + * LocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.io.*; +import javax.microedition.io.file.*; +import java.io.*; +import java.util.*; +/** + * + * @author kf6gpe + */ +public class LocationStore { + private static final String storeName = "wx"; + private static final String fileURLRoot = "file:///"; + private static String fileUrl; + Vector locations; + FileConnection fc; + + public LocationStore() { + locations = new Vector(); + Enumeration em = FileSystemRegistry.listRoots(); + if (em.hasMoreElements()) { + fileUrl = fileURLRoot + em.nextElement() + storeName; + } + load(); + } + + private void open() { + if (fc==null) { + try { + fc = (FileConnection)Connector.open(fileUrl, Connector.READ_WRITE); + } + catch(Exception ex) {} + } + } + + private void close() { + if (fc!=null) { + try { + fc.close(); + } catch( Exception ex ) {} + fc = null; + } + } + + public void addLocation(Location l) { + locations.addElement( l ); + save(); + } + + public String[] locationStrings() { + String result[] = new String[locations.size()]; + int i; + + for( i = 0; i < locations.size(); i++ ) { + result[i] = ((Location)locations.elementAt(i)).getLocation(); + } + return result; + } + + public Location location( final String location ) { + int i; + + for( i = 0; i < locations.size(); i++ ) { + Location l = (Location)locations.elementAt(i); + if (location.equals(l.getLocation())) { + return l; + } + } + return null; + } + + public void updateLocation(Location location) { + int i; + + for( i = 0; i < locations.size(); i++ ) { + Location l = (Location)locations.elementAt(i); + if (location.getLocation().equals(l.getLocation())) { + l.setForecast(location.getForecast()); + l.setId(location.getId()); + } + } + save(); + } + + public void load() { + try { + int v; + byte b[]; + int length; + Location l; + DataInputStream dis; + + locations.removeAllElements(); + open(); + dis = fc.openDataInputStream(); + + // Read version + v = dis.readInt(); + // While there are more elements, read them. + while(true) { + length = dis.readInt(); + b = new byte[length]; + dis.read( b, 0, length); + l = new Location(b); + locations.addElement( l ); + } + } + catch(Exception ex) {}; + close(); + } + + public void save() { + try { + int i; + byte[] b; + DataOutputStream dos; + open(); + dos = fc.openDataOutputStream(); + + // Write version + dos.writeInt( 1 ); + + for( i = 0; i < locations.size(); i++ ) { + Location l = (Location)locations.elementAt(i); + b = l.toBytes(); + dos.writeInt(b.length); + dos.write(b); + } + dos.close(); + close(); + } + catch(Exception ex) {} + } +} diff --git a/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java new file mode 100644 index 0000000..78d0c58 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java @@ -0,0 +1,242 @@ +/* + * WeatherWidget.java + * + * Created on March 1, 2008, 10:08 AM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.util.*; + +/** + * + * @author kf6gpe + * @version + */ +public class WeatherWidget extends MIDlet implements CommandListener { + private Form wxForm; + private StringItem locationItem; + private StringItem wxItem; + private Command exitCommand; + private Command screenCommand; + private Command settingCommand; + private Command okCommand; + private Command backCommand; + private List locationList; + private TextBox locationTextBox; + private Alert cannotAddLocationAlert; + + String location; + LocationStore locationStore; + + /** This method initializes UI of the application. + */ + private void initialize() { + locationStore = new LocationStore(); + String[] locations = locationStore.locationStrings(); + if (locations.length > 0 ) location = locations[0]; + + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == cannotAddLocationAlert) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_location() { + if (location == null) { + location = ""; + } + return location; + } + + public void set_location( String l ) { + location = l; + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + String locations[]; + int i; + try { + locationStore.addLocation( new Location( l, "" )); + } catch (Exception e) { + getDisplay().setCurrent(get_cannotAddLocationAlert()); + } + // Refresh the location list lazily. + locationList = null; + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", "Sunny."); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = locationStore.locationStrings(); + + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + public Alert get_cannotAddLocationAlert() { + if (cannotAddLocationAlert == null) + { + cannotAddLocationAlert = new Alert("Cannot Add Location"); + cannotAddLocationAlert.setString("An error occurred adding the location you entered. It has not been added."); + cannotAddLocationAlert.addCommand(get_backCommand()); + } + return cannotAddLocationAlert; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/ls.txt b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/ls.txt new file mode 100644 index 0000000..c7e1f44 --- /dev/null +++ b/Sample Code/chapter07/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/ls.txt @@ -0,0 +1,145 @@ +/* + * LocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.io.*; +import javax.microedition.io.file.*; +import java.io.*; +import java.util.*; +/** + * + * @author kf6gpe + */ +public class LocationStore { + private static final String storeName = "wx"; + private static final String fileURLRoot = "file:///"; + private static String fileUrl; + Vector locations; + FileConnection fc; + + public LocationStore() { + locations = new Vector(); + Enumeration em = FileSystemRegistry.listRoots(); + if (em.hasMoreElements()) { + fileUrl = fileURLRoot + em.nextElement() + storeName; + } + load(); + } + + private void open() { + if (fc==null) { + try { + fc = (FileConnection)Connector.open(fileUrl, Connector.REA~CCC +D_WRITE); + } + catch(Exception ex) {} + } + } + + private void close() { + if (fc!=null) { + try { + fc.close(); + } catch( Exception ex ) {} + fc = null; + } + } + + public void addLocation(Location l) { + locations.addElement( l ); + save(); + } + + public String[] locationStrings() { + String result[] = new String[locations.size()]; + int i; + + for( i = 0; i < locations.size(); i++ ) { + result[i] = ((Location)locations.elementAt(i)).getLocation(); ~CCC + + } + return result; + } + + public Location location( final String location ) { + int i; + + for( i = 0; i < locations.size(); i++ ) { + Location l = (Location)locations.elementAt(i); + if (location.equals(l.getLocation())) { + return l; + } + } + return null; + } + + public void updateLocation(Location location) { + int i; + + for( i = 0; i < locations.size(); i++ ) { + Location l = (Location)locations.elementAt(i); + if (location.getLocation().equals(l.getLocation())) { + l.setForecast(location.getForecast()); + l.setId(location.getId()); + } + } + save(); + } + + public void load() { + try { + int v; + byte b[]; + int length; + Location l; + DataInputStream dis; + + locations.removeAllElements(); + open(); + dis = fc.openDataInputStream(); + + // Read version + v = dis.readInt(); + // While there are more elements, read them. + while(true) { + length = dis.readInt(); + b = new byte[length]; + dis.read( b, 0, length); + l = new Location(b); + locations.addElement( l ); + } + } + catch(Exception ex) {}; + close(); + } + + public void save() { + try { + int i; + byte[] b; + DataOutputStream dos; + open(); + dos = fc.openDataOutputStream(); + + // Write version + dos.writeInt( 1 ); + + for( i = 0; i < locations.size(); i++ ) { + Location l = (Location)locations.elementAt(i); + b = l.toBytes(); + dos.writeInt(b.length); + dos.write(b); + } + dos.close(); + close(); + } + catch(Exception ex) {} + } +} diff --git a/Sample Code/chapter08/code/SpriteSample/build.xml b/Sample Code/chapter08/code/SpriteSample/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter08/code/SpriteSample/nbproject/build-impl.xml b/Sample Code/chapter08/code/SpriteSample/nbproject/build-impl.xml new file mode 100644 index 0000000..a2a8c8a --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/nbproject/build-impl.xml @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter08/code/SpriteSample/nbproject/genfiles.properties b/Sample Code/chapter08/code/SpriteSample/nbproject/genfiles.properties new file mode 100644 index 0000000..c9316cb --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=adce2788 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=adce2788 +nbproject/build-impl.xml.script.CRC32=036a5e16 +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter08/code/SpriteSample/nbproject/private/private.properties b/Sample Code/chapter08/code/SpriteSample/nbproject/private/private.properties new file mode 100644 index 0000000..7b953e2 --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/nbproject/private/private.properties @@ -0,0 +1,3 @@ +config.active= +javadoc.preview=true +netbeans.user=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 diff --git a/Sample Code/chapter08/code/SpriteSample/nbproject/project.properties b/Sample Code/chapter08/code/SpriteSample/nbproject/project.properties new file mode 100644 index 0000000..a88519f --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/nbproject/project.properties @@ -0,0 +1,67 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=SpriteSample.jad +dist.jar=SpriteSample.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: SpriteSample,,com.apress.rischpater.SpriteSampleMIDlet\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: SpriteSample\n +manifest.pushregistry= +name=SpriteSample +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias= +sign.enabled=false +sign.keystore= +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter08/code/SpriteSample/nbproject/project.xml b/Sample Code/chapter08/code/SpriteSample/nbproject/project.xml new file mode 100644 index 0000000..eb3fae2 --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + SpriteSample + 1.6 + + + diff --git a/Sample Code/chapter08/code/SpriteSample/src/com/apress/rischpater/SpriteCanvas.java b/Sample Code/chapter08/code/SpriteSample/src/com/apress/rischpater/SpriteCanvas.java new file mode 100644 index 0000000..87f479b --- /dev/null +++ b/Sample Code/chapter08/code/SpriteSample/src/com/apress/rischpater/SpriteCanvas.java @@ -0,0 +1,247 @@ +/* + * SpriteCanvas.java + * + * Created on April 8, 2008, 1:19 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater; + +import javax.microedition.lcdui.*; +import javax.microedition.lcdui.game.*; +import java.io.IOException; +import java.util.Random; + +/** + * + * @author kf6gpe + */ +public class SpriteCanvas + extends GameCanvas + implements Runnable { + + private final int DELAYMS=75; + private boolean paused; + + private Random random; + private Display display; + + private LayerManager layers; + private TiledLayer board; + private Sprite[] butterfly; + private Sprite cat; + + int[] map = { + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 1, 1, 1, + 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 1, + 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 }; + private static final int[] flightSequence = { + 0, 1, 2, 2, 1, 0 }; + private final int tileWidth = 16, tileHeight = 16; + private final int boardWidth = 8, boardHeight = 8; + + /** Creates a new instance of SpriteCanvas */ + public SpriteCanvas(Display d) + throws IOException { + super(true); + + display = d; + random = new Random(); + + layers = new LayerManager(); + layers.setViewWindow(-(getWidth()-128)/2, -(getHeight()-128)/2, 256, 256); + + createButterflies("/res/butterfly-sprite.png"); + createCat("/res/cat.png"); + createBoard("/res/ground-tiles.png"); + } + + private void createBoard( String imageName ) + throws IOException { + Image boardImage = Image.createImage(imageName); + + board = new TiledLayer( boardWidth, boardHeight, + boardImage, tileWidth, tileHeight); + + for( int i = 0; i < map.length; i++ ) { + int x = i % 8; + int y = i / 8; + board.setCell(x, y, map[i]); + } + layers.append(board); + } + + private void createButterflies( String imageName ) + throws IOException { + Image image = Image.createImage(imageName); + int x, y; + int i; + butterfly = new Sprite[2]; + + for ( i=0; i board.getWidth()-cat.getWidth() ) + x = board.getWidth()-cat.getWidth(); + if ( y > board.getHeight()-cat.getHeight() ) + y = board.getHeight()-cat.getHeight(); + cat.setPosition(x,y); + } + + private void moveButterflies() { + int dir; + int i; + int x, y, width, height; + for ( i=0; i board.getWidth() - width ) + x = board.getWidth() - width; + if ( y > board.getHeight() - height ) + y = board.getHeight() - height; + butterfly[i].setPosition(x,y); + butterfly[i].nextFrame(); + } + } + + public void start() { + Thread thread = new Thread(this); + thread.start(); + paused=false; + } + + private void detectCollisions() { + int i; + for (i=0; i + + + + + Builds, tests, and runs the project WeatherApplet. + + + diff --git a/Sample Code/chapter09/code/HelloXlet/manifest.mf b/Sample Code/chapter09/code/HelloXlet/manifest.mf new file mode 100644 index 0000000..328e8e5 --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/build-impl.xml b/Sample Code/chapter09/code/HelloXlet/nbproject/build-impl.xml new file mode 100644 index 0000000..2bc4f4f --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/build-impl.xml @@ -0,0 +1,584 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set platform.home + Must set platform.bootcp + Must set platform.java + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/build-target-impl.xml b/Sample Code/chapter09/code/HelloXlet/nbproject/build-target-impl.xml new file mode 100644 index 0000000..3f6b6a0 --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/build-target-impl.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + JUnit testing is not supported for this target. + + + Some tests failed; see details above. + + + + + + + + + diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/genfiles.properties b/Sample Code/chapter09/code/HelloXlet/nbproject/genfiles.properties new file mode 100644 index 0000000..0318740 --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/genfiles.properties @@ -0,0 +1,11 @@ +build.xml.data.CRC32=100831e2 +build.xml.script.CRC32=de46eb58 +build.xml.stylesheet.CRC32=e44f9c28 +nbproject/build-impl.xml.data.CRC32=100831e2 +nbproject/build-impl.xml.script.CRC32=c4554643 +nbproject/build-impl.xml.stylesheet.CRC32=c607b9ec +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-target-impl.xml.data.CRC32=100831e2 +nbproject/build-target-impl.xml.script.CRC32=8db5c960 +nbproject/build-target-impl.xml.stylesheet.CRC32=cf6e38a1 diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/private/private.properties b/Sample Code/chapter09/code/HelloXlet/nbproject/private/private.properties new file mode 100644 index 0000000..3d14d5a --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/private/private.properties @@ -0,0 +1,7 @@ +#Sat Dec 01 21:59:01 PST 2007 +application.version.counter=000006 +javac.debug=true +application.args= +javadoc.preview=true +application.version=0.0.5 +user.properties.file=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\build.properties diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/private/private.xml b/Sample Code/chapter09/code/HelloXlet/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/project.properties b/Sample Code/chapter09/code/HelloXlet/nbproject/project.properties new file mode 100644 index 0000000..adc968f --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/project.properties @@ -0,0 +1,76 @@ +application.args= +application.description= +application.description.detail= +application.name=WeatherApplet +application.vendor=Ray Rischpater +application.version.autoincrement=true +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form,**/*.mbm +# This directory is removed when the project is cleaned: +build.dir=build +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/${dist.jar.name} +dist.jar.name=WeatherApplet.jar +dist.javadoc.dir=${dist.dir}/javadoc +# Put all native components to this directory: +dll.dir=dll +jar.compress=false +javac.classpath=\ + ${libs.cdc-agui-swing-layout.classpath} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.4 +javac.target=1.4 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.cdc-junit.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=com.apress.rischpater.weatherxlet.HelloXlet +main.class.applet=false +main.class.xlet=true +manifest.file=manifest.mf +platform.active=Sun_Java_Toolkit_1.0_for_Connected_Device_Configuration +platform.bootclasspath=${platform.home}\\lib\\agui-1.0.jar;${platform.home}\\lib\\rt.jar;${platform.home}\\lib\\jce.jar;${platform.home}\\lib\\jaas.jar;${platform.home}\\lib\\jsse-cdc.jar +platform.device=DefaultColorPhone +platform.fat.jar=true +platform.profile=AGUI-1.0 +# Put all resources which should not be in jar file here. They will be handled per target platform +resources.dir=resources +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project +# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value +# or test-sys-prop.name=value to set system properties for unit tests): +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +savaje.bundle.base=c: +savaje.bundle.debug=false +src.dir=src +# This directory is removed when the project is cleaned: +target.dir=target +test.src.dir=test diff --git a/Sample Code/chapter09/code/HelloXlet/nbproject/project.xml b/Sample Code/chapter09/code/HelloXlet/nbproject/project.xml new file mode 100644 index 0000000..a09519c --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/nbproject/project.xml @@ -0,0 +1,17 @@ + + + org.netbeans.modules.j2me.cdc.nbproject + + + WeatherApplet + 1.6 + + + + + + + + + + diff --git a/Sample Code/chapter09/code/HelloXlet/src/com/apress/rischpater/HelloXlet/HelloXlet.java b/Sample Code/chapter09/code/HelloXlet/src/com/apress/rischpater/HelloXlet/HelloXlet.java new file mode 100644 index 0000000..91740f9 --- /dev/null +++ b/Sample Code/chapter09/code/HelloXlet/src/com/apress/rischpater/HelloXlet/HelloXlet.java @@ -0,0 +1,65 @@ +/* + * HelloXlet.java + * + * Created on November 24, 2007, 6:57 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.HelloXlet; + +import java.awt.*; +import javax.microedition.xlet.*; + +/** + * + * @author Ray Rischpater + */ +public class HelloXlet extends Component implements javax.microedition.xlet.Xlet { + private XletContext context; // our Xlet application context. + private Container rootContainer; // the root container of our screen. + + public HelloXlet() { + + } + + public void initXlet(final XletContext xletContext) throws XletStateChangeException { + context = xletContext; + if(rootContainer == null) { + try { + //This call to getContainer() tells the OS we want to be a graphical app. + rootContainer = context.getContainer(); + rootContainer.add(this); + } catch (UnavailableContainerException e) { + System.out.println("Ouch ! could not get our container!"); + // If we can't get the root container, + // abort the initialization + throw new XletStateChangeException( "Start aborted -- no container: " + + e.getMessage() ); + } + } + } + + public void startXlet() throws XletStateChangeException { + rootContainer.setVisible(true); + } + + public void pauseXlet() { + System.out.println("HelloXet.pauseXlet()"); + } + + public void destroyXlet(boolean b) throws XletStateChangeException { + System.out.println("HelloXet.destroyXlet() - goodbye"); + } + + public void exit(){ + rootContainer.setVisible( false ); + context.notifyDestroyed(); + } + + public void paint(Graphics g) { + g.drawString("Hello Xlet", 0, 100); + } + +} diff --git a/Sample Code/chapter09/code/IXCExample/Location.java b/Sample Code/chapter09/code/IXCExample/Location.java new file mode 100644 index 0000000..e8da933 --- /dev/null +++ b/Sample Code/chapter09/code/IXCExample/Location.java @@ -0,0 +1,41 @@ +import java.rmi.*; + +public class Location + implements java.rmi.Remote { + + private String location; + private String forecast; + + private Location() { + } + + public setLocation(String l) + throws RemoteException { + location = l; + } + + public setForecast(String f) + throws RemoteException { + forecast = f; + } + + public getLocation() + throws RemoteException { + if (location != null) { + return location; + } + else { + return ""; + } + } + + public getForecast() + throws RemoteException { + if (forecast != null) { + return forecast; + } + else { + return ""; + } + } +} diff --git a/Sample Code/chapter09/code/IXCExample/XletLocationConsumer.java b/Sample Code/chapter09/code/IXCExample/XletLocationConsumer.java new file mode 100644 index 0000000..11d1429 --- /dev/null +++ b/Sample Code/chapter09/code/IXCExample/XletLocationConsumer.java @@ -0,0 +1,44 @@ +import java.rmi.*; +import javax.microedition.xlet.*; +import javax.microedition.xlet.ixc.*; + + +public class XletLocationConsumer implements Xlet { + XletContext context; + Location location; + private static final String NAME = + "XletLocationProducer.location"; + + + public XletLocationConsumer () { + } + + public void initXlet( XletContext c ) + throws XletStateChangeException { + context = c; + + try { + IxcRegistry registry = IxcRegistry.getRegistry(context); + + location = (Location)registry.lookup(NAME); + } + catch( NotBoundException e ){ + throw new XletStateChangeException("Nothing bound"); + } + catch( StubException e ){ + throw new XletStateChangeException("Stub error"); + } + } + + public void pauseXlet() { + } + + public void startXlet() + throws XletStateChangeException { + } + + public void destroyXlet( boolean b ) + throws XletStateChangeException { + } + +} diff --git a/Sample Code/chapter09/code/IXCExample/XletLocationProducer.java b/Sample Code/chapter09/code/IXCExample/XletLocationProducer.java new file mode 100644 index 0000000..c78179e --- /dev/null +++ b/Sample Code/chapter09/code/IXCExample/XletLocationProducer.java @@ -0,0 +1,56 @@ +import java.rmi.*; +import javax.microedition.xlet.*; +import javax.microedition.xlet.ixc.*; + + +public class XletLocationProducer implements Xlet { + XletContext context; + Location location; + private static final String NAME = + "XletLocationProducer.location"; + + + public XletLocationProducer () { + } + + public void initXlet( XletContext c ) + throws XletStateChangeException { + location = new Location(); + context = c; + + try { + IxcRegistry registry = IxcRegistry.getRegistry(context); + + registry.bind(NAME, location); + } + catch( AlreadyBoundException e ){ + throw new XletStateChangeException("Something bound"); + } + catch( StubException e ){ + throw new XletStateChangeException("Stub error"); + } + } + + public void pauseXlet() { + } + + public void startXlet() + throws XletStateChangeException { + } + + public void destroyXlet( boolean unconditional ) + throws XletStateChangeException { + try { + IxcRegistry registry = IxcRegistry.getRegistry(context); + + registry.unbindAll(); + } + catch( Access e ){ + System.out.println("Permission failed"); + } + catch( StubException e ){ + System.out.println("Stub error"); + } + } + +} diff --git a/Sample Code/chapter11/code/Location.class b/Sample Code/chapter11/code/Location.class new file mode 100644 index 0000000..8cfe925 Binary files /dev/null and b/Sample Code/chapter11/code/Location.class differ diff --git a/Sample Code/chapter11/code/Location.java b/Sample Code/chapter11/code/Location.java new file mode 100644 index 0000000..428cca5 --- /dev/null +++ b/Sample Code/chapter11/code/Location.java @@ -0,0 +1,14 @@ +public interface Location + extends java.rmi.Remote { + public String getLocation() + throws java.rmi.RemoteException; + + public void setLocation(String l) + throws java.rmi.RemoteException; + + public String getForecast() + throws java.rmi.RemoteException; + + public void setForecast(String f) + throws java.rmi.RemoteException; +} diff --git a/Sample Code/chapter11/code/LocationBean.java b/Sample Code/chapter11/code/LocationBean.java new file mode 100644 index 0000000..8d255e9 --- /dev/null +++ b/Sample Code/chapter11/code/LocationBean.java @@ -0,0 +1,69 @@ +import javax.ejb.*; +import java.io.Serializable; +import java.util.*; +import java.rmi.*; + +public class LocationBean + extends SessionBean + implements Location { + private String location; + private String forecast; + + public LocationBean() + throws java.rmi.RemoteException { + super(); + } + + public String getLocation() + throws java.rmi.RemoteException { + if (location != null) { + return location; + } else { + return ""; + } + } + + public void setLocation(String l) + throws java.rmi.RemoteException { + location = l; + } + + public String getForecast() + throws java.rmi.RemoteException { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) + throws java.rmi.RemoteException { + forecast = f; + } + + private transient SessionContext ctx; + private transient Properties props; + + public void ejbActivate() { + System.out.println("ejbActivate called"); + } + + public void ejbRemove() { + System.out.println("ejbRemove called"); + } + + public void ejbPassivate() { + System.out.println("ejbPassivate called"); + } + + public void setSessionContext(SessionContext ctx) { + System.out.println("setSessionContext called"); + this.ctx = ctx; + props = ctx.getEnvironment(); + } + + public void ejbCreate () { + System.out.println("ejbCreate called"); + } +} \ No newline at end of file diff --git a/Sample Code/chapter11/code/LocationImpl.class b/Sample Code/chapter11/code/LocationImpl.class new file mode 100644 index 0000000..57fded4 Binary files /dev/null and b/Sample Code/chapter11/code/LocationImpl.class differ diff --git a/Sample Code/chapter11/code/LocationImpl.java b/Sample Code/chapter11/code/LocationImpl.java new file mode 100644 index 0000000..6a39077 --- /dev/null +++ b/Sample Code/chapter11/code/LocationImpl.java @@ -0,0 +1,42 @@ +public class LocationImpl + extends + java.rmi.server.UnicastRemoteObject + implements Location { + private String location; + private String forecast; + + /** Creates a new instance of Location */ + public LocationImpl() + throws java.rmi.RemoteException { + super(); + } + + + public String getLocation() + throws java.rmi.RemoteException { + if (location != null) { + return location; + } else { + return ""; + } + } + + public void setLocation(String l) + throws java.rmi.RemoteException { + location = l; + } + + public String getForecast() + throws java.rmi.RemoteException { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) + throws java.rmi.RemoteException { + forecast = f; + } +} diff --git a/Sample Code/chapter11/code/LocationImpl_Stub.class b/Sample Code/chapter11/code/LocationImpl_Stub.class new file mode 100644 index 0000000..41d5db5 Binary files /dev/null and b/Sample Code/chapter11/code/LocationImpl_Stub.class differ diff --git a/Sample Code/chapter11/code/LocationServer.class b/Sample Code/chapter11/code/LocationServer.class new file mode 100644 index 0000000..0a84cbe Binary files /dev/null and b/Sample Code/chapter11/code/LocationServer.class differ diff --git a/Sample Code/chapter11/code/LocationServer.java b/Sample Code/chapter11/code/LocationServer.java new file mode 100644 index 0000000..6dbf318 --- /dev/null +++ b/Sample Code/chapter11/code/LocationServer.java @@ -0,0 +1,17 @@ + +import java.rmi.Naming; + +public class LocationServer { + public LocationServer() { + try { + Location c = new LocationImpl(); + Naming.rebind("rmi://localhost:1099/LocationService", c); + } catch (Exception e) { + System.out.println("Exception: " + e); + } + } + + public static void main(String args[]) { + new LocationServer(); + } +} diff --git a/Sample Code/chapter12/code/WeatherWidget/build.xml b/Sample Code/chapter12/code/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter12/code/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter12/code/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter12/code/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter12/code/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter12/code/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter12/code/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..15c3478 --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,7 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active=Debug +deployment.number=0.0.2 diff --git a/Sample Code/chapter12/code/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter12/code/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter12/code/WeatherWidget/nbproject/project.properties b/Sample Code/chapter12/code/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..0b38c91 --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/nbproject/project.properties @@ -0,0 +1,81 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter12/code/WeatherWidget/nbproject/project.xml b/Sample Code/chapter12/code/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java b/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java new file mode 100644 index 0000000..ed6b3a9 --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java @@ -0,0 +1,140 @@ +/* + * Location.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; + +/** + * + * @author kf6gpe + */ +public class Location { + private final static int FIELD_VERSION = 1; + private final static int FIELD_LOCATION = 2; + private final static int FIELD_FORECAST = 3; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String location; + private String forecast; + private int recordid; + + /** Creates a new instance of Location */ + public Location(String l, String f) { + location = l; + forecast = f; + recordid = NO_ID; + } + + public Location(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + + public Location(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + if (location != null) { + return location; + } else { + return ""; + } + } + + public void setLocation(String l) { + location = l; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (location != null) { + dos.writeInt(FIELD_LOCATION); + dos.writeUTF(getLocation()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + } + catch( Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_LOCATION: + setLocation(dis.readUTF()); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + } + } + } + catch (Exception e) {} + + dis = null; + bais = null; + } +} diff --git a/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java b/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java new file mode 100644 index 0000000..8c6a34f --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java @@ -0,0 +1,132 @@ +/* + * LocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; + +/** + * + * @author kf6gpe + */ +public class LocationStore { + private static final String storeName = "wx"; + private RecordStore store = null; + + public LocationStore() { + } + + private void openStore() throws RecordStoreException { + if (store == null) { + store = RecordStore.openRecordStore(storeName, true); + } + } + + private void closeStore() { + if (store != null) { + try { + store.closeRecordStore(); + } catch( Exception ex ) {} + store = null; + } + } + + public void addLocation(Location l) throws RecordStoreException { + Location existing = getLocation(l.getLocation()); + if (existing!=null) { + existing.setForecast(l.getForecast()); + updateLocation(existing); + } else { + byte b[] = l.toBytes(); + openStore(); + l.setId(store.getNextRecordID()); + store.addRecord(b, 0, b.length); + closeStore(); + } + } + + public String[] getLocationStrings() { + String[] result = null; + try { + openStore(); + result = new String[store.getNumRecords()]; + RecordEnumeration e = store.enumerateRecords( + null, // No filter + new RecordComparator () { + public int compare( byte[] b1, byte[] b2 ) { + Location r1 = new Location(b1); + Location r2 = new Location(b2); + if (r1.getLocation().compareTo(r2.getLocation()) == 0) { + return RecordComparator.EQUIVALENT; + } else if (r1.getLocation().compareTo(r2.getLocation()) < 0) { + return RecordComparator.PRECEDES; + } else { + return RecordComparator.FOLLOWS; + } + } + }, + false); + int i; + + for (i=0; i=0x30 && b<=0x39) || + (b>=0x41 && b<=0x5A) || + (b>=0x61 && b<=0x7A)) { + tmp.append((char)b); + } else { + tmp.append("%"); + if (b <= 0xf) tmp.append("0"); + tmp.append(Integer.toHexString(b)); + } + } + } + catch (Exception e) {} + return tmp.toString(); + } + return null; + } + + +} \ No newline at end of file diff --git a/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java b/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java new file mode 100644 index 0000000..c84b92b --- /dev/null +++ b/Sample Code/chapter12/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java @@ -0,0 +1,275 @@ +/* + * WeatherWidget.java + * + * Created on March 1, 2008, 10:08 AM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.util.*; + +/** + * + * @author kf6gpe + * @version + */ +public class WeatherWidget extends MIDlet implements CommandListener { + private Form wxForm; + private StringItem locationItem; + private StringItem wxItem; + private Command exitCommand; + private Command screenCommand; + private Command settingCommand; + private Command okCommand; + private Command backCommand; + private Command updateCommand; + private List locationList; + private TextBox locationTextBox; + private Alert cannotAddLocationAlert; + private WeatherFetcher fetcher; + private Location location; + private LocationStore locationStore; + + /** This method initializes UI of the application. + */ + private void initialize() { + locationStore = new LocationStore(); + String[] locations = locationStore.getLocationStrings(); + try { + if (locations.length > 0 ) location = locationStore.getLocation(locations[0]); + } + catch(Exception e){} + fetcher = new WeatherFetcher(location, this); + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + if (fetcher!=null) fetcher.cancel(); + fetcher = null; + } + + public void update() { + get_wxItem().setText(get_forecast()); + try + { + locationStore.updateLocation(location); + } + catch(Exception e){} + fetcher = null; + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + if ( fetcher != null ) fetcher.cancel(); + fetcher = new WeatherFetcher(location, this); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == cannotAddLocationAlert) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_forecast() { + if (location == null) { + return "unknown forecast"; + } else { + return location.getForecast(); + } + } + + + public String get_location() { + if (location == null) { + return "unknown"; + } else { + return location.getLocation(); + } + } + + public void set_location( String l ) { + try { + location = locationStore.getLocation(l); + } + catch(Exception e) {} + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + String locations[]; + int i; + try { + locationStore.addLocation( new Location( l, "" )); + } catch (Exception e) { + getDisplay().setCurrent(get_cannotAddLocationAlert()); + } + // Refresh the location list lazily. + locationList = null; + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + if ( fetcher != null ) fetcher.cancel(); + fetcher = null; + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", get_forecast()); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = locationStore.getLocationStrings(); + + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + public Alert get_cannotAddLocationAlert() { + if (cannotAddLocationAlert == null) + { + cannotAddLocationAlert = new Alert("Cannot Add Location"); + cannotAddLocationAlert.setString("An error occurred adding the location you entered. It has not been added."); + cannotAddLocationAlert.addCommand(get_backCommand()); + } + return cannotAddLocationAlert; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/build.xml b/Sample Code/chapter13/code/WS-OP/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..15c3478 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,7 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active=Debug +deployment.number=0.0.2 diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..1680b78 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,8 @@ + + + + + file:/C:/book/Chapters/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java + file:/C:/book/Chapters/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParserHandler.java + + diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/project.properties b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..0b38c91 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/project.properties @@ -0,0 +1,81 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/project.xml b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java new file mode 100644 index 0000000..02ce208 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java @@ -0,0 +1,521 @@ +/* + * Location.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; +import javax.xml.parsers.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; +/** + * + * @author kf6gpe + */ +public class Location { + private final static int FIELD_VERSION = 1; + private final static int FIELD_CITY = 2; + private final static int FIELD_FORECAST = 3; + private final static int FIELD_TEMP = 4; + private final static int FIELD_WINDSPEED = 5; + private final static int FIELD_WINDDIR = 6; + private final static int FIELD_PRECIP = 7; + private final static int FIELD_STATE = 8; + private final static int FIELD_COUNTRY = 9; + private final static int FIELD_PRECIP_PROB = 10; + private final static int FIELD_PRECIP_TYPE = 11; + + private final static String XML_PREAMBLE = "\n"; + private final static String XML_START_OPEN = "<"; + private final static String XML_START_EMPTYOPEN = "<"; + private final static String XML_START_CLOSE=""; + private final static String XML_END_EMPTYOPEN = "/>"; + private final static String XML_END_CLOSE = ">"; + private final static String XML_ATTR_IS = "="; + private final static String XML_ATTR_QUOTE = "\""; + public final static String XML_TAG_WEATHER="weather"; + public final static String XML_ATTR_CITY="city"; + public final static String XML_ATTR_STATE="state"; + public final static String XML_ATTR_COUNTRY="country"; + public final static String XML_TAG_TEMPS="temperatures"; + public final static String XML_ATTR_UNITS="units"; + private final static String XML_ATTR_TUNITS=" units=\"F\""; + public final static String XML_TAG_TEMP="temperature"; + public final static String XML_ATTR_TYPE="type"; + public final static String XML_TAG_WIND="wind"; + private final static String XML_ATTR_WUNITS=" units=\"MPH\""; + public final static String XML_TAG_DIRECTION="direction"; + public final static String XML_TAG_SPEED="speed"; + public final static String XML_TAG_PRECIP="precipitation"; + public final static String XML_ATTR_PROB="probability"; + private final static String XML_ATTR_PUNITS=" units=\"in\""; + public final static String XML_TAG_TEXT="text"; + public final static String XML_TAG_WHEN="when"; + public final static String XML_ATTR_TIME="time"; + private final static String XML_ATTR_WTIME=" time=\"today\""; + private final static String XML_NEWLINE="\n"; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String city, state, country; + private String forecast; + private String temp; + private String windSpeed; + private String windDirection; + private String precipitation, precipitationProb, precipitationType; + private int recordid; + + /** Creates a new instance of Location */ + public Location() { + recordid = NO_ID; + } + + public Location(String l) { + setLocation(l); + recordid = NO_ID; + } + + public Location(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + public Location(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + StringBuffer result = new StringBuffer(); + if (city!=null) { + result.append(city); + } + result.append(","); + if (state!=null) { + result.append(state); + } + result.append(","); + if (country!=null) { + result.append(country); + } + return result.toString(); + } + + public String getCity() { + if(city != null) + return city; + else + return ""; + } + + public String getState() { + if(state != null) + return state; + else + return ""; + } + + public String getCountry() { + if(country != null) + return country; + else + return ""; + } + + public void setLocation(String l) { + int cityStart, stateStart, countryStart; + cityStart = 0; + stateStart = l.indexOf(","); + if (stateStart==-1) { + city = l; + state=""; + country=""; + return; + } + countryStart = l.indexOf(",",stateStart+1); + city = l.substring(cityStart,stateStart); + if (countryStart==-1) + { + state = l.substring(stateStart-1); + country = "USA"; + return; + } + state = l.substring(stateStart+1,countryStart); + country = l.substring(countryStart+1); + } + + public void setLocation(String c, String s, String co) { + city = c; + state = s; + country = co; + } + + public String getWind() { + if (windSpeed != null && windDirection != null) + return windSpeed + " mph from the " + windDirection; + else return ""; + } + + public void setWind(String s, String d) { + windSpeed = s; + windDirection = d; + } + + public String getTemperature() { + if (temp!=null) + return temp; + else + return ""; + } + + public void setTemperature(String t) { + temp = t; + } + + public String getPrecipitation() { + StringBuffer result = new StringBuffer(); + if (precipitation != null) { + result.append(precipitation); + } else { + result.append("unknown"); + } + result.append("in of "); + if (precipitationType != null) { + result.append(precipitationType); + } else { + result.append("unknown"); + } + result.append("("); + if (precipitationProb != null) { + result.append(precipitationProb); + } else { + result.append("unknown"); + } + result.append("%)"); + return result.toString(); + } + + public void setPrecipitation(String p, String pp, String pt) { + precipitation = p; + precipitationProb = pp; + precipitationType = pt; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (city != null) { + dos.writeInt(FIELD_CITY); + dos.writeUTF(getCity()); + } + if (state != null) { + dos.writeInt(FIELD_STATE); + dos.writeUTF(getState()); + } + if (country != null) { + dos.writeInt(FIELD_COUNTRY); + dos.writeUTF(getCountry()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + if (temp != null) { + dos.writeInt(FIELD_TEMP); + dos.writeUTF(getTemperature()); + } + if (precipitation != null && + precipitationProb != null && + precipitationType != null) { + dos.writeInt(FIELD_PRECIP); + dos.writeUTF(precipitation); + dos.writeInt(FIELD_PRECIP_PROB); + dos.writeUTF(precipitationProb); + dos.writeInt(FIELD_PRECIP_TYPE); + dos.writeUTF(precipitationType); + } + if (windDirection != null && windSpeed != null) { + dos.writeInt(FIELD_WINDDIR); + dos.writeUTF(windDirection); + dos.writeInt(FIELD_WINDSPEED); + dos.writeUTF(windSpeed); + } + } + catch(Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + String dir = null, speed = null; + String c = null, s = null, co = null; + String p = null, pp = null, pt = null; + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_CITY: + c = dis.readUTF(); + break; + case FIELD_STATE: + s = dis.readUTF(); + break; + case FIELD_COUNTRY: + co = dis.readUTF(); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + case FIELD_TEMP: + setTemperature(dis.readUTF()); + break; + case FIELD_PRECIP: + p = dis.readUTF(); + break; + case FIELD_PRECIP_PROB: + pp = dis.readUTF(); + break; + case FIELD_PRECIP_TYPE: + pt = dis.readUTF(); + break; + case FIELD_WINDDIR: + dir = dis.readUTF(); + break; + case FIELD_WINDSPEED: + speed = dis.readUTF(); + break; + } + } + } + catch (Exception e) {} + finally { + setLocation(c, s, co); + setPrecipitation(p, pp, pt); + setWind(speed, dir); + try { + dis.close(); + bais.close(); + } + catch (Exception e) {} + } + dis = null; + bais = null; + } + + public String toXml() { + StringBuffer xmlBuffer = new StringBuffer(); + xmlBuffer.append(XML_PREAMBLE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WEATHER); + if (city != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_CITY); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(city); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (state != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_STATE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(state); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (country != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_COUNTRY); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(country); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (forecast != null || + temp != null || + (precipitation != null && + precipitationProb != null && + precipitationType != null ) || + (windSpeed != null && windDirection != null)) { + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + if (temp != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEMPS); + xmlBuffer.append(XML_ATTR_TUNITS); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEMP); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_TYPE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append("\"current\""); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(temp); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEMP); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEMPS); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (windSpeed != null && windDirection != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WIND); + xmlBuffer.append(XML_ATTR_WUNITS); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_SPEED); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(windSpeed); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_SPEED); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_DIRECTION); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(windDirection); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_DIRECTION); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WIND); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (precipitation != null && + precipitationProb != null && + precipitationType != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_PRECIP); + xmlBuffer.append(XML_ATTR_PUNITS); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_PROB); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(precipitationProb); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_TYPE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(precipitationType); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(precipitation); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_PRECIP); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (forecast != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEXT); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WHEN); + xmlBuffer.append(XML_ATTR_WTIME); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(forecast); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WHEN); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEXT); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WEATHER); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } else { + xmlBuffer.append(XML_END_EMPTYOPEN); + } + + return xmlBuffer.toString(); + } + + public void fromXml(String xml) { + SAXParser parser = null; + LocationParserHandler handler = new LocationParserHandler(this); + byte[] xmlBytes; + ByteArrayInputStream bis; + + try { + SAXParserFactory f = SAXParserFactory.newInstance(); + parser = f.newSAXParser(); + } + catch(Exception e) { return; }; + xmlBytes = xml.getBytes(); + bis = new ByteArrayInputStream(xmlBytes); + try { + parser.parse(bis,handler); + } + catch(Exception e){} + finally { + try { + bis.close(); + } + catch(Exception e) {} + } + } +} diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParserHandler.java b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParserHandler.java new file mode 100644 index 0000000..7783425 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParserHandler.java @@ -0,0 +1,129 @@ +/* + * LocationParserHandler.java + * + * Created on July 6, 2008, 12:21 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.xml.parsers.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; + + +/** + * + * @author kf6gpe + */ +public class LocationParserHandler extends DefaultHandler { + private Location location; + private boolean setForecast; + private boolean hasForecast; + private boolean setTemp; + private String precipitation, precipType, precipProb; + private String windSpeed, windDirection; + private StringBuffer buffer; + + public LocationParserHandler( Location l ) { + location = l; + } + + public Location getLocation() { + return location; + } + + public void startDocument() { + if ( location == null ) + location = new Location(); + setForecast = false; + hasForecast = false; + setTemp = false; + } + + public void startElement(String uri, String localName, + String qName, Attributes attributes ) + throws SAXException { + buffer = new StringBuffer(); + if ( qName.compareTo(Location.XML_TAG_WEATHER) == 0) { + String c = attributes.getValue(Location.XML_ATTR_CITY); + String s = attributes.getValue(Location.XML_ATTR_STATE); + String co = attributes.getValue(Location.XML_ATTR_COUNTRY); + location.setLocation(c,s,co); + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_TEMPS) == 0) { + String u = attributes.getValue(Location.XML_ATTR_UNITS); + if ( u != null && u.compareTo("F") != 0) throw new SAXException("Invalid temperature units"); + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_TEMP) == 0 ) { + String t = attributes.getValue(Location.XML_ATTR_TYPE); + if (t != null && t.compareTo("current") != 0) { + setTemp = true; + } else { + setTemp = false; + } + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_WIND) == 0) { + String u = attributes.getValue(Location.XML_ATTR_UNITS); + if ( u != null && u.compareTo("MPH") != 0) + throw new SAXException("Invalid temperature units"); + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_PRECIP) == 0 ) + { + String u = attributes.getValue(Location.XML_ATTR_UNITS); + if (u != null && u.compareTo("in") != 0) + throw new SAXException("Invalid precipitation units"); + precipProb = attributes.getValue(Location.XML_ATTR_PROB); + precipType = attributes.getValue(Location.XML_ATTR_TYPE); + hasForecast = false; + } + if (qName.compareTo(Location.XML_TAG_TEXT) == 0) { + hasForecast = true; + } + if (qName.compareTo(Location.XML_TAG_WHEN) == 0 && hasForecast) { + String w = attributes.getValue(Location.XML_ATTR_TIME); + if (w != null && w.compareTo("now") == 0) { + setForecast = true; + } else { + setForecast = false; + } + } + } + + public void characters( char[] ch, int start, int length) { + if (buffer != null) + buffer.append(ch, start, length); + } + + public void endElement( String uri, String localName, String qName ) { + if (qName.compareTo(Location.XML_TAG_SPEED) == 0) { + windSpeed = buffer.toString(); + } + if (qName.compareTo(Location.XML_TAG_DIRECTION) == 0) { + windDirection = buffer.toString(); + } + if (qName.compareTo(Location.XML_TAG_WIND) == 0) { + location.setWind(windSpeed, windDirection); + } + if (qName.compareTo(Location.XML_TAG_PRECIP) == 0) { + precipitation = buffer.toString(); + location.setPrecipitation(precipitation,precipProb,precipType); + } + if (qName.compareTo(Location.XML_TAG_TEMP) == 0 && setTemp ) + { + location.setTemperature(buffer.toString()); + } + if (qName.compareTo(Location.XML_TAG_WHEN) == 0 && setForecast) { + location.setForecast( buffer.toString()); + } + } + + public void endDocument() { + } +} diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java new file mode 100644 index 0000000..8c6a34f --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java @@ -0,0 +1,132 @@ +/* + * LocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; + +/** + * + * @author kf6gpe + */ +public class LocationStore { + private static final String storeName = "wx"; + private RecordStore store = null; + + public LocationStore() { + } + + private void openStore() throws RecordStoreException { + if (store == null) { + store = RecordStore.openRecordStore(storeName, true); + } + } + + private void closeStore() { + if (store != null) { + try { + store.closeRecordStore(); + } catch( Exception ex ) {} + store = null; + } + } + + public void addLocation(Location l) throws RecordStoreException { + Location existing = getLocation(l.getLocation()); + if (existing!=null) { + existing.setForecast(l.getForecast()); + updateLocation(existing); + } else { + byte b[] = l.toBytes(); + openStore(); + l.setId(store.getNextRecordID()); + store.addRecord(b, 0, b.length); + closeStore(); + } + } + + public String[] getLocationStrings() { + String[] result = null; + try { + openStore(); + result = new String[store.getNumRecords()]; + RecordEnumeration e = store.enumerateRecords( + null, // No filter + new RecordComparator () { + public int compare( byte[] b1, byte[] b2 ) { + Location r1 = new Location(b1); + Location r2 = new Location(b2); + if (r1.getLocation().compareTo(r2.getLocation()) == 0) { + return RecordComparator.EQUIVALENT; + } else if (r1.getLocation().compareTo(r2.getLocation()) < 0) { + return RecordComparator.PRECEDES; + } else { + return RecordComparator.FOLLOWS; + } + } + }, + false); + int i; + + for (i=0; i=0x30 && b<=0x39) || + (b>=0x41 && b<=0x5A) || + (b>=0x61 && b<=0x7A)) { + tmp.append((char)b); + } else { + tmp.append("%"); + if (b <= 0xf) tmp.append("0"); + tmp.append(Integer.toHexString(b)); + } + } + } + catch (Exception e) {} + return tmp.toString(); + } + return null; + } + + private String requestEncode() { + StringBuffer result = new StringBuffer(); + result.append(url); + result.append(urlEncode(location.getLocation())); + return result.toString(); + } + + public void run() { + String requestUrl; + String response = ""; + HttpConnection hc = null; + InputStream in = null; + + requestUrl = requestEncode(); + + try { + hc = (HttpConnection)Connector.open(requestUrl); + hc.setRequestMethod(HttpConnection.GET); + in=hc.openInputStream(); + int length=(int)hc.getLength(); + byte[] data = new byte[length]; + in.read(data); + response = new String(data); + } + catch(Exception e){} + finally { + try { + if (in!=null) hc.close(); + if (hc!=null) hc.close(); + } + catch(Exception e) {} + } + if (!cancelled) { + System.out.println(response); + location.fromXml(response); + System.out.print(location.toXml()); + app.update(); + } + } +} \ No newline at end of file diff --git a/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java new file mode 100644 index 0000000..f87ef64 --- /dev/null +++ b/Sample Code/chapter13/code/WS-OP/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java @@ -0,0 +1,270 @@ +/* + * WeatherWidget.java + * + * Created on March 1, 2008, 10:08 AM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.util.*; + +/** + * + * @author kf6gpe + * @version + */ +public class WeatherWidget extends MIDlet implements CommandListener { + private Form wxForm; + private StringItem locationItem; + private StringItem wxItem; + private Command exitCommand; + private Command screenCommand; + private Command settingCommand; + private Command okCommand; + private Command backCommand; + private Command updateCommand; + private List locationList; + private TextBox locationTextBox; + private Alert cannotAddLocationAlert; + private WeatherFetcher fetcher; + private Location location; + private LocationStore locationStore; + + /** This method initializes UI of the application. + */ + private void initialize() { + locationStore = new LocationStore(); + String[] locations = locationStore.getLocationStrings(); + try { + if (locations.length > 0 ) location = locationStore.getLocation(locations[0]); + } + catch(Exception e){} + fetcher = new WeatherFetcher(location, this); + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void update() { + get_wxItem().setText(get_forecast()); + try + { + locationStore.updateLocation(location); + } + catch(Exception e){} + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + fetcher.cancel(); + fetcher = new WeatherFetcher(location, this); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == cannotAddLocationAlert) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_forecast() { + if (location == null) { + return "unknown forecast"; + } else { + return location.getForecast(); + } + } + + + public String get_location() { + if (location == null) { + return "unknown"; + } else { + return location.getLocation(); + } + } + + public void set_location( String l ) { + try { + location = locationStore.getLocation(l); + } + catch(Exception e) {e.printStackTrace();} + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + String locations[]; + int i; + try { + locationStore.addLocation( new Location( l )); + } catch (Exception e) { + getDisplay().setCurrent(get_cannotAddLocationAlert()); + } + // Refresh the location list lazily. + locationList = null; + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", get_forecast()); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = locationStore.getLocationStrings(); + + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + public Alert get_cannotAddLocationAlert() { + if (cannotAddLocationAlert == null) + { + cannotAddLocationAlert = new Alert("Cannot Add Location"); + cannotAddLocationAlert.setString("An error occurred adding the location you entered. It has not been added."); + cannotAddLocationAlert.addCommand(get_backCommand()); + } + return cannotAddLocationAlert; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/build.xml b/Sample Code/chapter13/code/kXML/WeatherWidget/build.xml new file mode 100644 index 0000000..c442465 --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/build.xml @@ -0,0 +1,80 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/lib/kxml2-min-2.3.0.jar b/Sample Code/chapter13/code/kXML/WeatherWidget/lib/kxml2-min-2.3.0.jar new file mode 100644 index 0000000..a77dd1d Binary files /dev/null and b/Sample Code/chapter13/code/kXML/WeatherWidget/lib/kxml2-min-2.3.0.jar differ diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..f2a26cf --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-modules-kjava-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set build.classes.dir + Must set preprocessed.dir + Must set preverify.classes.dir + Must set obfuscated.classes.dir + Must set dist.dir + Must set dist.jar + Must set dist.jad + Must set obfuscator.srcjar + Must set obfuscator.destjar + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..403c0e7 --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=868d4859 +build.xml.script.CRC32=7593e195 +build.xml.stylesheet.CRC32=790018fc +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=868d4859 +nbproject/build-impl.xml.script.CRC32=93e65e2b +nbproject/build-impl.xml.stylesheet.CRC32=a16fb29f diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..e154fb6 --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,8 @@ +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +file.reference.kxml2-min-2.3.0.jar=C:\\book\\Chapters\\chapter13\\code\\kXML\\WeatherWidget\\lib\\kxml2-min-2.3.0.jar +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1 +javadoc.preview=true +deployment.counter=000003 +config.active= +deployment.number=0.0.2 diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/project.properties b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..a90330f --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/project.properties @@ -0,0 +1,82 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +file.reference.kxml2-min-2.3.0.jar=lib/kxml2-min-2.3.0.jar +filter.exclude.tests=false +filter.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath=${file.reference.kxml2-min-2.3.0.jar} +manifest.apipermissions= +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.profile=MIDP-2.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +run.cmd.options= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/project.xml b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..3706bd7 --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/nbproject/project.xml @@ -0,0 +1,14 @@ + + + org.netbeans.modules.kjava.j2meproject + + + Release + Debug + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java new file mode 100644 index 0000000..f770007 --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/Location.java @@ -0,0 +1,515 @@ +/* + * Location.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; +import javax.xml.parsers.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; +/** + * + * @author kf6gpe + */ +public class Location { + private final static int FIELD_VERSION = 1; + private final static int FIELD_CITY = 2; + private final static int FIELD_FORECAST = 3; + private final static int FIELD_TEMP = 4; + private final static int FIELD_WINDSPEED = 5; + private final static int FIELD_WINDDIR = 6; + private final static int FIELD_PRECIP = 7; + private final static int FIELD_STATE = 8; + private final static int FIELD_COUNTRY = 9; + private final static int FIELD_PRECIP_PROB = 10; + private final static int FIELD_PRECIP_TYPE = 11; + + private final static String XML_PREAMBLE = "\n"; + private final static String XML_START_OPEN = "<"; + private final static String XML_START_EMPTYOPEN = "<"; + private final static String XML_START_CLOSE=""; + private final static String XML_END_EMPTYOPEN = "/>"; + private final static String XML_END_CLOSE = ">"; + private final static String XML_ATTR_IS = "="; + private final static String XML_ATTR_QUOTE = "\""; + public final static String XML_TAG_WEATHER="weather"; + public final static String XML_ATTR_CITY="city"; + public final static String XML_ATTR_STATE="state"; + public final static String XML_ATTR_COUNTRY="country"; + public final static String XML_TAG_TEMPS="temperatures"; + public final static String XML_ATTR_UNITS="units"; + private final static String XML_ATTR_TUNITS=" units=\"F\""; + public final static String XML_TAG_TEMP="temperature"; + public final static String XML_ATTR_TYPE="type"; + public final static String XML_TAG_WIND="wind"; + private final static String XML_ATTR_WUNITS=" units=\"MPH\""; + public final static String XML_TAG_DIRECTION="direction"; + public final static String XML_TAG_SPEED="speed"; + public final static String XML_TAG_PRECIP="precipitation"; + public final static String XML_ATTR_PROB="probability"; + private final static String XML_ATTR_PUNITS=" units=\"in\""; + public final static String XML_TAG_TEXT="text"; + public final static String XML_TAG_WHEN="when"; + public final static String XML_ATTR_TIME="time"; + private final static String XML_ATTR_WTIME=" time=\"today\""; + private final static String XML_NEWLINE="\n"; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String city, state, country; + private String forecast; + private String temp; + private String windSpeed; + private String windDirection; + private String precipitation, precipitationProb, precipitationType; + private int recordid; + + /** Creates a new instance of Location */ + public Location() { + recordid = NO_ID; + } + + public Location(String l) { + setLocation(l); + recordid = NO_ID; + } + + public Location(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + public Location(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + StringBuffer result = new StringBuffer(); + if (city!=null) { + result.append(city); + } + result.append(","); + if (state!=null) { + result.append(state); + } + result.append(","); + if (country!=null) { + result.append(country); + } + return result.toString(); + } + + public String getCity() { + if(city != null) + return city; + else + return ""; + } + + public String getState() { + if(state != null) + return state; + else + return ""; + } + + public String getCountry() { + if(country != null) + return country; + else + return ""; + } + + public void setLocation(String l) { + int cityStart, stateStart, countryStart; + cityStart = 0; + stateStart = l.indexOf(","); + if (stateStart==-1) { + city = l; + state=""; + country=""; + return; + } + countryStart = l.indexOf(",",stateStart+1); + city = l.substring(cityStart,stateStart); + if (countryStart==-1) + { + state = l.substring(stateStart-1); + country = "USA"; + return; + } + state = l.substring(stateStart+1,countryStart); + country = l.substring(countryStart+1); + } + + public void setLocation(String c, String s, String co) { + city = c; + state = s; + country = co; + } + + public String getWind() { + if (windSpeed != null && windDirection != null) + return windSpeed + " mph from the " + windDirection; + else return ""; + } + + public void setWind(String s, String d) { + windSpeed = s; + windDirection = d; + } + + public String getTemperature() { + if (temp!=null) + return temp; + else + return ""; + } + + public void setTemperature(String t) { + temp = t; + } + + public String getPrecipitation() { + StringBuffer result = new StringBuffer(); + if (precipitation != null) { + result.append(precipitation); + } else { + result.append("unknown"); + } + result.append("in of "); + if (precipitationType != null) { + result.append(precipitationType); + } else { + result.append("unknown"); + } + result.append("("); + if (precipitationProb != null) { + result.append(precipitationProb); + } else { + result.append("unknown"); + } + result.append("%)"); + return result.toString(); + } + + public void setPrecipitation(String p, String pp, String pt) { + precipitation = p; + precipitationProb = pp; + precipitationType = pt; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (city != null) { + dos.writeInt(FIELD_CITY); + dos.writeUTF(getCity()); + } + if (state != null) { + dos.writeInt(FIELD_STATE); + dos.writeUTF(getState()); + } + if (country != null) { + dos.writeInt(FIELD_COUNTRY); + dos.writeUTF(getCountry()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + if (temp != null) { + dos.writeInt(FIELD_TEMP); + dos.writeUTF(getTemperature()); + } + if (precipitation != null && + precipitationProb != null && + precipitationType != null) { + dos.writeInt(FIELD_PRECIP); + dos.writeUTF(precipitation); + dos.writeInt(FIELD_PRECIP_PROB); + dos.writeUTF(precipitationProb); + dos.writeInt(FIELD_PRECIP_TYPE); + dos.writeUTF(precipitationType); + } + if (windDirection != null && windSpeed != null) { + dos.writeInt(FIELD_WINDDIR); + dos.writeUTF(windDirection); + dos.writeInt(FIELD_WINDSPEED); + dos.writeUTF(windSpeed); + } + } + catch(Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + String dir = null, speed = null; + String c = null, s = null, co = null; + String p = null, pp = null, pt = null; + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_CITY: + c = dis.readUTF(); + break; + case FIELD_STATE: + s = dis.readUTF(); + break; + case FIELD_COUNTRY: + co = dis.readUTF(); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + case FIELD_TEMP: + setTemperature(dis.readUTF()); + break; + case FIELD_PRECIP: + p = dis.readUTF(); + break; + case FIELD_PRECIP_PROB: + pp = dis.readUTF(); + break; + case FIELD_PRECIP_TYPE: + pt = dis.readUTF(); + break; + case FIELD_WINDDIR: + dir = dis.readUTF(); + break; + case FIELD_WINDSPEED: + speed = dis.readUTF(); + break; + } + } + } + catch (Exception e) {} + finally { + setLocation(c, s, co); + setPrecipitation(p, pp, pt); + setWind(speed, dir); + try { + dis.close(); + bais.close(); + } + catch (Exception e) {} + } + dis = null; + bais = null; + } + + public String toXml() { + StringBuffer xmlBuffer = new StringBuffer(); + xmlBuffer.append(XML_PREAMBLE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WEATHER); + if (city != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_CITY); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(city); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (state != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_STATE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(state); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (country != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_COUNTRY); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(country); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (forecast != null || + temp != null || + (precipitation != null && + precipitationProb != null && + precipitationType != null ) || + (windSpeed != null && windDirection != null)) { + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + if (temp != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEMPS); + xmlBuffer.append(XML_ATTR_TUNITS); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEMP); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_TYPE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append("\"current\""); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(temp); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEMP); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEMPS); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (windSpeed != null && windDirection != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WIND); + xmlBuffer.append(XML_ATTR_WUNITS); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_SPEED); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(windSpeed); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_SPEED); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_DIRECTION); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(windDirection); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_DIRECTION); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WIND); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (precipitation != null && + precipitationProb != null && + precipitationType != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_PRECIP); + xmlBuffer.append(XML_ATTR_PUNITS); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_PROB); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(precipitationProb); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_TYPE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(precipitationType); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(precipitation); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_PRECIP); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (forecast != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEXT); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WHEN); + xmlBuffer.append(XML_ATTR_WTIME); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(forecast); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WHEN); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEXT); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WEATHER); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } else { + xmlBuffer.append(XML_END_EMPTYOPEN); + } + + return xmlBuffer.toString(); + } + + public void fromXml(String xml) { + LocationParser parser = new LocationParser(this); + byte[] xmlBytes; + ByteArrayInputStream bis; + + xmlBytes = xml.getBytes(); + bis = new ByteArrayInputStream(xmlBytes); + try { + parser.parse(bis); + } + catch(Exception e){} + finally { + try { + bis.close(); + } + catch(Exception e) {} + } + } +} diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParser.java b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParser.java new file mode 100644 index 0000000..f12c48c --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationParser.java @@ -0,0 +1,170 @@ +/* + * LocationParser.java + * + * Created on July 6, 2008, 12:21 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import org.kxml2.io.*; +import java.io.*; +import javax.microedition.io.*; +import java.util.Vector; + +/** + * + * @author kf6gpe + */ +public class LocationParser { + private Location location; + private boolean setForecast; + private boolean hasForecast; + private boolean setTemp; + private String precipitation, precipType, precipProb; + private String windSpeed, windDirection; + private StringBuffer buffer; + + public LocationParser() { + location = new Location(); + } + + public LocationParser(Location l) { + location = l; + } + + public void parse(ByteArrayInputStream in) { + try { + InputStreamReader reader = new InputStreamReader(in); + KXmlParser parser = new KXmlParser(); + boolean keepParsing = true; + parser.setInput(reader); + while(keepParsing) { + int type = parser.next(); + + switch(type) { + case KXmlParser.START_DOCUMENT: + startDocument(); + break; + case KXmlParser.START_TAG: + startElement(parser); + break; + case KXmlParser.END_TAG: + endElement(parser); + break; + case KXmlParser.TEXT: + characters(parser); + break; + case KXmlParser.END_DOCUMENT: + endDocument(); + keepParsing = false; + break; + } + + } + } + catch(Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + } + + public Location getLocation() { + return location; + } + + public void startDocument() { + if ( location == null ) + location = new Location(); + setForecast = false; + hasForecast = false; + setTemp = false; + } + + public void startElement(KXmlParser parser) + throws Exception { + String qName = parser.getName(); + buffer = new StringBuffer(); + if ( qName.compareTo(Location.XML_TAG_WEATHER) == 0) { + String c = parser.getAttributeValue(null,Location.XML_ATTR_CITY); + String s = parser.getAttributeValue(null,Location.XML_ATTR_STATE); + String co = parser.getAttributeValue(null,Location.XML_ATTR_COUNTRY); + location.setLocation(c,s,co); + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_TEMPS) == 0) { + String u = parser.getAttributeValue(null,Location.XML_ATTR_UNITS); + if ( u != null && u.compareTo("F") != 0) throw new Exception("Invalid temperature units"); + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_TEMP) == 0 ) { + String t = parser.getAttributeValue(null,Location.XML_ATTR_TYPE); + if (t != null && t.compareTo("current") == 0) { + setTemp = true; + } else { + setTemp = false; + } + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_WIND) == 0) { + String u = parser.getAttributeValue(null,Location.XML_ATTR_UNITS); + if ( u != null && u.compareTo("MPH") != 0) + throw new Exception("Invalid temperature units"); + hasForecast = false; + } + if ( qName.compareTo(Location.XML_TAG_PRECIP) == 0 ) + { + String u = parser.getAttributeValue(null,Location.XML_ATTR_UNITS); + if (u != null && u.compareTo("in") != 0) + throw new Exception("Invalid precipitation units"); + precipProb = parser.getAttributeValue(null,Location.XML_ATTR_PROB); + precipType = parser.getAttributeValue(null,Location.XML_ATTR_TYPE); + hasForecast = false; + } + if (qName.compareTo(Location.XML_TAG_TEXT) == 0) { + hasForecast = true; + } + if (qName.compareTo(Location.XML_TAG_WHEN) == 0 && hasForecast) { + String w = parser.getAttributeValue(null,Location.XML_ATTR_TIME); + if (w != null && w.compareTo("now") == 0) { + setForecast = true; + } else { + setForecast = false; + } + } + } + + public void characters(KXmlParser parser) { + if (buffer != null) + buffer.append(parser.getText()); + } + + public void endElement(KXmlParser parser) { + String qName = parser.getName(); + if (qName.compareTo(Location.XML_TAG_SPEED) == 0) { + windSpeed = buffer.toString(); + } + if (qName.compareTo(Location.XML_TAG_DIRECTION) == 0) { + windDirection = buffer.toString(); + } + if (qName.compareTo(Location.XML_TAG_WIND) == 0) { + location.setWind(windSpeed, windDirection); + } + if (qName.compareTo(Location.XML_TAG_PRECIP) == 0) { + precipitation = buffer.toString(); + location.setPrecipitation(precipitation,precipProb,precipType); + } + if (qName.compareTo(Location.XML_TAG_TEMP) == 0 && setTemp ) + { + location.setTemperature(buffer.toString()); + } + if (qName.compareTo(Location.XML_TAG_WHEN) == 0 && setForecast) { + location.setForecast( buffer.toString()); + } + } + + public void endDocument() { + } +} diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java new file mode 100644 index 0000000..8c6a34f --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/LocationStore.java @@ -0,0 +1,132 @@ +/* + * LocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; + +/** + * + * @author kf6gpe + */ +public class LocationStore { + private static final String storeName = "wx"; + private RecordStore store = null; + + public LocationStore() { + } + + private void openStore() throws RecordStoreException { + if (store == null) { + store = RecordStore.openRecordStore(storeName, true); + } + } + + private void closeStore() { + if (store != null) { + try { + store.closeRecordStore(); + } catch( Exception ex ) {} + store = null; + } + } + + public void addLocation(Location l) throws RecordStoreException { + Location existing = getLocation(l.getLocation()); + if (existing!=null) { + existing.setForecast(l.getForecast()); + updateLocation(existing); + } else { + byte b[] = l.toBytes(); + openStore(); + l.setId(store.getNextRecordID()); + store.addRecord(b, 0, b.length); + closeStore(); + } + } + + public String[] getLocationStrings() { + String[] result = null; + try { + openStore(); + result = new String[store.getNumRecords()]; + RecordEnumeration e = store.enumerateRecords( + null, // No filter + new RecordComparator () { + public int compare( byte[] b1, byte[] b2 ) { + Location r1 = new Location(b1); + Location r2 = new Location(b2); + if (r1.getLocation().compareTo(r2.getLocation()) == 0) { + return RecordComparator.EQUIVALENT; + } else if (r1.getLocation().compareTo(r2.getLocation()) < 0) { + return RecordComparator.PRECEDES; + } else { + return RecordComparator.FOLLOWS; + } + } + }, + false); + int i; + + for (i=0; i=0x30 && b<=0x39) || + (b>=0x41 && b<=0x5A) || + (b>=0x61 && b<=0x7A)) { + tmp.append((char)b); + } else { + tmp.append("%"); + if (b <= 0xf) tmp.append("0"); + tmp.append(Integer.toHexString(b)); + } + } + } + catch (Exception e) {} + return tmp.toString(); + } + return null; + } + + private String requestEncode() { + StringBuffer result = new StringBuffer(); + result.append(url); + result.append(urlEncode(location.getLocation())); + return result.toString(); + } + + public void run() { + String requestUrl; + String response = ""; + HttpConnection hc = null; + InputStream in = null; + + requestUrl = requestEncode(); + + try { + hc = (HttpConnection)Connector.open(requestUrl); + hc.setRequestMethod(HttpConnection.GET); + in=hc.openInputStream(); + int length=(int)hc.getLength(); + byte[] data = new byte[length]; + in.read(data); + response = new String(data); + } + catch(Exception e){} + finally { + try { + if (in!=null) hc.close(); + if (hc!=null) hc.close(); + } + catch(Exception e) {} + } + if (!cancelled) { + System.out.println(response); + location.fromXml(response); + System.out.print(location.toXml()); + app.update(); + } + } +} \ No newline at end of file diff --git a/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java new file mode 100644 index 0000000..f87ef64 --- /dev/null +++ b/Sample Code/chapter13/code/kXML/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherWidget.java @@ -0,0 +1,270 @@ +/* + * WeatherWidget.java + * + * Created on March 1, 2008, 10:08 AM + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.midlet.*; +import javax.microedition.lcdui.*; +import java.util.*; + +/** + * + * @author kf6gpe + * @version + */ +public class WeatherWidget extends MIDlet implements CommandListener { + private Form wxForm; + private StringItem locationItem; + private StringItem wxItem; + private Command exitCommand; + private Command screenCommand; + private Command settingCommand; + private Command okCommand; + private Command backCommand; + private Command updateCommand; + private List locationList; + private TextBox locationTextBox; + private Alert cannotAddLocationAlert; + private WeatherFetcher fetcher; + private Location location; + private LocationStore locationStore; + + /** This method initializes UI of the application. + */ + private void initialize() { + locationStore = new LocationStore(); + String[] locations = locationStore.getLocationStrings(); + try { + if (locations.length > 0 ) location = locationStore.getLocation(locations[0]); + } + catch(Exception e){} + fetcher = new WeatherFetcher(location, this); + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void update() { + get_wxItem().setText(get_forecast()); + try + { + locationStore.updateLocation(location); + } + catch(Exception e){} + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + fetcher.cancel(); + fetcher = new WeatherFetcher(location, this); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == cannotAddLocationAlert) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_forecast() { + if (location == null) { + return "unknown forecast"; + } else { + return location.getForecast(); + } + } + + + public String get_location() { + if (location == null) { + return "unknown"; + } else { + return location.getLocation(); + } + } + + public void set_location( String l ) { + try { + location = locationStore.getLocation(l); + } + catch(Exception e) {e.printStackTrace();} + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + String locations[]; + int i; + try { + locationStore.addLocation( new Location( l )); + } catch (Exception e) { + getDisplay().setCurrent(get_cannotAddLocationAlert()); + } + // Refresh the location list lazily. + locationList = null; + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", get_forecast()); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + } + return wxForm; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = locationStore.getLocationStrings(); + + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + public Alert get_cannotAddLocationAlert() { + if (cannotAddLocationAlert == null) + { + cannotAddLocationAlert = new Alert("Cannot Add Location"); + cannotAddLocationAlert.setString("An error occurred adding the location you entered. It has not been added."); + cannotAddLocationAlert.addCommand(get_backCommand()); + } + return cannotAddLocationAlert; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } +} diff --git a/Sample Code/chapter14/code/MMSMIDlet/build.xml b/Sample Code/chapter14/code/MMSMIDlet/build.xml new file mode 100644 index 0000000..d3ddddc --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/build.xml @@ -0,0 +1,83 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter14/code/MMSMIDlet/nbproject/build-impl.xml b/Sample Code/chapter14/code/MMSMIDlet/nbproject/build-impl.xml new file mode 100644 index 0000000..29ac5c7 --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/nbproject/build-impl.xml @@ -0,0 +1,1160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-mobility-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set dist.dir + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set preprocessed.dir + + + + + + + + + + + + + + + + + + Must set build.classes.dir + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + Must set obfuscated.classes.dir + + + + Must set obfuscated.classes.dir + Must set obfuscator.srcjar + Must set obfuscator.destjar + + + + + + + + + + + + + + + + + + + + Must set preverify.classes.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + Must set dist.jad + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + Classpath to Ant Contrib library (libs.ant-contrib.classpath property) is not set. + + + + + + + + + Active project configuration: @{cfg} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter14/code/MMSMIDlet/nbproject/genfiles.properties b/Sample Code/chapter14/code/MMSMIDlet/nbproject/genfiles.properties new file mode 100644 index 0000000..66f8152 --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=95b08a5f +build.xml.script.CRC32=aed34282 +build.xml.stylesheet.CRC32=03eab09b +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=95b08a5f +nbproject/build-impl.xml.script.CRC32=9a68685c +nbproject/build-impl.xml.stylesheet.CRC32=6baa93ad diff --git a/Sample Code/chapter14/code/MMSMIDlet/nbproject/private/private.properties b/Sample Code/chapter14/code/MMSMIDlet/nbproject/private/private.properties new file mode 100644 index 0000000..fb2ffad --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/nbproject/private/private.properties @@ -0,0 +1,7 @@ +#Tue Jul 29 12:59:40 PDT 2008 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\6.5m1 +javadoc.preview=true +deployment.counter=3 +config.active= +deployment.number=0.0.2 +app-version.autoincrement=true diff --git a/Sample Code/chapter14/code/MMSMIDlet/nbproject/private/private.xml b/Sample Code/chapter14/code/MMSMIDlet/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter14/code/MMSMIDlet/nbproject/project.properties b/Sample Code/chapter14/code/MMSMIDlet/nbproject/project.properties new file mode 100644 index 0000000..7261d34 --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/nbproject/project.properties @@ -0,0 +1,139 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +all.configurations=\ +application.args= +application.description= +application.description.detail= +application.name= +application.vendor=Vendor +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.instance=default +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=MMSMIDlet.jad +dist.jar=MMSMIDlet.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +extra.classpath= +filter.exclude.tests=false +filter.excludes= +filter.more.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.3 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +main.class= +main.class.class=applet +manifest.apipermissions= +manifest.file=manifest.mf +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: MMSMIDlet,,com.apress.rischpater.MMSMIDlet.MMSMIDlet\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: MMSMIDlet\n +manifest.pushregistry= +name=MMSMIDlet +no.dependencies=false +nokiaS80.application.icon= +nsicom.application.monitorhost= +nsicom.application.runremote= +nsicom.application.runverbose= +nsicom.remoteapp.location=\\My Documents\\NetBeans Applications +nsicom.remotevm.location=\\Windows\\creme\\bin\\CrEme.exe +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.fat.jar=true +platform.profile=MIDP-2.1 +platform.trigger=CLDC +platform.type=UEI-1.0.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +resources.dir=resources +ricoh.application.email= +ricoh.application.fax= +ricoh.application.icon= +ricoh.application.target-jar= +ricoh.application.telephone= +ricoh.application.uid=38906423 +ricoh.application.version= +ricoh.dalp.application-desc.auto-run=false +ricoh.dalp.application-desc.energy-save= +ricoh.dalp.application-desc.exec-auth= +ricoh.dalp.application-desc.visible=true +ricoh.dalp.argument= +ricoh.dalp.codebase= +ricoh.dalp.display-mode.color=true +ricoh.dalp.display-mode.is-4line-support=false +ricoh.dalp.display-mode.is-hvga-support=true +ricoh.dalp.display-mode.is-vga-support=false +ricoh.dalp.display-mode.is-wvga-support=false +ricoh.dalp.information.abbreviation= +ricoh.dalp.information.icon.basepath= +ricoh.dalp.information.icon.location= +ricoh.dalp.information.is-icon-used=true +ricoh.dalp.install.destination=hdd +ricoh.dalp.install.mode.auto=true +ricoh.dalp.install.work-dir=hdd +ricoh.dalp.is-managed=true +ricoh.dalp.resources.dsdk.version=2.0 +ricoh.dalp.resources.jar.basepath= +ricoh.dalp.resources.jar.version= +ricoh.dalp.version= +ricoh.icon.invert=false +ricoh.platform.target.version= +run.cmd.options= +run.jvmargs= +run.method=STANDARD +run.security.domain=manufacturer +run.use.security.domain=false +savaje.application.icon= +savaje.application.icon.focused= +savaje.application.icon.small= +savaje.application.uid=TBD +savaje.bundle.base= +savaje.bundle.debug=false +savaje.bundle.debug.port= +semc.application.caps= +semc.application.icon= +semc.application.icon.count= +semc.application.icon.splash= +semc.application.icon.splash.installonly=false +semc.application.uid=E0750154 +semc.certificate.path= +semc.private.key.password= +semc.private.key.path= +sign.alias= +sign.enabled=false +sign.keystore= +src.dir=src +use.emptyapis=true +use.preprocessor=true diff --git a/Sample Code/chapter14/code/MMSMIDlet/nbproject/project.xml b/Sample Code/chapter14/code/MMSMIDlet/nbproject/project.xml new file mode 100644 index 0000000..f0c35a4 --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + MMSMIDlet + 1.6 + + + diff --git a/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSMIDlet.java b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSMIDlet.java new file mode 100644 index 0000000..7503242 --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSMIDlet.java @@ -0,0 +1,148 @@ +package com.apress.rischpater.MMSMIDlet; + +import javax.microedition.midlet.*; +import javax.microedition.io.*; +import javax.microedition.lcdui.*; +import javax.wireless.messaging.*; +import java.io.IOException; + +public class MMSMIDlet + extends MIDlet + implements CommandListener, Runnable, MessageListener { + private MMSSender sender = null; + private Command exitCommand = new Command("Exit", Command.EXIT, 2); + private Command sendCommand = new Command("Send", Command.SCREEN, 1); + private TextField numberEntry = null; + private static final String FRACTAL_PATH = "/icons/fractal.png"; + private ImageItem imageItem = null; + private Form form = null; + private boolean endNow = false; + private MessageConnection c = null; + private final String appId = "MMSMIDlet"; + protected int msgAvail = 0; + private final Integer monitor = new Integer(0); + + public MMSMIDlet() { + sender = MMSSender.getInstance(); + } + + public void commandAction(javax.microedition.lcdui.Command c, + javax.microedition.lcdui.Displayable d) { + if (c == exitCommand) { + if (!sender.isSending()) { + destroyApp(true); + notifyDestroyed(); + } + } else if (c == sendCommand) { + String dest = numberEntry.getString(); + if (dest.length() > 0) + sender.sendMsg(dest, appId, "A fractal!", FRACTAL_PATH ); + } + } + + protected void destroyApp(boolean param) { + try { + endNow = true; + c.close(); + } catch (IOException ex) {} + } + + protected void pauseApp() { + endNow = true; + try { + c.setMessageListener(null); + c.close(); + } catch (IOException ex) {} + } + + protected void startApp() { + if (form == null) { + form = new Form("MMSMIDlet"); + numberEntry = new TextField("Connect to:", + null, 256, + TextField.PHONENUMBER); + imageItem = new ImageItem(null,null, + ImageItem.LAYOUT_DEFAULT,null); + + form.append(numberEntry); + form.append(imageItem); + + form.addCommand(exitCommand); + form.addCommand(sendCommand); + form.setCommandListener(this); + } + Display.getDisplay(this).setCurrent(form); + startReceive(); + } + + private void startReceive() { + Thread t; + try { + c = (MessageConnection) Connector.open("mms://:" + appId); + c.setMessageListener(this); + } catch (Exception e) {} + if (c != null) { + t = new Thread(this); + t.start(); + } + } + + public void run() { + Message msg = null; + endNow = false; + msgAvail = 0; + + while (!endNow) { + synchronized(monitor) { + if (msgAvail <= 0) + try { + monitor.wait(); + } catch (InterruptedException e) {} + msgAvail--; + } + try { + msg = c.receive(); + if (msg instanceof MultipartMessage) { + MultipartMessage mpm = (MultipartMessage)msg; + MessagePart[] parts = mpm.getMessageParts(); + if (parts != null) { + for (int i = 0; i < parts.length; i++) { + MessagePart mp = parts[i]; + String type = mp.getMIMEType(); + byte[] ba = mp.getContent(); + if (type.equals("image/png")) { + Image image = + Image.createImage(ba, 0, ba.length); + Display.getDisplay(this).callSerially( + new SetImage(image)); + } + } + } + } + } catch (Exception e) {} + } + } + + private void getMessage() { + synchronized(monitor) { + msgAvail++; + monitor.notify(); + } + } + + public void notifyIncomingMessage(MessageConnection msgConn) { + if (msgConn != null) { + getMessage(); + } + } + + class SetImage implements Runnable { + private Image img = null; + public SetImage(Image i) { + img = i; + } + public void run() { + imageItem.setImage(img); + } + } +} diff --git a/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSMIDlet.result b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSMIDlet.result new file mode 100644 index 0000000..e6ea41e --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSMIDlet.result @@ -0,0 +1,150 @@ +package com.apress.rischpater.MMSMIDlet; + +import javax.microedition.midlet.*; +import javax.microedition.io.*; +import javax.microedition.lcdui.*; +import javax.wireless.messaging.*; +import java.io.IOException; + +public class MMSMIDlet + extends MIDlet + implements CommandListener, Runnable, MessageListener { + private MMSSender sender = null; + private Command exitCommand = new Command("Exit", Command.EXIT, 2); + private Command sendCommand = new Command("Send", Command.SCREEN, 1); + + private TextField numberEntry = null; + private static final String FRACTAL_PATH = "/icons/fractal.png"; + private ImageItem imageItem = null; + private Form form = null; + private boolean endNow = false; + private MessageConnection c = null; + private final String appId = "MMSMIDlet"; + protected int msgAvail = 0; + private final Integer monitor = new Integer(0); + + public MMSMIDlet() { + sender = MMSSender.getInstance(); + } + + public void commandAction(javax.microedition.lcdui.Command c, + javax.microedition.lcdui.Displayable d) { + if (c == exitCommand) { + if (!sender.isSending()) { + destroyApp(true); + notifyDestroyed(); + } + } else if (c == sendCommand) { + String dest = numberEntry.getString(); + if (dest.length() > 0) + sender.sendMsg(dest, appId, "A fractal!", FRACTAL_PATH~CCC + ); + } + } + + protected void destroyApp(boolean param) { + try { + endNow = true; + c.close(); + } catch (IOException ex) {} + } + + protected void pauseApp() { + endNow = true; + try { + c.setMessageListener(null); + c.close(); + } catch (IOException ex) {} + } + + protected void startApp() { + if (form == null) { + form = new Form("MMSMIDlet"); + numberEntry = new TextField("Connect to:", + null, 256, + TextField.PHONENUMBER); + imageItem = new ImageItem(null,null, + ImageItem.LAYOUT_DEFAULT,null); + + form.append(numberEntry); + form.append(imageItem); + + form.addCommand(exitCommand); + form.addCommand(sendCommand); + form.setCommandListener(this); + } + Display.getDisplay(this).setCurrent(form); + startReceive(); + } + + private void startReceive() { + Thread t; + try { + c = (MessageConnection) Connector.open("mms://:" + appId); + c.setMessageListener(this); + } catch (Exception e) {} + if (c != null) { + t = new Thread(this); + t.start(); + } + } + + public void run() { + Message msg = null; + endNow = false; + msgAvail = 0; + + while (!endNow) { + synchronized(monitor) { + if (msgAvail <= 0) + try { + monitor.wait(); + } catch (InterruptedException e) {} + msgAvail--; + } + try { + msg = c.receive(); + if (msg instanceof MultipartMessage) { + MultipartMessage mpm = (MultipartMessage)msg; + MessagePart[] parts = mpm.getMessageParts(); + if (parts != null) { + for (int i = 0; i < parts.length; i++) { + MessagePart mp = parts[i]; + String type = mp.getMIMEType(); + byte[] ba = mp.getContent(); + if (type.equals("image/png")) { + Image image = + Image.createImage(ba, 0, ba.length); + Display.getDisplay(this).callSerially( + new SetImage(image)); + } + } + } + } + } catch (Exception e) {} + } + } + + private void getMessage() { + synchronized(monitor) { + msgAvail++; + monitor.notify(); + } + } + + public void notifyIncomingMessage(MessageConnection c) { + if (c != null) { + getMessage(); + } + } + + class SetImage implements Runnable { + private Image img = null; + public SetImage(Image i) { + img = i; + } + public void run() { + imageItem.setImage(img); + } + } +} diff --git a/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSSender.java b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSSender.java new file mode 100644 index 0000000..cc36dcb --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSSender.java @@ -0,0 +1,86 @@ +package com.apress.rischpater.MMSMIDlet; + +import javax.microedition.io.*; +import javax.wireless.messaging.*; +import java.io.*; +public class MMSSender implements Runnable { + private static MMSSender me = new MMSSender(); + private MMSSender() { + } + + public static MMSSender getInstance() { + return me; + } + + private String receiver = null; + private String appId = null; + private String image = null; + private String msg = null; + private String encoding = null; + private boolean sending = false; + + public void sendMsg(String r, String id, String m, String i) { + if (sending) return; + receiver = r; + appId = id; + msg = m; + image = i; + encoding = System.getProperty("microedition.encoding"); + Thread t = new Thread(this); + t.start(); + } + + public boolean isSending() { + return sending; + } + + public void run() { + sending = true; + try { + sendMMS(); + } catch (Exception e) { + System.out.println("run caught: "); + e.printStackTrace(); + } + sending = false; + } + + public void sendMMS() { + String address = "mms://" + receiver + ":" + appId; + System.out.println(address); + MessageConnection c = null; + try { + c = (MessageConnection) Connector.open(address); + MultipartMessage mpm = (MultipartMessage) c.newMessage( + MessageConnection.MULTIPART_MESSAGE); + mpm.setSubject("MMSMIDlet Image"); + if (image!=null) { + InputStream is = getClass().getResourceAsStream(image); + byte[] bImage = new byte[is.available()]; + is.read(bImage); + mpm.addMessagePart( + new MessagePart(bImage, 0, bImage.length, + "image/png", "id1", null, null)); + } + if (msg!=null) { + byte[] bMsg = msg.getBytes(); + mpm.addMessagePart( + new MessagePart(bMsg, 0, bMsg.length, + "text/plain", "txt1", null, encoding)); + } + c.send(mpm); + } catch (Exception e) { + System.out.println("Send caught: "); + e.printStackTrace(); + } finally { + if (c != null) { + try { + c.close(); + } catch (IOException e) { + System.out.println("Closing connection caught: "); + e.printStackTrace(); + } + } + } + } +} diff --git a/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSSender.result b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSSender.result new file mode 100644 index 0000000..cbb7ffb --- /dev/null +++ b/Sample Code/chapter14/code/MMSMIDlet/src/com/apress/rischpater/MMSMIDlet/MMSSender.result @@ -0,0 +1,86 @@ +package com.apress.rischpater.MMSMIDlet; + +import javax.microedition.io.*; +import javax.wireless.messaging.*; +import java.io.*; +public class MMSSender implements Runnable { + private static MMSSender me = new MMSSender(); + private MMSSender() { + } + + public static MMSSender getInstance() { + return me; + } + + private String receiver = null; + private String appId = null; + private String image = null; + private String msg = null; + private String encoding = null; + private boolean sending = false; + + public void sendMsg(String r, String id, String m, String i) { + if (sending) return; + receiver = r; + appId = id; + msg = m; + image = i; + encoding = System.getProperty("microedition.encoding"); + Thread t = new Thread(this); + t.start(); + } + + public boolean isSending() { + return sending; + } + + public void run() { + sending = true; + try { + sendMMS(); + } catch (Exception e) { + System.out.println("run caught: "); + e.printStackTrace(); + } + sending = false; + } + + private void sendMMS() { + String address = "mms://" + receiver + ":" + appId; + System.out.println(address); + MessageConnection c = null; + try { + c = (MessageConnection) Connector.open(address); + MultipartMessage mpm = (MultipartMessage) c.newMessage( + MessageConnection.MULTIPART_MESSAGE); + mpm.setSubject("MMSMIDlet Image"); + if (image!=null) { + InputStream is = getClass().getResourceAsStream(image); + byte[] bImage = new byte[is.available()]; + is.read(bImage); + mpm.addMessagePart( + new MessagePart(bImage, 0, bImage.length, + "image/png", "id1", null, null)); + } + if (msg!=null) { + byte[] bMsg = msg.getBytes(); + mpm.addMessagePart( + new MessagePart(bMsg, 0, bMsg.length, + "text/plain", "txt1", null, encoding)); + } + c.send(mpm); + } catch (Exception e) { + System.out.println("Send caught: "); + e.printStackTrace(); + } finally { + if (c != null) { + try { + c.close(); + } catch (IOException e) { + System.out.println("Closing connection caught: "); + e.printStackTrace(); + } + } + } + } +} diff --git a/Sample Code/chapter14/code/MMSMIDlet/src/icons/fractal.png b/Sample Code/chapter14/code/MMSMIDlet/src/icons/fractal.png new file mode 100644 index 0000000..23833b6 Binary files /dev/null and b/Sample Code/chapter14/code/MMSMIDlet/src/icons/fractal.png differ diff --git a/Sample Code/chapter14/code/SMSMIDlet/build.xml b/Sample Code/chapter14/code/SMSMIDlet/build.xml new file mode 100644 index 0000000..86cb69b --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/build.xml @@ -0,0 +1,83 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter14/code/SMSMIDlet/nbproject/build-impl.xml b/Sample Code/chapter14/code/SMSMIDlet/nbproject/build-impl.xml new file mode 100644 index 0000000..22f46a3 --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/nbproject/build-impl.xml @@ -0,0 +1,1160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-mobility-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set dist.dir + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set preprocessed.dir + + + + + + + + + + + + + + + + + + Must set build.classes.dir + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + Must set obfuscated.classes.dir + + + + Must set obfuscated.classes.dir + Must set obfuscator.srcjar + Must set obfuscator.destjar + + + + + + + + + + + + + + + + + + + + Must set preverify.classes.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + Must set dist.jad + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + Classpath to Ant Contrib library (libs.ant-contrib.classpath property) is not set. + + + + + + + + + Active project configuration: @{cfg} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter14/code/SMSMIDlet/nbproject/genfiles.properties b/Sample Code/chapter14/code/SMSMIDlet/nbproject/genfiles.properties new file mode 100644 index 0000000..66f8152 --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=95b08a5f +build.xml.script.CRC32=aed34282 +build.xml.stylesheet.CRC32=03eab09b +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=95b08a5f +nbproject/build-impl.xml.script.CRC32=9a68685c +nbproject/build-impl.xml.stylesheet.CRC32=6baa93ad diff --git a/Sample Code/chapter14/code/SMSMIDlet/nbproject/private/private.properties b/Sample Code/chapter14/code/SMSMIDlet/nbproject/private/private.properties new file mode 100644 index 0000000..fb2ffad --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/nbproject/private/private.properties @@ -0,0 +1,7 @@ +#Tue Jul 29 12:59:40 PDT 2008 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\6.5m1 +javadoc.preview=true +deployment.counter=3 +config.active= +deployment.number=0.0.2 +app-version.autoincrement=true diff --git a/Sample Code/chapter14/code/SMSMIDlet/nbproject/private/private.xml b/Sample Code/chapter14/code/SMSMIDlet/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter14/code/SMSMIDlet/nbproject/project.properties b/Sample Code/chapter14/code/SMSMIDlet/nbproject/project.properties new file mode 100644 index 0000000..6aa5919 --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/nbproject/project.properties @@ -0,0 +1,139 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +all.configurations=\ +application.args= +application.description= +application.description.detail= +application.name= +application.vendor=Vendor +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.instance=default +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=SMSMIDlet.jad +dist.jar=SMSMIDlet.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +extra.classpath= +filter.exclude.tests=false +filter.excludes= +filter.more.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.3 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +main.class= +main.class.class=applet +manifest.apipermissions= +manifest.file=manifest.mf +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: SMSMIDlet,,com.apress.rischpater.SMSMIDlet.SMSMIDlet\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: SMSMIDlet\n +manifest.pushregistry= +name=SMSMIDlet +no.dependencies=false +nokiaS80.application.icon= +nsicom.application.monitorhost= +nsicom.application.runremote= +nsicom.application.runverbose= +nsicom.remoteapp.location=\\My Documents\\NetBeans Applications +nsicom.remotevm.location=\\Windows\\creme\\bin\\CrEme.exe +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.fat.jar=true +platform.profile=MIDP-2.1 +platform.trigger=CLDC +platform.type=UEI-1.0.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +resources.dir=resources +ricoh.application.email= +ricoh.application.fax= +ricoh.application.icon= +ricoh.application.target-jar= +ricoh.application.telephone= +ricoh.application.uid=38906423 +ricoh.application.version= +ricoh.dalp.application-desc.auto-run=false +ricoh.dalp.application-desc.energy-save= +ricoh.dalp.application-desc.exec-auth= +ricoh.dalp.application-desc.visible=true +ricoh.dalp.argument= +ricoh.dalp.codebase= +ricoh.dalp.display-mode.color=true +ricoh.dalp.display-mode.is-4line-support=false +ricoh.dalp.display-mode.is-hvga-support=true +ricoh.dalp.display-mode.is-vga-support=false +ricoh.dalp.display-mode.is-wvga-support=false +ricoh.dalp.information.abbreviation= +ricoh.dalp.information.icon.basepath= +ricoh.dalp.information.icon.location= +ricoh.dalp.information.is-icon-used=true +ricoh.dalp.install.destination=hdd +ricoh.dalp.install.mode.auto=true +ricoh.dalp.install.work-dir=hdd +ricoh.dalp.is-managed=true +ricoh.dalp.resources.dsdk.version=2.0 +ricoh.dalp.resources.jar.basepath= +ricoh.dalp.resources.jar.version= +ricoh.dalp.version= +ricoh.icon.invert=false +ricoh.platform.target.version= +run.cmd.options= +run.jvmargs= +run.method=STANDARD +run.security.domain=manufacturer +run.use.security.domain=false +savaje.application.icon= +savaje.application.icon.focused= +savaje.application.icon.small= +savaje.application.uid=TBD +savaje.bundle.base= +savaje.bundle.debug=false +savaje.bundle.debug.port= +semc.application.caps= +semc.application.icon= +semc.application.icon.count= +semc.application.icon.splash= +semc.application.icon.splash.installonly=false +semc.application.uid=E0750154 +semc.certificate.path= +semc.private.key.password= +semc.private.key.path= +sign.alias= +sign.enabled=false +sign.keystore= +src.dir=src +use.emptyapis=true +use.preprocessor=true diff --git a/Sample Code/chapter14/code/SMSMIDlet/nbproject/project.xml b/Sample Code/chapter14/code/SMSMIDlet/nbproject/project.xml new file mode 100644 index 0000000..cc7e27b --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + SMSMIDlet + 1.6 + + + diff --git a/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSMIDlet.java b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSMIDlet.java new file mode 100644 index 0000000..7694d59 --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSMIDlet.java @@ -0,0 +1,114 @@ +package com.apress.rischpater.SMSMIDlet; + +import javax.microedition.midlet.*; +import javax.microedition.io.*; +import javax.microedition.lcdui.*; +import javax.wireless.messaging.*; +import java.io.IOException; + +public class SMSMIDlet + extends MIDlet + implements CommandListener, MessageListener, Runnable { + private SMSSender sender = null; + private Command exitCommand = new Command("Exit", Command.EXIT, 2); + private Command sendCommand = new Command("Send", Command.SCREEN, 1); + private Display display = null; + private String port = "1234"; + private TextField numberEntry= null; + private TextField msgEntry = null; + private Form form = null; + private String senderAddress = null; + private boolean endNow = false; + private MessageConnection c = null; + String msgReceived = null; + + + public SMSMIDlet() { + sender = SMSSender.getInstance(); + } + + public void commandAction(javax.microedition.lcdui.Command c, + javax.microedition.lcdui.Displayable d) { + if (c == exitCommand) { + if (!sender.isSending()) { + destroyApp(true); + notifyDestroyed(); + } + } else if (c == sendCommand) { + String dest = numberEntry.getString(); + String msg = msgEntry.getString(); + if (dest.length() > 0) + sender.sendMsg(dest, port, msg ); + } + } + + protected void destroyApp(boolean param) { + try { + endNow = true; + c.close(); + } catch (IOException ex) { + System.out.println("destroyApp caught: "); + ex.printStackTrace(); + } + } + + protected void pauseApp() { + try { + endNow = true; + c.close(); + } catch (IOException ex) {} + } + + protected void startApp() { + if (form == null) { + form = new Form("SMSMIDlet"); + numberEntry = new TextField("Connect to:", + null, 256, + TextField.PHONENUMBER); + msgEntry = new TextField("Message:", + null, 160, + TextField.ANY); + form.append(numberEntry); + form.append(msgEntry); + + form.addCommand(exitCommand); + form.addCommand(sendCommand); + form.setCommandListener(this); + } + Display.getDisplay(this).setCurrent(form); + startReceive(); + } + + private void startReceive() { + Thread t; + t = new Thread(this); + t.start(); + } + + public void run() { + Message msg = null; + c = null; + endNow = false; + + /** Check for sms connection. */ + try { + c = (MessageConnection) Connector.open("sms://:" + port); + msg = c.receive(); + while ((msg != null) && (!endNow)) { + if (msg instanceof TextMessage) { + msgReceived = ((TextMessage)msg).getPayloadText(); + Display.getDisplay(this).callSerially(new SetMessage()); + } + msg = c.receive(); + } + } catch (IOException e) { + // Normal exit when connection is closed + } + } + + class SetMessage implements Runnable { + public void run() { + msgEntry.setString( msgReceived ); + } + } +} diff --git a/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSMIDlet.result b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSMIDlet.result new file mode 100644 index 0000000..76c2865 --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSMIDlet.result @@ -0,0 +1,105 @@ +package com.apress.rischpater.SMSMIDlet; + +import javax.microedition.midlet.*; +import javax.microedition.io.*; +import javax.microedition.lcdui.*; +import javax.wireless.messaging.*; +import java.io.IOException; + +public class SMSMIDlet + extends MIDlet + implements CommandListener, MessageListener, Runnable { + private SMSSender sender = null; + private Command exitCommand = new Command("Exit", Command.EXIT, 2); + private Command sendCommand = new Command("Send", Command.SCREEN, 1); + + private String port = "1234"; + private TextField numberEntry= null; + private TextField msgEntry = null; + private Form form = null; + private String senderAddress = null; + private boolean endNow = false; + private MessageConnection c = null; + String msgReceived = null; + + + public SMSMIDlet() { + sender = SMSSender.getInstance(); + } + + public void commandAction(javax.microedition.lcdui.Command c, + javax.microedition.lcdui.Displayable d) { + if (c == exitCommand) { + if (!sender.isSending()) { + destroyApp(true); + notifyDestroyed(); + } + } else if (c == sendCommand) { + String dest = numberEntry.getString(); + String msg = msgEntry.getString(); + if (dest.length() > 0) + sender.sendMsg(dest, port, msg); + } + } + + protected void destroyApp(boolean param) { + try { + endNow = true; + c.close(); + } catch (IOException ex) {} + } + + protected void pauseApp() { + } + + protected void startApp() { + if (form == null) { + form = new Form("SMSMIDlet"); + numberEntry = new TextField("Connect to:", + null, 256, + TextField.PHONENUMBER); + msgEntry = new TextField("Message:", + null, 160, + TextField.ANY); + form.append(numberEntry); + form.append(msgEntry); + + form.addCommand(exitCommand); + form.addCommand(sendCommand); + form.setCommandListener(this); + } + Display.getDisplay(this).setCurrent(form); + startReceive(); + } + + private void startReceive() { + Thread t; + t = new Thread(this); + t.start(); + } + + public void run() { + Message msg = null; + c = null; + endNow = false; + + /** Check for sms connection. */ + try { + c = (MessageConnection) Connector.open("sms://:" + port); + msg = c.receive(); + while ((msg != null) && (!endNow)) { + if (msg instanceof TextMessage) { + msgReceived = ((TextMessage)msg).getPayloadText(); + Display.getDisplay(this).callSerially(new SetMessage()); + } + msg = c.receive(); + } + } catch (IOException e) {} + } + + class SetMessage implements Runnable { + public void run() { + msgEntry.setString(msgReceived); + } + } +} diff --git a/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSSender.java b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSSender.java new file mode 100644 index 0000000..e67b223 --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSSender.java @@ -0,0 +1,61 @@ +package com.apress.rischpater.SMSMIDlet; + +import javax.microedition.io.*; +import javax.wireless.messaging.*; +import java.io.IOException; + +public class SMSSender implements Runnable { + private static SMSSender me = new SMSSender(); + private String receiver = null; + private String port = null; + private String msgString = null; + private boolean sending = false; + + private SMSSender() { + } + + public static SMSSender getInstance() { + return me; + } + + public boolean isSending() { + return sending; + } + + public void sendMsg(String rcvr, String p, String msgText) { + if (sending) return; + receiver = rcvr; + port = p; + msgString = msgText; + Thread th = new Thread(this); + th.start(); + } + + public void run() { + String address = "sms://" + receiver + ":" + port; + sending = true; + MessageConnection conn = null; + try { + /** Open the message connection. */ + conn = (MessageConnection) Connector.open(address); + TextMessage txtmessage = (TextMessage) conn.newMessage( + MessageConnection.TEXT_MESSAGE); + txtmessage.setAddress(address); + txtmessage.setPayloadText(msgString); + conn.send(txtmessage); + } catch (Throwable t) { + System.out.println("Send caught: "); + t.printStackTrace(); + } + + if (conn != null) { + try { + conn.close(); + } catch (IOException ioe) { + System.out.println("Closing connection caught: "); + ioe.printStackTrace(); + } + } + sending = false; + } +} diff --git a/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSSender.result b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSSender.result new file mode 100644 index 0000000..a87457a --- /dev/null +++ b/Sample Code/chapter14/code/SMSMIDlet/src/com/apress/rischpater/SMSMIDlet/SMSSender.result @@ -0,0 +1,54 @@ +package com.apress.rischpater.SMSMIDlet; + +import javax.microedition.io.*; +import javax.wireless.messaging.*; +import java.io.IOException; + +public class SMSSender implements Runnable { + private static SMSSender me = new SMSSender(); + private String receiver = null; + private String port = null; + private String msgString = null; + private boolean sending = false; + + private SMSSender() { + } + + public static SMSSender getInstance() { + return me; + } + + public boolean isSending() { + return sending; + } + + public void sendMsg(String rcvr, String p, String msgText) { + if (sending) return; + receiver = rcvr; + port = p; + msgString = msgText; + Thread t = new Thread(this); + t.start(); + } + + public void run() { + String address = "sms://" + receiver + ":" + port; + sending = true; + MessageConnection c = null; + try { + c = (MessageConnection) Connector.open(address); + TextMessage txtmessage = (TextMessage) c.newMessage( + MessageConnection.TEXT_MESSAGE); + txtmessage.setAddress(address); + txtmessage.setPayloadText(msgString); + c.send(txtmessage); + } catch (Exception e) {} + + if (c != null) { + try { + c.close(); + } catch (IOException ioe) {} + } + sending = false; + } +} diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/build.xml b/Sample Code/chapter16/code/MultimediaMIDlet/build.xml new file mode 100644 index 0000000..2e97d74 --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/build.xml @@ -0,0 +1,83 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/build-impl.xml b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/build-impl.xml new file mode 100644 index 0000000..b73e76b --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/build-impl.xml @@ -0,0 +1,1160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-mobility-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set dist.dir + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set preprocessed.dir + + + + + + + + + + + + + + + + + + Must set build.classes.dir + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + Must set obfuscated.classes.dir + + + + Must set obfuscated.classes.dir + Must set obfuscator.srcjar + Must set obfuscator.destjar + + + + + + + + + + + + + + + + + + + + Must set preverify.classes.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + Must set dist.jad + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + Classpath to Ant Contrib library (libs.ant-contrib.classpath property) is not set. + + + + + + + + + Active project configuration: @{cfg} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/genfiles.properties b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/genfiles.properties new file mode 100644 index 0000000..c681289 --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=9ff20662 +build.xml.script.CRC32=a8e44233 +build.xml.stylesheet.CRC32=03eab09b +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=9ff20662 +nbproject/build-impl.xml.script.CRC32=b4d5cd9b +nbproject/build-impl.xml.stylesheet.CRC32=6baa93ad diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/private/private.properties b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/private/private.properties new file mode 100644 index 0000000..76504d7 --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/private/private.properties @@ -0,0 +1,7 @@ +#Sun Aug 17 14:25:22 PDT 2008 +netbeans.user=C\:\\Documents and Settings\\kf6gpe\\.netbeans\\6.5m1 +javadoc.preview=true +config.active= +deployment.counter=10 +app-version.autoincrement=true +deployment.number=0.0.9 diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/private/private.xml b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/project.properties b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/project.properties new file mode 100644 index 0000000..a5c3303 --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/project.properties @@ -0,0 +1,140 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +all.configurations=\ +application.args= +application.description= +application.description.detail= +application.name= +application.vendor=Vendor +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +debug.level=debug +deployment.copy.target=deploy +deployment.instance=default +deployment.jarurl=${dist.jar} +deployment.method=NONE +deployment.override.jarurl=false +dist.dir=dist/${config.active} +dist.jad=MultimediaMIDlet.jad +dist.jar=MultimediaMIDlet.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +extra.classpath= +file.reference.builtin.ks=${netbeans.user}/config/j2me/builtin.ks +filter.exclude.tests=false +filter.excludes= +filter.more.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.3 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath= +main.class= +main.class.class=applet +manifest.apipermissions= +manifest.file=manifest.mf +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: MultimediaMIDlet,,com.apress.rischpater.multimediamidlet.MultimediaMIDlet\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: MultimediaMIDlet\n +manifest.pushregistry= +name=SMSMIDlet +no.dependencies=false +nokiaS80.application.icon= +nsicom.application.monitorhost= +nsicom.application.runremote= +nsicom.application.runverbose= +nsicom.remoteapp.location=\\My Documents\\NetBeans Applications +nsicom.remotevm.location=\\Windows\\creme\\bin\\CrEme.exe +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_2_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.2 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.fat.jar=true +platform.profile=MIDP-2.1 +platform.trigger=CLDC +platform.type=UEI-1.0.1 +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +resources.dir=resources +ricoh.application.email= +ricoh.application.fax= +ricoh.application.icon= +ricoh.application.target-jar= +ricoh.application.telephone= +ricoh.application.uid=38906423 +ricoh.application.version= +ricoh.dalp.application-desc.auto-run=false +ricoh.dalp.application-desc.energy-save= +ricoh.dalp.application-desc.exec-auth= +ricoh.dalp.application-desc.visible=true +ricoh.dalp.argument= +ricoh.dalp.codebase= +ricoh.dalp.display-mode.color=true +ricoh.dalp.display-mode.is-4line-support=false +ricoh.dalp.display-mode.is-hvga-support=true +ricoh.dalp.display-mode.is-vga-support=false +ricoh.dalp.display-mode.is-wvga-support=false +ricoh.dalp.information.abbreviation= +ricoh.dalp.information.icon.basepath= +ricoh.dalp.information.icon.location= +ricoh.dalp.information.is-icon-used=true +ricoh.dalp.install.destination=hdd +ricoh.dalp.install.mode.auto=true +ricoh.dalp.install.work-dir=hdd +ricoh.dalp.is-managed=true +ricoh.dalp.resources.dsdk.version=2.0 +ricoh.dalp.resources.jar.basepath= +ricoh.dalp.resources.jar.version= +ricoh.dalp.version= +ricoh.icon.invert=false +ricoh.platform.target.version= +run.cmd.options= +run.jvmargs= +run.method=STANDARD +run.security.domain=manufacturer +run.use.security.domain=false +savaje.application.icon= +savaje.application.icon.focused= +savaje.application.icon.small= +savaje.application.uid=TBD +savaje.bundle.base= +savaje.bundle.debug=false +savaje.bundle.debug.port= +semc.application.caps= +semc.application.icon= +semc.application.icon.count= +semc.application.icon.splash= +semc.application.icon.splash.installonly=false +semc.application.uid=E0750154 +semc.certificate.path= +semc.private.key.password= +semc.private.key.path= +sign.alias=minimal +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true +use.preprocessor=true diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/project.xml b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/project.xml new file mode 100644 index 0000000..49b0d13 --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + MultimediaMIDlet + 1.6 + + + diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/src/com/apress/rischpater/MultimediaMIDlet/MultimediaMIDlet.java b/Sample Code/chapter16/code/MultimediaMIDlet/src/com/apress/rischpater/MultimediaMIDlet/MultimediaMIDlet.java new file mode 100644 index 0000000..0d922d8 --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/src/com/apress/rischpater/MultimediaMIDlet/MultimediaMIDlet.java @@ -0,0 +1,228 @@ +package com.apress.rischpater.multimediamidlet; + +import java.io.*; +import javax.microedition.lcdui.*; +import javax.microedition.midlet.*; +import javax.microedition.media.*; +import javax.microedition.media.control.*; +import javax.microedition.m2g.*; + + + +public class MultimediaMIDlet + extends MIDlet + implements CommandListener, Runnable { + private Display display; + private List choiceScreen; + private Form mediaScreen; + Displayable viewerDisplayable; + private Item videoItem; + private ImageItem capturedImage; + private VideoControl videoControl; + private Command captureCommand; + private Command selectCommand; + String mediaName = null; + String mediaType = null; + private Player player = null; + SVGAnimator svgAnimator; + boolean endNow; + private static final String SVG_IMAGE_PATH = "/res/image.svg"; + private static final String SVG_IMAGE_TYPE = "image/svg+xml"; + private static final String WAV_SOUND_PATH = "/res/sound.wav"; + private static final String WAV_SOUND_TYPE = "audio/x-wav"; + private static final String MPG_MOVIE_PATH = "/res/movie.mpg"; + private static final String MPG_MOVIE_TYPE = "video/mpeg"; + private static final String CAP_VIDEO_PATH = "capture://video"; + private static final String CAP_VIDEO_TYPE = "video/x-capture"; + + + public void startApp() { + showSupportedMedia(); + display = Display.getDisplay(this); + if (choiceScreen == null) { + choiceScreen = new List("MultimediaMIDlet", List.IMPLICIT); + choiceScreen.addCommand(new Command("Exit", Command.EXIT, 0)); + selectCommand = new Command("Play", Command.ITEM,1); + choiceScreen.setSelectCommand(selectCommand); + choiceScreen.addCommand(selectCommand); + choiceScreen.setCommandListener(this); + choiceScreen.append("Sound", null); + choiceScreen.append("Video", null); + choiceScreen.append("SVG", null); + choiceScreen.append("Camera Capture",null); + } + display.setCurrent(choiceScreen); + } + + private void showSupportedMedia() { + String[] contentTypes = Manager.getSupportedContentTypes(null); + for (int i=0; i + + + + + + + + + + +

Test which verifies that the basic facilities of declarative animation are working.

+

This test uses the following elements : 'set', and 'animateColor

+

The test is a nine second animation with no repeats. It shows a circle changing color from 3s to 9s.

+

+ The file includes various guides that can be used to verify the correctness of the animation. Boxes on the left + show the correct circle color values at times 3s, 6s and 9s. +

+ + + $RCSfile: animate-elem-23-t.svg,v $ + + + + + + + + + + + Color at 3s + + + Color at 6s + + + Color at 9s + + + + + + + + + + + + + + $Revision: 1.8 $ + + + + + diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/src/res/image.svg b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/image.svg new file mode 100644 index 0000000..9f4aade --- /dev/null +++ b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/image.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + +

Test which verifies that the basic facilities of declarative animation are working.

+

This test uses the following elements : 'set', and 'animateColor

+

The test is a nine second animation with no repeats. It shows a circle changing color from 3s to 9s.

+

+ The file includes various guides that can be used to verify the correctness of the animation. Boxes on the left + show the correct circle color values at times 3s, 6s and 9s. +

+ + + $RCSfile: animate-elem-23-t.svg,v $ + + + + + + + + + + + Color at 3s + + + Color at 6s + + + Color at 9s + + + + + + + + + + + + + + $Revision: 1.8 $ + + + + + diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/src/res/movie.3g2 b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/movie.3g2 new file mode 100644 index 0000000..513758e Binary files /dev/null and b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/movie.3g2 differ diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/src/res/movie.mpg b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/movie.mpg new file mode 100644 index 0000000..bf8ac7e Binary files /dev/null and b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/movie.mpg differ diff --git a/Sample Code/chapter16/code/MultimediaMIDlet/src/res/sound.wav b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/sound.wav new file mode 100644 index 0000000..633f731 Binary files /dev/null and b/Sample Code/chapter16/code/MultimediaMIDlet/src/res/sound.wav differ diff --git a/Sample Code/chapter17/code/WeatherWidget/build.xml b/Sample Code/chapter17/code/WeatherWidget/build.xml new file mode 100644 index 0000000..59b2863 --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/build.xml @@ -0,0 +1,83 @@ + + + + + + Builds, tests, and runs the project . + + + diff --git a/Sample Code/chapter17/code/WeatherWidget/lib/kxml2-min-2.3.0.jar b/Sample Code/chapter17/code/WeatherWidget/lib/kxml2-min-2.3.0.jar new file mode 100644 index 0000000..a77dd1d Binary files /dev/null and b/Sample Code/chapter17/code/WeatherWidget/lib/kxml2-min-2.3.0.jar differ diff --git a/Sample Code/chapter17/code/WeatherWidget/nbproject/build-impl.xml b/Sample Code/chapter17/code/WeatherWidget/nbproject/build-impl.xml new file mode 100644 index 0000000..1b4d18d --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/nbproject/build-impl.xml @@ -0,0 +1,1160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Classpath to J2ME Ant extension library (libs.j2me_ant_ext.classpath property) is not set. For example: location of mobility/modules/org-netbeans-mobility-antext.jar file in the IDE installation directory. + Platform home (platform.home property) is not set. Value of this property should be ${platform.active.description} emulator home directory location. + Platform boot classpath (platform.bootclasspath property) is not set. Value of this property should be ${platform.active.description} emulator boot classpath containing all J2ME classes provided by emulator. + Must set src.dir + Must set build.dir + Must set dist.dir + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set preprocessed.dir + + + + + + + + + + + + + + + + + + Must set build.classes.dir + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + Must set obfuscated.classes.dir + + + + Must set obfuscated.classes.dir + Must set obfuscator.srcjar + Must set obfuscator.destjar + + + + + + + + + + + + + + + + + + + + Must set preverify.classes.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MicroEdition-Configuration: ${platform.configuration} + + MicroEdition-Configuration: ${platform.configuration} + + + + MicroEdition-Profile: ${platform.profile} + + MicroEdition-Profile: ${platform.profile} + + + + Must set dist.jad + + + + + + + + + + + + + + + + + + + + + + + + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.jad} + ${manifest.midlets}${evaluated.manifest.apipermissions}${evaluated.manifest.pushregistry}${manifest.others}${manifest.manifest} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set dist.javadoc.dir + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property deployment.${deployment.method}.scriptfile not set. The property should point to an Ant script providing ${deployment.method} deployment. + + + + + + + + Classpath to Ant Contrib library (libs.ant-contrib.classpath property) is not set. + + + + + + + + + Active project configuration: @{cfg} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property build.root.dir is not set. By default its value should be \"build\". + Property dist.root.dir is not set. By default its value should be \"dist\". + + + + + + + diff --git a/Sample Code/chapter17/code/WeatherWidget/nbproject/genfiles.properties b/Sample Code/chapter17/code/WeatherWidget/nbproject/genfiles.properties new file mode 100644 index 0000000..0a1617d --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=210f81fc +build.xml.script.CRC32=d4ed6131 +build.xml.stylesheet.CRC32=03eab09b +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=210f81fc +nbproject/build-impl.xml.script.CRC32=d5b88ab2 +nbproject/build-impl.xml.stylesheet.CRC32=6baa93ad diff --git a/Sample Code/chapter17/code/WeatherWidget/nbproject/private/private.properties b/Sample Code/chapter17/code/WeatherWidget/nbproject/private/private.properties new file mode 100644 index 0000000..8556692 --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/nbproject/private/private.properties @@ -0,0 +1,9 @@ +app-version.autoincrement=true +file.reference.builtin.ks=C:\\Documents and Settings\\kf6gpe\\.netbeans\\5.5.1\\config\\j2me\\builtin.ks +file.reference.kxml2-min-2.3.0.jar=C:\\book\\Chapters\\chapter13\\code\\kXML\\WeatherWidget\\lib\\kxml2-min-2.3.0.jar +#Sat Nov 24 12:19:50 PST 2007 +netbeans.user=C:\\Documents and Settings\\kf6gpe\\.netbeans\\6.5m1 +javadoc.preview=true +deployment.counter=000003 +config.active= +deployment.number=0.0.2 diff --git a/Sample Code/chapter17/code/WeatherWidget/nbproject/private/private.xml b/Sample Code/chapter17/code/WeatherWidget/nbproject/private/private.xml new file mode 100644 index 0000000..c1f155a --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/nbproject/private/private.xml @@ -0,0 +1,4 @@ + + + + diff --git a/Sample Code/chapter17/code/WeatherWidget/nbproject/project.properties b/Sample Code/chapter17/code/WeatherWidget/nbproject/project.properties new file mode 100644 index 0000000..c350e03 --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/nbproject/project.properties @@ -0,0 +1,153 @@ +abilities=JSR234=1.0,WMA=2.0,SATSACRYPTO=1.0,OBEX=1.0,MMAPI=1.1,JSR211=1.0,JSR172=1.0,ScreenWidth=240,JSR239=1.0,ScreenColorDepth=8,JSR177=1.0,ColorScreen,JSR238=1.0,JSR179=1.0.1,JSR226=1.0,JSR75=1.0,ScreenHeight=320,CLDC=1.1,J2MEWS=1.0,J2MEXMLRPC=1.0,SATSAAPDU=1.0,JSR229=1.1.0,JSR180=1.0.1,SATSAJCRMI=1.0,JSR184=1.1,SATSAPKI=1.0,MIDP=2.1,JSR82=1.1, +all.configurations=\ ,Debug,Release +application.args= +application.description= +application.description.detail= +application.name= +application.vendor=Vendor +build.classes.dir=${build.dir}/compiled +build.classes.excludes=**/*.java,**/*.form,**/*.class,**/.nbintdb,**/*.mvd,**/*.wsclient +build.dir=build/${config.active} +build.root.dir=build +configs.Release.debug.level=debug +configs.Release.javac.debug=false +configs.Release.javac.deprecation=false +configs.Release.javac.encoding=Cp1252 +configs.Release.javac.optimize=true +configs.Release.obfuscation.custom= +configs.Release.obfuscation.level=9 +configs.Release.sign.alias=trusted +configs.Release.sign.enabled=true +configs.Release.sign.keystore=${file.reference.builtin.ks} +debug.level=debug +deployment.copy.target=deploy +deployment.instance=default +deployment.jarurl=${dist.jar} +deployment.method=Scp +deployment.override.jarurl=false +deployment.scp.remotedir= +deployment.scp.server= +deployment.scp.userid= +dist.dir=dist/${config.active} +dist.jad=WeatherWidget.jad +dist.jar=WeatherWidget.jar +dist.javadoc.dir=${dist.dir}/doc +dist.root.dir=dist +extra.classpath= +file.reference.builtin.ks=../../../../../Documents and Settings/kf6gpe/.netbeans/5.5.1/config/j2me/builtin.ks +file.reference.kxml2-min-2.3.0.jar=lib/kxml2-min-2.3.0.jar +filter.exclude.tests=false +filter.excludes= +filter.more.excludes= +filter.use.standard=true +jar.compress=true +javac.debug=true +javac.deprecation=false +javac.encoding=Cp1252 +javac.optimize=false +javac.source=1.3 +javac.target=1.1 +javadoc.author=false +javadoc.encoding= +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +libs.classpath=${file.reference.kxml2-min-2.3.0.jar} +main.class= +main.class.class=applet +manifest.apipermissions= +manifest.file=manifest.mf +manifest.jad= +manifest.manifest= +manifest.midlets=MIDlet-1: Weather,,com.apress.rischpater.weatherwidget.WeatherWidget\n +manifest.others=MIDlet-Vendor: Vendor\nMIDlet-Version: 1.0\nMIDlet-Name: WeatherWidget\n +manifest.pushregistry= +name=WeatherWidget +no.dependencies=false +nokiaS80.application.icon= +nsicom.application.monitorhost= +nsicom.application.runremote= +nsicom.application.runverbose= +nsicom.remoteapp.location=\\My Documents\\NetBeans Applications +nsicom.remotevm.location=\\Windows\\creme\\bin\\CrEme.exe +obfuscated.classes.dir=${build.dir}/obfuscated +obfuscation.custom= +obfuscation.level=0 +obfuscator.destjar=${build.dir}/obfuscated.jar +obfuscator.srcjar=${build.dir}/before-obfuscation.jar +platform.active=Sun_Java_TM__Wireless_Toolkit_2_5_1_for_CLDC +platform.active.description=Sun Java(TM) Wireless Toolkit 2.5.1 for CLDC +platform.apis=JSR234-1.0,SATSA-APDU-1.0,JSR211-1.0,JSR75-1.0,J2ME-WS-1.0,JSR172-1.0,J2ME-XMLRPC-1.0,JSR82-1.1,SATSA-JCRMI-1.0,SATSA-CRYPTO-1.0,JSR239-1.0,JSR179-1.0.1,JSR184-1.1,JSR238-1.0,MMAPI-1.1,OBEX-1.0,JSR229-1.1.0,SATSA-PKI-1.0,JSR180-1.0.1,JSR226-1.0,JSR177-1.0,WMA-2.0 +platform.bootclasspath=${platform.home}/lib/wma20.jar:${platform.home}/lib/jsr082.jar:${platform.home}/lib/j2me-xmlrpc.jar:${platform.home}/lib/satsa-jcrmi.jar:${platform.home}/lib/satsa-apdu.jar:${platform.home}/lib/satsa-crypto.jar:${platform.home}/lib/jsr179.jar:${platform.home}/lib/satsa-pki.jar:${platform.home}/lib/jsr75.jar:${platform.home}/lib/jsr180.jar:${platform.home}/lib/jsr238.jar:${platform.home}/lib/jsr229.jar:${platform.home}/lib/j2me-ws.jar:${platform.home}/lib/jsr234.jar:${platform.home}/lib/jsr226.jar:${platform.home}/lib/jsr184.jar:${platform.home}/lib/mmapi.jar:${platform.home}/lib/jsr239.jar:${platform.home}/lib/jsr211.jar:${platform.home}/lib/midpapi21.jar:${platform.home}/lib/cldcapi11.jar +platform.configuration=CLDC-1.1 +platform.device=DefaultColorPhone +platform.fat.jar=true +platform.profile=MIDP-2.1 +platform.trigger=CLDC +preprocessed.dir=${build.dir}/preprocessed +preverify.classes.dir=${build.dir}/preverified +resources.dir=resources +ricoh.application.email= +ricoh.application.fax= +ricoh.application.icon= +ricoh.application.target-jar= +ricoh.application.telephone= +ricoh.application.uid=21080274 +ricoh.application.version= +ricoh.dalp.application-desc.auto-run=false +ricoh.dalp.application-desc.energy-save= +ricoh.dalp.application-desc.exec-auth= +ricoh.dalp.application-desc.visible=true +ricoh.dalp.argument= +ricoh.dalp.codebase= +ricoh.dalp.display-mode.color=true +ricoh.dalp.display-mode.is-4line-support=false +ricoh.dalp.display-mode.is-hvga-support=true +ricoh.dalp.display-mode.is-vga-support=false +ricoh.dalp.display-mode.is-wvga-support=false +ricoh.dalp.information.abbreviation= +ricoh.dalp.information.icon.basepath= +ricoh.dalp.information.icon.location= +ricoh.dalp.information.is-icon-used=true +ricoh.dalp.install.destination=hdd +ricoh.dalp.install.mode.auto=true +ricoh.dalp.install.work-dir=hdd +ricoh.dalp.is-managed=true +ricoh.dalp.resources.dsdk.version=2.0 +ricoh.dalp.resources.jar.basepath= +ricoh.dalp.resources.jar.version= +ricoh.dalp.version= +ricoh.icon.invert=false +ricoh.platform.target.version= +run.cmd.options= +run.jvmargs= +run.method=STANDARD +run.security.domain=trusted +run.use.security.domain=false +savaje.application.icon= +savaje.application.icon.focused= +savaje.application.icon.small= +savaje.application.uid=TBD +savaje.bundle.base= +savaje.bundle.debug=false +savaje.bundle.debug.port= +semc.application.caps= +semc.application.icon= +semc.application.icon.count= +semc.application.icon.splash= +semc.application.icon.splash.installonly=false +semc.application.uid=E8297860 +semc.certificate.path= +semc.private.key.password= +semc.private.key.path= +sign.alias=trusted +sign.enabled=false +sign.keystore=${file.reference.builtin.ks} +src.dir=src +use.emptyapis=true +use.preprocessor=true diff --git a/Sample Code/chapter17/code/WeatherWidget/nbproject/project.xml b/Sample Code/chapter17/code/WeatherWidget/nbproject/project.xml new file mode 100644 index 0000000..271dc4b --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/nbproject/project.xml @@ -0,0 +1,10 @@ + + + org.netbeans.modules.kjava.j2meproject + + + WeatherWidget + 1.6 + + + diff --git a/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherFetcher.java b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherFetcher.java new file mode 100644 index 0000000..7897bc2 --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherFetcher.java @@ -0,0 +1,106 @@ +/* + * WeatherFetcher.java + * + * Created on June 24, 2008, 2:48 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import java.io.*; +import javax.microedition.io.*; +/** + * + * @author kf6gpe + */ +public class WeatherFetcher implements Runnable { + private static String url = "http://www.noplace.com/wx/"; + + + private Thread thread; + private WeatherLocation location; + private boolean cancelled; + WeatherWidget app; + + /** Creates a new instance of WeatherFetcher */ + public WeatherFetcher(WeatherLocation l, WeatherWidget a) { + location = l; + app = a; + cancelled = false; + if (l!=null && a!=null) { + thread = new Thread(this); + thread.start(); + } + } + + public void cancel() { + cancelled = true; + } + + private static String urlEncode(String s) + { + if (s!=null) { + StringBuffer tmp = new StringBuffer(); + int i=0; + try { + while (true) { + int b = (int)s.charAt(i++); + if ((b>=0x30 && b<=0x39) || + (b>=0x41 && b<=0x5A) || + (b>=0x61 && b<=0x7A)) { + tmp.append((char)b); + } else { + tmp.append("%"); + if (b <= 0xf) tmp.append("0"); + tmp.append(Integer.toHexString(b)); + } + } + } + catch (Exception e) {} + return tmp.toString(); + } + return null; + } + + private String requestEncode() { + StringBuffer result = new StringBuffer(); + result.append(url); + result.append(urlEncode(location.getLocation())); + return result.toString(); + } + + public void run() { + String requestUrl; + String response = ""; + HttpConnection hc = null; + InputStream in = null; + + requestUrl = requestEncode(); + + try { + hc = (HttpConnection)Connector.open(requestUrl); + hc.setRequestMethod(HttpConnection.GET); + in=hc.openInputStream(); + int length=(int)hc.getLength(); + byte[] data = new byte[length]; + in.read(data); + response = new String(data); + } + catch(Exception e){} + finally { + try { + if (in!=null) hc.close(); + if (hc!=null) hc.close(); + } + catch(Exception e) {} + } + if (!cancelled) { + System.out.println(response); + location.fromXml(response); + System.out.print(location.toXml()); + app.update(); + } + } +} \ No newline at end of file diff --git a/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocation.java b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocation.java new file mode 100644 index 0000000..8f0dc52 --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocation.java @@ -0,0 +1,515 @@ +/* + * WeatherLocation.java + * + * Created on March 2, 2008, 9:01 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; +import java.io.*; +import javax.xml.parsers.*; +import org.xml.sax.*; +import org.xml.sax.helpers.*; +/** + * + * @author kf6gpe + */ +public class WeatherLocation { + private final static int FIELD_VERSION = 1; + private final static int FIELD_CITY = 2; + private final static int FIELD_FORECAST = 3; + private final static int FIELD_TEMP = 4; + private final static int FIELD_WINDSPEED = 5; + private final static int FIELD_WINDDIR = 6; + private final static int FIELD_PRECIP = 7; + private final static int FIELD_STATE = 8; + private final static int FIELD_COUNTRY = 9; + private final static int FIELD_PRECIP_PROB = 10; + private final static int FIELD_PRECIP_TYPE = 11; + + private final static String XML_PREAMBLE = "\n"; + private final static String XML_START_OPEN = "<"; + private final static String XML_START_EMPTYOPEN = "<"; + private final static String XML_START_CLOSE=""; + private final static String XML_END_EMPTYOPEN = "/>"; + private final static String XML_END_CLOSE = ">"; + private final static String XML_ATTR_IS = "="; + private final static String XML_ATTR_QUOTE = "\""; + public final static String XML_TAG_WEATHER="weather"; + public final static String XML_ATTR_CITY="city"; + public final static String XML_ATTR_STATE="state"; + public final static String XML_ATTR_COUNTRY="country"; + public final static String XML_TAG_TEMPS="temperatures"; + public final static String XML_ATTR_UNITS="units"; + private final static String XML_ATTR_TUNITS=" units=\"F\""; + public final static String XML_TAG_TEMP="temperature"; + public final static String XML_ATTR_TYPE="type"; + public final static String XML_TAG_WIND="wind"; + private final static String XML_ATTR_WUNITS=" units=\"MPH\""; + public final static String XML_TAG_DIRECTION="direction"; + public final static String XML_TAG_SPEED="speed"; + public final static String XML_TAG_PRECIP="precipitation"; + public final static String XML_ATTR_PROB="probability"; + private final static String XML_ATTR_PUNITS=" units=\"in\""; + public final static String XML_TAG_TEXT="text"; + public final static String XML_TAG_WHEN="when"; + public final static String XML_ATTR_TIME="time"; + private final static String XML_ATTR_WTIME=" time=\"today\""; + private final static String XML_NEWLINE="\n"; + + public final static int NO_ID = -1; + + private final static int version = 1; + private String city, state, country; + private String forecast; + private String temp; + private String windSpeed; + private String windDirection; + private String precipitation, precipitationProb, precipitationType; + private int recordid; + + /** Creates a new instance of WeatherLocation */ + public WeatherLocation() { + recordid = NO_ID; + } + + public WeatherLocation(String l) { + setLocation(l); + recordid = NO_ID; + } + + public WeatherLocation(byte[] b) { + fromBytes(b); + recordid = NO_ID; + } + + public WeatherLocation(byte[] b, int id) { + fromBytes(b); + recordid = id; + } + + public String getLocation() { + StringBuffer result = new StringBuffer(); + if (city!=null) { + result.append(city); + } + result.append(","); + if (state!=null) { + result.append(state); + } + result.append(","); + if (country!=null) { + result.append(country); + } + return result.toString(); + } + + public String getCity() { + if(city != null) + return city; + else + return ""; + } + + public String getState() { + if(state != null) + return state; + else + return ""; + } + + public String getCountry() { + if(country != null) + return country; + else + return ""; + } + + public void setLocation(String l) { + int cityStart, stateStart, countryStart; + cityStart = 0; + stateStart = l.indexOf(","); + if (stateStart==-1) { + city = l; + state=""; + country=""; + return; + } + countryStart = l.indexOf(",",stateStart+1); + city = l.substring(cityStart,stateStart); + if (countryStart==-1) + { + state = l.substring(stateStart-1); + country = "USA"; + return; + } + state = l.substring(stateStart+1,countryStart); + country = l.substring(countryStart+1); + } + + public void setLocation(String c, String s, String co) { + city = c; + state = s; + country = co; + } + + public String getWind() { + if (windSpeed != null && windDirection != null) + return windSpeed + " mph from the " + windDirection; + else return ""; + } + + public void setWind(String s, String d) { + windSpeed = s; + windDirection = d; + } + + public String getTemperature() { + if (temp!=null) + return temp; + else + return ""; + } + + public void setTemperature(String t) { + temp = t; + } + + public String getPrecipitation() { + StringBuffer result = new StringBuffer(); + if (precipitation != null) { + result.append(precipitation); + } else { + result.append("unknown"); + } + result.append("in of "); + if (precipitationType != null) { + result.append(precipitationType); + } else { + result.append("unknown"); + } + result.append("("); + if (precipitationProb != null) { + result.append(precipitationProb); + } else { + result.append("unknown"); + } + result.append("%)"); + return result.toString(); + } + + public void setPrecipitation(String p, String pp, String pt) { + precipitation = p; + precipitationProb = pp; + precipitationType = pt; + } + + public String getForecast() { + if (forecast != null) { + return forecast; + } else { + return ""; + } + } + + public void setForecast(String f) { + forecast = f; + } + + public int getId() { + return recordid; + } + + public void setId(int id) { + recordid = id; + } + + public byte[] toBytes() { + byte[] b; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + + + // Record format is field-tag, then field for each + try { + dos.writeInt(FIELD_VERSION); + dos.writeInt(version); + if (city != null) { + dos.writeInt(FIELD_CITY); + dos.writeUTF(getCity()); + } + if (state != null) { + dos.writeInt(FIELD_STATE); + dos.writeUTF(getState()); + } + if (country != null) { + dos.writeInt(FIELD_COUNTRY); + dos.writeUTF(getCountry()); + } + if (forecast != null) + { + dos.writeInt(FIELD_FORECAST); + dos.writeUTF(getForecast()); + } + if (temp != null) { + dos.writeInt(FIELD_TEMP); + dos.writeUTF(getTemperature()); + } + if (precipitation != null && + precipitationProb != null && + precipitationType != null) { + dos.writeInt(FIELD_PRECIP); + dos.writeUTF(precipitation); + dos.writeInt(FIELD_PRECIP_PROB); + dos.writeUTF(precipitationProb); + dos.writeInt(FIELD_PRECIP_TYPE); + dos.writeUTF(precipitationType); + } + if (windDirection != null && windSpeed != null) { + dos.writeInt(FIELD_WINDDIR); + dos.writeUTF(windDirection); + dos.writeInt(FIELD_WINDSPEED); + dos.writeUTF(windSpeed); + } + } + catch(Exception e) { + return null; + } + + // Get the bytes for this item. + b = baos.toByteArray(); + dos = null; + baos = null; + + return b; + } + + public void fromBytes(byte[] b) { + ByteArrayInputStream bais = new ByteArrayInputStream(b); + DataInputStream dis = new DataInputStream(bais); + String dir = null, speed = null; + String c = null, s = null, co = null; + String p = null, pp = null, pt = null; + // Read each tag, then each field + try + { + while(true) { + int tag = dis.readInt(); + switch(tag) { + case FIELD_VERSION: + // Don't check version; there's only one + dis.readInt(); + break; + case FIELD_CITY: + c = dis.readUTF(); + break; + case FIELD_STATE: + s = dis.readUTF(); + break; + case FIELD_COUNTRY: + co = dis.readUTF(); + break; + case FIELD_FORECAST: + setForecast(dis.readUTF()); + break; + case FIELD_TEMP: + setTemperature(dis.readUTF()); + break; + case FIELD_PRECIP: + p = dis.readUTF(); + break; + case FIELD_PRECIP_PROB: + pp = dis.readUTF(); + break; + case FIELD_PRECIP_TYPE: + pt = dis.readUTF(); + break; + case FIELD_WINDDIR: + dir = dis.readUTF(); + break; + case FIELD_WINDSPEED: + speed = dis.readUTF(); + break; + } + } + } + catch (Exception e) {} + finally { + setLocation(c, s, co); + setPrecipitation(p, pp, pt); + setWind(speed, dir); + try { + dis.close(); + bais.close(); + } + catch (Exception e) {} + } + dis = null; + bais = null; + } + + public String toXml() { + StringBuffer xmlBuffer = new StringBuffer(); + xmlBuffer.append(XML_PREAMBLE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WEATHER); + if (city != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_CITY); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(city); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (state != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_STATE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(state); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (country != null) { + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_COUNTRY); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(country); + xmlBuffer.append(XML_ATTR_QUOTE); + } + if (forecast != null || + temp != null || + (precipitation != null && + precipitationProb != null && + precipitationType != null ) || + (windSpeed != null && windDirection != null)) { + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + if (temp != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEMPS); + xmlBuffer.append(XML_ATTR_TUNITS); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEMP); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_TYPE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append("\"current\""); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(temp); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEMP); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEMPS); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (windSpeed != null && windDirection != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WIND); + xmlBuffer.append(XML_ATTR_WUNITS); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_SPEED); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(windSpeed); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_SPEED); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_DIRECTION); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(windDirection); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_DIRECTION); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WIND); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (precipitation != null && + precipitationProb != null && + precipitationType != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_PRECIP); + xmlBuffer.append(XML_ATTR_PUNITS); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_PROB); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(precipitationProb); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(" "); + xmlBuffer.append(XML_ATTR_TYPE); + xmlBuffer.append(XML_ATTR_IS); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(precipitationType); + xmlBuffer.append(XML_ATTR_QUOTE); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(precipitation); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_PRECIP); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + if (forecast != null) { + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_TEXT); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_OPEN); + xmlBuffer.append(XML_TAG_WHEN); + xmlBuffer.append(XML_ATTR_WTIME); + xmlBuffer.append(XML_END_OPEN); + xmlBuffer.append(forecast); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WHEN); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_TEXT); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } + xmlBuffer.append(XML_START_CLOSE); + xmlBuffer.append(XML_TAG_WEATHER); + xmlBuffer.append(XML_END_CLOSE); + xmlBuffer.append(XML_NEWLINE); + } else { + xmlBuffer.append(XML_END_EMPTYOPEN); + } + + return xmlBuffer.toString(); + } + + public void fromXml(String xml) { + WeatherLocationParser parser = new WeatherLocationParser(this); + byte[] xmlBytes; + ByteArrayInputStream bis; + + xmlBytes = xml.getBytes(); + bis = new ByteArrayInputStream(xmlBytes); + try { + parser.parse(bis); + } + catch(Exception e){} + finally { + try { + bis.close(); + } + catch(Exception e) {} + } + } +} diff --git a/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocationParser.java b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocationParser.java new file mode 100644 index 0000000..f727edc --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocationParser.java @@ -0,0 +1,170 @@ +/* + * WeatherLocationParser.java + * + * Created on July 6, 2008, 12:21 PM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import org.kxml2.io.*; +import java.io.*; +import javax.microedition.io.*; +import java.util.Vector; + +/** + * + * @author kf6gpe + */ +public class WeatherLocationParser { + private WeatherLocation location; + private boolean setForecast; + private boolean hasForecast; + private boolean setTemp; + private String precipitation, precipType, precipProb; + private String windSpeed, windDirection; + private StringBuffer buffer; + + public WeatherLocationParser() { + location = new WeatherLocation(); + } + + public WeatherLocationParser(WeatherLocation l) { + location = l; + } + + public void parse(ByteArrayInputStream in) { + try { + InputStreamReader reader = new InputStreamReader(in); + KXmlParser parser = new KXmlParser(); + boolean keepParsing = true; + parser.setInput(reader); + while(keepParsing) { + int type = parser.next(); + + switch(type) { + case KXmlParser.START_DOCUMENT: + startDocument(); + break; + case KXmlParser.START_TAG: + startElement(parser); + break; + case KXmlParser.END_TAG: + endElement(parser); + break; + case KXmlParser.TEXT: + characters(parser); + break; + case KXmlParser.END_DOCUMENT: + endDocument(); + keepParsing = false; + break; + } + + } + } + catch(Exception e) { + System.out.println(e.toString()); + e.printStackTrace(); + } + } + + public WeatherLocation getLocation() { + return location; + } + + public void startDocument() { + if ( location == null ) + location = new WeatherLocation(); + setForecast = false; + hasForecast = false; + setTemp = false; + } + + public void startElement(KXmlParser parser) + throws Exception { + String qName = parser.getName(); + buffer = new StringBuffer(); + if ( qName.compareTo(WeatherLocation.XML_TAG_WEATHER) == 0) { + String c = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_CITY); + String s = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_STATE); + String co = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_COUNTRY); + location.setLocation(c,s,co); + hasForecast = false; + } + if ( qName.compareTo(WeatherLocation.XML_TAG_TEMPS) == 0) { + String u = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_UNITS); + if ( u != null && u.compareTo("F") != 0) throw new Exception("Invalid temperature units"); + hasForecast = false; + } + if ( qName.compareTo(WeatherLocation.XML_TAG_TEMP) == 0 ) { + String t = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_TYPE); + if (t != null && t.compareTo("current") == 0) { + setTemp = true; + } else { + setTemp = false; + } + hasForecast = false; + } + if ( qName.compareTo(WeatherLocation.XML_TAG_WIND) == 0) { + String u = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_UNITS); + if ( u != null && u.compareTo("MPH") != 0) + throw new Exception("Invalid temperature units"); + hasForecast = false; + } + if ( qName.compareTo(WeatherLocation.XML_TAG_PRECIP) == 0 ) + { + String u = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_UNITS); + if (u != null && u.compareTo("in") != 0) + throw new Exception("Invalid precipitation units"); + precipProb = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_PROB); + precipType = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_TYPE); + hasForecast = false; + } + if (qName.compareTo(WeatherLocation.XML_TAG_TEXT) == 0) { + hasForecast = true; + } + if (qName.compareTo(WeatherLocation.XML_TAG_WHEN) == 0 && hasForecast) { + String w = parser.getAttributeValue(null,WeatherLocation.XML_ATTR_TIME); + if (w != null && w.compareTo("now") == 0) { + setForecast = true; + } else { + setForecast = false; + } + } + } + + public void characters(KXmlParser parser) { + if (buffer != null) + buffer.append(parser.getText()); + } + + public void endElement(KXmlParser parser) { + String qName = parser.getName(); + if (qName.compareTo(WeatherLocation.XML_TAG_SPEED) == 0) { + windSpeed = buffer.toString(); + } + if (qName.compareTo(WeatherLocation.XML_TAG_DIRECTION) == 0) { + windDirection = buffer.toString(); + } + if (qName.compareTo(WeatherLocation.XML_TAG_WIND) == 0) { + location.setWind(windSpeed, windDirection); + } + if (qName.compareTo(WeatherLocation.XML_TAG_PRECIP) == 0) { + precipitation = buffer.toString(); + location.setPrecipitation(precipitation,precipProb,precipType); + } + if (qName.compareTo(WeatherLocation.XML_TAG_TEMP) == 0 && setTemp ) + { + location.setTemperature(buffer.toString()); + } + if (qName.compareTo(WeatherLocation.XML_TAG_WHEN) == 0 && setForecast) { + location.setForecast( buffer.toString()); + } + } + + public void endDocument() { + } +} diff --git a/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocationStore.java b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocationStore.java new file mode 100644 index 0000000..d0634ca --- /dev/null +++ b/Sample Code/chapter17/code/WeatherWidget/src/com/apress/rischpater/weatherwidget/WeatherLocationStore.java @@ -0,0 +1,132 @@ +/* + * WeatherLocationStore.java + * + * Created on March 2, 2008, 9:29 AM + * + * To change this template, choose Tools | Template Manager + * and open the template in the editor. + */ + +package com.apress.rischpater.weatherwidget; + +import javax.microedition.rms.*; + +/** + * + * @author kf6gpe + */ +public class WeatherLocationStore { + private static final String storeName = "wx"; + private RecordStore store = null; + + public WeatherLocationStore() { + } + + private void openStore() throws RecordStoreException { + if (store == null) { + store = RecordStore.openRecordStore(storeName, true); + } + } + + private void closeStore() { + if (store != null) { + try { + store.closeRecordStore(); + } catch( Exception ex ) {} + store = null; + } + } + + public void addLocation(WeatherLocation l) throws RecordStoreException { + WeatherLocation existing = getLocation(l.getLocation()); + if (existing!=null) { + existing.setForecast(l.getForecast()); + updateLocation(existing); + } else { + byte b[] = l.toBytes(); + openStore(); + l.setId(store.getNextRecordID()); + store.addRecord(b, 0, b.length); + closeStore(); + } + } + + public String[] getLocationStrings() { + String[] result = null; + try { + openStore(); + result = new String[store.getNumRecords()]; + RecordEnumeration e = store.enumerateRecords( + null, // No filter + new RecordComparator () { + public int compare( byte[] b1, byte[] b2 ) { + WeatherLocation r1 = new WeatherLocation(b1); + WeatherLocation r2 = new WeatherLocation(b2); + if (r1.getLocation().compareTo(r2.getLocation()) == 0) { + return RecordComparator.EQUIVALENT; + } else if (r1.getLocation().compareTo(r2.getLocation()) < 0) { + return RecordComparator.PRECEDES; + } else { + return RecordComparator.FOLLOWS; + } + } + }, + false); + int i; + + for (i=0; i 0 ) + wxlocation = locationStore.getLocation(locations[0]); + } + catch(Exception e){} + fetcher = new WeatherFetcher(wxlocation, this); + getDisplay().setCurrent(get_wxForm()); + } + + public void startApp() { + initialize(); + } + + public void pauseApp() { + } + + public void destroyApp(boolean unconditional) { + } + + public void update() { + get_wxItem().setText(get_forecast()); + try + { + locationStore.updateLocation(wxlocation); + } + catch(Exception e){} + } + + public void commandAction(Command command, Displayable displayable) { + // Insert global pre-action code here + if (displayable == wxForm) { + if (command == exitCommand) { + exitMIDlet(); + } else if (command == settingCommand) { + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == locationList) { + if (command == locateCommand) { + getDisplay().setCurrent(get_locatingAlert()); + Thread t = new Thread(this); + t.start(); + } else if (command == screenCommand) { + getDisplay().setCurrent(get_locationTextBox()); + } else if (command == List.SELECT_COMMAND) { + int index = get_locationList().getSelectedIndex(); + set_location(get_locationList().getString(index)); + fetcher.cancel(); + fetcher = new WeatherFetcher(wxlocation, this); + getDisplay().setCurrent(get_wxForm()); + } else if (command == backCommand) { + getDisplay().setCurrent(get_wxForm()); + } + } else if (displayable == locationTextBox) { + if (command == locateCommand) { + getDisplay().setCurrent(get_locatingAlert()); + Thread t = new Thread(this); + t.start(); + } else if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } else if (command == okCommand) { + add_location(locationTextBox.getString()); + getDisplay().setCurrent(get_locationList()); + } + } else if (displayable == cannotAddLocationAlert) { + if (command == backCommand) { + getDisplay().setCurrent(get_locationList()); + } + } + } + + public String get_forecast() { + if (wxlocation == null) { + return "unknown forecast"; + } else { + return wxlocation.getForecast(); + } + } + + + public String get_location() { + if (wxlocation == null) { + return "unknown"; + } else { + return wxlocation.getLocation(); + } + } + + public void set_location( String l ) { + try { + wxlocation = locationStore.getLocation(l); + } + catch(Exception e) {e.printStackTrace();} + get_locationTextBox().setString(l); + get_wxForm().setTitle(l); + } + + public void add_location( String l ) { + wxlocation = new WeatherLocation(l); + try { + locationStore.addLocation( wxlocation ); + } catch (Exception e) { + getDisplay().setCurrent(get_cannotAddLocationAlert()); + } + // Refresh the wxlocation list lazily. + locationList = null; + } + + + /** + * This method should return an instance of the display. + */ + public Display getDisplay() { + return Display.getDisplay(this); + } + + /** + * This method should exit the midlet. + */ + public void exitMIDlet() { + getDisplay().setCurrent(null); + destroyApp(true); + notifyDestroyed(); + } + + + /** This method returns instance for wxItem component and should be called instead of accessing wxItem field directly. + * @return Instance for wxItem component + */ + public StringItem get_wxItem() { + if (wxItem == null) { + wxItem = new StringItem("Forecast", get_forecast()); + } + return wxItem; + } + + /** This method returns instance for wxForm component and should be called instead of accessing wxForm field directly. + * @return Instance for wxForm component + */ + public Form get_wxForm() { + if (wxForm == null) { + wxForm = new Form(get_location(), new Item[] { + get_wxItem() + }); + wxForm.addCommand(get_exitCommand()); + wxForm.addCommand(get_settingCommand()); + wxForm.setCommandListener(this); + } + return wxForm; + } + + public Alert get_locatingAlert() { + if (locatingAlert == null) { + locatingAlert = new Alert("Locating", "Finding your location", + null, null); + locatingAlert.setTimeout(Alert.FOREVER); + } + return locatingAlert; + } + + /** This method returns instance for locationTextBox component and should be called instead of accessing locationTextBox field directly. + * @return Instance for locationTextBox component + */ + public TextBox get_locationTextBox() { + if (locationTextBox == null) { + locationTextBox = new TextBox("Add Location", "", 80, 0); + locationTextBox.addCommand(get_locateCommand()); + locationTextBox.addCommand(get_backCommand()); + locationTextBox.addCommand(get_okCommand()); + locationTextBox.setCommandListener(this); + } + return locationTextBox; + } + + /** This method returns instance for locationList component and should be called instead of accessing locationList field directly. + * @return Instance for locationList component + */ + public List get_locationList() { + if (locationList == null) { + String[] locations; + locations = locationStore.getLocationStrings(); + + locationList = new List("Where", List.IMPLICIT, locations, null); + locationList.addCommand(get_screenCommand()); + locationList.addCommand(get_backCommand()); + locationList.addCommand(get_locateCommand()); + locationList.setCommandListener(this); + } + return locationList; + } + + public Alert get_cannotAddLocationAlert() { + if (cannotAddLocationAlert == null) + { + cannotAddLocationAlert = new Alert("Cannot Add Location"); + cannotAddLocationAlert.setString("An error occurred adding ~CCC +the location you entered. It has not been added."); + cannotAddLocationAlert.addCommand(get_backCommand()); + } + return cannotAddLocationAlert; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_settingCommand() { + if (settingCommand == null) { + settingCommand = new Command("Settings", Command.OK, 1); + } + return settingCommand; + } + + /** This method returns instance for settingCommand component and should be called instead of accessing settingCommand field directly. + * @return Instance for settingCommand component + */ + public Command get_okCommand() { + if (okCommand == null) { + okCommand = new Command("OK", Command.OK, 1); + } + return okCommand; + } + + public Command get_locateCommand() { + if (locateCommand == null) { + locateCommand = new Command("Use this location", Command.ITEM, 1); + } + return locateCommand; + } + + + /** This method returns instance for exitCommand component and should be called instead of accessing exitCommand field directly. + * @return Instance for exitCommand component + */ + public Command get_exitCommand() { + if (exitCommand == null) { + exitCommand = new Command("Exit", Command.EXIT, 1); + } + return exitCommand; + } + + /** This method returns instance for screenCommand component and should be called instead of accessing screenCommand field directly. + * @return Instance for itemCommand component + */ + public Command get_screenCommand() { + if (screenCommand == null) { + screenCommand = new Command("Add Location", Command.SCREEN, 1); + } + return screenCommand; + } + + + /** This method returns instance for backCommand component and should be called instead of accessing backCommand field directly. + * @return Instance for backCommand component + */ + public Command get_backCommand() { + if (backCommand == null) { + backCommand = new Command("Back", Command.BACK, 1); + } + return backCommand; + } + + private class LocationUpdater implements Runnable { + String location; + public LocationUpdater(String l) { + location = l; + } + public void run() { + add_location(location); + set_location(location); + getDisplay().setCurrent(get_locationTextBox()); + } + } + + public void run() { + Criteria criteria = new Criteria(); + LocationProvider lp; + StringBuffer cl = new StringBuffer(); + String location; + + criteria.setCostAllowed(true); + criteria.setAddressInfoRequired(true); + criteria.setHorizontalAccuracy(100); + + try { + lp = LocationProvider.getInstance(criteria); + Location l = lp.getLocation(60); + if ( l != null && l.isValid() ) { + AddressInfo ai = l.getAddressInfo(); + QualifiedCoordinates c = l.getQualifiedCoordinates(); + if ( ai != null ) { + cl.append(ai.getField(AddressInfo.CITY)); + cl.append(", "); + cl.append(ai.getField(AddressInfo.STATE)); + cl.append(", "); + cl.append(ai.getField(AddressInfo.COUNTRY)); + } else { + int r = QualifiedCoordinates.DD_MM; + String s; + cl.append("GPS Coordinates, "); + s = QualifiedCoordinates.convert(c.getLatitude(), r); + cl.append(s); + cl.append(", "); + s = QualifiedCoordinates.convert(c.getLongitude(), r); + cl.append(s); + } + } + } catch(Exception e) {e.printStackTrace();}; + if ( cl.length() > 0 ) { + location = cl.toString(); + } else { + location = "Could not determine location."; + } + // Update later + Display.getDisplay(this).callSerially(new LocationUpdater(location)); + } +} diff --git a/contributing.md b/contributing.md new file mode 100644 index 0000000..f6005ad --- /dev/null +++ b/contributing.md @@ -0,0 +1,14 @@ +# Contributing to Apress Source Code + +Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers. + +## How to Contribute + +1. Make sure you have a GitHub account. +2. Fork the repository for the relevant book. +3. Create a new branch on which to make your change, e.g. +`git checkout -b my_code_contribution` +4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted. +5. Submit a pull request. + +Thank you for your contribution! \ No newline at end of file