├── .checkstyle ├── .classpath ├── .editorconfig ├── .gitignore ├── .project ├── alx.template ├── autopass.ahk ├── build.xml ├── jad.template ├── lib └── thirdparty │ ├── SignatureTool.jar │ ├── ant-contrib-1.0b3.jar │ ├── antenna-bin-0.9.14.jar │ ├── jde4.0.2 │ ├── net_rim_api.jar │ ├── preverify.exe │ ├── rapc.exe │ └── rapc.jar │ ├── jde4.0 │ ├── net_rim_api.jar │ ├── preverify.exe │ ├── rapc.exe │ └── rapc.jar │ ├── jde4.1.0 │ ├── net_rim_api.jar │ ├── preverify.exe │ ├── rapc.exe │ └── rapc.jar │ ├── jde4.2.0 │ ├── net_rim_api.jar │ ├── preverify.exe │ ├── rapc.exe │ └── rapc.jar │ └── jde4.3.0 │ ├── net_rim_api.jar │ ├── preverify.exe │ ├── rapc.exe │ └── rapc.jar ├── res └── img │ ├── folder_logo.png │ ├── heading_240x26.jpg │ ├── heading_320x34.jpg │ ├── icons │ ├── icon_doc.gif │ ├── icon_generic.gif │ ├── icon_image.gif │ ├── icon_pdf.gif │ ├── icon_ppt.gif │ ├── icon_txt.gif │ ├── icon_xls.gif │ └── icon_zip.gif │ ├── img_err_11x11.png │ ├── img_err_15x15.png │ ├── infobar_240x13.jpg │ ├── infobar_320x13.jpg │ ├── infobar_bottom_320x4.jpg │ ├── line.png │ ├── loadingbar_320x16.jpg │ ├── loadingbar_done_320x16.jpg │ ├── loadingbar_err_240x24.png │ ├── loadingbar_err_320x32.png │ ├── lock.jpg │ ├── more_off_240x14.jpg │ ├── more_off_320x14.jpg │ ├── more_on_240x14.jpg │ ├── more_on_320x14.jpg │ ├── original-follows-text_240x12.png │ ├── original-follows-text_320x12.png │ ├── pencil.gif │ ├── separator_320x1.jpg │ ├── separator_320x4.jpg │ ├── smartnote-on-16.png │ └── smileys │ ├── laugh.gif │ ├── love.gif │ ├── mad.gif │ ├── ohmy.gif │ ├── sad.gif │ ├── smile.gif │ ├── tongue.gif │ └── wink.gif └── src └── com └── bbsmart └── pda └── blackberry └── smartview ├── BuildVersion.java ├── SmartView.java ├── io ├── EmailColorPreference.java ├── GeneralStoreInterface.java ├── ImageCache.java ├── PersistenceManager.java ├── Preferences.java ├── SmartNote.java ├── SmartNoteManager.java └── WAPGatewayProvider.java ├── multi └── Semaphore.java ├── net ├── HttpConnectionThread.java ├── HttpContentReceiver.java ├── HttpHelper.java ├── ImageConnectionManager.java └── ImageHttpConnection.java ├── ui ├── customfield │ ├── GenericLoadingAnimation.java │ ├── GenericLoadingDialog.java │ ├── HTMLField.java │ ├── ImageLoadingAnimation.java │ ├── ImageLoadingDialog.java │ ├── ImageLoadingManager.java │ └── SmartNoteListField.java ├── screens │ ├── CommsHelpScreen.java │ ├── CommsScreen.java │ ├── EmailViewScreen.java │ ├── NewTemplateScreen.java │ ├── OptionsScreen.java │ ├── RegisterScreen.java │ ├── SmartNoteScreen.java │ ├── SmartSayScreen.java │ └── TrialEndedScreen.java └── util │ └── UiUtilities.java └── util ├── ColorChoices.java ├── ColorPickerField.java ├── EmailFormatter.java ├── EmailTemplate.java ├── EmailUtils.java ├── HTMLRetriever.java ├── MessageUtils.java ├── MoreListener.java ├── MoreRetriever.java ├── RPNState.java ├── RPNString.java ├── StringUtils.java └── Tokenizer.java /.checkstyle: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | Thumbs.db -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SmartView 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.ui.externaltools.ExternalToolBuilder 10 | full,incremental, 11 | 12 | 13 | LaunchConfigHandle 14 | <project>/.externalToolBuilders/org.eclipse.jdt.core.javabuilder.launch 15 | 16 | 17 | 18 | 19 | org.eclipse.ui.externaltools.ExternalToolBuilder 20 | 21 | 22 | LaunchConfigHandle 23 | <project>/.externalToolBuilders/New_Builder.launch 24 | 25 | 26 | 27 | 28 | 29 | org.eclipse.jdt.core.javanature 30 | 31 | 32 | -------------------------------------------------------------------------------- /alx.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @midletName@ 5 | 6 | 7 | The Smart Way to View Email 8 | 9 | 10 | @buildVer@ 11 | 12 | 13 | BlackBerrySmart 14 | 15 | 16 | Copyright (c) 2008 BBSmart 17 | 18 | 19 | 20 | 21 | 22 | 23 | @midletName@.cod 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /autopass.ahk: -------------------------------------------------------------------------------- 1 | Run java -jar lib\thirdparty\SignatureTool.jar -a -c SmartView.cod 2 | Sleep, 1000 -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | package com.bbsmart.pda.blackberry.smartview; 82 | 83 | public class BuildVersion { 84 | public final static String OS_VERSION = "${blackberry.os.version}"; 85 | } 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /jad.template: -------------------------------------------------------------------------------- 1 | MIDlet-Name: @midletName@ 2 | MIDlet-Version: @buildVer@ 3 | MIDlet-Vendor: BlackBerrySmart 4 | MIDlet-Description: The Smart Way to View Email 5 | MicroEdition-Profile: MIDP-2.0 6 | MicroEdition-Configuration: CLDC-1.1 7 | MIDlet-Jar-URL: @jarName@ 8 | MIDlet-Jar-Size: @jarSize@ 9 | MIDlet-1: BBSmart,, 10 | RIM-MIDlet-Flags-1: 35 -------------------------------------------------------------------------------- /lib/thirdparty/SignatureTool.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/SignatureTool.jar -------------------------------------------------------------------------------- /lib/thirdparty/ant-contrib-1.0b3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/ant-contrib-1.0b3.jar -------------------------------------------------------------------------------- /lib/thirdparty/antenna-bin-0.9.14.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/antenna-bin-0.9.14.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0.2/net_rim_api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0.2/net_rim_api.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0.2/preverify.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0.2/preverify.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0.2/rapc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0.2/rapc.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0.2/rapc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0.2/rapc.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0/net_rim_api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0/net_rim_api.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0/preverify.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0/preverify.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0/rapc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0/rapc.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.0/rapc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.0/rapc.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.1.0/net_rim_api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.1.0/net_rim_api.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.1.0/preverify.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.1.0/preverify.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.1.0/rapc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.1.0/rapc.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.1.0/rapc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.1.0/rapc.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.2.0/net_rim_api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.2.0/net_rim_api.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.2.0/preverify.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.2.0/preverify.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.2.0/rapc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.2.0/rapc.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.2.0/rapc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.2.0/rapc.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.3.0/net_rim_api.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.3.0/net_rim_api.jar -------------------------------------------------------------------------------- /lib/thirdparty/jde4.3.0/preverify.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.3.0/preverify.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.3.0/rapc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.3.0/rapc.exe -------------------------------------------------------------------------------- /lib/thirdparty/jde4.3.0/rapc.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/lib/thirdparty/jde4.3.0/rapc.jar -------------------------------------------------------------------------------- /res/img/folder_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/folder_logo.png -------------------------------------------------------------------------------- /res/img/heading_240x26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/heading_240x26.jpg -------------------------------------------------------------------------------- /res/img/heading_320x34.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/heading_320x34.jpg -------------------------------------------------------------------------------- /res/img/icons/icon_doc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_doc.gif -------------------------------------------------------------------------------- /res/img/icons/icon_generic.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_generic.gif -------------------------------------------------------------------------------- /res/img/icons/icon_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_image.gif -------------------------------------------------------------------------------- /res/img/icons/icon_pdf.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_pdf.gif -------------------------------------------------------------------------------- /res/img/icons/icon_ppt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_ppt.gif -------------------------------------------------------------------------------- /res/img/icons/icon_txt.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_txt.gif -------------------------------------------------------------------------------- /res/img/icons/icon_xls.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_xls.gif -------------------------------------------------------------------------------- /res/img/icons/icon_zip.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/icons/icon_zip.gif -------------------------------------------------------------------------------- /res/img/img_err_11x11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/img_err_11x11.png -------------------------------------------------------------------------------- /res/img/img_err_15x15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/img_err_15x15.png -------------------------------------------------------------------------------- /res/img/infobar_240x13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/infobar_240x13.jpg -------------------------------------------------------------------------------- /res/img/infobar_320x13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/infobar_320x13.jpg -------------------------------------------------------------------------------- /res/img/infobar_bottom_320x4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/infobar_bottom_320x4.jpg -------------------------------------------------------------------------------- /res/img/line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/line.png -------------------------------------------------------------------------------- /res/img/loadingbar_320x16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/loadingbar_320x16.jpg -------------------------------------------------------------------------------- /res/img/loadingbar_done_320x16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/loadingbar_done_320x16.jpg -------------------------------------------------------------------------------- /res/img/loadingbar_err_240x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/loadingbar_err_240x24.png -------------------------------------------------------------------------------- /res/img/loadingbar_err_320x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/loadingbar_err_320x32.png -------------------------------------------------------------------------------- /res/img/lock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/lock.jpg -------------------------------------------------------------------------------- /res/img/more_off_240x14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/more_off_240x14.jpg -------------------------------------------------------------------------------- /res/img/more_off_320x14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/more_off_320x14.jpg -------------------------------------------------------------------------------- /res/img/more_on_240x14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/more_on_240x14.jpg -------------------------------------------------------------------------------- /res/img/more_on_320x14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/more_on_320x14.jpg -------------------------------------------------------------------------------- /res/img/original-follows-text_240x12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/original-follows-text_240x12.png -------------------------------------------------------------------------------- /res/img/original-follows-text_320x12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/original-follows-text_320x12.png -------------------------------------------------------------------------------- /res/img/pencil.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/pencil.gif -------------------------------------------------------------------------------- /res/img/separator_320x1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/separator_320x1.jpg -------------------------------------------------------------------------------- /res/img/separator_320x4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/separator_320x4.jpg -------------------------------------------------------------------------------- /res/img/smartnote-on-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smartnote-on-16.png -------------------------------------------------------------------------------- /res/img/smileys/laugh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/laugh.gif -------------------------------------------------------------------------------- /res/img/smileys/love.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/love.gif -------------------------------------------------------------------------------- /res/img/smileys/mad.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/mad.gif -------------------------------------------------------------------------------- /res/img/smileys/ohmy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/ohmy.gif -------------------------------------------------------------------------------- /res/img/smileys/sad.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/sad.gif -------------------------------------------------------------------------------- /res/img/smileys/smile.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/smile.gif -------------------------------------------------------------------------------- /res/img/smileys/tongue.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/tongue.gif -------------------------------------------------------------------------------- /res/img/smileys/wink.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/res/img/smileys/wink.gif -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/BuildVersion.java: -------------------------------------------------------------------------------- 1 | 2 | package com.bbsmart.pda.blackberry.smartview; 3 | 4 | public class BuildVersion { 5 | public final static String OS_VERSION = "4.3.0"; 6 | } 7 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/SmartView.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 4 | import com.bbsmart.pda.blackberry.smartview.io.Preferences; 5 | import com.bbsmart.pda.blackberry.smartview.ui.customfield.ImageLoadingDialog; 6 | import com.bbsmart.pda.blackberry.smartview.ui.screens.CommsScreen; 7 | import com.bbsmart.pda.blackberry.smartview.ui.screens.EmailViewScreen; 8 | import com.bbsmart.pda.blackberry.smartview.ui.screens.NewTemplateScreen; 9 | import com.bbsmart.pda.blackberry.smartview.ui.screens.OptionsScreen; 10 | import com.bbsmart.pda.blackberry.smartview.ui.screens.RegisterScreen; 11 | import com.bbsmart.pda.blackberry.smartview.ui.screens.SmartSayScreen; 12 | import com.bbsmart.pda.blackberry.smartview.ui.screens.TrialEndedScreen; 13 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 14 | import com.bbsmart.pda.blackberry.smartview.util.EmailFormatter; 15 | 16 | import net.rim.blackberry.api.mail.Message; 17 | import net.rim.blackberry.api.mail.Session; 18 | import net.rim.blackberry.api.mail.event.MessageEvent; 19 | import net.rim.blackberry.api.mail.event.ViewListener; 20 | import net.rim.blackberry.api.menuitem.ApplicationMenuItem; 21 | import net.rim.blackberry.api.menuitem.ApplicationMenuItemRepository; 22 | import net.rim.device.api.system.Application; 23 | import net.rim.device.api.system.Bitmap; 24 | import net.rim.device.api.ui.Field; 25 | import net.rim.device.api.ui.Screen; 26 | import net.rim.device.api.ui.UiApplication; 27 | import net.rim.device.api.ui.component.ActiveAutoTextEditField; 28 | import net.rim.device.api.ui.component.Dialog; 29 | import net.rim.device.api.ui.container.VerticalFieldManager; 30 | 31 | public final class SmartView extends Application implements ViewListener { 32 | private PersistenceManager persistManager; 33 | 34 | private Preferences prefs; 35 | 36 | // Flag to indicate whether this is a trial version 37 | public static boolean DEFAULT_TRIAL = false; 38 | public static final long TRIAL_DURATION_DAYS = 4; // In days 39 | public static final String VERSION_STRING = "2.3"; 40 | public static final String VERSION = "v" + VERSION_STRING; 41 | 42 | // Flag to indicate whether the full version has been registered 43 | public static boolean DEFAULT_REGISTERED = true; 44 | 45 | public static void main(String[] args) { 46 | SmartView sv = new SmartView(); 47 | sv.enterEventDispatcher(); 48 | } 49 | 50 | public SmartView() { 51 | // On startup, register the Message View menu items 52 | ApplicationMenuItemRepository repository = ApplicationMenuItemRepository 53 | .getInstance(); 54 | 55 | BBSmartViewMenuItem viewMenuItem = new BBSmartViewMenuItem(); 56 | BBSmartOptionsMenuItem optionsMenuItem = new BBSmartOptionsMenuItem(); 57 | SmartSayMenuItem smartSayMenuItem = new SmartSayMenuItem(); 58 | CreateTemplateMenuItem createTemplateMenuItem = new CreateTemplateMenuItem(); 59 | 60 | // Add "BBSmart View" to all view and edit email screens 61 | repository 62 | .addMenuItem(ApplicationMenuItemRepository.MENUITEM_EMAIL_VIEW, 63 | viewMenuItem); 64 | repository 65 | .addMenuItem(ApplicationMenuItemRepository.MENUITEM_EMAIL_EDIT, 66 | viewMenuItem); 67 | 68 | // Add "BBSmart Options" to all email screens 69 | repository.addMenuItem( 70 | ApplicationMenuItemRepository.MENUITEM_MESSAGE_LIST, 71 | optionsMenuItem); 72 | repository.addMenuItem( 73 | ApplicationMenuItemRepository.MENUITEM_EMAIL_VIEW, 74 | optionsMenuItem); 75 | repository.addMenuItem( 76 | ApplicationMenuItemRepository.MENUITEM_EMAIL_EDIT, 77 | optionsMenuItem); 78 | 79 | // Add "SmartSay" menu options 80 | repository.addMenuItem( 81 | ApplicationMenuItemRepository.MENUITEM_EMAIL_EDIT, 82 | smartSayMenuItem); 83 | repository.addMenuItem( 84 | ApplicationMenuItemRepository.MENUITEM_EMAIL_VIEW, 85 | createTemplateMenuItem); 86 | 87 | // Also register listeners for message opened events 88 | Session.addViewListener(this); 89 | 90 | // Enable key up events for this application 91 | Application.getApplication().enableKeyUpEvents(true); 92 | 93 | persistManager = PersistenceManager.getInstance(); 94 | prefs = PersistenceManager.getInstance().getPreferences(); 95 | 96 | if (prefs.isTrial()) { 97 | // Record the time the application was first run 98 | // Used to determine when trial version has expired 99 | if (prefs.isFirstTime()) { 100 | prefs.setFirstTimeRun(System.currentTimeMillis()); 101 | persistManager.savePreferences(prefs); 102 | } 103 | } 104 | } 105 | 106 | public void open(MessageEvent e) { 107 | Message m = e.getMessage(); 108 | if (m.getStatus() == Message.Status.TX_COMPOSING) { 109 | return; 110 | } 111 | 112 | if (prefs.isDontAskMeAgain()) { 113 | if (prefs.isDefaultDisplaySmartView()) { 114 | if (prefs.isFirstTime()) { 115 | // On first time running, pop up the Comms Setup Screen 116 | UiApplication.getUiApplication().pushModalScreen( 117 | new CommsScreen()); 118 | } 119 | 120 | // Display the SmartView application 121 | displayEmailViewer(m); 122 | } else { 123 | // Don't do anything - user does not want to see smartview by 124 | // default 125 | } 126 | } else { 127 | Dialog d = new Dialog(Dialog.D_YES_NO, 128 | "View with BBSmart Email Viewer?", Dialog.NO, Bitmap 129 | .getPredefinedBitmap(Bitmap.QUESTION), 0, true); 130 | d.doModal(); 131 | 132 | prefs.setDontAskMeAgain(d.getDontAskAgainValue()); 133 | prefs 134 | .setDefaultDisplaySmartView(d.getSelectedValue() == Dialog.YES); 135 | persistManager.savePreferences(prefs); 136 | 137 | if (d.getSelectedValue() == Dialog.YES) { 138 | if (prefs.isFirstTime()) { 139 | // On first time running, pop up the Comms Setup Screen 140 | UiApplication.getUiApplication().pushModalScreen( 141 | new CommsScreen()); 142 | } 143 | 144 | // Display the SmartView application 145 | displayEmailViewer(m); 146 | } else { 147 | // Don't do anything - user does not want to see smartview by 148 | // default 149 | } 150 | } 151 | } 152 | 153 | public void close(MessageEvent e) { 154 | // Do nothing on email close (don't care) 155 | } 156 | 157 | private void displayEmailViewer(final Message m) { 158 | if (hasExpired()) { 159 | UiApplication.getUiApplication().pushScreen(new TrialEndedScreen()); 160 | } else { 161 | if (!prefs.isTrial() && !prefs.isRegistered()) { 162 | // Recently purchased full copy 163 | UiApplication.getUiApplication().pushScreen( 164 | new RegisterScreen()); 165 | } else { 166 | if (prefs.isDisplayImagesInEmail() 167 | && !prefs.isLastConnSuccessful()) { 168 | prefs.setDisplayImagesInEmail(false); 169 | persistManager.savePreferences(prefs); 170 | 171 | Dialog d = new Dialog( 172 | Dialog.D_OK, 173 | "BBSmart Email Viewer has detected that your " 174 | + "connection settings may not be correct and has disabled images from displaying.\n\n" 175 | + "To configure your connection settings, please go to the Connection Setup screen (" 176 | + "available from the BBSmart Options screen) and test your connection.\n\n" 177 | + "Images can be re-enabled from the Options Screen.", 178 | Dialog.OK, Bitmap 179 | .getPredefinedBitmap(Bitmap.EXCLAMATION), 0); 180 | d.doModal(); 181 | } 182 | 183 | // format the email prior to launching the new display 184 | EmailFormatter formatter = new EmailFormatter(m); 185 | formatter.formatEmail(); 186 | UiApplication.getUiApplication().pushScreen( 187 | new EmailViewScreen(m, formatter)); 188 | 189 | if (formatter.getNumImagesInEmail() > 0) { 190 | UiApplication.getUiApplication().pushScreen( 191 | new ImageLoadingDialog(formatter 192 | .getNumImagesInEmail())); 193 | } 194 | } 195 | } 196 | } 197 | 198 | public boolean hasExpired() { 199 | if (prefs.isTrial()) { 200 | final long MILLIS_IN_DAY = 1000 * 60 * 60 * 24; 201 | 202 | long currentTime = System.currentTimeMillis(); 203 | long startTime = prefs.getFirstTimeRun(); 204 | 205 | if (currentTime < startTime) { // Catch out funny business... 206 | return true; 207 | } 208 | 209 | if (currentTime - startTime >= MILLIS_IN_DAY * TRIAL_DURATION_DAYS) { 210 | // Trial period has expired 211 | return true; 212 | } 213 | } 214 | 215 | return false; 216 | } 217 | 218 | class BBSmartViewMenuItem extends ApplicationMenuItem { 219 | public BBSmartViewMenuItem() { 220 | super(0); 221 | } 222 | 223 | public Object run(Object context) { 224 | if (context == null || !(context instanceof Message)) { 225 | UiUtilities 226 | .alertDialog("No email selected. Please select an email first"); 227 | return null; 228 | } else { 229 | if (PersistenceManager.getInstance().getPreferences() 230 | .isFirstTime()) { 231 | // On first time running, pop up the Comms Setup Screen 232 | UiApplication.getUiApplication().pushModalScreen( 233 | new CommsScreen()); 234 | } 235 | 236 | Message message = (Message) context; 237 | displayEmailViewer(message); 238 | return message; 239 | } 240 | } 241 | 242 | public String toString() { 243 | return "BBSmart View"; 244 | } 245 | } 246 | 247 | class BBSmartOptionsMenuItem extends ApplicationMenuItem { 248 | public BBSmartOptionsMenuItem() { 249 | super(0); 250 | } 251 | 252 | public Object run(Object context) { 253 | UiApplication.getUiApplication().pushScreen(new OptionsScreen()); 254 | return context; 255 | } 256 | 257 | public String toString() { 258 | return "BBSmart Options"; 259 | } 260 | } 261 | 262 | class SmartSayMenuItem extends ApplicationMenuItem { 263 | public SmartSayMenuItem() { 264 | super(0); 265 | } 266 | 267 | public Object run(Object context) { 268 | if (hasExpired()) { 269 | UiApplication.getUiApplication().pushScreen( 270 | new TrialEndedScreen()); 271 | } else { 272 | Screen s = UiApplication.getUiApplication().getActiveScreen(); 273 | 274 | // Due to layout changes in OS 4.3, need to grab the edit 275 | // field to insert template text in a different way 276 | if (BuildVersion.OS_VERSION.equals("4.3.0")) { 277 | Field f = s.getLeafFieldWithFocus(); 278 | 279 | if (f instanceof ActiveAutoTextEditField) { 280 | UiApplication.getUiApplication() 281 | .pushScreen( 282 | new SmartSayScreen( 283 | (ActiveAutoTextEditField) f)); 284 | } else { 285 | // Did not have the text entry field highlighted 286 | UiUtilities 287 | .alertDialog("Please position your cursor where you would like the template inserted first"); 288 | } 289 | } else { 290 | VerticalFieldManager vfm = (VerticalFieldManager) s 291 | .getDelegate().getField(0); 292 | 293 | ActiveAutoTextEditField editField; 294 | try { 295 | editField = (ActiveAutoTextEditField) vfm.getField(vfm 296 | .getFieldCount() - 1); 297 | } catch (Exception e) { 298 | editField = (ActiveAutoTextEditField) vfm.getField(vfm 299 | .getFieldCount() - 2); 300 | } 301 | 302 | UiApplication.getUiApplication().pushScreen( 303 | new SmartSayScreen(editField)); 304 | } 305 | } 306 | return context; 307 | } 308 | 309 | public String toString() { 310 | return "SmartSay..."; 311 | } 312 | } 313 | 314 | class CreateTemplateMenuItem extends ApplicationMenuItem { 315 | public CreateTemplateMenuItem() { 316 | super(0); 317 | } 318 | 319 | public Object run(Object context) { 320 | if (hasExpired()) { 321 | UiApplication.getUiApplication().pushScreen( 322 | new TrialEndedScreen()); 323 | } else { 324 | if (context != null && context instanceof Message) { 325 | Message m = (Message) context; 326 | 327 | UiApplication.getUiApplication().pushScreen( 328 | new NewTemplateScreen(m.getBodyText())); 329 | } 330 | } 331 | 332 | return context; 333 | } 334 | 335 | public String toString() { 336 | return "Save as Template"; 337 | } 338 | } 339 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/EmailColorPreference.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import net.rim.device.api.util.Persistable; 4 | 5 | public class EmailColorPreference implements Persistable { 6 | public int color; 7 | public String emailAddress; 8 | public String emailAccountName; 9 | 10 | public EmailColorPreference(String emailAddress, String emailAccountName, 11 | int color) { 12 | this.emailAccountName = emailAccountName; 13 | this.emailAddress = emailAddress; 14 | this.color = color; 15 | } 16 | 17 | public String toString() { 18 | return emailAddress; 19 | } 20 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/GeneralStoreInterface.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import java.util.Vector; 4 | 5 | import com.bbsmart.pda.blackberry.smartview.util.EmailTemplate; 6 | 7 | public class GeneralStoreInterface { 8 | public static String getStoreVersion() { 9 | return (String) getProperty("storeVersion"); 10 | } 11 | 12 | public static String getHeaderFontSize() { 13 | return (String) getProperty("headerFontSize"); 14 | } 15 | 16 | public static String getBISConnUID() { 17 | return (String) getProperty("bisConnUID"); 18 | } 19 | 20 | public static void setBISConnUID(String bisConnUID) { 21 | setProperty("bisConnUID", bisConnUID); 22 | } 23 | 24 | public static void setHeaderFontSize(String value) { 25 | setProperty("headerFontSize", value); 26 | } 27 | 28 | public static boolean isHeaderBoldFont() { 29 | return ((Boolean) getProperty("headerBoldFont")).booleanValue(); 30 | } 31 | 32 | public static void setHeaderBoldFont(boolean value) { 33 | setProperty("headerBoldFont", new Boolean(value)); 34 | } 35 | 36 | public static EmailTemplate[] getEmailTemplates() { 37 | Vector titles = (Vector) getProperty("templateTitles"); 38 | Vector texts = (Vector) getProperty("templateValues"); 39 | 40 | EmailTemplate[] templates = new EmailTemplate[titles.size()]; 41 | for (int i = 0; i < titles.size(); i++) { 42 | templates[i] = new EmailTemplate((String) titles.elementAt(i), 43 | (String) texts.elementAt(i)); 44 | } 45 | 46 | return templates; 47 | } 48 | 49 | public static boolean createEmailTemplate(String title, String text) { 50 | Vector titles = (Vector) getProperty("templateTitles"); 51 | Vector texts = (Vector) getProperty("templateValues"); 52 | 53 | // Cannot create two templates with the same name 54 | if (titles.contains(title)) { 55 | return false; 56 | } else { 57 | titles.addElement(title); 58 | texts.addElement(text); 59 | return true; 60 | } 61 | } 62 | 63 | public static boolean updateEmailTemplate(String oldTitle, String newTitle, 64 | String text) { 65 | Vector titles = (Vector) getProperty("templateTitles"); 66 | Vector texts = (Vector) getProperty("templateValues"); 67 | 68 | int index = titles.indexOf(oldTitle); 69 | if (index != -1) { 70 | if (oldTitle.equals(newTitle)) { 71 | // No title change so just update the text 72 | texts.removeElementAt(index); 73 | texts.insertElementAt(text, index); 74 | return true; 75 | } else { 76 | // Title has changed...make sure the new title isn't already in use 77 | if (titles.contains(newTitle)) { 78 | return false; 79 | } else { 80 | // New title is different from old title and new title 81 | // is not in use. Delete old, insert new 82 | titles.removeElementAt(index); 83 | texts.removeElementAt(index); 84 | 85 | titles.insertElementAt(newTitle, index); 86 | texts.insertElementAt(text, index); 87 | return true; 88 | } 89 | } 90 | } 91 | 92 | return false; 93 | } 94 | 95 | public static void moveTemplateUp(String title) { 96 | Vector titles = (Vector) getProperty("templateTitles"); 97 | Vector texts = (Vector) getProperty("templateValues"); 98 | 99 | // Move the title up 100 | int index = titles.indexOf(title); 101 | String toMoveDown = (String) titles.elementAt(index - 1); 102 | titles.removeElementAt(index - 1); 103 | titles.insertElementAt(toMoveDown, index); 104 | 105 | // Move the template up 106 | toMoveDown = (String) texts.elementAt(index - 1); 107 | texts.removeElementAt(index - 1); 108 | texts.insertElementAt(toMoveDown, index); 109 | } 110 | 111 | public static void moveTemplateDown(String title) { 112 | Vector titles = (Vector) getProperty("templateTitles"); 113 | Vector texts = (Vector) getProperty("templateValues"); 114 | 115 | // Move the title up 116 | int index = titles.indexOf(title); 117 | String toMoveUp = (String) titles.elementAt(index); 118 | titles.removeElementAt(index); 119 | titles.insertElementAt(toMoveUp, index + 1); 120 | 121 | // Move the template up 122 | toMoveUp = (String) texts.elementAt(index); 123 | texts.removeElementAt(index); 124 | texts.insertElementAt(toMoveUp, index + 1); 125 | } 126 | 127 | public static void deleteEmailTemplate(String title) { 128 | Vector titles = (Vector) getProperty("templateTitles"); 129 | Vector texts = (Vector) getProperty("templateValues"); 130 | 131 | int index = titles.indexOf(title); 132 | if (index != -1) { 133 | titles.removeElementAt(index); 134 | texts.removeElementAt(index); 135 | } 136 | } 137 | 138 | private static void setProperty(String key, Object value) { 139 | PersistenceManager.getInstance().getDataStore().put(key, value); 140 | } 141 | 142 | private static Object getProperty(String key) { 143 | return PersistenceManager.getInstance().getDataStore().get(key); 144 | } 145 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/ImageCache.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import java.util.Enumeration; 4 | 5 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 6 | 7 | import net.rim.device.api.util.MultiMap; 8 | import net.rim.device.api.util.Persistable; 9 | 10 | public final class ImageCache implements Persistable { 11 | // The number of images held in the cache 12 | private int numImages; 13 | 14 | // The total size of the cache (in bytes) 15 | private int cacheSize; 16 | 17 | // The actual cache itself: url(key) -> data(value) mapping 18 | private MultiMap cache; 19 | 20 | // Holds the images which are "always in cache" (predefined) 21 | private MultiMap predefinedCache; 22 | 23 | public ImageCache() { 24 | numImages = 0; 25 | cacheSize = 0; 26 | cache = new MultiMap(); 27 | 28 | initPredefinedCache(); 29 | addPredefinedCache(); 30 | } 31 | 32 | private void initPredefinedCache() { 33 | // Initialise the predefined cache 34 | predefinedCache = new MultiMap(2, 1); 35 | 36 | String image; 37 | if (UiUtilities.DEVICE_240W) { 38 | image = new String(UiUtilities 39 | .getImageBytes("original-follows-text_240x12.png")); 40 | } else { 41 | image = new String(UiUtilities 42 | .getImageBytes("original-follows-text_320x12.png")); 43 | } 44 | predefinedCache.add("http://localhost/original.png", image); 45 | 46 | image = new String(UiUtilities.getImageBytes("separator_320x4.jpg")); 47 | predefinedCache.add("http://localhost/line.jpg", image); 48 | 49 | image = new String(UiUtilities.getImageBytes("lock.jpg")); 50 | predefinedCache.add("http://localhost/lock.jpg", image); 51 | 52 | // Insert Smileys into cache 53 | image = new String(UiUtilities.getImageBytes("smileys/smile.gif")); 54 | predefinedCache.add("http://localhost/smile.gif", image); 55 | 56 | image = new String(UiUtilities.getImageBytes("smileys/tongue.gif")); 57 | predefinedCache.add("http://localhost/tongue.gif", image); 58 | 59 | image = new String(UiUtilities.getImageBytes("smileys/sad.gif")); 60 | predefinedCache.add("http://localhost/sad.gif", image); 61 | 62 | image = new String(UiUtilities.getImageBytes("smileys/laugh.gif")); 63 | predefinedCache.add("http://localhost/laugh.gif", image); 64 | 65 | image = new String(UiUtilities.getImageBytes("smileys/wink.gif")); 66 | predefinedCache.add("http://localhost/wink.gif", image); 67 | 68 | image = new String(UiUtilities.getImageBytes("smileys/love.gif")); 69 | predefinedCache.add("http://localhost/love.gif", image); 70 | 71 | image = new String(UiUtilities.getImageBytes("smileys/mad.gif")); 72 | predefinedCache.add("http://localhost/mad.gif", image); 73 | 74 | image = new String(UiUtilities.getImageBytes("smileys/ohmy.gif")); 75 | predefinedCache.add("http://localhost/ohmy.gif", image); 76 | } 77 | 78 | public boolean addImageToCache(String url, String contents) { 79 | if (!cache.containsKey(url)) { 80 | if (cache.add(url, contents)) { 81 | numImages++; 82 | cacheSize += contents.getBytes().length; 83 | return true; 84 | } else { 85 | return false; 86 | } 87 | } else { 88 | return false; 89 | } 90 | } 91 | 92 | public String getImage(String url) { 93 | if (cache.containsKey(url)) { 94 | return (String) cache.elements(url).nextElement(); 95 | } else { 96 | return null; 97 | } 98 | } 99 | 100 | public boolean containsImage(String url) { 101 | return cache.containsKey(url); 102 | } 103 | 104 | public int getCacheSize() { 105 | return cacheSize; 106 | } 107 | 108 | public MultiMap getPredefinedCache() { 109 | return predefinedCache; 110 | } 111 | 112 | private void addPredefinedCache() { 113 | Enumeration elements = predefinedCache.elements(); 114 | Enumeration keys = predefinedCache.keys(); 115 | while (keys.hasMoreElements()) { 116 | cache.add((String) keys.nextElement(), (String) elements 117 | .nextElement()); 118 | } 119 | } 120 | 121 | public void clear() { 122 | cache.clear(); 123 | numImages = 0; 124 | cacheSize = 0; 125 | addPredefinedCache(); 126 | } 127 | 128 | /** 129 | * Automatically clears the cache out if a certain amount of time has past 130 | * (as specified by the preferences). This method is invoked every time an 131 | * email is opened using the Email Viewer. 132 | */ 133 | public void autoClear() { 134 | PersistenceManager persistManager = PersistenceManager.getInstance(); 135 | Preferences prefs = persistManager.getPreferences(); 136 | 137 | long currentTime = System.currentTimeMillis(); 138 | long lastClearTime = prefs.getLastCacheClearTime(); 139 | 140 | // The number of milliseconds in a day 141 | long millisInDay = 1000 * 60 * 60 * 24; 142 | 143 | boolean clearCache = false; 144 | 145 | switch (prefs.getCacheClearFreq()) { 146 | case Preferences.CACHE_CLEAR_DAY: 147 | clearCache = currentTime > (lastClearTime + millisInDay); 148 | break; 149 | case Preferences.CACHE_CLEAR_2DAYS: 150 | clearCache = currentTime > (lastClearTime + millisInDay * 2); 151 | break; 152 | case Preferences.CACHE_CLEAR_WEEK: 153 | clearCache = currentTime > (lastClearTime + millisInDay * 7); 154 | break; 155 | case Preferences.CACHE_CLEAR_MONTH: 156 | clearCache = currentTime > (lastClearTime + millisInDay * 30); 157 | break; 158 | case Preferences.CACHE_CLEAR_NEVER: 159 | clearCache = false; 160 | break; 161 | } 162 | 163 | if (clearCache) { 164 | clear(); 165 | prefs.updateLastCacheClearTime(); 166 | 167 | persistManager.savePreferences(prefs); 168 | persistManager.saveImageCache(this); 169 | } 170 | } 171 | 172 | public String getDisplayableCacheSize() { 173 | final int KB = 1024; 174 | final int MB = 1048576; 175 | 176 | if (cacheSize < KB) { 177 | return cacheSize + "b"; 178 | } else if (cacheSize < MB) { 179 | return (cacheSize / KB) + "KB"; 180 | } else { 181 | return (cacheSize / MB) + "MB"; 182 | } 183 | } 184 | 185 | public static boolean isImage(String filename) { 186 | return (filename.endsWith(".jpg") || filename.endsWith(".jpeg") 187 | || filename.endsWith(".gif") || filename.endsWith(".png") || filename 188 | .endsWith(".bmp")); 189 | } 190 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/PersistenceManager.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import java.util.Hashtable; 4 | import java.util.Vector; 5 | 6 | import net.rim.device.api.system.PersistentObject; 7 | import net.rim.device.api.system.PersistentStore; 8 | 9 | /** 10 | * Save the preferences and other items to the PDA. 11 | * 12 | * @author Neil Sainsbury 13 | */ 14 | public final class PersistenceManager { 15 | // key is hash of string "com.bbsmart.pda.blackberry.smartview" 16 | private static PersistentObject store = PersistentStore 17 | .getPersistentObject(0xb40623371807f332L); 18 | 19 | private static Vector data; 20 | 21 | private static final int STORE_PREF_INDX = 0; 22 | private static final int STORE_WAP_LIST_INDX = 1; 23 | private static final int STORE_ICACHE_INDX = 2; 24 | public static final int STORE_SNOTE_INDX = 3; 25 | public static final int STORE_CPREF_INDX = 4; 26 | public static final int STORE_GDATA_INDX = 5; 27 | 28 | private static PersistenceManager instance; 29 | 30 | // Singleton Accessor 31 | public static PersistenceManager getInstance() { 32 | if (instance == null) { 33 | instance = new PersistenceManager(); 34 | } 35 | return instance; 36 | } 37 | 38 | static { 39 | synchronized (store) { 40 | data = (Vector) store.getContents(); 41 | if (data == null) { 42 | data = new Vector(); 43 | 44 | // PERSISTENT DATA 45 | data.addElement(new Preferences()); // Preferences 46 | data.addElement(initWAPProviderList()); // WAP Provider list 47 | data.addElement(new ImageCache()); // Image Cache 48 | data.addElement(new SmartNoteManager()); // Smart Notes -- added v2.2 49 | data.addElement(new Vector()); // Color preferences -- added v2.2 50 | data.addElement(new Hashtable()); // General data store - added v2.3 51 | // END PERSISTENT DATA 52 | 53 | store.setContents(data); 54 | store.commit(); 55 | } else { 56 | // Data is not null - if only 3 elements in list user has v2.1 57 | // or lower so perform an upgrade to v2.3 which now has the 58 | // smart note manager, email header color preferences and general data store 59 | if (data.size() == 3) { 60 | data.addElement(new SmartNoteManager()); 61 | data.addElement(new Vector()); 62 | data.addElement(new Hashtable()); 63 | } else if (data.size() == 5) { 64 | // User had v2.2 - upgrade to v2.3 which now has general data store 65 | data.addElement(new Hashtable()); 66 | } 67 | } 68 | 69 | upgradeDataStore(); 70 | } 71 | } 72 | 73 | private static void upgradeDataStore() { 74 | Hashtable gData = (Hashtable) data.elementAt(STORE_GDATA_INDX); 75 | 76 | // Upgrade from v2.2 to v2.3 -- previously no general data store 77 | if (gData.size() == 0) { 78 | gData.put("storeVersion", "2.3"); 79 | gData.put("headerFontSize", "Medium"); 80 | gData.put("headerBoldFont", Boolean.TRUE); 81 | gData.put("templateTitles", new Vector()); 82 | gData.put("templateValues", new Vector()); 83 | 84 | initDefaultTemplates(); 85 | } 86 | } 87 | 88 | private static void initDefaultTemplates() { 89 | Hashtable gData = (Hashtable) data.elementAt(STORE_GDATA_INDX); 90 | 91 | Vector titles = (Vector) gData.get("templateTitles"); 92 | Vector templates = (Vector) gData.get("templateValues"); 93 | 94 | titles.addElement("Business Email Signature"); 95 | templates 96 | .addElement("Replace this text with your business email signature.\n\n" 97 | + "Then, next time you are composing a business email select \"SmartSay...\"" 98 | + " from the menu, highlight this entry in the list and select \"Insert in Email\"." 99 | + " Your business signature will be automatically inserted into the email!\n\n" 100 | + "Less typing! Less frustration! More time to take care of what is really important..."); 101 | 102 | titles.addElement("Personal Email Signature"); 103 | templates 104 | .addElement("Replace this text with your personal email signature.\n\n" 105 | + "Then, next time you are composing a personal email select \"SmartSay...\"" 106 | + " from the menu, highlight this entry in the list and select \"Insert in Email\"." 107 | + " Your personal signature will be automatically inserted into the email!\n\n" 108 | + "Less typing! Less frustration! More time to take care of what is really important..."); 109 | 110 | titles.addElement("My Phone Number"); 111 | templates 112 | .addElement("Need to email somebody your phone number? Dread grappling with the small number keys?\n\n" 113 | + "Easy! Replace this text with your phone number and then the next time you are composing an email select \"SmartSay...\"" 114 | + " from the menu, highlight this entry in the list and select \"Insert in Email\"." 115 | + " Your phone number will be automatically inserted into the email!\n\n" 116 | + "Less typing! Less frustration! More time to take care of what is really important..."); 117 | 118 | } 119 | 120 | public Hashtable getDataStore() { 121 | return (Hashtable) getStoreDataAtIndex(STORE_GDATA_INDX); 122 | } 123 | 124 | public void saveDataStore(Hashtable t) { 125 | setStoreDataAtIndex(STORE_GDATA_INDX, t); 126 | } 127 | 128 | // Suppress generation of public (default) constructor 129 | private PersistenceManager() { 130 | } 131 | 132 | public Preferences getPreferences() { 133 | return (Preferences) getStoreDataAtIndex(STORE_PREF_INDX); 134 | } 135 | 136 | public void savePreferences(Preferences p) { 137 | setStoreDataAtIndex(STORE_PREF_INDX, p); 138 | } 139 | 140 | public Vector getProviderList() { 141 | return (Vector) getStoreDataAtIndex(STORE_WAP_LIST_INDX); 142 | } 143 | 144 | public ImageCache getImageCache() { 145 | return (ImageCache) getStoreDataAtIndex(STORE_ICACHE_INDX); 146 | } 147 | 148 | public void saveImageCache(ImageCache ic) { 149 | setStoreDataAtIndex(STORE_ICACHE_INDX, ic); 150 | } 151 | 152 | public SmartNoteManager getSmartNoteManager() { 153 | return (SmartNoteManager) getStoreDataAtIndex(STORE_SNOTE_INDX); 154 | } 155 | 156 | public void saveSmartNoteManager(SmartNoteManager snm) { 157 | setStoreDataAtIndex(STORE_SNOTE_INDX, snm); 158 | } 159 | 160 | public Vector getEmailColorPrefs() { 161 | return (Vector) getStoreDataAtIndex(STORE_CPREF_INDX); 162 | } 163 | 164 | public void saveEmailColorPrefs(Vector cprefs) { 165 | setStoreDataAtIndex(STORE_CPREF_INDX, cprefs); 166 | } 167 | 168 | private static Vector initWAPProviderList() { 169 | Vector providers = new Vector(40); 170 | 171 | providers.addElement(new WAPGatewayProvider(1, "Amena (ESP)", 172 | "internet", "213.143.33.8")); 173 | providers.addElement(new WAPGatewayProvider(2, "AT&T Wireless (USA)", 174 | "proxy", "10.250.250.250")); 175 | providers.addElement(new WAPGatewayProvider(3, "BT Mobile (UK)", 176 | "mobile.bt.uk", "149.254.201.132")); 177 | providers.addElement(new WAPGatewayProvider(4, "Cincinnati Bell (USA)", 178 | "wap.gocbw.com", "216.68.79.199")); 179 | providers.addElement(new WAPGatewayProvider(5, "Cingular (USA)", 180 | "wap.cingular", "66.209.11.61", "9203")); 181 | providers.addElement(new WAPGatewayProvider(6, "CSL 1010 (HKG)", 182 | "hkcsl", "192.168.59.51")); 183 | providers.addElement(new WAPGatewayProvider(7, "E-Plus (GBR)", 184 | "wap.eplus.de", "212.23.97.9")); 185 | providers.addElement(new WAPGatewayProvider(8, "Fido (CAN)", 186 | "internet.fido.ca", "205.151.11.11", "fido", "fido")); 187 | providers.addElement(new WAPGatewayProvider(9, "Movistar (ESP)", 188 | "movistar.es", "194.179.1.100")); 189 | providers.addElement(new WAPGatewayProvider(10, "Omnitel (ITA)", 190 | "wap.omnitel.it", "10.128.201.76")); 191 | providers.addElement(new WAPGatewayProvider(11, "Optus (AUS)", 192 | "wap.optus.net.au", "202.139.83.152")); 193 | providers.addElement(new WAPGatewayProvider(12, "Orange (FRA)", 194 | "orange.fr", "192.168.10.200")); 195 | providers.addElement(new WAPGatewayProvider(13, "Orange (GBR)", 196 | "orangewap", "192.168.71.35")); 197 | providers.addElement(new WAPGatewayProvider(14, "O2 (GBR)", 198 | "wap.o2.co.uk", "193.113.200.195", "o2wap", "password")); 199 | providers.addElement(new WAPGatewayProvider(15, "O2 (DEU)", 200 | "wap.viaginterkorn.de", "195.182.114.52")); 201 | providers.addElement(new WAPGatewayProvider(16, "O2 (NLD)", "internet", 202 | "193.113.200.195")); 203 | providers.addElement(new WAPGatewayProvider(17, "O2 (IRL)", 204 | "wap.dol.ie", "192.168.90.74")); 205 | providers.addElement(new WAPGatewayProvider(18, "Rogers AT&T (CAN)", 206 | "blackberry.net", "208.200.67.150")); 207 | providers.addElement(new WAPGatewayProvider(19, "SFR (FRA)", "wapsfr", 208 | "195.115.25.129")); 209 | providers.addElement(new WAPGatewayProvider(20, "Sunrise (CHE)", 210 | "wap.sunrise.ch", "212.35.34.70")); 211 | providers.addElement(new WAPGatewayProvider(21, "Swisscom (CHE)", 212 | "gprs.swisscom.ch", "192.168.210.1")); 213 | providers.addElement(new WAPGatewayProvider(22, 214 | "Telefonica Movil (USA)", "wap.movistar.es", "192.168.80.21")); 215 | providers.addElement(new WAPGatewayProvider(23, "Telstra (AUS)", 216 | "telstra.wap", "10.1.1.150")); 217 | providers.addElement(new WAPGatewayProvider(24, "Telstra (USA)", 218 | "telstra.internet", "10.1.1.150")); 219 | providers.addElement(new WAPGatewayProvider(25, "Tesco (GBR)", 220 | "prepay.tesco-mobile.com", "193.113.200.195")); 221 | providers.addElement(new WAPGatewayProvider(26, "TIM (ITA)", 222 | "wap.tim.it", "213.26.205.1")); 223 | providers.addElement(new WAPGatewayProvider(27, "T-Mobile (AUT)", 224 | "gprswap", "10.12.0.2")); 225 | providers.addElement(new WAPGatewayProvider(28, "T-Mobile (DEU)", 226 | "wap.t-d1.de", "193.254.160.2")); 227 | providers.addElement(new WAPGatewayProvider(29, "T-Mobile (GBR1)", 228 | "general.t-mobile.uk", "149.254.1.10")); 229 | providers.addElement(new WAPGatewayProvider(30, "T-Mobile (GBR2)", 230 | "blackberry.net", "140.254.1.0")); 231 | providers.addElement(new WAPGatewayProvider(31, "T-Mobile (USA)", 232 | "wap.voicestream.com", "216.155.165.50")); 233 | providers.addElement(new WAPGatewayProvider(32, "Virgin Mobile (GBR)", 234 | "goto.virginmobile.uk", "193.30.166.3")); 235 | providers.addElement(new WAPGatewayProvider(33, "Vodafone (AUS)", 236 | "live.vodafone.com", "10.202.2.60")); 237 | providers.addElement(new WAPGatewayProvider(34, "Vodafone (DEU)", 238 | "wap.vodafone.de", "139.007.029.001")); 239 | providers.addElement(new WAPGatewayProvider(35, "Vodafone (ESP)", 240 | "airtelwap.es", "212.73.32.10")); 241 | providers.addElement(new WAPGatewayProvider(36, "Vodafone (GBR)", 242 | "wap.vodafone.co.uk", "212.183.137.12", "user@vodafone.net", 243 | "user")); 244 | providers.addElement(new WAPGatewayProvider(37, "Vodafone (IRL)", 245 | "live.vodafone.com", "10.24.59.100")); 246 | providers.addElement(new WAPGatewayProvider(38, "Vodafone (NLD)", 247 | "blackberry.vodafone.nl", "192.168.251.150")); 248 | providers.addElement(new WAPGatewayProvider(39, "Vodafone (NZL)", 249 | "wap.vodafone.net.nz", "172.30.38.3")); 250 | providers.addElement(new WAPGatewayProvider(40, "Vodafone (SWE)", 251 | "services.vodafone.net", "172.030.253.241")); 252 | 253 | return providers; 254 | } 255 | 256 | private Object getStoreDataAtIndex(int index) { 257 | Object o = null; 258 | synchronized (store) { 259 | try { 260 | data = (Vector) store.getContents(); 261 | o = data.elementAt(index); 262 | } catch (Exception e) { 263 | return null; // Controlled access exception - hide silently 264 | } 265 | } 266 | return o; 267 | } 268 | 269 | private void setStoreDataAtIndex(int index, Object o) { 270 | synchronized (store) { 271 | try { 272 | data = (Vector) store.getContents(); 273 | data.setElementAt(o, index); 274 | store.setContents(data); 275 | store.commit(); 276 | } catch (Exception e) { 277 | // Controlled access exception - hide silently 278 | } 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/Preferences.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.SmartView; 4 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 5 | import com.bbsmart.pda.blackberry.smartview.io.WAPGatewayProvider; 6 | 7 | import net.rim.device.api.ui.Color; 8 | import net.rim.device.api.util.Persistable; 9 | 10 | /** 11 | * User preferences. These are saved to persistent storage. 12 | * 13 | * @author Neil Sainsbury 14 | */ 15 | public final class Preferences implements Persistable { 16 | public static final int CONN_METH_ENT = 1; 17 | 18 | public static final int CONN_METH_TCP = 2; 19 | 20 | public static final int CONN_METH_WAP = 3; 21 | 22 | public static final int CACHE_CLEAR_DAY = 0; 23 | 24 | public static final int CACHE_CLEAR_2DAYS = 1; 25 | 26 | public static final int CACHE_CLEAR_WEEK = 2; 27 | 28 | public static final int CACHE_CLEAR_MONTH = 3; 29 | 30 | public static final int CACHE_CLEAR_NEVER = 4; 31 | 32 | private int connectionMethod; 33 | 34 | private WAPGatewayProvider provider; 35 | 36 | private boolean displayImagesInEmail; 37 | 38 | private boolean defaultDisplaySmartView; 39 | 40 | private boolean dontAskMeAgain; 41 | 42 | private boolean showFullDetails; 43 | 44 | private boolean firstTime; 45 | 46 | private long firstTimeRun; 47 | 48 | private int cacheClearFreq; 49 | 50 | private long lastCacheClearTime; 51 | 52 | private boolean showFullLinks; 53 | 54 | private String fontSize; 55 | 56 | private int fontColor; 57 | 58 | private int fontBgColor; 59 | 60 | private String fontStyle; 61 | 62 | private boolean lastConnSuccessful; 63 | 64 | private boolean displayedConnHelp; 65 | 66 | private boolean autoSetTaskSubject; 67 | 68 | private boolean autoAddTaskNotes; 69 | 70 | private boolean autoSetCalendarSubject; 71 | 72 | private boolean autoAddCalendarNotes; 73 | 74 | private boolean trial; 75 | 76 | private boolean registered; 77 | 78 | public Preferences() { 79 | setDisplayImagesInEmail(true); 80 | 81 | setDefaultDisplaySmartView(true); 82 | 83 | setDontAskMeAgain(false); 84 | 85 | // OS 4.3 does not handle the "Don't ask me again" dialog properly 86 | // so we set this property to true to ensure it never appears 87 | /* //[s430] 88 | setDontAskMeAgain(true); 89 | //[e430] */ 90 | 91 | // default font preferences 92 | setFontSize("3"); 93 | setFontColor(Color.BLACK); 94 | setFontStyle("Comic Sans MS (Bold)"); 95 | setFontBgColor(Color.LEMONCHIFFON); 96 | 97 | setTrial(SmartView.DEFAULT_TRIAL); 98 | setRegistered(SmartView.DEFAULT_REGISTERED); 99 | 100 | setAutoAddTaskNotes(true); 101 | setAutoSetTaskSubject(true); 102 | setAutoSetCalendarSubject(true); 103 | setAutoAddCalendarNotes(false); 104 | setShowFullDetails(false); 105 | setFirstTime(true); 106 | setShowFullLinks(false); 107 | setLastConnSuccessful(false); 108 | setDisplayedConnHelp(false); 109 | setConnectionMethod(CONN_METH_ENT); 110 | setCacheClearFreq(CACHE_CLEAR_WEEK); 111 | updateLastCacheClearTime(); 112 | } 113 | 114 | public void setDisplayImagesInEmail(boolean displayImagesInEmail) { 115 | this.displayImagesInEmail = displayImagesInEmail; 116 | } 117 | 118 | public boolean isDisplayImagesInEmail() { 119 | return displayImagesInEmail; 120 | } 121 | 122 | public void setDontAskMeAgain(boolean dontAskMeAgain) { 123 | this.dontAskMeAgain = dontAskMeAgain; 124 | } 125 | 126 | public boolean isDontAskMeAgain() { 127 | return dontAskMeAgain; 128 | } 129 | 130 | public void setDefaultDisplaySmartView(boolean defaultDisplaySmartView) { 131 | this.defaultDisplaySmartView = defaultDisplaySmartView; 132 | } 133 | 134 | public boolean isDefaultDisplaySmartView() { 135 | return defaultDisplaySmartView; 136 | } 137 | 138 | public void setShowFullDetails(boolean showFullDetails) { 139 | this.showFullDetails = showFullDetails; 140 | } 141 | 142 | public boolean isShowFullDetails() { 143 | return showFullDetails; 144 | } 145 | 146 | public void setFirstTime(boolean firstTime) { 147 | this.firstTime = firstTime; 148 | } 149 | 150 | public boolean isFirstTime() { 151 | return firstTime; 152 | } 153 | 154 | public void setConnectionMethod(int connectionMethod) { 155 | this.connectionMethod = connectionMethod; 156 | } 157 | 158 | public int getConnectionMethod() { 159 | return connectionMethod; 160 | } 161 | 162 | public void setProvider(WAPGatewayProvider provider) { 163 | this.provider = provider; 164 | } 165 | 166 | public WAPGatewayProvider getProvider() { 167 | return provider; 168 | } 169 | 170 | public String getConnectionSuffix() { 171 | String suffix = UiUtilities.EMPTY_STRING; 172 | 173 | switch (connectionMethod) { 174 | case CONN_METH_ENT: 175 | suffix = ";deviceside=false"; 176 | break; 177 | case CONN_METH_TCP: 178 | suffix = ";deviceside=true"; 179 | break; 180 | case CONN_METH_WAP: 181 | suffix = provider.getConnectionSuffix(); 182 | break; 183 | } 184 | 185 | return suffix; 186 | } 187 | 188 | public void setCacheClearFreq(int cacheClearFreq) { 189 | this.cacheClearFreq = cacheClearFreq; 190 | } 191 | 192 | public int getCacheClearFreq() { 193 | return cacheClearFreq; 194 | } 195 | 196 | public void updateLastCacheClearTime() { 197 | this.lastCacheClearTime = System.currentTimeMillis(); 198 | } 199 | 200 | public long getLastCacheClearTime() { 201 | return lastCacheClearTime; 202 | } 203 | 204 | public void setFirstTimeRun(long firstTimeRun) { 205 | this.firstTimeRun = firstTimeRun; 206 | } 207 | 208 | public long getFirstTimeRun() { 209 | return firstTimeRun; 210 | } 211 | 212 | public void setShowFullLinks(boolean showFullLinks) { 213 | this.showFullLinks = showFullLinks; 214 | } 215 | 216 | public boolean isShowFullLinks() { 217 | return showFullLinks; 218 | } 219 | 220 | public void setFontSize(String fontSize) { 221 | this.fontSize = fontSize; 222 | } 223 | 224 | public String getFontSize() { 225 | return fontSize; 226 | } 227 | 228 | public void setFontColor(int fontColor) { 229 | this.fontColor = fontColor; 230 | } 231 | 232 | public int getFontColor() { 233 | return fontColor; 234 | } 235 | 236 | public void setFontStyle(String fontStyle) { 237 | this.fontStyle = fontStyle; 238 | } 239 | 240 | public String getFontStyle() { 241 | return fontStyle; 242 | } 243 | 244 | public void setFontBgColor(int fontBgColor) { 245 | this.fontBgColor = fontBgColor; 246 | } 247 | 248 | public int getFontBgColor() { 249 | return fontBgColor; 250 | } 251 | 252 | public void setLastConnSuccessful(boolean lastConnSuccessful) { 253 | this.lastConnSuccessful = lastConnSuccessful; 254 | } 255 | 256 | public boolean isLastConnSuccessful() { 257 | return lastConnSuccessful; 258 | } 259 | 260 | public void setDisplayedConnHelp(boolean displayedConnHelp) { 261 | this.displayedConnHelp = displayedConnHelp; 262 | } 263 | 264 | public boolean isDisplayedConnHelp() { 265 | return displayedConnHelp; 266 | } 267 | 268 | public void setTrial(boolean trial) { 269 | this.trial = trial; 270 | } 271 | 272 | public boolean isTrial() { 273 | return trial; 274 | } 275 | 276 | public void setRegistered(boolean registered) { 277 | this.registered = registered; 278 | } 279 | 280 | public boolean isRegistered() { 281 | return registered; 282 | } 283 | 284 | public void setAutoSetTaskSubject(boolean autoSetTaskSubject) { 285 | this.autoSetTaskSubject = autoSetTaskSubject; 286 | } 287 | 288 | public boolean isAutoSetTaskSubject() { 289 | return autoSetTaskSubject; 290 | } 291 | 292 | public void setAutoAddTaskNotes(boolean autoAddTaskNotes) { 293 | this.autoAddTaskNotes = autoAddTaskNotes; 294 | } 295 | 296 | public boolean isAutoAddTaskNotes() { 297 | return autoAddTaskNotes; 298 | } 299 | 300 | public void setAutoSetCalendarSubject(boolean autoSetCalendarSubject) { 301 | this.autoSetCalendarSubject = autoSetCalendarSubject; 302 | } 303 | 304 | public boolean isAutoSetCalendarSubject() { 305 | return autoSetCalendarSubject; 306 | } 307 | 308 | public void setAutoAddCalendarNotes(boolean autoAddCalendarNotes) { 309 | this.autoAddCalendarNotes = autoAddCalendarNotes; 310 | } 311 | 312 | public boolean isAutoAddCalendarNotes() { 313 | return autoAddCalendarNotes; 314 | } 315 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/SmartNote.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import net.rim.device.api.util.Persistable; 4 | 5 | /** 6 | * Represents a single SmartNote 7 | * 8 | * @author Neil 9 | */ 10 | public final class SmartNote implements Persistable { 11 | public static final String LOW_P = "Low"; 12 | public static final String NORM_P = "Normal"; 13 | public static final String HIGH_P = "High"; 14 | 15 | public int id; 16 | public String text; 17 | public String priority; 18 | 19 | public boolean equals(Object obj) { 20 | if (obj instanceof SmartNote) { 21 | SmartNote sn = (SmartNote) obj; 22 | return sn.id == this.id; 23 | } 24 | 25 | return false; 26 | } 27 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/SmartNoteManager.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import java.util.Enumeration; 4 | import java.util.Vector; 5 | 6 | import net.rim.blackberry.api.mail.Message; 7 | import net.rim.device.api.util.MultiMap; 8 | import net.rim.device.api.util.Persistable; 9 | 10 | public final class SmartNoteManager implements Persistable { 11 | // Maintains the collection of notes (key is message ID) 12 | private MultiMap notes; 13 | private MultiMap priorities; 14 | private int nextSmartNoteID; 15 | 16 | public SmartNoteManager() { 17 | notes = new MultiMap(); 18 | priorities = new MultiMap(); 19 | nextSmartNoteID = 0; 20 | } 21 | 22 | public Vector getSmartNotes(Message m) { 23 | Vector v = new Vector(); 24 | Enumeration e = notes.elements(new Integer(m.getMessageId())); 25 | while (e.hasMoreElements()) { 26 | v.addElement(e.nextElement()); 27 | } 28 | 29 | return v; 30 | } 31 | 32 | // Deletes all smartnotes associated with a message 33 | public void deleteSmartNotes(Message m) { 34 | Integer key = new Integer(m.getMessageId()); 35 | 36 | notes.removeKey(key); 37 | priorities.removeKey(key); 38 | } 39 | 40 | public void addSmartNote(Message m, SmartNote sn) { 41 | Integer key = new Integer(m.getMessageId()); 42 | 43 | if (!notes.containsKey(key)) { 44 | // Save the priority of the message for restoration later 45 | priorities.add(key, new Byte(m.getPriority())); 46 | } 47 | 48 | sn.id = nextSmartNoteID++; 49 | notes.add(key, sn); 50 | 51 | m.setPriority(Message.Priority.HIGH); 52 | } 53 | 54 | public void deleteSmartNote(Message m, SmartNote sn) { 55 | Integer key = new Integer(m.getMessageId()); 56 | 57 | if (notes.containsKey(key)) { 58 | notes.removeValue(key, sn); 59 | } 60 | 61 | // If there are no more smartnotes now for this message 62 | // then set the priority back to what it used to be 63 | if (!notes.containsKey(key)) { 64 | Enumeration e = priorities.elements(key); 65 | byte oldPriority = ((Byte) e.nextElement()).byteValue(); 66 | 67 | m.setPriority(oldPriority); 68 | 69 | // Now delete this message from the priorities list 70 | // No more smartnotes so no need to save it 71 | priorities.removeKey(key); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/io/WAPGatewayProvider.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.io; 2 | 3 | import net.rim.device.api.util.Comparator; 4 | import net.rim.device.api.util.Persistable; 5 | 6 | /** 7 | * Container class for WAP Gateway Provider information 8 | * 9 | * @author Neil Sainsbury 10 | */ 11 | public final class WAPGatewayProvider implements Persistable, Comparator { 12 | public static final int CUSTOM_ID = -1; 13 | public static final String CUSTOM_NAME = "Custom"; 14 | public static final String DEFAULT_PORT = "9201"; 15 | 16 | private int id; 17 | private String name; 18 | private String apn; 19 | private String ip; 20 | private String port; 21 | private String username; 22 | private String password; 23 | 24 | public WAPGatewayProvider() { 25 | 26 | } 27 | 28 | public WAPGatewayProvider(int id, String name, String apn, String ip) { 29 | this.id = id; 30 | this.name = name; 31 | this.apn = apn; 32 | this.ip = ip; 33 | this.port = DEFAULT_PORT; 34 | } 35 | 36 | public WAPGatewayProvider(int id, String name, String apn, String ip, 37 | String port) { 38 | this.id = id; 39 | this.name = name; 40 | this.apn = apn; 41 | this.ip = ip; 42 | this.port = port; 43 | } 44 | 45 | public WAPGatewayProvider(int id, String name, String apn, String ip, 46 | String username, String password) { 47 | this(id, name, apn, ip); 48 | this.username = username; 49 | this.password = password; 50 | } 51 | 52 | public void setApn(String apn) { 53 | this.apn = apn; 54 | } 55 | 56 | public String getApn() { 57 | return apn; 58 | } 59 | 60 | public void setIp(String ip) { 61 | this.ip = ip; 62 | } 63 | 64 | public String getIp() { 65 | return ip; 66 | } 67 | 68 | public void setPort(String port) { 69 | this.port = port; 70 | } 71 | 72 | public String getPort() { 73 | return port; 74 | } 75 | 76 | public void setUsername(String username) { 77 | this.username = username; 78 | } 79 | 80 | public String getUsername() { 81 | return username; 82 | } 83 | 84 | public void setPassword(String password) { 85 | this.password = password; 86 | } 87 | 88 | public String getPassword() { 89 | return password; 90 | } 91 | 92 | public void setId(int id) { 93 | this.id = id; 94 | } 95 | 96 | public int getId() { 97 | return id; 98 | } 99 | 100 | public void setName(String name) { 101 | this.name = name; 102 | } 103 | 104 | public String getName() { 105 | return name; 106 | } 107 | 108 | public String toString() { 109 | return this.name; 110 | } 111 | 112 | /** 113 | * Returns the String required to append to the end of a connection 114 | * URL when establishing an external HTTP connection over WAP. 115 | * 116 | * @return The connection suffix 117 | */ 118 | public String getConnectionSuffix() { 119 | StringBuffer suffix = new StringBuffer(); 120 | 121 | // Append mandatory wap parameters 122 | suffix.append(";WapGatewayIP="); 123 | suffix.append(getIp()); 124 | suffix.append(";WapGatewayAPN="); 125 | suffix.append(getApn()); 126 | 127 | // Append optional wap parameters 128 | if (port != null && port.length() > 0) { 129 | suffix.append(";WapGatewayPort="); 130 | suffix.append(port); 131 | } 132 | 133 | if (username != null && username.length() > 0) { 134 | suffix.append(";TunnelAuthUsername="); 135 | suffix.append(username); 136 | } 137 | 138 | if (password != null && password.length() > 0) { 139 | suffix.append(";TunnelAuthPassword="); 140 | suffix.append(password); 141 | } 142 | 143 | return suffix.toString(); 144 | } 145 | 146 | public boolean equals(Object obj) { 147 | if (obj instanceof WAPGatewayProvider) { 148 | return ((WAPGatewayProvider) obj).getName() == this.name; 149 | } 150 | return false; 151 | } 152 | 153 | public int compare(Object o1, Object o2) throws ClassCastException { 154 | return ((WAPGatewayProvider) o1).getName().compareTo( 155 | ((WAPGatewayProvider) o2).getName()); 156 | } 157 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/multi/Semaphore.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.multi; 2 | 3 | public final class Semaphore { 4 | 5 | // Semaphore state: (> 0, available); (<= 0, not available) 6 | private int value; 7 | 8 | /** 9 | * Semaphore() creates and returns a reference to a new available binary 10 | * Semaphore preconditions: none postconditions: new free binary Semaphore 11 | * created 12 | */ 13 | public Semaphore() { 14 | value = 1; 15 | } 16 | 17 | /** 18 | * Semaphore(initial) creates and returns a reference to a new Semaphore 19 | * with starting value initial preconditions: none postconditions: new 20 | * Semaphore created with value initial 21 | */ 22 | public Semaphore(int initial) { 23 | value = initial; 24 | } 25 | 26 | /** 27 | * procure() attempts to gain access to the protected critical region, 28 | * waiting until the state specifies this is possible. preconditions: none 29 | * postconditions: InterruptedException thrown if interrupted during wait 30 | * wait is finished. Semaphore state is decremented. 31 | */ 32 | public synchronized void procure() throws InterruptedException { 33 | while (value <= 0) { 34 | wait(); 35 | } 36 | value--; 37 | } 38 | 39 | /** 40 | * vacate() exits the protected critical region, notifying a thread waiting 41 | * on this to occur. preconditions: none; postconditions: Semaphore state is 42 | * incremented. thread waiting is notified 43 | */ 44 | public synchronized void vacate() { 45 | value++; 46 | notify(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/net/HttpConnectionThread.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.net; 2 | 3 | import java.util.Timer; 4 | import java.util.TimerTask; 5 | 6 | /** 7 | * Retrieve content via http/https, and notify the receiver of the raw data when 8 | * it's all received. 9 | * 10 | * @author Neil Sainsbury 11 | */ 12 | public final class HttpConnectionThread extends Thread { 13 | // 15 second connection timeout 14 | public static final int TIMEOUT = 15000; // in ms 15 | 16 | private String url; 17 | 18 | private HttpContentReceiver receiver; 19 | 20 | private boolean cancelled = false; 21 | 22 | public boolean completed = false; 23 | 24 | // Flag to indicate for this connection thread to retrieve the 25 | // clean connection data (perform no post-processing) 26 | private boolean connOnly; 27 | 28 | private Timer timeoutHandler; 29 | 30 | public HttpConnectionThread(String url, HttpContentReceiver receiver, 31 | boolean connOnly) { 32 | this.url = url; 33 | this.receiver = receiver; 34 | this.connOnly = connOnly; 35 | } 36 | 37 | /** 38 | * Cancel the current http request. This may not actually cancel the 39 | * request, just stop the receiver from getting responses after this call. 40 | */ 41 | public synchronized void cancel() { 42 | this.cancelled = true; 43 | timeoutHandler.cancel(); 44 | } 45 | 46 | /** 47 | * Has this request been cancelled? 48 | */ 49 | public synchronized boolean isCancelled() { 50 | return cancelled; 51 | } 52 | 53 | /** 54 | * The main loop to retrieve the data. 55 | */ 56 | public void run() { 57 | String content = null; 58 | 59 | // Initiate the timeout countdown 60 | completed = false; 61 | timeoutHandler = new Timer(); 62 | timeoutHandler.schedule(new TimeoutHandler(this), TIMEOUT); 63 | 64 | try { 65 | content = HttpHelper.getUrl(url, !connOnly); 66 | } catch (Exception e) { 67 | if (receiver != null && !isCancelled()) { 68 | receiver.receivedHttpError(this, e.getMessage()); 69 | } 70 | return; 71 | } finally { 72 | timeoutHandler.cancel(); 73 | completed = true; 74 | } 75 | 76 | if (receiver != null && !isCancelled()) { 77 | receiver.receivedHttpContent(this, content); 78 | } 79 | } 80 | 81 | public HttpContentReceiver getReceiver() { 82 | return receiver; 83 | } 84 | 85 | /** 86 | * The URL for the current request. 87 | * 88 | * @return 89 | */ 90 | public String getUrl() { 91 | return url; 92 | } 93 | } 94 | 95 | class TimeoutHandler extends TimerTask { 96 | private HttpConnectionThread httpConnThread; 97 | 98 | public TimeoutHandler(HttpConnectionThread httpConnThread) { 99 | this.httpConnThread = httpConnThread; 100 | } 101 | 102 | public void run() { 103 | if (!httpConnThread.completed && !httpConnThread.isCancelled()) { 104 | httpConnThread.cancel(); 105 | if (httpConnThread.getReceiver() != null) { 106 | httpConnThread.getReceiver().receivedHttpError(httpConnThread, 107 | "Timeout"); 108 | } 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/net/HttpContentReceiver.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.net; 2 | 3 | /** 4 | * Interface to receive responses from http requests that run in another thread. 5 | * 6 | * @author Neil Sainsbury 7 | */ 8 | public interface HttpContentReceiver { 9 | 10 | /** 11 | * Content from http request was received successfully, and here it is. 12 | * 13 | * @param thread 14 | * @param content 15 | */ 16 | public void receivedHttpContent(HttpConnectionThread thread, String content); 17 | 18 | /** 19 | * There was a problem loading the http content. 20 | * 21 | * @param thread 22 | * @param error 23 | */ 24 | public void receivedHttpError(HttpConnectionThread thread, String error); 25 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/net/HttpHelper.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.net; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | import javax.microedition.io.Connector; 7 | import javax.microedition.io.HttpConnection; 8 | 9 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 10 | 11 | import net.rim.device.api.system.RadioInfo; 12 | 13 | public final class HttpHelper { 14 | public static final String NET_ERR_MSG = "A problem was encountered connecting to the requested server." 15 | + "\n\nPlease check your blackberry has network coverage and try again later" 16 | + "\n\nIf the problem persists, the resource you are requesting may no longer exist"; 17 | 18 | public static final String COVER_ERR_MSG = "Device has no network coverage. " 19 | + "Please ensure the radio is turned on and your blackberry has network coverage"; 20 | 21 | public static String getUrl(String url, boolean unifyEOLs) throws Exception { 22 | HttpConnection httpConn = null; 23 | 24 | if (PersistenceManager.getInstance().getPreferences() 25 | .getConnectionMethod() == 4) { 26 | url += ";deviceside=false;ConnectionType=mds-public"; 27 | } else { 28 | url += PersistenceManager.getInstance().getPreferences() 29 | .getConnectionSuffix(); 30 | } 31 | 32 | if (RadioInfo.getSignalLevel() == RadioInfo.LEVEL_NO_COVERAGE) { 33 | // Device has no coverage - do not even attempt a connection 34 | throw new Exception(COVER_ERR_MSG); 35 | } 36 | 37 | try { 38 | httpConn = (HttpConnection) Connector.open(url, Connector.READ, 39 | true); 40 | 41 | int status = httpConn.getResponseCode(); 42 | if (status == HttpConnection.HTTP_OK) { 43 | // Read the data returned from the server 44 | StringBuffer raw = readHttpData(httpConn); 45 | if (unifyEOLs) { 46 | HttpHelper.unifyEols(raw); 47 | } 48 | return raw.toString(); 49 | } else { 50 | throw new Exception(NET_ERR_MSG); 51 | } 52 | } catch (Exception e) { 53 | throw new Exception(NET_ERR_MSG); 54 | } finally { 55 | if (httpConn != null) { 56 | httpConn.close(); 57 | } 58 | } 59 | } 60 | 61 | private static StringBuffer readHttpData(HttpConnection httpConn) 62 | throws IOException { 63 | InputStream input = null; 64 | StringBuffer raw = new StringBuffer(); 65 | int len = 0; 66 | try { 67 | input = httpConn.openInputStream(); 68 | 69 | byte[] data = new byte[256]; 70 | while (-1 != (len = input.read(data))) { 71 | raw.append(new String(data, 0, len)); 72 | } 73 | } finally { 74 | if (input != null) { 75 | input.close(); 76 | } 77 | } 78 | 79 | return raw; 80 | } 81 | 82 | /** 83 | * remove all the \r's out of the string buffer. This should just remove 84 | * \r's before \n's, but it currently just removes them all. 85 | * 86 | * @param sb 87 | */ 88 | public static void unifyEols(StringBuffer sb) { 89 | for (int i = sb.length(); --i >= 0;) 90 | if (sb.charAt(i) == '\r') 91 | sb.deleteCharAt(i); 92 | } 93 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/net/ImageConnectionManager.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.net; 2 | 3 | import java.util.Vector; 4 | 5 | import javax.microedition.io.HttpConnection; 6 | 7 | import com.bbsmart.pda.blackberry.smartview.io.ImageCache; 8 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 9 | import com.bbsmart.pda.blackberry.smartview.multi.Semaphore; 10 | 11 | import net.rim.device.api.browser.field.BrowserContent; 12 | import net.rim.device.api.browser.field.RequestedResource; 13 | 14 | public final class ImageConnectionManager { 15 | private int completedRequests; 16 | 17 | private int erroredRequests; 18 | 19 | private Semaphore connLimiter; 20 | 21 | private volatile ImageCache iCache; 22 | 23 | private final static ImageConnectionManager instance = new ImageConnectionManager(); 24 | 25 | private volatile Vector failedConnections; 26 | 27 | private volatile Vector requestedConnections; 28 | 29 | private boolean cancelled; 30 | 31 | public static ImageConnectionManager getInstance() { 32 | return instance; 33 | } 34 | 35 | private ImageConnectionManager() { 36 | reset(); 37 | connLimiter = new Semaphore(); 38 | iCache = PersistenceManager.getInstance().getImageCache(); 39 | } 40 | 41 | public void reset() { 42 | cancelled = false; 43 | completedRequests = 0; 44 | erroredRequests = 0; 45 | failedConnections = new Vector(); 46 | requestedConnections = new Vector(); 47 | } 48 | 49 | public void cancel() { 50 | reset(); 51 | this.cancelled = true; 52 | } 53 | 54 | public int getNumCompletedRequests() { 55 | return completedRequests; 56 | } 57 | 58 | public int getNumErroredRequests() { 59 | return erroredRequests; 60 | } 61 | 62 | public void requestImage(RequestedResource resource, BrowserContent referrer) { 63 | if (cancelled) { 64 | return; 65 | } 66 | 67 | try { 68 | connLimiter.procure(); 69 | } catch (InterruptedException ie) { 70 | // Interrupted by some other means 71 | return; 72 | } 73 | 74 | requestedConnections.addElement(resource.getUrl()); 75 | new HttpConnectionThread(resource.getUrl(), new ResourceReceiver( 76 | referrer, resource), true).start(); 77 | } 78 | 79 | public HttpConnection requestCachedImage(RequestedResource resource) { 80 | if (cancelled) { 81 | return null; 82 | } 83 | 84 | // If the image exists in the cache, return it rather than establishing 85 | // an HTTP connection 86 | if (iCache.containsImage(resource.getUrl())) { 87 | if (!iCache.getPredefinedCache().containsKey(resource.getUrl())) { 88 | completedRequests++; 89 | } 90 | 91 | // This image can be returned from the cache 92 | ImageHttpConnection iConn = new ImageHttpConnection(); 93 | iConn.setURL(resource.getUrl()); 94 | iConn.setContent(iCache.getImage(resource.getUrl())); 95 | 96 | return iConn; 97 | } else { 98 | if (failedConnections.contains(resource.getUrl())) { 99 | erroredRequests++; 100 | } 101 | 102 | if (requestedConnections.contains(resource.getUrl())) { 103 | // This image is already being requested from another source 104 | // The browser is smart enough to know this and will therefore 105 | // take care of handling this image in its internal cache 106 | completedRequests++; 107 | } 108 | 109 | return null; 110 | } 111 | } 112 | 113 | class ResourceReceiver implements HttpContentReceiver { 114 | private RequestedResource resource; 115 | 116 | private BrowserContent referrer; 117 | 118 | public ResourceReceiver(BrowserContent referrer, 119 | RequestedResource resource) { 120 | this.resource = resource; 121 | this.referrer = referrer; 122 | } 123 | 124 | public void receivedHttpContent(HttpConnectionThread thread, 125 | String content) { 126 | completedRequests++; 127 | 128 | // Construct a new ImageHttpConnection with the image content loaded 129 | ImageHttpConnection iConn = new ImageHttpConnection(); 130 | iConn.setURL(thread.getUrl()); 131 | iConn.setContent(content); 132 | 133 | resource.setHttpConnection(iConn); 134 | 135 | // Inform the referrer that the resource is ready 136 | referrer.resourceReady(resource); 137 | 138 | // Content has been received - make way for another HttpConnection 139 | connLimiter.vacate(); 140 | 141 | // Store the retrieved image content in cache 142 | if (!iCache.containsImage(thread.getUrl())) { 143 | iCache.addImageToCache(thread.getUrl(), content); 144 | PersistenceManager.getInstance().saveImageCache(iCache); 145 | } 146 | } 147 | 148 | public void receivedHttpError(HttpConnectionThread thread, String error) { 149 | erroredRequests++; 150 | 151 | failedConnections.addElement(thread.getUrl()); 152 | 153 | // This connection has ended - make way for another HttpConnection 154 | connLimiter.vacate(); 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/net/ImageHttpConnection.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.net; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.DataInputStream; 5 | import java.io.DataOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | 10 | import javax.microedition.io.HttpConnection; 11 | 12 | public final class ImageHttpConnection implements HttpConnection { 13 | private String url; 14 | 15 | private String mimeType; 16 | 17 | private String content; 18 | 19 | private ByteArrayInputStream is; 20 | 21 | public void setContent(String content) { 22 | this.content = content; 23 | is = new ByteArrayInputStream(this.content.getBytes()); 24 | } 25 | 26 | public void setURL(String url) { 27 | this.url = url; 28 | determineMimeType(); 29 | } 30 | 31 | private void determineMimeType() { 32 | if (url.endsWith(".gif")) { 33 | mimeType = "image/gif"; 34 | } else if (url.endsWith(".png")) { 35 | mimeType = "image/x-png"; 36 | } else if (url.endsWith(".jpeg") || url.endsWith(".jpg") 37 | || url.endsWith(".jpe")) { 38 | mimeType = "image/jpeg"; 39 | } 40 | } 41 | 42 | public void close() throws IOException { 43 | if (is != null) { 44 | is.close(); 45 | } 46 | } 47 | 48 | public long getDate() throws IOException { 49 | return 0; 50 | } 51 | 52 | public String getEncoding() { 53 | return null; 54 | } 55 | 56 | public long getExpiration() throws IOException { 57 | return 0; 58 | } 59 | 60 | public String getFile() { 61 | return null; 62 | } 63 | 64 | public String getHeaderField(int n) throws IOException { 65 | return null; 66 | } 67 | 68 | public String getHeaderField(String name) throws IOException { 69 | if (name.equals("content-type")) { 70 | return mimeType; 71 | } else { 72 | return null; 73 | } 74 | } 75 | 76 | public long getHeaderFieldDate(String name, long def) throws IOException { 77 | return 0; 78 | } 79 | 80 | public int getHeaderFieldInt(String name, int def) throws IOException { 81 | return 0; 82 | } 83 | 84 | public String getHeaderFieldKey(int n) throws IOException { 85 | return null; 86 | } 87 | 88 | public String getHost() { 89 | return "localhost"; 90 | } 91 | 92 | public long getLastModified() throws IOException { 93 | return 0; 94 | } 95 | 96 | public long getLength() { 97 | return 0; 98 | } 99 | 100 | public int getPort() { 101 | return 0; 102 | } 103 | 104 | public String getProtocol() { 105 | return null; 106 | } 107 | 108 | public String getRef() { 109 | return null; 110 | } 111 | 112 | public String getRequestMethod() { 113 | return null; 114 | } 115 | 116 | public String getRequestProperty(String key) { 117 | return null; 118 | } 119 | 120 | public int getResponseCode() throws IOException { 121 | return HTTP_OK; 122 | } 123 | 124 | public String getResponseMessage() throws IOException { 125 | return null; 126 | } 127 | 128 | public String getType() { 129 | return mimeType; 130 | } 131 | 132 | public String getURL() { 133 | return url; 134 | } 135 | 136 | public DataInputStream openDataInputStream() throws IOException { 137 | return new DataInputStream(is); 138 | } 139 | 140 | public DataOutputStream openDataOutputStream() throws IOException { 141 | return null; 142 | } 143 | 144 | public InputStream openInputStream() throws IOException { 145 | is.reset(); 146 | return is; 147 | } 148 | 149 | public OutputStream openOutputStream() throws IOException { 150 | return null; 151 | } 152 | 153 | public void setRequestMethod(String method) throws IOException { 154 | } 155 | 156 | public void setRequestProperty(String key, String value) throws IOException { 157 | } 158 | 159 | public String getQuery() { 160 | return null; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/GenericLoadingAnimation.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import java.util.Timer; 4 | import java.util.TimerTask; 5 | 6 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 7 | 8 | import net.rim.device.api.system.Bitmap; 9 | import net.rim.device.api.ui.Color; 10 | import net.rim.device.api.ui.Font; 11 | import net.rim.device.api.ui.Graphics; 12 | import net.rim.device.api.ui.component.BitmapField; 13 | 14 | public final class GenericLoadingAnimation extends BitmapField { 15 | private static final int WIDTH = Graphics.getScreenWidth() / 2; 16 | 17 | private static final int HEIGHT; 18 | 19 | static { 20 | if (UiUtilities.DEVICE_240W) { 21 | HEIGHT = 12; 22 | } else { 23 | HEIGHT = 16; 24 | } 25 | } 26 | 27 | private static final int UPDATE_DELAY = 50; // ms 28 | 29 | private static final int UPDATE_INTERVAL = 100; // ms 30 | 31 | public static final int PERCENT_INCREMENT = 5; 32 | 33 | private Timer imageUpdateTimer; 34 | 35 | private Bitmap loadingBitmap; 36 | 37 | private float percentUILen; 38 | 39 | private volatile int percentComplete; 40 | 41 | private String loadingMessage; 42 | 43 | public GenericLoadingAnimation(String loadingMessage) { 44 | loadingBitmap = UiUtilities.getLoadingBar(); 45 | 46 | this.loadingMessage = loadingMessage; 47 | 48 | percentUILen = (float) WIDTH / (float) 100; 49 | percentComplete = 0; 50 | } 51 | 52 | public int getPreferredWidth() { 53 | return WIDTH; 54 | } 55 | 56 | public int getPreferredHeight() { 57 | return HEIGHT; 58 | } 59 | 60 | protected void onDisplay() { 61 | imageUpdateTimer = new Timer(); 62 | imageUpdateTimer.scheduleAtFixedRate(new TimerTask() { 63 | public void run() { 64 | percentComplete += PERCENT_INCREMENT; 65 | if (percentComplete > 100) { 66 | percentComplete = 0; 67 | } 68 | 69 | invalidate(); 70 | } 71 | }, UPDATE_DELAY, UPDATE_INTERVAL); 72 | } 73 | 74 | protected void paint(Graphics graphics) { 75 | super.paint(graphics); 76 | 77 | graphics.setFont(graphics.getFont().derive(Font.BOLD, HEIGHT)); 78 | graphics.setColor(Color.BLACK); 79 | 80 | graphics.drawBitmap(0, 0, (int) (percentUILen * percentComplete), 81 | HEIGHT, loadingBitmap, 0, 0); 82 | graphics.drawRect(0, 0, getPreferredWidth(), HEIGHT); 83 | 84 | graphics.drawText(loadingMessage, 0, 0); 85 | } 86 | 87 | public void cancel() { 88 | imageUpdateTimer.cancel(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/GenericLoadingDialog.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 4 | 5 | import net.rim.device.api.system.Bitmap; 6 | import net.rim.device.api.ui.Field; 7 | import net.rim.device.api.ui.FieldChangeListener; 8 | import net.rim.device.api.ui.UiApplication; 9 | import net.rim.device.api.ui.component.BitmapField; 10 | import net.rim.device.api.ui.component.ButtonField; 11 | import net.rim.device.api.ui.container.PopupScreen; 12 | import net.rim.device.api.ui.container.VerticalFieldManager; 13 | 14 | public final class GenericLoadingDialog extends PopupScreen { 15 | public GenericLoadingDialog(String loadingMessage) { 16 | super(new VerticalFieldManager()); 17 | 18 | final GenericLoadingAnimation loadingAnim = new GenericLoadingAnimation( 19 | loadingMessage); 20 | 21 | add(new BitmapField(UiUtilities.getSmallHeading())); 22 | add(new BitmapField(Bitmap.getBitmapResource("img/line.png"))); 23 | add(loadingAnim); 24 | add(new BitmapField(Bitmap.getBitmapResource("img/line.png"))); 25 | 26 | ButtonField cancelButton = new ButtonField("Cancel", 27 | Field.FIELD_HCENTER); 28 | cancelButton.setChangeListener(new FieldChangeListener() { 29 | public void fieldChanged(Field field, int context) { 30 | UiApplication.getUiApplication().invokeLater(new Runnable() { 31 | public void run() { 32 | loadingAnim.cancel(); 33 | fieldChangeNotify(0); 34 | close(); 35 | } 36 | }); 37 | } 38 | }); 39 | add(cancelButton); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/HTMLField.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.DataInputStream; 5 | import java.io.DataOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.OutputStream; 9 | 10 | import javax.microedition.io.HttpConnection; 11 | 12 | import com.bbsmart.pda.blackberry.smartview.net.ImageConnectionManager; 13 | 14 | import net.rim.blackberry.api.browser.Browser; 15 | import net.rim.device.api.browser.field.BrowserContent; 16 | import net.rim.device.api.browser.field.Event; 17 | import net.rim.device.api.browser.field.RenderingApplication; 18 | import net.rim.device.api.browser.field.RenderingException; 19 | import net.rim.device.api.browser.field.RenderingSession; 20 | import net.rim.device.api.browser.field.RequestedResource; 21 | import net.rim.device.api.browser.field.UrlRequestedEvent; 22 | import net.rim.device.api.ui.Field; 23 | 24 | public final class HTMLField { 25 | CustomHTTPConnection httpConn; 26 | 27 | public void setContent(String content) { 28 | httpConn = new CustomHTTPConnection(); 29 | httpConn.setContent(content); 30 | } 31 | 32 | public Field getHTMLField() throws RenderingException { 33 | BrowserContent bc = RenderingSession.getNewInstance() 34 | .getBrowserContent(httpConn, new RenderHelper(), 0); 35 | new RenderingThread(bc).start(); 36 | Field htmlField = bc.getDisplayableContent(); 37 | 38 | if (httpConn != null) { 39 | try { 40 | httpConn.close(); 41 | } catch (Exception e) { 42 | // Some exception closing the connection..ignore 43 | } 44 | } 45 | 46 | return htmlField; 47 | } 48 | } 49 | 50 | class RenderHelper implements RenderingApplication { 51 | private ImageConnectionManager iManager = ImageConnectionManager 52 | .getInstance(); 53 | 54 | public Object eventOccurred(Event event) { 55 | if (event instanceof UrlRequestedEvent) { 56 | UrlRequestedEvent urlEvent = (UrlRequestedEvent) event; 57 | Browser.getDefaultSession().displayPage(urlEvent.getURL()); 58 | } 59 | return null; 60 | } 61 | 62 | public int getAvailableHeight(BrowserContent browserContent) { 63 | return 0; 64 | } 65 | 66 | public int getAvailableWidth(BrowserContent browserContent) { 67 | return 0; 68 | } 69 | 70 | public int getHistoryPosition(BrowserContent browserContent) { 71 | return 0; 72 | } 73 | 74 | public String getHTTPCookie(String url) { 75 | return null; 76 | } 77 | 78 | public HttpConnection getResource(final RequestedResource resource, 79 | final BrowserContent referrer) { 80 | if (resource.isCacheOnly()) { 81 | return iManager.requestCachedImage(resource); 82 | } else { 83 | iManager.requestImage(resource, referrer); 84 | return null; 85 | } 86 | } 87 | 88 | public void invokeRunnable(Runnable runnable) { 89 | } 90 | } 91 | 92 | class CustomHTTPConnection implements HttpConnection { 93 | private String content; 94 | 95 | private ByteArrayInputStream is; 96 | 97 | public void setContent(String content) { 98 | this.content = content; 99 | } 100 | 101 | public void close() throws IOException { 102 | if (is != null) { 103 | is.close(); 104 | } 105 | } 106 | 107 | public long getDate() throws IOException { 108 | return 0; 109 | } 110 | 111 | public String getEncoding() { 112 | return null; 113 | } 114 | 115 | public long getExpiration() throws IOException { 116 | return 0; 117 | } 118 | 119 | public String getFile() { 120 | return null; 121 | } 122 | 123 | public String getHeaderField(int n) throws IOException { 124 | return null; 125 | } 126 | 127 | public String getHeaderField(String name) throws IOException { 128 | if (name.equals("content-type")) { 129 | return "text/html"; 130 | } else { 131 | return null; 132 | } 133 | } 134 | 135 | public long getHeaderFieldDate(String name, long def) throws IOException { 136 | return 0; 137 | } 138 | 139 | public int getHeaderFieldInt(String name, int def) throws IOException { 140 | return 0; 141 | } 142 | 143 | public String getHeaderFieldKey(int n) throws IOException { 144 | return null; 145 | } 146 | 147 | public String getHost() { 148 | return "localhost"; 149 | } 150 | 151 | public long getLastModified() throws IOException { 152 | return 0; 153 | } 154 | 155 | public long getLength() { 156 | return 0; 157 | } 158 | 159 | public int getPort() { 160 | return 0; 161 | } 162 | 163 | public String getProtocol() { 164 | return null; 165 | } 166 | 167 | public String getRef() { 168 | return null; 169 | } 170 | 171 | public String getRequestMethod() { 172 | return null; 173 | } 174 | 175 | public String getRequestProperty(String key) { 176 | return null; 177 | } 178 | 179 | public int getResponseCode() throws IOException { 180 | return HTTP_OK; 181 | } 182 | 183 | public String getResponseMessage() throws IOException { 184 | return null; 185 | } 186 | 187 | public String getType() { 188 | return "text/html"; 189 | } 190 | 191 | public String getURL() { 192 | return "http://localhost"; 193 | } 194 | 195 | public DataInputStream openDataInputStream() throws IOException { 196 | is = new ByteArrayInputStream(content.getBytes()); 197 | 198 | return new DataInputStream(is); 199 | } 200 | 201 | public DataOutputStream openDataOutputStream() throws IOException { 202 | return null; 203 | } 204 | 205 | public InputStream openInputStream() throws IOException { 206 | is = new ByteArrayInputStream(content.getBytes()); 207 | return is; 208 | } 209 | 210 | public OutputStream openOutputStream() throws IOException { 211 | return null; 212 | } 213 | 214 | public void setRequestMethod(String method) throws IOException { 215 | } 216 | 217 | public void setRequestProperty(String key, String value) throws IOException { 218 | } 219 | 220 | public String getQuery() { 221 | return null; 222 | } 223 | } 224 | 225 | class RenderingThread extends Thread { 226 | private BrowserContent _browserField; 227 | 228 | RenderingThread(BrowserContent field) { 229 | _browserField = field; 230 | } 231 | 232 | public void run() { 233 | try { 234 | _browserField.finishLoading(); 235 | } catch (RenderingException e) { 236 | // Do nothing 237 | } 238 | } 239 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/ImageLoadingAnimation.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import java.util.Timer; 4 | import java.util.TimerTask; 5 | 6 | import com.bbsmart.pda.blackberry.smartview.net.ImageConnectionManager; 7 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 8 | 9 | import net.rim.device.api.system.Bitmap; 10 | import net.rim.device.api.ui.Color; 11 | import net.rim.device.api.ui.Font; 12 | import net.rim.device.api.ui.Graphics; 13 | import net.rim.device.api.ui.component.BitmapField; 14 | 15 | public final class ImageLoadingAnimation extends BitmapField { 16 | private static final int WIDTH = Graphics.getScreenWidth() / 2; 17 | 18 | private static final int HEIGHT; 19 | 20 | static { 21 | if (UiUtilities.DEVICE_240W) { 22 | HEIGHT = 12; 23 | } else { 24 | HEIGHT = 16; 25 | } 26 | } 27 | 28 | private static final int POLL_INTERVAL = 300; // ms 29 | 30 | private volatile int numCompleteImages; 31 | 32 | private volatile int numErroredImages; 33 | 34 | private int totalNumImages; 35 | 36 | private float imageUiLen; 37 | 38 | private Timer imageCompletionPoller; 39 | 40 | private ImageConnectionManager iManager; 41 | 42 | private Bitmap loadingBitmap; 43 | 44 | private Bitmap completedBitmap; 45 | 46 | private Bitmap errBitmap; 47 | 48 | private Bitmap errIcon; 49 | 50 | private boolean finished; 51 | 52 | public ImageLoadingAnimation() { 53 | iManager = ImageConnectionManager.getInstance(); 54 | loadingBitmap = UiUtilities.getLoadingBar(); 55 | completedBitmap = UiUtilities.getDoneLoadingBar(); 56 | errBitmap = UiUtilities.getErrLoadingBar(); 57 | errIcon = UiUtilities.getErrLoadingIcon(); 58 | finished = false; 59 | totalNumImages = 0; 60 | numCompleteImages = 0; 61 | numErroredImages = 0; 62 | } 63 | 64 | public int getPreferredWidth() { 65 | return WIDTH; 66 | } 67 | 68 | public int getPreferredHeight() { 69 | if (numErroredImages > 0) { 70 | return HEIGHT * 2; 71 | } else { 72 | return HEIGHT; 73 | } 74 | } 75 | 76 | public void setNumImages(int totalNumImages) { 77 | this.totalNumImages = totalNumImages; 78 | imageUiLen = (float) WIDTH / (float) totalNumImages; 79 | } 80 | 81 | protected void onDisplay() { 82 | imageCompletionPoller = new Timer(); 83 | imageCompletionPoller.scheduleAtFixedRate(new UpdateTask(this), 84 | POLL_INTERVAL, POLL_INTERVAL); 85 | } 86 | 87 | protected void onUndisplay() { 88 | imageCompletionPoller.cancel(); 89 | finished = true; 90 | } 91 | 92 | public void setTotalNumImages(int totalNumImages) { 93 | this.totalNumImages = totalNumImages; 94 | finished = false; 95 | imageUiLen = (float) WIDTH / (float) totalNumImages; 96 | } 97 | 98 | protected void paint(Graphics graphics) { 99 | super.paint(graphics); 100 | 101 | int done = numCompleteImages + numErroredImages; 102 | 103 | if (!finished) { 104 | graphics.setFont(graphics.getFont().derive(Font.BOLD, HEIGHT)); 105 | graphics.setColor(Color.BLACK); 106 | 107 | if (numErroredImages > 0) { 108 | graphics.drawBitmap(0, 0, (int) (imageUiLen * done), 109 | HEIGHT * 2, errBitmap, 0, 0); 110 | graphics.drawBitmap(0, HEIGHT, errIcon.getWidth(), errIcon 111 | .getHeight(), errIcon, 0, 0); 112 | graphics.drawText(String.valueOf(numErroredImages) 113 | + " image(s)", errIcon.getWidth(), HEIGHT); 114 | } else { 115 | graphics.drawBitmap(0, 0, (int) (imageUiLen * done), HEIGHT, 116 | loadingBitmap, 0, 0); 117 | } 118 | 119 | graphics.drawRect(0, 0, getPreferredWidth(), HEIGHT); 120 | 121 | graphics.drawText(" Images: (" + done + "/" + totalNumImages + ")", 122 | 0, 0); 123 | } else { 124 | graphics.drawBitmap(0, 0, WIDTH, HEIGHT, completedBitmap, 0, 0); 125 | 126 | graphics.setFont(graphics.getFont().derive(Font.BOLD, HEIGHT)); 127 | graphics.setColor(Color.BLACK); 128 | graphics.drawRect(0, 0, getPreferredWidth(), getPreferredHeight()); 129 | 130 | graphics.drawText(" Images: (Done)", 0, 0); 131 | } 132 | } 133 | 134 | public void updateDisplay() { 135 | if ((numCompleteImages + numErroredImages) >= totalNumImages) { 136 | // Finished loading all images 137 | finished = true; 138 | iManager.cancel(); 139 | imageCompletionPoller.cancel(); 140 | fieldChangeNotify(0); 141 | } 142 | 143 | if (numErroredImages > 0) { 144 | setExtent(getPreferredWidth(), getPreferredHeight()); 145 | ((ImageLoadingManager) this.getManager()).updateDisplay(); 146 | } 147 | 148 | invalidate(); 149 | } 150 | 151 | public void cancel() { 152 | iManager.cancel(); 153 | imageCompletionPoller.cancel(); 154 | } 155 | 156 | class UpdateTask extends TimerTask { 157 | ImageLoadingAnimation bitmapField; 158 | 159 | public UpdateTask(ImageLoadingAnimation bitmapField) { 160 | this.bitmapField = bitmapField; 161 | } 162 | 163 | public void run() { 164 | int newNumCompleted = iManager.getNumCompletedRequests(); 165 | int newNumErrored = iManager.getNumErroredRequests(); 166 | 167 | if (newNumCompleted + newNumErrored > (numCompleteImages + numErroredImages)) { 168 | numCompleteImages = newNumCompleted; 169 | numErroredImages = newNumErrored; 170 | 171 | bitmapField.updateDisplay(); 172 | } 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/ImageLoadingDialog.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import net.rim.device.api.system.Bitmap; 4 | import net.rim.device.api.ui.Field; 5 | import net.rim.device.api.ui.FieldChangeListener; 6 | import net.rim.device.api.ui.UiApplication; 7 | import net.rim.device.api.ui.component.BitmapField; 8 | import net.rim.device.api.ui.component.ButtonField; 9 | import net.rim.device.api.ui.container.PopupScreen; 10 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 11 | 12 | public final class ImageLoadingDialog extends PopupScreen { 13 | public ImageLoadingDialog(int totalNumImages) { 14 | super(new ImageLoadingManager()); 15 | 16 | final ImageLoadingAnimation loadingAnim = new ImageLoadingAnimation(); 17 | loadingAnim.setNumImages(totalNumImages); 18 | loadingAnim.setChangeListener(new FieldChangeListener() { 19 | public void fieldChanged(Field field, int context) { 20 | UiApplication.getUiApplication().invokeLater(new Runnable() { 21 | public void run() { 22 | close(); 23 | } 24 | }); 25 | } 26 | }); 27 | 28 | add(new BitmapField(UiUtilities.getSmallHeading())); 29 | add(new BitmapField(Bitmap.getBitmapResource("img/line.png"))); 30 | add(loadingAnim); 31 | add(new BitmapField(Bitmap.getBitmapResource("img/line.png"))); 32 | 33 | ButtonField cancelButton = new ButtonField("Cancel", 34 | Field.FIELD_HCENTER); 35 | cancelButton.setChangeListener(new FieldChangeListener() { 36 | public void fieldChanged(Field field, int context) { 37 | UiApplication.getUiApplication().invokeLater(new Runnable() { 38 | public void run() { 39 | loadingAnim.cancel(); 40 | close(); 41 | } 42 | }); 43 | } 44 | }); 45 | add(cancelButton); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/ImageLoadingManager.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import net.rim.device.api.ui.UiApplication; 4 | import net.rim.device.api.ui.container.VerticalFieldManager; 5 | 6 | public final class ImageLoadingManager extends VerticalFieldManager { 7 | public void updateDisplay() { 8 | synchronized (UiApplication.getEventLock()) { 9 | updateLayout(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/customfield/SmartNoteListField.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.customfield; 2 | 3 | import java.util.Vector; 4 | 5 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 6 | import com.bbsmart.pda.blackberry.smartview.io.SmartNote; 7 | import com.bbsmart.pda.blackberry.smartview.io.SmartNoteManager; 8 | import com.bbsmart.pda.blackberry.smartview.ui.screens.EmailViewScreen; 9 | import com.bbsmart.pda.blackberry.smartview.ui.screens.SmartNoteScreen; 10 | 11 | import net.rim.blackberry.api.mail.Message; 12 | import net.rim.device.api.system.Bitmap; 13 | import net.rim.device.api.system.Characters; 14 | import net.rim.device.api.ui.Color; 15 | import net.rim.device.api.ui.ContextMenu; 16 | import net.rim.device.api.ui.Font; 17 | import net.rim.device.api.ui.Graphics; 18 | import net.rim.device.api.ui.MenuItem; 19 | import net.rim.device.api.ui.UiApplication; 20 | import net.rim.device.api.ui.component.Dialog; 21 | import net.rim.device.api.ui.component.ListField; 22 | import net.rim.device.api.ui.component.ListFieldCallback; 23 | 24 | public final class SmartNoteListField extends ListField implements 25 | ListFieldCallback { 26 | private Vector smartNotes; 27 | private Bitmap lightBulbBitmap; 28 | private SmartNoteManager snm; 29 | private Message m; 30 | 31 | public SmartNoteListField(SmartNoteManager snm, Message m) { 32 | this.snm = snm; 33 | this.m = m; 34 | lightBulbBitmap = Bitmap.getBitmapResource("img/smartnote-on-16.png"); 35 | update(); 36 | } 37 | 38 | public Object get(ListField listField, int index) { 39 | return smartNotes.elementAt(index); 40 | } 41 | 42 | public int getPreferredWidth(ListField listField) { 43 | return Graphics.getScreenWidth(); 44 | } 45 | 46 | public int indexOfList(ListField arg0, String arg1, int arg2) { 47 | return -1; // Not implemented 48 | } 49 | 50 | public void drawListRow(ListField listField, Graphics graphics, int index, 51 | int y, int width) { 52 | SmartNote sn = (SmartNote) smartNotes.elementAt(index); 53 | 54 | graphics.drawBitmap(0, y, lightBulbBitmap.getWidth(), lightBulbBitmap 55 | .getHeight(), lightBulbBitmap, 0, 0); 56 | 57 | int textColor; 58 | if (sn.priority.equals(SmartNote.HIGH_P)) { 59 | textColor = Color.RED; 60 | } else if (sn.priority.equals(SmartNote.LOW_P)) { 61 | textColor = Color.LIGHTBLUE; 62 | } else { 63 | textColor = Color.GREEN; 64 | } 65 | graphics.setColor(textColor); 66 | graphics.setFont(graphics.getFont().derive(Font.BOLD)); 67 | 68 | graphics.drawText(sn.text, lightBulbBitmap.getWidth(), y, 69 | Graphics.ELLIPSIS); 70 | } 71 | 72 | public void update() { 73 | this.smartNotes = snm.getSmartNotes(m); 74 | setSize(smartNotes.size()); 75 | } 76 | 77 | protected void makeContextMenu(ContextMenu contextMenu) { 78 | contextMenu.clear(); 79 | 80 | contextMenu.addItem(new MenuItem("View/Edit SmartNote", 0, 0) { 81 | public void run() { 82 | viewSmartNote(); 83 | } 84 | }); 85 | 86 | contextMenu.addItem(new MenuItem("Delete SmartNote", 0, 0) { 87 | public void run() { 88 | deleteSmartNote(); 89 | } 90 | }); 91 | } 92 | 93 | private void viewSmartNote() { 94 | SmartNote selected = (SmartNote) get(this, getSelectedIndex()); 95 | UiApplication.getUiApplication().pushScreen( 96 | new SmartNoteScreen(selected, m)); 97 | } 98 | 99 | private void deleteSmartNote() { 100 | SmartNote selected = (SmartNote) get(this, getSelectedIndex()); 101 | EmailViewScreen emailViewScreen = (EmailViewScreen) UiApplication 102 | .getUiApplication().getActiveScreen(); 103 | 104 | Dialog d = new Dialog(Dialog.D_YES_NO, "Delete selected SmartNote?", 105 | Dialog.YES, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), 0, 106 | false); 107 | d.doModal(); 108 | 109 | if (d.getSelectedValue() == Dialog.YES) { 110 | snm.deleteSmartNote(m, selected); 111 | PersistenceManager.getInstance().saveSmartNoteManager(snm); 112 | emailViewScreen.displaySmartNotes(); 113 | } 114 | } 115 | 116 | public boolean keyChar(char key, int status, int time) { 117 | switch (key) { 118 | case 8: // DEL key 119 | deleteSmartNote(); 120 | return true; 121 | case Characters.ENTER: 122 | viewSmartNote(); 123 | return true; 124 | default: 125 | return super.keyChar(key, status, time); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/screens/CommsHelpScreen.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.screens; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.ui.customfield.HTMLField; 4 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 5 | 6 | import net.rim.device.api.browser.field.RenderingException; 7 | import net.rim.device.api.system.Bitmap; 8 | import net.rim.device.api.ui.Color; 9 | import net.rim.device.api.ui.Field; 10 | import net.rim.device.api.ui.FieldChangeListener; 11 | import net.rim.device.api.ui.Font; 12 | import net.rim.device.api.ui.Graphics; 13 | import net.rim.device.api.ui.component.BitmapField; 14 | import net.rim.device.api.ui.component.ButtonField; 15 | import net.rim.device.api.ui.component.NullField; 16 | import net.rim.device.api.ui.container.MainScreen; 17 | 18 | public final class CommsHelpScreen extends MainScreen { 19 | public CommsHelpScreen() { 20 | // Write the heading... 21 | Bitmap headingBitmap = UiUtilities.getHeading(); 22 | writeHeading(new Graphics(headingBitmap)); 23 | add(new BitmapField(headingBitmap)); 24 | 25 | add(new NullField()); // for focus 26 | 27 | HTMLField htmlField = new HTMLField(); 28 | htmlField.setContent(getHelpScreenContent()); 29 | 30 | try { 31 | add(htmlField.getHTMLField()); 32 | } catch (RenderingException re) { 33 | // Never happens 34 | } 35 | 36 | ButtonField closeField = new ButtonField("Setup My Connection!", 37 | ButtonField.FIELD_HCENTER | ButtonField.CONSUME_CLICK); 38 | closeField.setChangeListener(new FieldChangeListener() { 39 | public void fieldChanged(Field field, int context) { 40 | close(); 41 | } 42 | }); 43 | 44 | add(closeField); 45 | } 46 | 47 | private void writeHeading(Graphics g) { 48 | g.setColor(Color.FIREBRICK); 49 | 50 | if (UiUtilities.DEVICE_240W) { 51 | g.setFont(getFont().derive(Font.BOLD, 16)); 52 | g.drawText("CONNECTION HELP", 90, 8); 53 | } else { 54 | g.setFont(getFont().derive(Font.BOLD, 18)); 55 | g.drawText("CONNECTION HELP", 120, 13); 56 | } 57 | } 58 | 59 | public String getHelpScreenContent() { 60 | StringBuffer content = new StringBuffer(); 61 | 62 | content.append(""); 63 | content.append("In order to retrieve and display images in your email, BBSmart Email Viewer "); 64 | content.append("needs to establish a connection to the Internet. For this to happen, you first need to configure"); 65 | content.append(" your connection settings.

"); 66 | 67 | content.append("Please note that if you do not wish to view images in your emails, this functionality can be disabled from the Options screen.

"); 68 | content.append("Also note that if you are unable to configure your connection settings, you will still be able to view emails using BBSmart Email Viewer"); 69 | content.append(" however will not be able to see any images in the emails.

"); 70 | 71 | content.append("On the Connection Setup screen, please select how you think you connect to the Internet and test your connection. "); 72 | content.append("If you are having trouble getting your connection settings to work, please first try to contact your "); 73 | content.append(" Wireless Network Provider or BlackBerry Network Administrator who may be able to provide assistance. "); 74 | content.append("

For any support queries, please email us at: support@blackberrysmart.com

"); 75 | 76 | return content.toString(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/screens/NewTemplateScreen.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.screens; 2 | 3 | import java.util.Vector; 4 | 5 | import com.bbsmart.pda.blackberry.smartview.io.GeneralStoreInterface; 6 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 7 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 8 | import com.bbsmart.pda.blackberry.smartview.util.EmailTemplate; 9 | 10 | import net.rim.device.api.system.Bitmap; 11 | import net.rim.device.api.ui.Color; 12 | import net.rim.device.api.ui.Font; 13 | import net.rim.device.api.ui.Graphics; 14 | import net.rim.device.api.ui.MenuItem; 15 | import net.rim.device.api.ui.component.AutoTextEditField; 16 | import net.rim.device.api.ui.component.BitmapField; 17 | import net.rim.device.api.ui.component.Dialog; 18 | import net.rim.device.api.ui.component.Menu; 19 | import net.rim.device.api.ui.component.SeparatorField; 20 | import net.rim.device.api.ui.container.MainScreen; 21 | 22 | public class NewTemplateScreen extends MainScreen { 23 | // 0 = New, 1 = View/Edit, 2 = Create from sent email 24 | private int mode; 25 | private EmailTemplate emailTemplate; 26 | private String text; 27 | 28 | private AutoTextEditField titleField; 29 | private AutoTextEditField textField; 30 | 31 | private boolean clearedTemplateText; 32 | 33 | public NewTemplateScreen() { 34 | mode = 0; 35 | init(); 36 | } 37 | 38 | public NewTemplateScreen(EmailTemplate emailTemplate) { 39 | mode = 1; 40 | this.emailTemplate = emailTemplate; 41 | init(); 42 | } 43 | 44 | public NewTemplateScreen(String text) { 45 | mode = 2; 46 | this.text = text; 47 | init(); 48 | } 49 | 50 | private void init() { 51 | displayHeading(); 52 | 53 | String defaultTitle = null, defaultText = null; 54 | switch (mode) { 55 | case 0: 56 | defaultTitle = UiUtilities.EMPTY_STRING; 57 | defaultText = ""; 58 | break; 59 | case 1: 60 | defaultTitle = emailTemplate.title; 61 | defaultText = emailTemplate.text; 62 | break; 63 | case 2: 64 | defaultTitle = UiUtilities.EMPTY_STRING; 65 | defaultText = text; 66 | break; 67 | } 68 | 69 | titleField = new AutoTextEditField("Title: ", defaultTitle); 70 | 71 | clearedTemplateText = false; 72 | textField = new AutoTextEditField(UiUtilities.EMPTY_STRING, defaultText) { 73 | protected void onFocus(int arg0) { 74 | if (mode == 0 && !clearedTemplateText) { 75 | setText(UiUtilities.EMPTY_STRING); 76 | clearedTemplateText = true; 77 | } 78 | } 79 | }; 80 | 81 | add(titleField); 82 | add(new SeparatorField()); 83 | add(textField); 84 | } 85 | 86 | private void displayHeading() { 87 | Bitmap penBitmap = Bitmap.getBitmapResource("img/pencil.gif"); 88 | Bitmap headingBitmap = UiUtilities.getHeading(); 89 | Graphics g = new Graphics(headingBitmap); 90 | 91 | String headingText = (mode == 1) ? "VIEW/EDIT..." : "CREATE NEW..."; 92 | 93 | g.setColor(Color.FIREBRICK); 94 | if (UiUtilities.DEVICE_240W) { 95 | g.setFont(getFont().derive(Font.BOLD, 16)); 96 | int len = g.drawText(headingText, 90, 8); 97 | g.drawBitmap(90 + len, 0, penBitmap.getWidth(), penBitmap 98 | .getHeight(), penBitmap, 0, 0); 99 | } else { 100 | g.setFont(getFont().derive(Font.BOLD, 18)); 101 | int len = g.drawText(headingText, 120, 13); 102 | g.drawBitmap(120 + len, 6, penBitmap.getWidth(), penBitmap 103 | .getHeight(), penBitmap, 0, 0); 104 | } 105 | 106 | add(new BitmapField(headingBitmap)); 107 | add(new SeparatorField()); 108 | } 109 | 110 | protected void makeMenu(Menu menu, int instance) { 111 | super.makeMenu(menu, instance); 112 | 113 | menu.add(new MenuItem("Save and Exit", 0, 0) { 114 | public void run() { 115 | if (onSave()) { 116 | close(); 117 | } 118 | } 119 | }); 120 | } 121 | 122 | protected boolean onSave() { 123 | if (titleField.getText().length() == 0) { 124 | Dialog.alert("No Title Entered!"); 125 | return false; 126 | } else if (textField.getText().length() == 0 127 | || (mode == 0 && !clearedTemplateText)) { 128 | Dialog.alert("No Template Text Entered!"); 129 | return false; 130 | } else { 131 | if (mode == 1) { 132 | if (!GeneralStoreInterface.updateEmailTemplate( 133 | emailTemplate.title, titleField.getText(), textField 134 | .getText())) { 135 | Dialog.alert("A template with this title already exists!"); 136 | return false; 137 | } 138 | } else { 139 | // Creating a whole new template 140 | if (!GeneralStoreInterface.createEmailTemplate(titleField 141 | .getText(), textField.getText())) { 142 | Dialog.alert("A template with this title already exists!"); 143 | return false; 144 | } 145 | } 146 | 147 | return true; 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/screens/RegisterScreen.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.screens; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 4 | import com.bbsmart.pda.blackberry.smartview.io.Preferences; 5 | import com.bbsmart.pda.blackberry.smartview.ui.customfield.HTMLField; 6 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 7 | import com.bbsmart.pda.blackberry.smartview.util.RPNString; 8 | 9 | import net.rim.blackberry.api.browser.Browser; 10 | import net.rim.device.api.browser.field.RenderingException; 11 | import net.rim.device.api.system.Bitmap; 12 | import net.rim.device.api.system.DeviceInfo; 13 | import net.rim.device.api.ui.Color; 14 | import net.rim.device.api.ui.Field; 15 | import net.rim.device.api.ui.FieldChangeListener; 16 | import net.rim.device.api.ui.Font; 17 | import net.rim.device.api.ui.Graphics; 18 | import net.rim.device.api.ui.component.BasicEditField; 19 | import net.rim.device.api.ui.component.BitmapField; 20 | import net.rim.device.api.ui.component.ButtonField; 21 | import net.rim.device.api.ui.component.NullField; 22 | import net.rim.device.api.ui.container.HorizontalFieldManager; 23 | import net.rim.device.api.ui.container.MainScreen; 24 | 25 | public final class RegisterScreen extends MainScreen { 26 | private String buyNowURL = "https://www.mobihand.com/mobilecart/mc1.asp?posid=16&pid=12362&did=" 27 | + Integer.toHexString(DeviceInfo.getDeviceId()).toUpperCase(); 28 | 29 | public RegisterScreen() { 30 | // Write the heading... 31 | Bitmap headingBitmap = UiUtilities.getHeading(); 32 | writeHeading(new Graphics(headingBitmap)); 33 | add(new BitmapField(headingBitmap)); 34 | 35 | add(new NullField()); // for focus 36 | 37 | HTMLField htmlField = new HTMLField(); 38 | htmlField.setContent(getRegisterContent()); 39 | 40 | try { 41 | add(htmlField.getHTMLField()); 42 | } catch (RenderingException re) { 43 | // Never happens 44 | } 45 | 46 | final BasicEditField keyField = new BasicEditField("Key: ", "", 10, 47 | BasicEditField.FILTER_NUMERIC); 48 | add(keyField); 49 | 50 | HorizontalFieldManager buttonFieldManager = new HorizontalFieldManager( 51 | Field.FIELD_HCENTER); 52 | 53 | ButtonField activateButton = new ButtonField("Activate", 54 | ButtonField.CONSUME_CLICK | ButtonField.NEVER_DIRTY); 55 | activateButton.setChangeListener(new FieldChangeListener() { 56 | public void fieldChanged(Field field, int context) { 57 | if (keyField.getText().trim().length() == 0) { 58 | UiUtilities 59 | .alertDialog("No activation key entered. Please enter your activation key in the \"Key\" field first."); 60 | return; 61 | } 62 | 63 | if (activateProduct(keyField.getText())) { 64 | Preferences p = PersistenceManager.getInstance() 65 | .getPreferences(); 66 | p.setTrial(false); 67 | p.setRegistered(true); 68 | PersistenceManager.getInstance().savePreferences(p); 69 | UiUtilities 70 | .alertDialog("Thank you for purchasing the full version of BBSmart Email Viewer!"); 71 | close(); 72 | } else { 73 | UiUtilities 74 | .alertDialog("Invalid Key Entered.\nIf you have purchased a valid key, please contact support@blackberrysmart.com for assistance"); 75 | } 76 | } 77 | }); 78 | 79 | ButtonField buyNowButton = new ButtonField("Buy Now!", 80 | ButtonField.CONSUME_CLICK | ButtonField.NEVER_DIRTY); 81 | buyNowButton.setChangeListener(new FieldChangeListener() { 82 | public void fieldChanged(Field field, int context) { 83 | Browser.getDefaultSession().displayPage(buyNowURL); 84 | } 85 | }); 86 | 87 | buttonFieldManager.add(activateButton); 88 | buttonFieldManager.add(buyNowButton); 89 | add(buttonFieldManager); 90 | } 91 | 92 | public boolean activateProduct(String key) { 93 | String basePIN = Integer.toHexString(DeviceInfo.getDeviceId()); 94 | String devicePINUpper = basePIN.toUpperCase(); 95 | String devicePINLower = basePIN.toLowerCase(); 96 | 97 | boolean success = false; 98 | String out = RPNString.apply("key 33 * c +", devicePINUpper); 99 | success = out.equals(key); 100 | 101 | if (success) { 102 | return true; 103 | } else { 104 | // Uppercase device PIN didn't work - let's try lowercase too just in case 105 | out = RPNString.apply("key 33 * c +", devicePINLower); 106 | return out.equals(key); 107 | } 108 | } 109 | 110 | public boolean onClose() { 111 | close(); 112 | return true; 113 | } 114 | 115 | private void writeHeading(Graphics g) { 116 | g.setColor(Color.FIREBRICK); 117 | 118 | if (UiUtilities.DEVICE_240W) { 119 | g.setFont(getFont().derive(Font.BOLD, 16)); 120 | g.drawText("ACTIVATION SCREEN", 90, 8); 121 | } else { 122 | g.setFont(getFont().derive(Font.BOLD, 18)); 123 | g.drawText("ACTIVATION SCREEN", 120, 13); 124 | } 125 | } 126 | 127 | public String getRegisterContent() { 128 | StringBuffer content = new StringBuffer(); 129 | 130 | String devicePIN = Integer.toHexString(DeviceInfo.getDeviceId()) 131 | .toUpperCase(); 132 | 133 | content.append(""); 134 | content.append(""); 135 | content.append("To activate the full version of this software, please enter your product activation key below and click \"Activate\".

"); 136 | content.append("If you do not have an activation key, one can be purchased at Handango (www.handango.com) "); 137 | content.append("Alternatively, you can buy one online right now by clicking the Buy Now button below!

"); 138 | content.append("Your device PIN is: " + devicePIN); 139 | content.append(""); 140 | 141 | return content.toString(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/screens/SmartNoteScreen.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.screens; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.io.PersistenceManager; 4 | import com.bbsmart.pda.blackberry.smartview.io.SmartNote; 5 | import com.bbsmart.pda.blackberry.smartview.io.SmartNoteManager; 6 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 7 | 8 | import net.rim.blackberry.api.mail.Message; 9 | import net.rim.device.api.system.Bitmap; 10 | import net.rim.device.api.ui.Color; 11 | import net.rim.device.api.ui.Field; 12 | import net.rim.device.api.ui.FieldChangeListener; 13 | import net.rim.device.api.ui.Font; 14 | import net.rim.device.api.ui.Graphics; 15 | import net.rim.device.api.ui.MenuItem; 16 | import net.rim.device.api.ui.UiApplication; 17 | import net.rim.device.api.ui.component.BitmapField; 18 | import net.rim.device.api.ui.component.ButtonField; 19 | import net.rim.device.api.ui.component.Dialog; 20 | import net.rim.device.api.ui.component.EditField; 21 | import net.rim.device.api.ui.component.Menu; 22 | import net.rim.device.api.ui.component.ObjectChoiceField; 23 | import net.rim.device.api.ui.container.PopupScreen; 24 | import net.rim.device.api.ui.container.VerticalFieldManager; 25 | 26 | public final class SmartNoteScreen extends PopupScreen { 27 | private EditField notesField; 28 | private ButtonField saveAndExit; 29 | private ObjectChoiceField priorityField; 30 | private SmartNote sn; 31 | private Message m; 32 | private final EmailViewScreen emailViewScreen; 33 | 34 | public SmartNoteScreen(Message m) { 35 | this(null, m); 36 | } 37 | 38 | public SmartNoteScreen(final SmartNote sn, final Message m) { 39 | super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL 40 | | VerticalFieldManager.VERTICAL_SCROLLBAR), 41 | PopupScreen.VERTICAL_SCROLL | PopupScreen.DEFAULT_MENU 42 | | PopupScreen.DEFAULT_CLOSE); 43 | 44 | this.sn = sn; 45 | this.m = m; 46 | 47 | emailViewScreen = (EmailViewScreen) UiApplication.getUiApplication() 48 | .getActiveScreen(); 49 | 50 | notesField = new EditField(UiUtilities.EMPTY_STRING, 51 | (sn == null) ? UiUtilities.EMPTY_STRING : sn.text); 52 | 53 | if (sn == null) { 54 | notesField.setCursorPosition(0); 55 | } 56 | 57 | Bitmap heading = Bitmap.getBitmapResource("loadingbar_320x16.jpg"); 58 | BitmapField headingField = new BitmapField(heading); 59 | 60 | // Display the lightbulb 61 | Graphics g = new Graphics(heading); 62 | Bitmap lightbulb = Bitmap.getBitmapResource("smartnote-on-16.png"); 63 | g.drawBitmap(0, 0, lightbulb.getWidth(), lightbulb.getHeight(), 64 | lightbulb, 0, 0); 65 | 66 | Font f = g.getFont(); 67 | f = f.derive(Font.BOLD, 14); 68 | g.setFont(f); 69 | 70 | g.drawText((sn == null) ? "Add new SmartNote..." 71 | : "View/Edit SmartNote...", lightbulb.getWidth(), 2); 72 | 73 | add(headingField); 74 | priorityField = new ObjectChoiceField("Priority: ", new Object[] { 75 | "High", "Normal", "Low" }, (sn == null) ? "Normal" 76 | : sn.priority); 77 | add(priorityField); 78 | add(new BitmapField(Bitmap 79 | .getBitmapResource("infobar_bottom_320x4.jpg"))); 80 | add(notesField); 81 | 82 | add(new BitmapField(Bitmap 83 | .getBitmapResource("infobar_bottom_320x4.jpg"))); 84 | add(new BitmapField(Bitmap.getBitmapResource("line.png"))); 85 | saveAndExit = new ButtonField("Save and Exit", 86 | ButtonField.FIELD_HCENTER | ButtonField.CONSUME_CLICK); 87 | 88 | saveAndExit.setChangeListener(new FieldChangeListener() { 89 | public void fieldChanged(Field field, int context) { 90 | saveAndExit(); 91 | } 92 | }); 93 | 94 | add(saveAndExit); 95 | 96 | // Initially focus on the text entry field 97 | notesField.setFocus(); 98 | } 99 | 100 | public boolean onClose() { 101 | if (isDirty()) { 102 | Dialog d = new Dialog(Dialog.D_YES_NO, "Changes made. Save?", 103 | Dialog.YES, Bitmap.getPredefinedBitmap(Bitmap.QUESTION), 0, 104 | false); 105 | d.doModal(); 106 | 107 | if (d.getSelectedValue() == Dialog.YES) { 108 | saveAndExit(); 109 | return false; 110 | } 111 | } 112 | close(); 113 | return true; 114 | } 115 | 116 | protected void makeMenu(Menu menu, int instance) { 117 | menu.add(new MenuItem("Help", 0, 0) { 118 | public void run() { 119 | String msg = "With SmartNotes, you can easily link notes (that only you can see) to an email.\n\n"; 120 | msg += "When you send an email with SmartNotes, those notes aren't sent - they are only for"; 121 | msg += " you to see. They are your personal place to store information you might want to remember -"; 122 | msg += " for example, you might add a SmartNote that you have to follow-up on the email.\n\nSmartNotes"; 123 | msg += " are similar to Tasks in that way, but offer tighter integration with emails."; 124 | 125 | UiUtilities.informDialog(msg); 126 | } 127 | }); 128 | super.makeMenu(menu, instance); 129 | } 130 | 131 | private void saveAndExit() { 132 | if (notesField.getText().trim().length() == 0) { 133 | UiUtilities.alertDialog("No text entered!"); 134 | } else { 135 | SmartNoteManager snm = PersistenceManager.getInstance() 136 | .getSmartNoteManager(); 137 | 138 | if (sn == null) { // Creating a new SmartNote 139 | SmartNote n = new SmartNote(); 140 | n.text = notesField.getText(); 141 | n.priority = (String) priorityField.getChoice(priorityField 142 | .getSelectedIndex()); 143 | snm.addSmartNote(m, n); 144 | } else { // Editing an existing SmartNote 145 | sn.text = notesField.getText(); 146 | sn.priority = (String) priorityField.getChoice(priorityField 147 | .getSelectedIndex()); 148 | } 149 | 150 | PersistenceManager.getInstance().saveSmartNoteManager(snm); 151 | emailViewScreen.displaySmartNotes(); 152 | close(); 153 | } 154 | } 155 | 156 | protected void paint(Graphics graphics) { 157 | graphics.setBackgroundColor(Color.WHITE); 158 | graphics.clear(); 159 | super.paint(graphics); 160 | } 161 | 162 | protected void paintBackground(Graphics graphics) { 163 | graphics.setBackgroundColor(Color.WHITE); 164 | graphics.clear(); 165 | super.paintBackground(graphics); 166 | } 167 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/screens/SmartSayScreen.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.screens; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.io.GeneralStoreInterface; 4 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 5 | import com.bbsmart.pda.blackberry.smartview.util.EmailTemplate; 6 | 7 | import net.rim.device.api.system.Bitmap; 8 | import net.rim.device.api.ui.Color; 9 | import net.rim.device.api.ui.Field; 10 | import net.rim.device.api.ui.FieldChangeListener; 11 | import net.rim.device.api.ui.Font; 12 | import net.rim.device.api.ui.Graphics; 13 | import net.rim.device.api.ui.MenuItem; 14 | import net.rim.device.api.ui.UiApplication; 15 | import net.rim.device.api.ui.component.ActiveAutoTextEditField; 16 | import net.rim.device.api.ui.component.BitmapField; 17 | import net.rim.device.api.ui.component.ButtonField; 18 | import net.rim.device.api.ui.component.Dialog; 19 | import net.rim.device.api.ui.component.Menu; 20 | import net.rim.device.api.ui.component.ObjectListField; 21 | import net.rim.device.api.ui.component.SeparatorField; 22 | import net.rim.device.api.ui.container.MainScreen; 23 | 24 | public class SmartSayScreen extends MainScreen { 25 | // The default email composer edit field (when in insert mode) 26 | private ActiveAutoTextEditField editField; 27 | private ButtonField createNewButton; 28 | private ObjectListField templatesList; 29 | 30 | public SmartSayScreen() { 31 | // In Configure Mode... 32 | editField = null; 33 | init(); 34 | } 35 | 36 | public SmartSayScreen(ActiveAutoTextEditField editField) { 37 | // In Insert Mode... 38 | this.editField = editField; 39 | init(); 40 | } 41 | 42 | private void init() { 43 | displayHeading(); 44 | initList(); 45 | 46 | createNewButton = new ButtonField("Create New", Field.FIELD_HCENTER 47 | | ButtonField.CONSUME_CLICK | ButtonField.NEVER_DIRTY); 48 | createNewButton.setChangeListener(new FieldChangeListener() { 49 | public void fieldChanged(Field field, int context) { 50 | UiApplication.getUiApplication().pushModalScreen( 51 | new NewTemplateScreen()); 52 | 53 | // Refresh the templates list since a new one may have been 54 | // created on the new template screen 55 | templatesList.set(GeneralStoreInterface.getEmailTemplates()); 56 | } 57 | }); 58 | add(new SeparatorField()); 59 | add(createNewButton); 60 | } 61 | 62 | private void initList() { 63 | templatesList = new ObjectListField(); 64 | templatesList.set(GeneralStoreInterface.getEmailTemplates()); 65 | add(templatesList); 66 | } 67 | 68 | private void displayHeading() { 69 | Bitmap headingBitmap = UiUtilities.getHeading(); 70 | Graphics g = new Graphics(headingBitmap); 71 | 72 | g.setColor(Color.FIREBRICK); 73 | if (UiUtilities.DEVICE_240W) { 74 | g.setFont(getFont().derive(Font.BOLD, 16)); 75 | g.drawText("EMAIL TEMPLATES", 90, 8); 76 | } else { 77 | g.setFont(getFont().derive(Font.BOLD, 18)); 78 | g.drawText("EMAIL TEMPLATES", 120, 13); 79 | } 80 | 81 | add(new BitmapField(headingBitmap)); 82 | add(new SeparatorField()); 83 | } 84 | 85 | private MenuItem deleteTemplate = new MenuItem("Delete", 0, 0) { 86 | public void run() { 87 | int selectedIndx = templatesList.getSelectedIndex(); 88 | 89 | if (selectedIndx != -1 && getFieldWithFocus() == templatesList) { 90 | EmailTemplate selected = (EmailTemplate) templatesList.get( 91 | templatesList, templatesList.getSelectedIndex()); 92 | 93 | if (Dialog.ask(Dialog.D_YES_NO, "Delete Template '" 94 | + selected.title + "'?", Dialog.YES) == Dialog.YES) { 95 | GeneralStoreInterface.deleteEmailTemplate(selected.title); 96 | templatesList.delete(selectedIndx); 97 | } 98 | } 99 | } 100 | }; 101 | 102 | private MenuItem viewEdit = new MenuItem("View/Edit", 0, 0) { 103 | public void run() { 104 | int selectedIndx = templatesList.getSelectedIndex(); 105 | 106 | if (selectedIndx != -1 && getFieldWithFocus() == templatesList) { 107 | EmailTemplate selected = (EmailTemplate) templatesList.get( 108 | templatesList, templatesList.getSelectedIndex()); 109 | UiApplication.getUiApplication().pushModalScreen( 110 | new NewTemplateScreen(selected)); 111 | 112 | // Refresh the templates list since the title of the selected 113 | // one may have changed 114 | templatesList.set(GeneralStoreInterface.getEmailTemplates()); 115 | } 116 | } 117 | }; 118 | 119 | private MenuItem createNew = new MenuItem("Create New", 0, 0) { 120 | public void run() { 121 | UiApplication.getUiApplication().pushModalScreen( 122 | new NewTemplateScreen()); 123 | 124 | // Refresh the templates list since a new one may have been 125 | // created on the new template screen 126 | templatesList.set(GeneralStoreInterface.getEmailTemplates()); 127 | } 128 | }; 129 | 130 | private MenuItem insert = new MenuItem("Insert in Email", 0, 0) { 131 | public void run() { 132 | int selectedIndx = templatesList.getSelectedIndex(); 133 | 134 | if (selectedIndx != -1 && getFieldWithFocus() == templatesList) { 135 | EmailTemplate selected = (EmailTemplate) templatesList.get( 136 | templatesList, templatesList.getSelectedIndex()); 137 | 138 | editField.insert(selected.text); 139 | close(); 140 | } 141 | } 142 | }; 143 | 144 | private MenuItem moveUp = new MenuItem("Move Up (U)", 0, 0) { 145 | public void run() { 146 | int selectedIndx = templatesList.getSelectedIndex(); 147 | 148 | if (selectedIndx > 0 && getFieldWithFocus() == templatesList) { 149 | String selectedTitle = ((EmailTemplate) templatesList.get( 150 | templatesList, selectedIndx)).title; 151 | GeneralStoreInterface.moveTemplateUp(selectedTitle); 152 | 153 | // Refresh the templates list... 154 | templatesList.set(GeneralStoreInterface.getEmailTemplates()); 155 | templatesList.setSelectedIndex(selectedIndx - 1); 156 | } 157 | } 158 | }; 159 | 160 | private MenuItem moveDown = new MenuItem( 161 | UiUtilities.DEVICE_SURETYPE ? "Move Down (M)" : "Move Down (D)", 0, 162 | 0) { 163 | public void run() { 164 | int selectedIndx = templatesList.getSelectedIndex(); 165 | 166 | if (selectedIndx != -1 167 | && selectedIndx < templatesList.getSize() - 1 168 | && getFieldWithFocus() == templatesList) { 169 | String selectedTitle = ((EmailTemplate) templatesList.get( 170 | templatesList, selectedIndx)).title; 171 | GeneralStoreInterface.moveTemplateDown(selectedTitle); 172 | 173 | // Refresh the templates list... 174 | templatesList.set(GeneralStoreInterface.getEmailTemplates()); 175 | templatesList.setSelectedIndex(selectedIndx + 1); 176 | } 177 | } 178 | }; 179 | 180 | protected void makeMenu(Menu menu, int instance) { 181 | super.makeMenu(menu, instance); 182 | 183 | menu.add(createNew); 184 | if (templatesList.getSelectedIndex() != -1) { 185 | if (editField != null) { 186 | menu.add(insert); 187 | } 188 | menu.add(viewEdit); 189 | menu.add(deleteTemplate); 190 | } 191 | 192 | menu.add(MenuItem.separator(0)); 193 | if (templatesList.getSelectedIndex() > 0) { 194 | menu.add(moveUp); 195 | } 196 | 197 | if (templatesList.getSelectedIndex() < templatesList.getSize() - 1) { 198 | menu.add(moveDown); 199 | } 200 | menu.add(MenuItem.separator(0)); 201 | 202 | if (editField == null) { 203 | // In configure mode - default selection should be "View/Edit" 204 | menu.setDefault(viewEdit); 205 | } else { 206 | // In insert mode - default should be "Insert" option 207 | menu.setDefault(insert); 208 | } 209 | } 210 | 211 | protected boolean keyChar(char c, int status, int time) { 212 | switch (c) { 213 | case 8: // DEL key 214 | deleteTemplate.run(); 215 | return true; 216 | case 'u': 217 | moveUp.run(); 218 | return true; 219 | case 'm': 220 | if (UiUtilities.DEVICE_SURETYPE) { 221 | moveDown.run(); 222 | return true; 223 | } else { 224 | return false; 225 | } 226 | case 'd': 227 | if (!UiUtilities.DEVICE_SURETYPE) { 228 | moveDown.run(); 229 | return true; 230 | } else { 231 | return false; 232 | } 233 | default: 234 | return super.keyChar(c, status, time); 235 | } 236 | } 237 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/screens/TrialEndedScreen.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.screens; 2 | 3 | import com.bbsmart.pda.blackberry.smartview.ui.customfield.HTMLField; 4 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 5 | 6 | import net.rim.blackberry.api.browser.Browser; 7 | import net.rim.device.api.browser.field.RenderingException; 8 | import net.rim.device.api.system.Bitmap; 9 | import net.rim.device.api.system.DeviceInfo; 10 | import net.rim.device.api.ui.Color; 11 | import net.rim.device.api.ui.Field; 12 | import net.rim.device.api.ui.FieldChangeListener; 13 | import net.rim.device.api.ui.Font; 14 | import net.rim.device.api.ui.Graphics; 15 | import net.rim.device.api.ui.UiApplication; 16 | import net.rim.device.api.ui.component.BitmapField; 17 | import net.rim.device.api.ui.component.ButtonField; 18 | import net.rim.device.api.ui.component.NullField; 19 | import net.rim.device.api.ui.container.HorizontalFieldManager; 20 | import net.rim.device.api.ui.container.MainScreen; 21 | 22 | public final class TrialEndedScreen extends MainScreen { 23 | private String buyNowURL = "https://www.mobihand.com/mobilecart/mc1.asp?posid=16&pid=12362&did=" 24 | + Integer.toHexString(DeviceInfo.getDeviceId()).toUpperCase(); 25 | 26 | public TrialEndedScreen() { 27 | // Write the heading... 28 | Bitmap headingBitmap = UiUtilities.getHeading(); 29 | writeHeading(new Graphics(headingBitmap)); 30 | add(new BitmapField(headingBitmap)); 31 | 32 | add(new NullField()); // for focus 33 | 34 | HTMLField htmlField = new HTMLField(); 35 | htmlField.setContent(getTrialEndedContent()); 36 | 37 | try { 38 | add(htmlField.getHTMLField()); 39 | } catch (RenderingException re) { 40 | // Never happens 41 | } 42 | 43 | HorizontalFieldManager buttonManager = new HorizontalFieldManager( 44 | Field.FIELD_HCENTER); 45 | 46 | ButtonField activateButton = new ButtonField("Activate!", 47 | ButtonField.CONSUME_CLICK | ButtonField.NEVER_DIRTY); 48 | activateButton.setChangeListener(new FieldChangeListener() { 49 | public void fieldChanged(Field field, int context) { 50 | close(); 51 | UiApplication.getUiApplication().pushScreen( 52 | new RegisterScreen()); 53 | } 54 | }); 55 | 56 | ButtonField buyNowButton = new ButtonField("Buy Now!", 57 | ButtonField.CONSUME_CLICK | ButtonField.NEVER_DIRTY); 58 | buyNowButton.setChangeListener(new FieldChangeListener() { 59 | public void fieldChanged(Field field, int context) { 60 | Browser.getDefaultSession().displayPage(buyNowURL); 61 | } 62 | }); 63 | 64 | buttonManager.add(buyNowButton); 65 | buttonManager.add(activateButton); 66 | add(buttonManager); 67 | } 68 | 69 | private void writeHeading(Graphics g) { 70 | g.setColor(Color.FIREBRICK); 71 | 72 | if (UiUtilities.DEVICE_240W) { 73 | g.setFont(getFont().derive(Font.BOLD, 16)); 74 | g.drawText("TRIAL ENDED!", 90, 8); 75 | } else { 76 | g.setFont(getFont().derive(Font.BOLD, 18)); 77 | g.drawText("TRIAL ENDED!", 120, 13); 78 | } 79 | } 80 | 81 | public String getTrialEndedContent() { 82 | StringBuffer content = new StringBuffer(); 83 | 84 | content.append(""); 85 | content.append(""); 86 | content.append("Thanks for trying out the trial version of BBSmart Email Viewer!

"); 87 | content.append("If you enjoyed using this product, and now dread going back to using the"); 88 | content.append(" bland default email client, there is another way!

"); 89 | content.append("Head on over to the Handango website (www.handango.com) and pick up a copy today! "); 90 | content.append("Alternatively, you can buy online right now by clicking the Buy Now button below!

"); 91 | content.append("Got some feedback you would like to give? Loved it? Hated it? Got a cool idea to make it better?"); 92 | content.append(" Feel free to email us at support@blackberrysmart.com"); 93 | content.append("

"); 94 | content.append("Finally, be sure to visit us at BBSmart (www.blackberrysmart.com) every now and then"); 95 | content.append(" to hear about any new exciting up and coming products!"); 96 | content.append(""); 97 | 98 | return content.toString(); 99 | } 100 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/ui/util/UiUtilities.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.ui.util; 2 | 3 | import java.io.InputStream; 4 | 5 | import net.rim.device.api.system.Bitmap; 6 | import net.rim.device.api.system.DeviceInfo; 7 | import net.rim.device.api.system.EncodedImage; 8 | import net.rim.device.api.ui.Field; 9 | import net.rim.device.api.ui.UiApplication; 10 | import net.rim.device.api.ui.component.Dialog; 11 | 12 | public final class UiUtilities { 13 | public static final String EMPTY_STRING = ""; 14 | 15 | public static final String DEVICE_NAME = DeviceInfo.getDeviceName(); 16 | 17 | public static final boolean DEVICE_240W = (DEVICE_NAME.startsWith("7") || DEVICE_NAME 18 | .startsWith("81")); 19 | 20 | public static final boolean DEVICE_SURETYPE = (DEVICE_NAME.startsWith("71") || DEVICE_NAME 21 | .startsWith("81")); 22 | 23 | public static final String HEADING_ICON_320 = "heading_320x34.jpg"; 24 | 25 | public static final String HEADING_ICON_240 = "heading_240x26.jpg"; 26 | 27 | public static final String INFOBAR_320x13 = "infobar_320x13.jpg"; 28 | 29 | public static final String INFOBAR_240x13 = "infobar_240x13.jpg"; 30 | 31 | public static final String INFOBAR_BOTTOM_320x4 = "infobar_bottom_320x4.jpg"; 32 | 33 | public static final String MORE_ON_320x14 = "more_on_320x14.jpg"; 34 | 35 | public static final String MORE_ON_240x14 = "more_on_240x14.jpg"; 36 | 37 | public static final String MORE_OFF_320x14 = "more_off_320x14.jpg"; 38 | 39 | public static final String MORE_OFF_240x14 = "more_off_240x14.jpg"; 40 | 41 | public static final String LOADING_BAR_ERR_320x32 = "loadingbar_err_320x32.png"; 42 | 43 | public static final String LOADING_BAR_ERR_240x24 = "loadingbar_err_240x24.png"; 44 | 45 | public static final String LOADING_BAR_ERR_ICON_15x15 = "img_err_15x15.png"; 46 | 47 | public static final String LOADING_BAR_ERR_ICON_11x11 = "img_err_11x11.png"; 48 | 49 | public static final String LOADING_BAR_320x16 = "loadingbar_320x16.jpg"; 50 | 51 | public static final String LOADING_BAR_DONE_320x16 = "loadingbar_done_320x16.jpg"; 52 | 53 | public static void informDialog(final String message) { 54 | UiApplication.getUiApplication().invokeLater(new Runnable() { 55 | public void run() { 56 | Dialog.inform(message); 57 | } 58 | }); 59 | } 60 | 61 | public static void alertDialog(final String message) { 62 | UiApplication.getUiApplication().invokeLater(new Runnable() { 63 | public void run() { 64 | Dialog.alert(message); 65 | } 66 | }); 67 | } 68 | 69 | public static void setFocus(final Field field) { 70 | UiApplication.getUiApplication().invokeLater(new Runnable() { 71 | public void run() { 72 | field.setFocus(); 73 | } 74 | }); 75 | } 76 | 77 | public static Bitmap getMoreOnBar() { 78 | return getImage(DEVICE_240W ? MORE_ON_240x14 : MORE_ON_320x14); 79 | } 80 | 81 | public static Bitmap getMoreOffBar() { 82 | return getImage(DEVICE_240W ? MORE_OFF_240x14 : MORE_OFF_320x14); 83 | } 84 | 85 | public static Bitmap getInfoBar() { 86 | return getImage(DEVICE_240W ? INFOBAR_240x13 : INFOBAR_320x13); 87 | } 88 | 89 | public static Bitmap getInfoBarBottom() { 90 | return getImage(INFOBAR_BOTTOM_320x4); 91 | } 92 | 93 | public static Bitmap getLoadingBar() { 94 | return getImage(LOADING_BAR_320x16); 95 | } 96 | 97 | public static Bitmap getDoneLoadingBar() { 98 | return getImage(LOADING_BAR_DONE_320x16); 99 | } 100 | 101 | public static Bitmap getErrLoadingBar() { 102 | return getImage(DEVICE_240W ? LOADING_BAR_ERR_240x24 103 | : LOADING_BAR_ERR_320x32); 104 | } 105 | 106 | public static Bitmap getErrLoadingIcon() { 107 | return getImage(DEVICE_240W ? LOADING_BAR_ERR_ICON_11x11 108 | : LOADING_BAR_ERR_ICON_15x15); 109 | } 110 | 111 | public static Bitmap getSmallHeading() { 112 | return getImage(DEVICE_240W ? HEADING_ICON_240 : HEADING_ICON_320, 2); 113 | } 114 | 115 | public static Bitmap getHeading() { 116 | return getImage(DEVICE_240W ? HEADING_ICON_240 : HEADING_ICON_320); 117 | } 118 | 119 | public static Bitmap getImage(String imageName) { 120 | return getImage(imageName, 1); 121 | } 122 | 123 | public static Bitmap getImage(String imageName, int scaleFactor) { 124 | InputStream input; 125 | try { 126 | input = Class.forName( 127 | "com.bbsmart.pda.blackberry.smartview.SmartView") 128 | .getResourceAsStream("/img/" + imageName); 129 | byte[] data = new byte[input.available()]; 130 | input.read(data); 131 | 132 | EncodedImage image = EncodedImage.createEncodedImage(data, 0, 133 | data.length); 134 | image.setScale(scaleFactor); 135 | return image.getBitmap(); 136 | } catch (Exception e) { 137 | return null; 138 | } 139 | } 140 | 141 | public static byte[] getImageBytes(String imageName) { 142 | InputStream input; 143 | try { 144 | input = Class.forName( 145 | "com.bbsmart.pda.blackberry.smartview.SmartView") 146 | .getResourceAsStream("/img/" + imageName); 147 | byte[] data = new byte[input.available()]; 148 | input.read(data); 149 | return data; 150 | } catch (Exception e) { 151 | return null; 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/ColorChoices.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | import net.rim.device.api.ui.Color; 4 | 5 | public class ColorChoices { 6 | private static Object[] colorChoices = null; 7 | 8 | public static Object[] getColorChoices() { 9 | if (colorChoices != null) { 10 | return colorChoices; 11 | } 12 | colorChoices = new Object[] { 13 | new ColorChoice(Color.WHITE, "White"), 14 | new ColorChoice(Color.ALICEBLUE, "Alice Blue"), 15 | new ColorChoice(Color.ANTIQUEWHITE, "Antique White"), 16 | new ColorChoice(Color.AQUA, "Aqua"), 17 | new ColorChoice(Color.AQUAMARINE, "Aquamarine"), 18 | new ColorChoice(Color.AZURE, "Azure"), 19 | new ColorChoice(Color.BEIGE, "Beige"), 20 | new ColorChoice(Color.BISQUE, "Bisque"), 21 | new ColorChoice(Color.BLACK, "Black"), 22 | new ColorChoice(Color.BLANCHEDALMOND, "Blanched Almond"), 23 | new ColorChoice(Color.BLUE, "Blue"), 24 | new ColorChoice(Color.BLUEVIOLET, "Blue Violet"), 25 | new ColorChoice(Color.BROWN, "Brown"), 26 | new ColorChoice(Color.BURLYWOOD, "Burlywood"), 27 | new ColorChoice(Color.CADETBLUE, "Cadet Blue"), 28 | new ColorChoice(Color.CHARTREUSE, "Chartreuse"), 29 | new ColorChoice(Color.CHOCOLATE, "Chocolate"), 30 | new ColorChoice(Color.CORAL, "Coral"), 31 | new ColorChoice(Color.CORNFLOWERBLUE, "Cornflower Blue"), 32 | new ColorChoice(Color.CORNSILK, "Cornsilk"), 33 | new ColorChoice(Color.CRIMSON, "Crimson"), 34 | new ColorChoice(Color.CYAN, "Cyan"), 35 | new ColorChoice(Color.DARKBLUE, "Dark Blue"), 36 | new ColorChoice(Color.DARKCYAN, "Dark Cyan"), 37 | new ColorChoice(Color.DARKGOLDENROD, "Dark Goldenrod"), 38 | new ColorChoice(Color.DARKGRAY, "Dark Gray"), 39 | new ColorChoice(Color.DARKGREEN, "Dark Green"), 40 | new ColorChoice(Color.DARKKHAKI, "Dark Khaki"), 41 | new ColorChoice(Color.DARKMAGENTA, "Dark Magenta"), 42 | new ColorChoice(Color.DARKOLIVEGREEN, "Dark Olive Green"), 43 | new ColorChoice(Color.DARKORANGE, "Dark Orange"), 44 | new ColorChoice(Color.DARKORCHID, "Dark Orchid"), 45 | new ColorChoice(Color.DARKRED, "Dark Red"), 46 | new ColorChoice(Color.DARKSALMON, "Dark Salmon"), 47 | new ColorChoice(Color.DARKSEAGREEN, "Dark Sea Green"), 48 | new ColorChoice(Color.DARKSLATEBLUE, "Dark Slate Blue"), 49 | new ColorChoice(Color.DARKSLATEGRAY, "Dark Slate Gray"), 50 | new ColorChoice(Color.DARKTURQUOISE, "Dark Turquoise"), 51 | new ColorChoice(Color.DARKVIOLET, "Dark Violet"), 52 | new ColorChoice(Color.DEEPPINK, "Deep Pink"), 53 | new ColorChoice(Color.DEEPSKYBLUE, "Deep Sky Blue"), 54 | new ColorChoice(Color.DIMGRAY, "Dim Gray"), 55 | new ColorChoice(Color.DODGERBLUE, "Dodger Blue"), 56 | new ColorChoice(Color.FIREBRICK, "Firebrick"), 57 | new ColorChoice(Color.FLORALWHITE, "Floral White"), 58 | new ColorChoice(Color.FORESTGREEN, "Forest Green"), 59 | new ColorChoice(Color.FUCHSIA, "Fuchsia"), 60 | new ColorChoice(Color.GAINSBORO, "Gainsboro"), 61 | new ColorChoice(Color.GHOSTWHITE, "Ghost White"), 62 | new ColorChoice(Color.GOLD, "Gold"), 63 | new ColorChoice(Color.GOLDENROD, "Goldenrod"), 64 | new ColorChoice(Color.GRAY, "Gray"), 65 | new ColorChoice(Color.GREEN, "Green"), 66 | new ColorChoice(Color.GREENYELLOW, "Green Yellow"), 67 | new ColorChoice(Color.HONEYDEW, "Honeydew"), 68 | new ColorChoice(Color.HOTPINK, "Hot Pink"), 69 | new ColorChoice(Color.INDIANRED, "Indian Red"), 70 | new ColorChoice(Color.INDIGO, "Indigo"), 71 | new ColorChoice(Color.IVORY, "Ivory"), 72 | new ColorChoice(Color.KHAKI, "Khaki"), 73 | new ColorChoice(Color.LAVENDER, "Lavender"), 74 | new ColorChoice(Color.LAVENDERBLUSH, "Lavender Blush"), 75 | new ColorChoice(Color.LAWNGREEN, "Lawn Green"), 76 | new ColorChoice(Color.LEMONCHIFFON, "Lemon Chiffon"), 77 | new ColorChoice(Color.LIGHTBLUE, "Light Blue"), 78 | new ColorChoice(Color.LIGHTCORAL, "Light Coral"), 79 | new ColorChoice(Color.LIGHTCYAN, "Light Cyan"), 80 | new ColorChoice(Color.LIGHTGOLDENRODYELLOW, 81 | "Light Goldenrod Yellow"), 82 | new ColorChoice(Color.LIGHTGREEN, "Light Green"), 83 | new ColorChoice(Color.LIGHTGREY, "Light Grey"), 84 | new ColorChoice(Color.LIGHTPINK, "Light Pink"), 85 | new ColorChoice(Color.LIGHTSALMON, "Light Salmon"), 86 | new ColorChoice(Color.LIGHTSEAGREEN, "Light Sea Green"), 87 | new ColorChoice(Color.LIGHTSKYBLUE, "Light Sky Blue"), 88 | new ColorChoice(Color.LIGHTSLATEGRAY, "Light Slate Gray"), 89 | new ColorChoice(Color.LIGHTSTEELBLUE, "Light Steel Blue"), 90 | new ColorChoice(Color.LIGHTYELLOW, "Light Yellow"), 91 | new ColorChoice(Color.LIME, "Lime"), 92 | new ColorChoice(Color.LIMEGREEN, "Lime Green"), 93 | new ColorChoice(Color.LINEN, "Linen"), 94 | new ColorChoice(Color.MAGENTA, "Magenta"), 95 | new ColorChoice(Color.MAROON, "Maroon"), 96 | new ColorChoice(Color.MEDIUMAQUAMARINE, "Medium Aquamarine"), 97 | new ColorChoice(Color.MEDIUMBLUE, "Medium Blue"), 98 | new ColorChoice(Color.MEDIUMORCHID, "Medium Orchid"), 99 | new ColorChoice(Color.MEDIUMPURPLE, "Medium Purple"), 100 | new ColorChoice(Color.MEDIUMSEAGREEN, "Medium Sea Green"), 101 | new ColorChoice(Color.MEDIUMSLATEBLUE, "Medium Slate Blue"), 102 | new ColorChoice(Color.MEDIUMSPRINGGREEN, "Medium Spring Green"), 103 | new ColorChoice(Color.MEDIUMTURQUOISE, "Medium Turquoise"), 104 | new ColorChoice(Color.MEDIUMVIOLETRED, "Medium Violet Red"), 105 | new ColorChoice(Color.MIDNIGHTBLUE, "Midnight Blue"), 106 | new ColorChoice(Color.MINTCREAM, "Mint Cream"), 107 | new ColorChoice(Color.MISTYROSE, "Misty Rose"), 108 | new ColorChoice(Color.MOCCASIN, "Moccasin"), 109 | new ColorChoice(Color.NAVAJOWHITE, "Navajo White"), 110 | new ColorChoice(Color.NAVY, "Navy"), 111 | new ColorChoice(Color.OLDLACE, "Old Lace"), 112 | new ColorChoice(Color.OLIVE, "Olive"), 113 | new ColorChoice(Color.OLIVEDRAB, "Olive Drab"), 114 | new ColorChoice(Color.ORANGE, "Orange"), 115 | new ColorChoice(Color.ORANGERED, "Orange Red"), 116 | new ColorChoice(Color.ORCHID, "Orchid"), 117 | new ColorChoice(Color.PALEGOLDENROD, "Pale Goldenrod"), 118 | new ColorChoice(Color.PALEGREEN, "Pale Green"), 119 | new ColorChoice(Color.PALETURQUOISE, "Pale Turquoise"), 120 | new ColorChoice(Color.PALEVIOLETRED, "Pale Violet Red"), 121 | new ColorChoice(Color.PAPAYAWHIP, "Papaya Whip"), 122 | new ColorChoice(Color.PEACHPUFF, "Peach Puff"), 123 | new ColorChoice(Color.PERU, "Peru"), 124 | new ColorChoice(Color.PINK, "Pink"), 125 | new ColorChoice(Color.PLUM, "Plum"), 126 | new ColorChoice(Color.POWDERBLUE, "Powder Blue"), 127 | new ColorChoice(Color.PURPLE, "Purple"), 128 | new ColorChoice(Color.RED, "Red"), 129 | new ColorChoice(Color.ROSYBROWN, "Rosy Brown"), 130 | new ColorChoice(Color.ROYALBLUE, "Royal Blue"), 131 | new ColorChoice(Color.SADDLEBROWN, "Saddle Brown"), 132 | new ColorChoice(Color.SALMON, "Salmon"), 133 | new ColorChoice(Color.SANDYBROWN, "Sandy Brown"), 134 | new ColorChoice(Color.SEAGREEN, "Sea Green"), 135 | new ColorChoice(Color.SEASHELL, "Seashell"), 136 | new ColorChoice(Color.SIENNA, "Sienna"), 137 | new ColorChoice(Color.SILVER, "Silver"), 138 | new ColorChoice(Color.SKYBLUE, "Sky Blue"), 139 | new ColorChoice(Color.SLATEBLUE, "Slate Blue"), 140 | new ColorChoice(Color.SLATEGRAY, "Slate Gray"), 141 | new ColorChoice(Color.SNOW, "Snow"), 142 | new ColorChoice(Color.SPRINGGREEN, "Spring Green"), 143 | new ColorChoice(Color.STEELBLUE, "Steel Blue"), 144 | new ColorChoice(Color.TAN, "Tan"), 145 | new ColorChoice(Color.TEAL, "Teal"), 146 | new ColorChoice(Color.THISTLE, "Thistle"), 147 | new ColorChoice(Color.TOMATO, "Tomato"), 148 | new ColorChoice(Color.TURQUOISE, "Turquoise"), 149 | new ColorChoice(Color.VIOLET, "Violet"), 150 | new ColorChoice(Color.WHEAT, "Wheat"), 151 | new ColorChoice(Color.WHITESMOKE, "White Smoke"), 152 | new ColorChoice(Color.YELLOW, "Yellow"), 153 | new ColorChoice(Color.YELLOWGREEN, "Yellow Green") }; 154 | 155 | return colorChoices; 156 | } 157 | 158 | public static class ColorChoice { 159 | private int colorValue = -1; 160 | 161 | private String name = null; 162 | 163 | public ColorChoice(int aValue, String aName) { 164 | name = aName; 165 | colorValue = aValue; 166 | } 167 | 168 | public int getColorValue() { 169 | return colorValue; 170 | } 171 | 172 | public String getName() { 173 | return name; 174 | } 175 | 176 | public String toString() { 177 | return name; 178 | } 179 | } 180 | 181 | public static String getColorText(int colorValue) { 182 | Object[] colorChoices = getColorChoices(); 183 | int numChoices = colorChoices.length; 184 | for (int i = 0; i < numChoices; i++) { 185 | ColorChoice choice = (ColorChoice) colorChoices[i]; 186 | if (choice.getColorValue() == colorValue) { 187 | return choice.getName(); 188 | } 189 | } 190 | return "NO COLOR"; 191 | } 192 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/ColorPickerField.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ColorPickerField.java 3 | */ 4 | package com.bbsmart.pda.blackberry.smartview.util; 5 | 6 | import java.util.Vector; 7 | 8 | import net.rim.device.api.system.Characters; 9 | import net.rim.device.api.ui.Color; 10 | import net.rim.device.api.ui.Field; 11 | import net.rim.device.api.ui.FieldChangeListener; 12 | import net.rim.device.api.ui.FocusChangeListener; 13 | import net.rim.device.api.ui.Font; 14 | import net.rim.device.api.ui.Graphics; 15 | import net.rim.device.api.ui.Manager; 16 | import net.rim.device.api.ui.Ui; 17 | import net.rim.device.api.ui.component.LabelField; 18 | import net.rim.device.api.ui.container.HorizontalFieldManager; 19 | import net.rim.device.api.ui.container.PopupScreen; 20 | import net.rim.device.api.ui.container.VerticalFieldManager; 21 | 22 | import com.bbsmart.pda.blackberry.smartview.util.ColorChoices.ColorChoice; 23 | import com.bbsmart.pda.blackberry.smartview.util.ColorPickerField.ColorPickerScreen.ColorChoiceLabel; 24 | 25 | public class ColorPickerField extends HorizontalFieldManager { 26 | private int fontColor = Color.BLACK; // Default 27 | 28 | private String choicesValue; 29 | 30 | private int bgColor = Color.WHITE; // Default 31 | 32 | private Font font; 33 | 34 | private Font italicFont; 35 | 36 | private ColorPickerInnerField innerCPF; 37 | 38 | private HorizontalFieldManager innerHFM; 39 | 40 | private FieldChangeListener changeListener; 41 | 42 | private Field thisField; 43 | 44 | private Vector choiceLabels = new Vector(); 45 | 46 | /** 47 | * Allows a change listener to identify the field firing off a change. 48 | * Useful if you have the same change listener for multiple fields of this 49 | * type. 50 | */ 51 | private int context; 52 | 53 | /** 54 | * Indicates if this color picker is changing the background color, or the 55 | * font color. true for background, false for font. 56 | */ 57 | private boolean backgroundPicker; 58 | 59 | /** 60 | * ColorPickerField allows the choosing of background and font colors. 61 | * 62 | * @param aBackgroundPicker 63 | * true iff this picker picks the background color, false to pick 64 | * font color 65 | * @param aFont 66 | * The font to display in the dialogs. 67 | * @param aFontColor 68 | * The initial font color to display. 69 | * @param aBgColor 70 | * The initial background color to display. 71 | * @param aChoicesValue 72 | * The value to display in the choice boxes. 73 | * @param aChangeListener 74 | * The listener who cares about changes. 75 | * @param aContext 76 | * The context for the field change event context argument. 77 | */ 78 | public ColorPickerField(boolean aBackgroundPicker, Font aFont, 79 | int aFontColor, int aBgColor, String aChoicesValue, 80 | FieldChangeListener aChangeListener, int aContext) { 81 | super(); 82 | backgroundPicker = aBackgroundPicker; 83 | context = aContext; 84 | thisField = this; 85 | changeListener = aChangeListener; 86 | choicesValue = aChoicesValue; 87 | font = aFont; 88 | 89 | int fontMask = (font.isBold() ? Font.BOLD : 0) 90 | | (font.isPlain() ? Font.PLAIN : 0) 91 | | (font.isUnderlined() ? Font.UNDERLINED : 0) | Font.ITALIC; 92 | 93 | italicFont = font.derive(fontMask, font.getHeight(), Ui.UNITS_px, 94 | Font.ANTIALIAS_STANDARD, 0); 95 | 96 | bgColor = aBgColor; 97 | fontColor = aFontColor; 98 | 99 | innerHFM = new HorizontalFieldManager(); 100 | innerHFM.setPadding(1, 1, 1, 1); 101 | innerCPF = new ColorPickerInnerField(); 102 | innerHFM.add(innerCPF); 103 | add(innerHFM); 104 | } 105 | 106 | public int getBgColor() { 107 | return bgColor; 108 | } 109 | 110 | public int getFontColor() { 111 | return fontColor; 112 | } 113 | 114 | public void setBgColor(int color) { 115 | bgColor = color; 116 | innerCPF.updateText(); 117 | invalidate(); 118 | } 119 | 120 | public void setFontColor(int color) { 121 | fontColor = color; 122 | innerCPF.updateText(); 123 | invalidate(); 124 | } 125 | 126 | /** 127 | * @see net.rim.device.api.ui.container.HorizontalFieldManager#subpaint(net.rim.device.api.ui.Graphics) 128 | */ 129 | protected void subpaint(Graphics aGraphics) { 130 | aGraphics.setBackgroundColor(bgColor); 131 | aGraphics.clear(); 132 | super.subpaint(aGraphics); 133 | } 134 | 135 | private ColorChoiceLabel updateFocus() { 136 | int vecSize = choiceLabels.size(); 137 | for (int i = 0; i < vecSize; i++) { 138 | ColorChoiceLabel label = (ColorChoiceLabel) choiceLabels 139 | .elementAt(i); 140 | if (backgroundPicker && (label.getColor() == bgColor)) { 141 | label.setFocus(); 142 | return label; 143 | } else if (!backgroundPicker && (label.getColor() == fontColor)) { 144 | label.setFocus(); 145 | return label; 146 | } 147 | } 148 | return null; 149 | } 150 | 151 | private class ColorPickerInnerField extends LabelField implements 152 | FocusChangeListener { 153 | private ColorPickerScreen colorPickerScreen; 154 | 155 | private ColorPickerInnerField() { 156 | super("", LabelField.FOCUSABLE); 157 | setFocusListener(this); 158 | setFont(font); 159 | updateText(); 160 | } 161 | 162 | protected void updateText() { 163 | String colorText = ColorChoices 164 | .getColorText(backgroundPicker ? bgColor : fontColor); 165 | setText(colorText); 166 | } 167 | 168 | protected void paint(Graphics aGraphics) { 169 | if (isFocus()) { 170 | setFont(italicFont); 171 | } else { 172 | setFont(font); 173 | } 174 | 175 | aGraphics.setBackgroundColor(bgColor); 176 | aGraphics.clear(); 177 | aGraphics.setColor(fontColor); 178 | super.paint(aGraphics); 179 | } 180 | 181 | protected boolean trackwheelClick(int status, int time) { 182 | if (colorPickerScreen == null) { 183 | VerticalFieldManager vfg = new VerticalFieldManager( 184 | VerticalFieldManager.VERTICAL_SCROLL 185 | | VerticalFieldManager.VERTICAL_SCROLLBAR); 186 | colorPickerScreen = new ColorPickerScreen(vfg, this); 187 | } 188 | 189 | Ui.getUiEngine().pushScreen(colorPickerScreen); 190 | 191 | ColorChoiceLabel focused = updateFocus(); 192 | if (focused != null) { 193 | int size = choiceLabels.size(); 194 | int index = 0; 195 | for (int i = 0; i < size; i++) { 196 | ColorChoiceLabel label = (ColorChoiceLabel) choiceLabels 197 | .elementAt(i); 198 | if (label.getColor() == focused.getColor()) { 199 | index = i; 200 | break; 201 | } 202 | } 203 | 204 | if (index < (size - 3) && (index > 3)) { 205 | ColorChoiceLabel label = (ColorChoiceLabel) choiceLabels 206 | .elementAt(index + 2); 207 | label.setFocus(); 208 | label = (ColorChoiceLabel) choiceLabels 209 | .elementAt(index - 2); 210 | label.setFocus(); 211 | focused.setFocus(); 212 | } 213 | } 214 | return true; 215 | } 216 | 217 | public void focusChanged(Field aField, int aEventType) { 218 | switch (aEventType) { 219 | case FOCUS_LOST: 220 | invalidate(); 221 | break; 222 | default: 223 | break; 224 | } 225 | } 226 | } 227 | 228 | protected class ColorPickerScreen extends PopupScreen { 229 | public ColorPickerScreen(Manager delegate, ColorPickerInnerField aField) { 230 | super(delegate, PopupScreen.DEFAULT_MENU 231 | | PopupScreen.DEFAULT_CLOSE | PopupScreen.VERTICAL_SCROLL); 232 | addColorRows(); 233 | } 234 | 235 | private void addColorRows() { 236 | Object[] colorChoices = ColorChoices.getColorChoices(); 237 | for (int i = 0; i < colorChoices.length; i++) { 238 | ColorChoice choice = (ColorChoice) colorChoices[i]; 239 | addChoiceRow(choice); 240 | } 241 | } 242 | 243 | private void addChoiceRow(ColorChoice aChoice) { 244 | ColorChoiceHFM mgr = new ColorChoiceHFM(aChoice); 245 | String choiceName = choicesValue == null ? aChoice.getName() 246 | : choicesValue; 247 | ColorChoiceLabel choiceField = new ColorChoiceLabel(aChoice 248 | .getColorValue(), choiceName, LabelField.FOCUSABLE 249 | | LabelField.ELLIPSIS); 250 | choiceField.setFocusListener(mgr); 251 | choiceLabels.addElement(choiceField); 252 | 253 | HorizontalFieldManager iMgr = new HorizontalFieldManager(); 254 | iMgr.setPadding(9, 9, 9, 9); 255 | iMgr.add(choiceField); 256 | mgr.add(iMgr); 257 | add(mgr); 258 | } 259 | 260 | public boolean keyChar(char key, int status, int time) { 261 | switch (key) { 262 | case Characters.ESCAPE: 263 | onClose(); 264 | return true; 265 | } 266 | return super.keyChar(key, status, time); 267 | } 268 | 269 | protected class ColorChoiceLabel extends LabelField { 270 | private int myColor; 271 | 272 | public ColorChoiceLabel(int color, String text, long style) { 273 | super(text, style); 274 | myColor = color; 275 | } 276 | 277 | protected int getColor() { 278 | return myColor; 279 | } 280 | 281 | protected void paint(Graphics aGraphics) { 282 | aGraphics.setBackgroundColor(backgroundPicker ? myColor 283 | : bgColor); 284 | aGraphics.clear(); 285 | aGraphics.setColor(backgroundPicker ? fontColor : myColor); 286 | super.paint(aGraphics); 287 | } 288 | 289 | protected boolean trackwheelClick(int status, int time) { 290 | if (backgroundPicker) { 291 | bgColor = myColor; 292 | } else { 293 | fontColor = myColor; 294 | } 295 | innerCPF.updateText(); 296 | innerHFM.invalidate(); 297 | changeListener.fieldChanged(thisField, context); 298 | getUiEngine().popScreen(getScreen()); 299 | return true; 300 | } 301 | 302 | public int getPreferredWidth() { 303 | return ((Graphics.getScreenWidth() / 3) * 2) - 18; 304 | } 305 | 306 | protected void layout(int aWidth, int aHeight) { 307 | int width = ((Graphics.getScreenWidth() / 3) * 2) - 18; 308 | setExtent(width, aHeight); 309 | super.layout(width, aHeight); 310 | } 311 | 312 | } 313 | 314 | private class ColorChoiceHFM extends HorizontalFieldManager implements 315 | FocusChangeListener { 316 | private int myBgColor = 0; 317 | 318 | private Graphics graphics; 319 | 320 | private boolean inFocus; 321 | 322 | public ColorChoiceHFM(ColorChoice aColorChoice) { 323 | myBgColor = aColorChoice.getColorValue(); 324 | } 325 | 326 | protected void subpaint(Graphics aGraphics) { 327 | int newBgColor = backgroundPicker ? myBgColor : bgColor; 328 | graphics = aGraphics; 329 | int color = graphics.getColor(); 330 | aGraphics.setBackgroundColor(newBgColor); 331 | aGraphics.clear(); 332 | int bwidth = getExtent().width; 333 | int bheight = getExtent().height; 334 | if (inFocus) { 335 | graphics.setColor(Color.RED); 336 | graphics.drawRect(0, 0, bwidth, bheight); 337 | graphics.drawRect(1, 1, bwidth - 2, bheight - 2); 338 | } else { 339 | graphics.setColor(Color.WHITE); 340 | graphics.drawRect(0, 0, bwidth, bheight); 341 | graphics.drawRect(1, 1, bwidth - 2, bheight - 2); 342 | graphics.drawRect(2, 2, bwidth - 4, bheight - 4); 343 | graphics.drawRect(3, 3, bwidth - 6, bheight - 6); 344 | graphics.drawRect(4, 4, bwidth - 8, bheight - 8); 345 | graphics.drawRect(5, 5, bwidth - 10, bheight - 10); 346 | } 347 | 348 | graphics.setColor(color); 349 | super.subpaint(aGraphics); 350 | } 351 | 352 | public void focusChanged(Field aField, int aEventType) { 353 | switch (aEventType) { 354 | case FOCUS_GAINED: 355 | inFocus = true; 356 | break; 357 | case FOCUS_LOST: 358 | inFocus = false; 359 | break; 360 | default: 361 | break; 362 | } 363 | invalidate(); 364 | } 365 | } 366 | } 367 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/EmailFormatter.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neilwithdata/BBSmart-Email-Viewer/023963f49c46beec79e5bf69e3fc4fab509cf47c/src/com/bbsmart/pda/blackberry/smartview/util/EmailFormatter.java -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/EmailTemplate.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | public class EmailTemplate { 4 | public String title; 5 | public String text; 6 | 7 | public EmailTemplate(String title, String text) { 8 | this.title = title; 9 | this.text = text; 10 | } 11 | 12 | public String toString() { 13 | return title; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/EmailUtils.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | /** 4 | * Utility class for handling Emails 5 | * 6 | * @author Neil Sainsbury 7 | * 8 | */ 9 | public final class EmailUtils { 10 | 11 | public static String getLocalPart(String emailAddy) { 12 | return emailAddy.substring(0, emailAddy.indexOf('@')); 13 | } 14 | 15 | public static int getEmailStartIndx(String body, int atSymbolIndx) { 16 | // Walk backwards until we encounter an illegal local-part character 17 | int startIndx = atSymbolIndx - 1; 18 | while ((startIndx >= 0) && isValidLocalPartChar(body.charAt(startIndx))) { 19 | startIndx--; 20 | } 21 | 22 | startIndx++; // set it back to the true email start index 23 | 24 | // Though this isn't technically correct, Outlook sometimes inserts 25 | // 's around the email address. If a local part contains a dash as 26 | // the first char (shouldn't really happen much in real life (TM)) 27 | // then let's just scrap it 28 | if (body.charAt(startIndx) == '\'') { 29 | startIndx++; 30 | } 31 | 32 | if (startIndx == atSymbolIndx) { 33 | return -1; // local-part cannot have 0 length 34 | } 35 | 36 | if (body.charAt(startIndx) == '.' 37 | || body.charAt(atSymbolIndx - 1) == '.') { 38 | return -1; // local-part cannot start or end with a '.' 39 | } 40 | 41 | 42 | return startIndx; 43 | } 44 | 45 | public static int getEmailEndIndx(String body, int atSymbolIndx) { 46 | boolean dotFound = false; 47 | 48 | // Walk forwards until we encounter an illegal domain-part character 49 | int endIndx = atSymbolIndx + 1; 50 | while ((endIndx < body.length()) 51 | && isValidDomainPartChar(body.charAt(endIndx))) { 52 | if (body.charAt(endIndx) == '.') { 53 | dotFound = true; 54 | } 55 | endIndx++; 56 | } 57 | 58 | endIndx--; // set it back to the true email end index 59 | 60 | // Though this isn't technically correct, Outlook sometimes inserts 61 | // 's around the email address. If a domain-part contains a dash as 62 | // the last char (shouldn't really happen much in real life (TM)) 63 | // then let's just scrap it 64 | if (body.charAt(endIndx) == '\'') { 65 | endIndx--; 66 | } 67 | 68 | if (atSymbolIndx == endIndx) { 69 | return -1; // domain part cannot have length 0 70 | } 71 | 72 | if (body.charAt(atSymbolIndx + 1) == '.' || body.charAt(endIndx) == '.') { 73 | return -1; // domain-part cannot start or end with a '.' 74 | } 75 | 76 | if (!dotFound) { 77 | return -1; // domain-part must have at least one dot 78 | } 79 | 80 | return endIndx; 81 | } 82 | 83 | // According to RFC 2822 84 | public static final String VALID_LOCAL_CHARS = "!#$%&'*+-/=?^_`{|}~."; 85 | public static boolean isValidLocalPartChar(char c) { 86 | if (Character.isDigit(c)) { 87 | return true; 88 | } 89 | 90 | // If uppercase or lowercase letter 91 | if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)) { 92 | return true; 93 | } 94 | 95 | // Some other valid character 96 | if (VALID_LOCAL_CHARS.indexOf(c) != -1) { 97 | return true; 98 | } 99 | 100 | // Didn't match any of the conditions 101 | return false; 102 | } 103 | 104 | // According to RFC 2822 105 | public static boolean isValidDomainPartChar(char c) { 106 | if (Character.isDigit(c)) { 107 | return true; 108 | } 109 | 110 | // Some other valid local chars 111 | if (VALID_LOCAL_CHARS.indexOf(c) != -1) { 112 | return true; 113 | } 114 | 115 | // If uppercase or lowercase letter 116 | if ((c >= 65 && c <= 90) || (c >= 97 && c <= 122)) { 117 | return true; 118 | } 119 | 120 | if (c == '-' || c == '.') { 121 | return true; 122 | } 123 | 124 | // No match for any other conditions 125 | return false; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/HTMLRetriever.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | import net.rim.blackberry.api.mail.Message; 4 | 5 | public class HTMLRetriever { 6 | private Message message; 7 | 8 | public HTMLRetriever(Message message) { 9 | this.message = message; 10 | } 11 | 12 | public static boolean isHTMLEmail() { 13 | return true; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/MessageUtils.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | import java.util.Date; 4 | import java.util.Vector; 5 | 6 | import com.bbsmart.pda.blackberry.smartview.ui.util.UiUtilities; 7 | 8 | import net.rim.blackberry.api.mail.Address; 9 | import net.rim.blackberry.api.mail.BodyPart; 10 | import net.rim.blackberry.api.mail.Message; 11 | import net.rim.blackberry.api.mail.MessagingException; 12 | import net.rim.blackberry.api.mail.Multipart; 13 | import net.rim.blackberry.api.mail.TextBodyPart; 14 | import net.rim.device.api.ui.Color; 15 | import net.rim.device.api.util.StringUtilities; 16 | 17 | /** 18 | * Utility class for operating on messages. Essentially, a clean wrapper that 19 | * sits around the RIM Message class but provides specific functionality for the 20 | * EmailViewing application 21 | * 22 | * @author Neil 23 | */ 24 | public final class MessageUtils { 25 | private Message message; 26 | 27 | private Address[] toRecips, ccRecips, bccRecips; 28 | 29 | private boolean preferAddress; 30 | 31 | public MessageUtils(Message message) { 32 | this.message = message; 33 | 34 | try { 35 | toRecips = cleanRecips(message 36 | .getRecipients(Message.RecipientType.TO)); 37 | ccRecips = cleanRecips(message 38 | .getRecipients(Message.RecipientType.CC)); 39 | bccRecips = cleanRecips(message 40 | .getRecipients(Message.RecipientType.BCC)); 41 | } catch (MessagingException me) { 42 | UiUtilities.alertDialog("Error reading recipients: " 43 | + me.getMessage()); 44 | } 45 | } 46 | 47 | public void setPreferAddress(boolean preferAddress) { 48 | this.preferAddress = preferAddress; 49 | } 50 | 51 | public String getFrom() { 52 | try { 53 | return getDisplayableEmail(message.getFrom()); 54 | } catch (MessagingException me) { 55 | return UiUtilities.EMPTY_STRING; 56 | } 57 | } 58 | 59 | public String getShortRecip() { 60 | int recipSum = toRecips.length + ccRecips.length + bccRecips.length; 61 | 62 | Address[] recips = toRecips; 63 | if (toRecips.length == 0) { 64 | recips = ccRecips; 65 | if (ccRecips.length == 0) { 66 | recips = bccRecips; 67 | if (bccRecips.length == 0) { 68 | recips = null; 69 | } 70 | } 71 | } 72 | 73 | if (recips != null) { 74 | String recip = getDisplayableEmail(recips[0]); 75 | if (recipSum > 1) { 76 | recip = recip + ", ... (" + recipSum + ")"; 77 | } 78 | return recip; 79 | } else { 80 | return UiUtilities.EMPTY_STRING; 81 | } 82 | } 83 | 84 | public String getShortRecipType() { 85 | String type = "To: "; 86 | if (toRecips.length == 0) { 87 | type = "Cc: "; 88 | if (ccRecips.length == 0) { 89 | type = "Bcc: "; 90 | if (bccRecips.length == 0) { 91 | type = "To: "; 92 | } 93 | } 94 | } 95 | 96 | return type; 97 | } 98 | 99 | public int getPriorityColor() { 100 | switch (message.getPriority()) { 101 | case Message.Priority.HIGH: 102 | return Color.RED; 103 | case Message.Priority.NORMAL: 104 | return Color.GREEN; 105 | case Message.Priority.LOW: 106 | return Color.LIGHTBLUE; 107 | default: 108 | return Color.GREEN; 109 | } 110 | } 111 | 112 | public String getPriority() { 113 | switch (message.getPriority()) { 114 | case Message.Priority.LOW: 115 | return "Low"; 116 | case Message.Priority.NORMAL: 117 | return "Normal"; 118 | case Message.Priority.HIGH: 119 | return "High"; 120 | default: 121 | return "Normal"; 122 | } 123 | } 124 | 125 | public String getMessageStatus() { 126 | String friendlyStatus; 127 | 128 | switch (message.getStatus()) { 129 | case Message.Status.RX_ERROR: 130 | friendlyStatus = "Error Receiving"; 131 | break; 132 | case Message.Status.RX_RECEIVED: 133 | friendlyStatus = "Received"; 134 | break; 135 | case Message.Status.RX_RECEIVING: 136 | friendlyStatus = "Receiving"; 137 | break; 138 | case Message.Status.TX_COMPOSING: 139 | friendlyStatus = "Composing"; 140 | break; 141 | case Message.Status.TX_COMPRESSING: 142 | friendlyStatus = "Compressing"; 143 | break; 144 | case Message.Status.TX_DELIVERED: 145 | friendlyStatus = "Delivered"; 146 | break; 147 | case Message.Status.TX_ENCRYPTING: 148 | friendlyStatus = "Encrypting"; 149 | break; 150 | case Message.Status.TX_ERROR: 151 | case Message.Status.TX_GENERAL_FAILURE: 152 | friendlyStatus = "Error Sending"; 153 | break; 154 | case Message.Status.TX_MAILBOXED: 155 | friendlyStatus = "Mailboxed"; 156 | break; 157 | case Message.Status.TX_PENDING: 158 | friendlyStatus = "Pending Send"; 159 | break; 160 | case Message.Status.TX_READ: 161 | friendlyStatus = "Read"; 162 | break; 163 | case Message.Status.TX_RETRIEVING_KEY: 164 | friendlyStatus = "Retrieving Key"; 165 | break; 166 | case Message.Status.TX_SENDING: 167 | friendlyStatus = "Sending"; 168 | break; 169 | case Message.Status.TX_SENT: 170 | friendlyStatus = "Sent"; 171 | break; 172 | default: 173 | friendlyStatus = UiUtilities.EMPTY_STRING; 174 | break; 175 | } 176 | 177 | return friendlyStatus; 178 | } 179 | 180 | public String getReplyTo() { 181 | try { 182 | Address[] replyTo = message.getReplyTo(); 183 | 184 | if (replyTo != null && replyTo.length > 0) { 185 | return getDisplayableEmail(replyTo[0]); 186 | } else { 187 | return UiUtilities.EMPTY_STRING; 188 | } 189 | } catch (MessagingException me) { 190 | return UiUtilities.EMPTY_STRING; 191 | } 192 | } 193 | 194 | public String makeFullToString() { 195 | return joinAddresses(toRecips); 196 | } 197 | 198 | public String makeFullCcString() { 199 | return joinAddresses(ccRecips); 200 | } 201 | 202 | public String makeFullBccString() { 203 | return joinAddresses(bccRecips); 204 | } 205 | 206 | private String joinAddresses(Address[] addresses) { 207 | StringBuffer addressStr = new StringBuffer(); 208 | 209 | int numAddresses = addresses.length; 210 | for (int i = 0; i < numAddresses; i++) { 211 | addressStr.append(getDisplayableEmail(addresses[i])); 212 | 213 | if (i != numAddresses - 1) { 214 | addressStr.append(", "); 215 | } 216 | } 217 | 218 | return addressStr.toString(); 219 | } 220 | 221 | public String getSentDate() { 222 | if (message.getStatus() == Message.Status.TX_COMPOSING) { 223 | return UiUtilities.EMPTY_STRING; 224 | } 225 | 226 | Date sentDate = message.getSentDate(); 227 | 228 | if (sentDate == null) { 229 | return "Unknown"; 230 | } 231 | 232 | String[] parts = StringUtilities.stringToWords(sentDate.toString()); 233 | 234 | StringBuffer newDate = new StringBuffer(); 235 | 236 | newDate.append(parts[0]); // dow 237 | newDate.append(' '); 238 | newDate.append(parts[1]); // mon 239 | newDate.append(' '); 240 | 241 | // Remove any leading '0' from dd 242 | String dd = parts[2]; 243 | if (dd.charAt(0) == '0') { 244 | dd = dd.substring(1); 245 | } 246 | 247 | newDate.append(dd); // dd 248 | newDate.append(", "); // , 249 | 250 | // Format the time display nicely and in 12hr time 251 | String hourStr = parts[3]; 252 | int hour = Integer.parseInt(hourStr); 253 | String meridian; 254 | if (hour == 0) { 255 | hour = 12; 256 | meridian = "AM"; 257 | } else if (hour < 12) { 258 | meridian = "AM"; 259 | } else if (hour == 12) { 260 | meridian = "PM"; 261 | } else { 262 | meridian = "PM"; 263 | hour = hour % 12; 264 | } 265 | 266 | newDate.append(hour); 267 | newDate.append(':'); 268 | newDate.append(parts[4]); 269 | newDate.append(" "); 270 | newDate.append(meridian); 271 | 272 | return newDate.toString(); 273 | } 274 | 275 | private String getDisplayableEmail(Address addr) { 276 | if (addr == null) { 277 | return UiUtilities.EMPTY_STRING; 278 | } 279 | 280 | if (preferAddress) { 281 | return addr.getAddr(); 282 | } else { 283 | // Return the address only if the name does not exist 284 | String name = addr.getName(); 285 | if (name == null) { 286 | name = addr.getAddr(); 287 | if (name == null) { 288 | name = UiUtilities.EMPTY_STRING; 289 | } 290 | } 291 | return name; 292 | } 293 | } 294 | 295 | public boolean hasAttachments() { 296 | return (message.getContent() instanceof Multipart); 297 | } 298 | 299 | public Vector getAttachments() { 300 | Multipart parts = (Multipart) message.getContent(); 301 | int numParts = parts.getCount(); 302 | 303 | Vector attachments = new Vector(numParts); 304 | BodyPart part; 305 | for (int i = 0; i < numParts; i++) { 306 | part = parts.getBodyPart(i); 307 | 308 | if (!(part instanceof TextBodyPart)) { 309 | attachments.addElement(part); 310 | } 311 | } 312 | 313 | return attachments; 314 | } 315 | 316 | private Address[] cleanRecips(Address[] addresses) { 317 | if (addresses == null) { 318 | return new Address[0]; 319 | } 320 | 321 | Vector cleaned = new Vector(addresses.length); 322 | 323 | for (int i = 0; i < addresses.length; i++) { 324 | if (addresses[i] != null) { 325 | if (!(addresses[i].getAddr().trim().length() == 0)) { 326 | cleaned.addElement(addresses[i]); 327 | } 328 | } 329 | } 330 | 331 | // Convert the vector of cleaned addresses to an array and return 332 | Address[] cleanedAddresses = new Address[cleaned.size()]; 333 | for (int j = 0; j < cleaned.size(); j++) { 334 | cleanedAddresses[j] = (Address) cleaned.elementAt(j); 335 | } 336 | 337 | return cleanedAddresses; 338 | } 339 | 340 | /** 341 | * Returns the TextBodyPart of the email or null if it has none 342 | */ 343 | public TextBodyPart getTextBodyPart() { 344 | Object content = message.getContent(); 345 | 346 | if (content instanceof BodyPart) { 347 | return (TextBodyPart) content; 348 | } else { 349 | // Must be a MultiPart - search through for the TextBodyPart 350 | Multipart mp = (Multipart) content; 351 | for (int i = 0; i < mp.getCount(); i++) { 352 | if (mp.getBodyPart(i) instanceof TextBodyPart) { 353 | return (TextBodyPart) mp.getBodyPart(i); 354 | } 355 | } 356 | } 357 | 358 | return null; 359 | } 360 | 361 | /** 362 | * Returns the TextBodyPart of the email or null if it has none 363 | */ 364 | public static TextBodyPart getTextBodyPart(Message m) { 365 | Object content = m.getContent(); 366 | 367 | if (content instanceof BodyPart) { 368 | return (TextBodyPart) content; 369 | } else { 370 | // Must be a MultiPart - search through for the TextBodyPart 371 | Multipart mp = (Multipart) content; 372 | for (int i = 0; i < mp.getCount(); i++) { 373 | if (mp.getBodyPart(i) instanceof TextBodyPart) { 374 | return (TextBodyPart) mp.getBodyPart(i); 375 | } 376 | } 377 | } 378 | 379 | return null; 380 | } 381 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/MoreListener.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | import net.rim.blackberry.api.mail.BodyPart; 4 | 5 | public interface MoreListener { 6 | public void notifySuccess(BodyPart bp); 7 | 8 | public void notifyFailure(BodyPart bp, String errorMessage); 9 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/MoreRetriever.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | import java.util.Timer; 4 | import java.util.TimerTask; 5 | 6 | import net.rim.blackberry.api.mail.BodyPart; 7 | import net.rim.blackberry.api.mail.Message; 8 | import net.rim.blackberry.api.mail.Transport; 9 | import net.rim.blackberry.api.mail.event.MessageEvent; 10 | import net.rim.blackberry.api.mail.event.MessageListener; 11 | 12 | public final class MoreRetriever { 13 | public static final String MORE_ERR = "Sorry. More could not be retrieved.\n\nPlease check your connection status and try again later"; 14 | 15 | // Used by the message listener to determine when more has been retrieved 16 | private int oldContentLength; 17 | 18 | // The listener to notify if the retrieval was successful 19 | private MoreListener listener; 20 | 21 | private BodyPart bp; 22 | 23 | private Message msg; 24 | 25 | private MessageListener moreMessageListener; 26 | 27 | // Flag to indicate whether we are currently retrieving more or not 28 | private boolean retrievingMore = false; 29 | 30 | // The thread to poll until new content comes in 31 | private Thread updatePoller; 32 | 33 | // The timeout timer which kicks in after a specified time 34 | // to halt the more retrieval process 35 | private Timer moreWatchdog; 36 | 37 | public static boolean hasMore(BodyPart bp) { 38 | return bp.hasMore(); 39 | } 40 | 41 | public void retrieveMore(Message msg, BodyPart bp, MoreListener listener) { 42 | if (retrievingMore) { 43 | return; 44 | } 45 | 46 | this.listener = listener; 47 | this.msg = msg; 48 | this.bp = bp; 49 | 50 | if (bp.hasMore() && !bp.moreRequestSent()) { 51 | try { 52 | // Construct a new message listener (to notify us when new 53 | // content comes in) 54 | oldContentLength = bp.getContent().toString().length(); 55 | 56 | moreMessageListener = new MessageMoreListener(); 57 | msg.addMessageListener(moreMessageListener); 58 | 59 | Transport.more(bp, false); 60 | retrievingMore = true; 61 | initMoreTimeoutListener(); 62 | } catch (Exception e) { 63 | retrievingMore = false; 64 | msg.removeMessageListener(moreMessageListener); 65 | listener.notifyFailure(bp, MORE_ERR); 66 | } 67 | } else { 68 | retrievingMore = false; 69 | listener.notifyFailure(bp, MORE_ERR); 70 | } 71 | } 72 | 73 | private void initMoreTimeoutListener() { 74 | // Timeout attempting to retrieve more after 50 seconds... 75 | final int MORE_TIMEOUT = 50000; 76 | 77 | moreWatchdog = new Timer(); 78 | moreWatchdog.schedule(new TimerTask() { 79 | public void run() { 80 | if (updatePoller != null && updatePoller.isAlive()) { 81 | updatePoller.interrupt(); 82 | } 83 | 84 | // Perform a cleanup 85 | msg.removeMessageListener(moreMessageListener); 86 | retrievingMore = false; 87 | listener.notifyFailure(bp, MORE_ERR); 88 | 89 | } 90 | }, MORE_TIMEOUT); 91 | } 92 | 93 | class MessageMoreListener implements MessageListener { 94 | 95 | public void changed(MessageEvent e) { 96 | final Message msg = e.getMessage(); 97 | 98 | if (retrievingMore) { // Already in the process of retrieving more 99 | return; 100 | } 101 | 102 | retrievingMore = true; 103 | 104 | updatePoller = new Thread() { 105 | public void run() { 106 | // Continue sleeping until we receive more of the email 107 | while (msg.getBodyText().length() <= oldContentLength) { 108 | try { 109 | Thread.sleep(1500); 110 | } catch (InterruptedException ie) { 111 | // Notified to stop polling - exit 112 | return; 113 | } 114 | } 115 | 116 | // Call of the timeout watchdog - we did our job 117 | if (moreWatchdog != null) { 118 | moreWatchdog.cancel(); 119 | } 120 | 121 | msg.removeMessageListener(moreMessageListener); 122 | retrievingMore = false; 123 | listener.notifySuccess(bp); 124 | } 125 | }; 126 | updatePoller.start(); 127 | } 128 | } 129 | } -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/RPNState.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | public final class RPNState { 4 | protected final int[] stack; 5 | protected int pos; 6 | 7 | public RPNState() { 8 | // Hard limit! Bleh 9 | stack = new int[30]; 10 | pos = 0; 11 | } 12 | 13 | public void push(int value) { 14 | stack[pos++] = value; 15 | } 16 | 17 | public int pop() { 18 | return stack[--pos]; 19 | } 20 | 21 | public int size() { 22 | return pos; 23 | } 24 | 25 | public boolean apply(String term, int c, int i, int key) { 26 | if (pushVariable(term, c, i, key) || pushConstant(term) || applyOperator(term)) 27 | return true; 28 | 29 | return false; 30 | } 31 | 32 | protected boolean pushVariable(String term, int c, int i, int key) { 33 | if (term.equals("c")) { 34 | push(c); 35 | return true; 36 | } 37 | 38 | if (term.equals("i")) { 39 | push(i); 40 | return true; 41 | } 42 | 43 | if (term.equals("key")) { 44 | push(key); 45 | return true; 46 | } 47 | 48 | return false; 49 | } 50 | 51 | protected boolean pushConstant(String term) { 52 | try { 53 | push(Integer.parseInt(term)); 54 | return true; 55 | } catch (NumberFormatException ex) { 56 | return false; 57 | } 58 | } 59 | 60 | protected boolean applyOperator(String term) { 61 | if (size() >= 2 && applyBinaryOperator(term)) 62 | return true; 63 | 64 | if (size() >= 1 && applyUnaryOperator(term)) 65 | return true; 66 | 67 | return false; 68 | } 69 | 70 | protected boolean applyBinaryOperator(String op) { 71 | // Pop in reverse order 72 | int b = pop(); 73 | int a = pop(); 74 | int c = 0; 75 | 76 | // Arithmetic 77 | if (op.equals("+")) 78 | c = a + b; 79 | else if (op.equals("-")) 80 | c = a - b; 81 | else if (op.equals("*")) 82 | c = a * b; 83 | else if (op.equals("/")) 84 | c = a / b; 85 | else if (op.equals("%")) 86 | c = a % b; 87 | 88 | // Equality 89 | else if (op.equals("==")) 90 | c = asint(a == b); 91 | else if (op.equals(">=")) 92 | c = asint(a >= b); 93 | else if (op.equals("<=")) 94 | c = asint(a <= b); 95 | else if (op.equals("<")) 96 | c = asint(a < b); 97 | else if (op.equals(">")) 98 | c = asint(a > b); 99 | else if (op.equals("!=")) 100 | c = asint(a != b); 101 | 102 | // Logic 103 | else if (op.equals("&&")) 104 | c = asint(asbool(a) && asbool(b)); 105 | else if (op.equals("||")) 106 | c = asint(asbool(a) || asbool(b)); 107 | 108 | // Bitwise 109 | else if (op.equals(">>")) 110 | c = a >> b; 111 | else if (op.equals("<<")) 112 | c = a << b; 113 | else if (op.equals("|")) 114 | c = a | b; 115 | else if (op.equals("&")) 116 | c = a & b; 117 | else if (op.equals("^")) 118 | c = a ^ b; 119 | 120 | // Or all failed 121 | else 122 | return false; 123 | 124 | // Push result 125 | push(c); 126 | return true; 127 | } 128 | 129 | public boolean applyUnaryOperator(String op) { 130 | int a = pop(); 131 | int c = 0; 132 | 133 | if (op.equals("!")) 134 | c = asint(!asbool(a)); 135 | else if (op.equals("~")) 136 | c = ~a; 137 | else 138 | return false; 139 | 140 | // Push result 141 | push(c); 142 | return true; 143 | } 144 | 145 | protected static boolean asbool(int val) { 146 | return val != 0; 147 | } 148 | 149 | protected static int asint(boolean res) { 150 | return res ? 1 : 0; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/RPNString.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | public final class RPNString { 4 | protected final String string; 5 | 6 | public RPNString(String nstring) { 7 | string = nstring; 8 | } 9 | 10 | public int apply(int c, int i, int key) { 11 | RPNState state = new RPNState(); 12 | 13 | Tokenizer tokens = new Tokenizer(string); 14 | while (tokens.hasNext()) 15 | state.apply(tokens.next(), c, i, key); 16 | 17 | if (state.size() == 0) 18 | return 0; 19 | 20 | return state.pop(); 21 | } 22 | 23 | public String apply(String name) { 24 | name = toTen(name); 25 | 26 | int key = 0; 27 | 28 | for (int i = 0; i < name.length(); i++) { 29 | int c = name.charAt(i) & 0xFF; 30 | key = apply(c, i, key); 31 | } 32 | 33 | return padInt(key & 0xFFFF); 34 | } 35 | 36 | public static String toTen(String name) { 37 | int len = name.length(); 38 | 39 | if (len <= 10) 40 | return name; 41 | 42 | String left = name.substring(0, 5); 43 | String right = name.substring(len - 5, len); 44 | return left + right; 45 | } 46 | 47 | public static String padInt(int val) { 48 | if (val == 0) 49 | return "00000"; 50 | 51 | char[] out = new char[5]; 52 | for (int i = 4; i >= 0; i--) { 53 | out[i] = (char) ('0' + (val % 10)); 54 | val /= 10; 55 | } 56 | 57 | return new String(out); 58 | } 59 | 60 | public static String apply(String rpnstring, String name) { 61 | return new RPNString(rpnstring).apply(name); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | public final class StringUtils { 4 | public static int indexOfIgnoreCase(String str1, String str2, int fromIndex) { 5 | if (str1 == null || str2 == null) { 6 | return -1; 7 | } 8 | 9 | if (fromIndex < 0) { 10 | fromIndex = 0; 11 | } 12 | 13 | int str1Len = str1.length(), str2Len = str2.length(); 14 | int limit = str1Len - str2Len; 15 | for (; fromIndex <= limit; fromIndex++) { 16 | if (str1.regionMatches(true, fromIndex, str2, 0, str2Len)) { 17 | return fromIndex; 18 | } 19 | } 20 | 21 | return -1; 22 | } 23 | 24 | public static String replace(String _text, String _searchStr, 25 | String _replacementStr) { 26 | // String buffer to store str 27 | StringBuffer sb = new StringBuffer(); 28 | 29 | // Search for search 30 | int searchStringPos = _text.indexOf(_searchStr); 31 | int startPos = 0; 32 | int searchStringLength = _searchStr.length(); 33 | 34 | // Iterate to add string 35 | while (searchStringPos != -1) { 36 | sb.append(_text.substring(startPos, searchStringPos)).append( 37 | _replacementStr); 38 | startPos = searchStringPos + searchStringLength; 39 | searchStringPos = _text.indexOf(_searchStr, startPos); 40 | } 41 | 42 | // Create string 43 | sb.append(_text.substring(startPos, _text.length())); 44 | 45 | return sb.toString(); 46 | } 47 | 48 | /** 49 | * Removes all instances of toRemove from text irrespective of case 50 | * 51 | * @param text 52 | * @param toRemove 53 | * @return 54 | */ 55 | public static String removeIgnoreCase(String text, String toRemove) { 56 | // String buffer to store str 57 | StringBuffer sb = new StringBuffer(); 58 | 59 | // Search for search 60 | int searchStringPos = indexOfIgnoreCase(text, toRemove, 0); 61 | int toRemoveLength = toRemove.length(); 62 | int startPos = 0; 63 | 64 | // Iterate to add string 65 | while (searchStringPos != -1) { 66 | sb.append(text.substring(startPos, searchStringPos)); 67 | startPos = searchStringPos + toRemoveLength; 68 | searchStringPos = indexOfIgnoreCase(text, toRemove, startPos); 69 | } 70 | 71 | // Create string 72 | sb.append(text.substring(startPos, text.length())); 73 | 74 | return sb.toString(); 75 | } 76 | 77 | public static String replace(String _text, char _searchChr, 78 | String _replacementStr) { 79 | // String buffer to store str 80 | StringBuffer sb = new StringBuffer(); 81 | 82 | // Search for search 83 | int searchStringPos = _text.indexOf(_searchChr); 84 | int startPos = 0; 85 | 86 | // Iterate to add string 87 | while (searchStringPos != -1) { 88 | sb.append(_text.substring(startPos, searchStringPos)).append( 89 | _replacementStr); 90 | startPos = searchStringPos + 1; 91 | searchStringPos = _text.indexOf(_searchChr, startPos); 92 | } 93 | 94 | // Create string 95 | sb.append(_text.substring(startPos, _text.length())); 96 | 97 | return sb.toString(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/com/bbsmart/pda/blackberry/smartview/util/Tokenizer.java: -------------------------------------------------------------------------------- 1 | package com.bbsmart.pda.blackberry.smartview.util; 2 | 3 | public final class Tokenizer { 4 | protected final String line; 5 | protected final int len; 6 | 7 | protected int pos; 8 | protected String token; 9 | 10 | public Tokenizer(String nline) { 11 | line = nline; 12 | len = line.length(); 13 | pos = 0; 14 | token = ""; 15 | } 16 | 17 | public boolean hasNext() { 18 | while (pos < len && here() == ' ') 19 | pos++; 20 | 21 | int sublen = 0; 22 | while (pos < len && here() != ' ') { 23 | pos++; 24 | sublen++; 25 | } 26 | 27 | token = line.substring(pos - sublen, pos); 28 | return sublen > 0; 29 | } 30 | 31 | public String next() { 32 | return token; 33 | } 34 | 35 | protected char here() { 36 | return line.charAt(pos); 37 | } 38 | } 39 | --------------------------------------------------------------------------------