BlackBerry WebWorks SDK 2.3.0 #86

Merged
merged 14 commits into from Jan 10, 2012
Jump to file
+17,311 −1,891
Sorry, we could not display the entire diff because it was too big.
View
7 api/CommonAPI/sharedglobal/3_xhr.js
@@ -179,8 +179,11 @@
blackberry.transport.call(url, opts, function (response) {
if (callback(response)) {
- this.blackberry.transport.poll(url, opts, callback);
- }
+ setTimeout(
+ function() { this.blackberry.transport.poll(url, opts, callback); },
+ 0
+ );
+ }
});
};
})();
View
1 api/app/src/main/java/blackberry/app/ExitFunction.java
@@ -35,6 +35,7 @@ public Object execute( Object thiz, Object[] args ) {
static class ExitRunner implements Runnable {
public void run() {
+ System.gc(); // MemoryMaid
System.exit( 0 );
}
}
View
BIN api/bbm/lib/net_rim_bb_qm_platform.jar
Binary file not shown.
View
52 api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformContextListenerImpl.java
@@ -17,9 +17,15 @@
import net.rim.blackberry.api.bbm.platform.BBMPlatformContext;
import net.rim.blackberry.api.bbm.platform.BBMPlatformContextListener;
+import net.rim.blackberry.api.bbm.platform.profile.BBMPlatformContact;
+import net.rim.blackberry.api.bbm.platform.profile.Presence;
+import net.rim.blackberry.api.bbm.platform.profile.UserProfile;
import net.rim.blackberry.api.bbm.platform.profile.UserProfileBoxItem;
+import net.rim.device.api.script.Scriptable;
import net.rim.device.api.script.ScriptableFunction;
+import blackberry.bbm.platform.self.SelfNamespace;
import blackberry.bbm.platform.self.profilebox.ScriptableProfileBoxItem;
+import blackberry.bbm.platform.users.BBMPlatformUser;
import blackberry.bbm.platform.util.ConstantsUtil;
import blackberry.bbm.platform.util.Util;
@@ -60,23 +66,55 @@ public void accessChanged(boolean isAccessAllowed, int code) {
Util.dispatchCallback(callback, args);
}
- public void appInvoked(int reason, Object param) {
+ public void appInvoked(int reason, Object param, Presence user) {
final ScriptableFunction callback;
try {
callback = (ScriptableFunction) _platform.getField(BBMPlatformNamespace.EVENT_ON_APP_INVOKED);
} catch(Exception e1){
return;
}
- final Object[] args;
- if(reason == BBMPlatformContext.INVOKE_PROFILE_BOX_ITEM) {
- final ScriptableProfileBoxItem scriptItem =
- new ScriptableProfileBoxItem(_platform.getProfileBox(), (UserProfileBoxItem) param);
- args = new Object[] { "profilebox", scriptItem };
+ // Get reason string and scriptable param
+ final String reasonStr;
+ final Object scriptableParam;
+ switch(reason) {
+ case BBMPlatformContext.INVOKE_PROFILE_BOX_ITEM:
+ reasonStr = "profilebox";
+ scriptableParam = new ScriptableProfileBoxItem(_platform.getProfileBox(), (UserProfileBoxItem) param);
+ break;
+ case BBMPlatformContext.INVOKE_PROFILE_BOX:
+ reasonStr = "profileboxtitle";
+ scriptableParam = Scriptable.UNDEFINED;
+ break;
+ case BBMPlatformContext.INVOKE_PERSONAL_MESSAGE:
+ reasonStr = "personalmessage";
+ scriptableParam = (String) param;
+ break;
+ case BBMPlatformContext.INVOKE_CHAT_MESSAGE:
+ reasonStr = "chatmessage";
+ scriptableParam = Scriptable.UNDEFINED;
+ break;
+ default:
+ // Don't invoke if we don't know what to do with the reason
+ return;
+ }
+
+ // Get scriptable user: either self namespace of BBMPlatformUser instance
+ final Object scriptableUser;
+ if(user instanceof UserProfile) {
+ scriptableUser = SelfNamespace.getInstance();
+ } else if(user instanceof BBMPlatformContact) {
+ scriptableUser = new BBMPlatformUser(user);
} else {
- return;
+ scriptableUser = Scriptable.UNDEFINED;
}
+ final Object[] args = {
+ reasonStr,
+ scriptableParam,
+ scriptableUser,
+ };
Util.dispatchCallback(callback, args);
}
+
}
View
63 api/bbm/src/main/java/blackberry/bbm/platform/BBMPlatformNamespace.java
@@ -27,6 +27,7 @@
import blackberry.bbm.platform.io.IONamespace;
import blackberry.bbm.platform.io.MessagingServiceListenerImpl;
import blackberry.bbm.platform.self.SelfNamespace;
+import blackberry.bbm.platform.settings.SettingsNamespace;
import blackberry.bbm.platform.ui.UINamespace;
import blackberry.bbm.platform.users.UsersNamespace;
import blackberry.bbm.platform.util.ConstantsUtil;
@@ -43,6 +44,7 @@
public static final String FUNC_REGISTER = "register";
public static final String FUNC_REQUEST_USER_PERMISSION = "requestUserPermission";
+ public static final String FUNC_SHOW_OPTIONS = "showBBMAppOptions";
public static final String FIELD_ENVIRONMENT = "environment";
public static final String EVENT_ON_APP_INVOKED = "onappinvoked";
public static final String EVENT_ON_ACCESS_CHANGED = "onaccesschanged";
@@ -99,6 +101,8 @@ public Object getField(String name) throws Exception {
return new RegisterFunction();
} else if(name.equals(BBMPlatformNamespace.FUNC_REQUEST_USER_PERMISSION)) {
return new RequestUserPermissionFunction();
+ } else if(name.equals(BBMPlatformNamespace.FUNC_SHOW_OPTIONS)) {
+ return new ShowOptionsFunction();
} else if(name.equals(SelfNamespace.NAME)) {
return SelfNamespace.getInstance();
} else if(name.equals(UsersNamespace.NAME)) {
@@ -107,6 +111,8 @@ public Object getField(String name) throws Exception {
return IONamespace.getInstance();
} else if(name.equals(UINamespace.NAME)) {
return UINamespace.getInstance();
+ } else if(name.equals(SettingsNamespace.NAME)) {
+ return SettingsNamespace.getInstance();
} else if(_wFields.hasField(name)){
return _wFields.getField(name);
} else if(name.equals(FIELD_ENVIRONMENT)) {
@@ -126,22 +132,42 @@ private Object getEnvironment() {
} catch(ControlledAccessException e) {
return UNDEFINED;
}
-
}
private class RegisterFunction extends ScriptableFunctionBase {
- public static final String OPTIONS_FIELD_UUID = "uuid";
+ public static final String OPTIONS_FIELD_UUID = "uuid";
+ public static final String OPTIONS_FIELD_SHARECONTENTSPLAT = "shareContentSplat";
protected Object execute(Object thiz, Object[] args) throws Exception {
final Object onAccessChanged = BBMPlatformNamespace.this.getField(EVENT_ON_ACCESS_CHANGED);
if(onAccessChanged.equals(UNDEFINED)) {
- throw new IllegalStateException("blackberry.bbm.platform.onAccessChanged == undefined");
+ throw new IllegalStateException("blackberry.bbm.platform.onaccesschanged == undefined");
}
final Scriptable options = (Scriptable) args[0];
final String uuid = (String) options.getField(OPTIONS_FIELD_UUID);
- final BBMPlatformApplication bbmApp = new BBMPlatformApplication(uuid);
+
+ // Get optional shareContentSplat property
+ final Object shareContentSplatObj = options.getField(OPTIONS_FIELD_SHARECONTENTSPLAT);
+ boolean shareContentSplat;
+ try {
+ shareContentSplat = ((Boolean) shareContentSplatObj).booleanValue();
+ } catch(Exception e) {
+ shareContentSplat = false;
+ }
+ final boolean finalShareContentSplat = shareContentSplat;
+
+ final BBMPlatformApplication bbmApp = new BBMPlatformApplication(uuid) {
+ public int getDefaultSettings() {
+ if(finalShareContentSplat) {
+ return super.getDefaultSettings() | BBMPlatformContext.SETTING_SHARECONTENT_SPLAT;
+ } else {
+ return super.getDefaultSettings();
+ }
+
+ }
+ };
Dispatcher.getInstance().dispatch(new DispatchableEvent(null) {
protected void dispatch() {
@@ -196,4 +222,33 @@ public void run() {
};
}
} // RequestUserPermissionFunction
+
+ private class ShowOptionsFunction extends ScriptableFunctionBase {
+
+ protected Object execute(Object thiz, Object[] args) throws Exception {
+
+ final ScriptableFunction onComplete = (ScriptableFunction) args[0];
+
+ UiApplication.getUiApplication().invokeLater(new Runnable() {
+ public void run() {
+ UiApplication.getUiApplication().invokeLater(new Runnable() {
+ public void run() {
+ _bbmpContext.requestAppSettings();
+ Util.dispatchCallback(onComplete, null);
+ }
+ });
+ }
+ });
+
+ return UNDEFINED;
+ }
+
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature sig1 = new FunctionSignature(1);
+ sig1.addParam(ScriptableFunction.class, true);
+ return new FunctionSignature[] {
+ sig1
+ };
+ }
+ } // ShowOptionsFunction
}
View
19 api/bbm/src/main/java/blackberry/bbm/platform/io/MessagingServiceListenerImpl.java
@@ -15,6 +15,7 @@
*/
package blackberry.bbm.platform.io;
+import java.util.Date;
import java.util.Hashtable;
import net.rim.blackberry.api.bbm.platform.io.BBMPlatformChannel;
@@ -28,6 +29,7 @@
import net.rim.blackberry.api.bbm.platform.service.MessagingServiceListener;
import net.rim.device.api.script.ScriptableFunction;
import blackberry.bbm.platform.users.BBMPlatformUser;
+import blackberry.bbm.platform.users.UsersNamespace;
import blackberry.bbm.platform.util.ConstantsUtil;
import blackberry.bbm.platform.util.Util;
import blackberry.core.threading.DispatchableEvent;
@@ -230,4 +232,21 @@ public void onMessagesExpired(BBMPlatformContact contact, BBMPlatformData[] data
};
Util.dispatchCallback(callback, args);
}
+
+ public void onShareContentReceived(BBMPlatformContact contact, String description, BBMPlatformData content, long timestamp) {
+ final ScriptableFunction callback;
+ try {
+ callback = (ScriptableFunction) UsersNamespace.getInstance().getField(UsersNamespace.EVENT_ON_SHARE_CONTENT);
+ } catch(Exception e) {
+ return;
+ }
+ final Object[] args = {
+ new BBMPlatformUser(contact),
+ content.getDataAsString(),
+ description,
+ new Date(timestamp),
+ };
+ Util.dispatchCallback(callback, args);
+ }
+
}
View
2 api/bbm/src/main/java/blackberry/bbm/platform/self/SelfNamespace.java
@@ -107,7 +107,7 @@ protected void dispatch() {
protected FunctionSignature[] getFunctionSignatures() {
FunctionSignature sig1 = new FunctionSignature(2);
- sig1.addParam(String.class, true);
+ sig1.addNullableParam(String.class, true);
sig1.addParam(ScriptableFunction.class, true);
return new FunctionSignature[] {
View
7 api/bbm/src/main/java/blackberry/bbm/platform/self/profilebox/ProfileBoxNamespace.java
@@ -15,6 +15,8 @@
*/
package blackberry.bbm.platform.self.profilebox;
+import java.nio.ByteBuffer;
+
import net.rim.blackberry.api.bbm.platform.profile.UserProfile;
import net.rim.blackberry.api.bbm.platform.profile.UserProfileBox;
import net.rim.blackberry.api.bbm.platform.profile.UserProfileBoxAccessException;
@@ -117,8 +119,9 @@ protected Object execute(Object thiz, Object[] args) throws Exception {
if(iconURI.equals(UNDEFINED)) {
iconID = -1;
} else {
- final Bitmap icon = Util.requestBitmap((String) iconURI);
- iconID = Math.abs(icon.hashCode()); // icon ID is hash code of bitmap
+ final byte[] iconBytes = Util.requestBitmapBytes((String) iconURI);
+ final Bitmap icon = Bitmap.createBitmapFromBytes(iconBytes, 0, iconBytes.length, 1);
+ iconID = Math.abs(ByteBuffer.wrap(iconBytes).hashCode()); // icon ID is hash code of bitmap
if(! _profileBox.isIconRegistered(iconID)) {
_profileBox.registerIcon(iconID, PNGEncodedImage.encode(icon));
}
View
39 api/bbm/src/main/java/blackberry/bbm/platform/settings/SettingsNamespace.java
@@ -0,0 +1,39 @@
+package blackberry.bbm.platform.settings;
+
+import blackberry.bbm.platform.BBMPlatformNamespace;
+import net.rim.blackberry.api.bbm.platform.SettingsManager;
+import net.rim.device.api.script.Scriptable;
+
+public class SettingsNamespace extends Scriptable {
+
+ public static final String NAME = "settings";
+
+ private static final String FIELD_PROFILE_BOX = "profileboxEnabled";
+ private static final String FIELD_PUBLIC_CONNS = "alwaysAllowPublicConns";
+
+ private static SettingsNamespace _instance;
+
+ private final SettingsManager _settings;
+
+ public SettingsNamespace(SettingsManager settings) {
+ _settings = settings;
+ }
+
+ public static SettingsNamespace getInstance() {
+ if(_instance == null) {
+ final SettingsManager settings = BBMPlatformNamespace.getInstance().getContext().getSettingsManager();
+ _instance = new SettingsNamespace(settings);
+ }
+ return _instance;
+ }
+
+ public Object getField(String name) throws Exception {
+ if(name.equals(FIELD_PROFILE_BOX)) {
+ return new Boolean(_settings.getSetting(SettingsManager.SETTING_PROFILE_BOX) == SettingsManager.VALUE_ENABLED);
+ } else if(name.equals(FIELD_PUBLIC_CONNS)) {
+ return new Boolean(_settings.getSetting(SettingsManager.SETTING_ALWAYS_ALLOW_PUBLIC_CONN) == SettingsManager.VALUE_ENABLED);
+ } else {
+ return UNDEFINED;
+ }
+ }
+}
View
22 api/bbm/src/main/java/blackberry/bbm/platform/users/BBMPlatformUser.java
@@ -23,14 +23,16 @@
public class BBMPlatformUser extends Scriptable {
- public static final String FIELD_DISPLAY_PIC = "displayPicture";
- public static final String FIELD_DISPLAY_NAME = "displayName";
- public static final String FIELD_PERSONAL_MSG = "personalMessage";
- public static final String FIELD_STATUS = "status";
- public static final String FIELD_STATUS_MSG = "statusMessage";
- public static final String FIELD_HANDLE = "handle";
- public static final String FIELD_PPID = "ppid";
- public static final String FIELD_TYPE = "type";
+ public static final String FIELD_DISPLAY_PIC = "displayPicture";
+ public static final String FIELD_DISPLAY_NAME = "displayName";
+ public static final String FIELD_PERSONAL_MSG = "personalMessage";
+ public static final String FIELD_STATUS = "status";
+ public static final String FIELD_STATUS_MSG = "statusMessage";
+ public static final String FIELD_HANDLE = "handle";
+ public static final String FIELD_PPID = "ppid";
+ public static final String FIELD_TYPE = "type";
+ public static final String FIELD_APP_VERSION = "appVersion";
+ public static final String FIELD_BBM_SDK_VERSION = "bbmsdkVersion";
public static final String STATUS_STR_AVAILABLE = "available";
public static final String STATUS_STR_BUSY = "busy";
@@ -57,6 +59,10 @@ public Object getField(String name) throws Exception {
return BBMPlatformUser.statusToString(_presence.getStatus());
} else if(name.equals(BBMPlatformUser.FIELD_STATUS_MSG)) {
return _presence.getStatusMessage();
+ } else if(name.equals(BBMPlatformUser.FIELD_APP_VERSION)) {
+ return _presence.getAppVersion();
+ } else if(name.equals(BBMPlatformUser.FIELD_BBM_SDK_VERSION)) {
+ return new Integer(_presence.getBBMSDKVersion());
} else if(name.equals(BBMPlatformUser.FIELD_TYPE)) {
return "BBM";
} else if(name.equals(BBMPlatformUser.FIELD_HANDLE)) {
View
80 api/bbm/src/main/java/blackberry/bbm/platform/users/UsersNamespace.java
@@ -17,6 +17,7 @@
import net.rim.blackberry.api.bbm.platform.BBMPlatformContext;
import net.rim.blackberry.api.bbm.platform.io.BBMPlatformConnection;
+import net.rim.blackberry.api.bbm.platform.io.BBMPlatformData;
import net.rim.blackberry.api.bbm.platform.io.IOErrorCode;
import net.rim.blackberry.api.bbm.platform.profile.BBMInvitationRequest;
import net.rim.blackberry.api.bbm.platform.profile.BBMPlatformContact;
@@ -52,6 +53,8 @@
private static final String FUNC_SEND_FILE = "sendFile";
private static final String FIELD_CONTACTS_WITH_APP = "contactsWithApp";
private static final String EVENT_ON_UPDATE = "onupdate";
+ private static final String FUNC_SHARE_CONTENT = "shareContent";
+ public static final String EVENT_ON_SHARE_CONTENT = "onsharecontent";
private static UsersNamespace instance;
@@ -62,6 +65,7 @@
private UsersNamespace() {
_wFields = new ScriptableFieldManager();
_wFields.addField(EVENT_ON_UPDATE);
+ _wFields.addField(EVENT_ON_SHARE_CONTENT);
}
public static UsersNamespace getInstance() {
@@ -98,6 +102,8 @@ public Object getField(String name) throws Exception {
return new InviteToBBMConnFunction();
} else if(name.equals(FUNC_SEND_FILE)) {
return new SendFileFunction();
+ } else if(name.equals(FUNC_SHARE_CONTENT)) {
+ return new ShareContentFunction();
} else if(_wFields.hasField(name)) {
return _wFields.getField(name);
} else {
@@ -485,6 +491,80 @@ protected Object execute(Object thiz, Object[] args) throws Exception {
};
}
} // SendFileFunction
+
+ private static class ShareContentFunction extends ScriptableFunctionBase {
+
+ protected Object execute(Object thiz, Object[] args) throws Exception {
+ final String content = (String) args[0];
+ final String description = (String) args[1];
+ final ScriptableFunction onComplete = (ScriptableFunction) args[2];
+ final Object options;
+ if(args.length >= 4) {
+ options = args[3];
+ } else {
+ options = null;
+ }
+
+ // Throw exceptions for too long parameters
+ final int maxContentLength = 61124;
+ if(content.length() > maxContentLength) {
+ throw new IllegalArgumentException("content.length > " + maxContentLength);
+ }
+ final int maxDescLength = 128;
+ if(description.length() > maxDescLength) {
+ throw new IllegalArgumentException("description.length > " + maxDescLength);
+ }
+
+ // Parse options object for title and contacts
+ final String title;
+ final ContactListProvider contacts;
+ if(options == null || options.equals(UNDEFINED)) {
+ title = null;
+ contacts = null;
+ } else {
+ // Title
+ final Scriptable optionsObj = (Scriptable) options;
+ final Object titleObj = optionsObj.getField("title");
+ if(titleObj.equals(UNDEFINED)) {
+ title = null;
+ } else {
+ title = (String) titleObj;
+ }
+
+ // Contacts
+ Object contactsObj = optionsObj.getField("users");
+ if(contactsObj.equals(UNDEFINED)) {
+ contacts = null;
+ } else {
+ final BBMPlatformUser[] users = Util.scriptableUsersArrayToUserArray((Scriptable) contactsObj);
+ contacts = new Util.SimpleContactListProvider(users);
+ }
+ }
+
+ // Call API
+ final BBMPlatformNamespace bbmpNpsc = BBMPlatformNamespace.getInstance();
+ final MessagingService msgService = bbmpNpsc.getMessagingService();
+ UiApplication.getUiApplication().invokeLater(new Runnable() {
+ public void run() {
+ msgService.shareContent(description, new BBMPlatformData(content), contacts, title);
+ Util.dispatchCallback(onComplete, null);
+ }
+ });
+
+ return UNDEFINED;
+ }
+
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature sig1 = new FunctionSignature(4);
+ sig1.addParam(String.class, true);
+ sig1.addParam(String.class, true);
+ sig1.addParam(ScriptableFunction.class, true);
+ sig1.addParam(Scriptable.class, false);
+ return new FunctionSignature[] {
+ sig1
+ };
+ }
+ } // ShareContentFunction
private static String eventTypeToString(int eventType) {
switch(eventType) {
View
7 api/bbm/src/main/java/blackberry/bbm/platform/util/Util.java
@@ -73,6 +73,11 @@ public static String bitmapToBase64Str(Bitmap bitmap) {
}
public static Bitmap requestBitmap(String uri) throws Exception {
+ byte[] bmpBytes = requestBitmapBytes(uri);
+ return Bitmap.createBitmapFromBytes(bmpBytes, 0, bmpBytes.length, 1);
+ }
+
+ public static byte[] requestBitmapBytes(String uri) throws Exception {
BrowserField browserField = (BrowserField) BBMPlatformExtension._browserField.get();
final BrowserFieldConfig bfConfig = browserField.getConfig();
final BrowserFieldController bfController =
@@ -94,7 +99,7 @@ public static Bitmap requestBitmap(String uri) throws Exception {
} catch(EOFException e) {
}
- return Bitmap.createBitmapFromBytes(bmpBytes.getArray(), 0, bmpBytes.size(), 1);
+ return bmpBytes.getArray();
} finally {
try {
ic.close();
View
72 api/dialog/src/main/java/blackberry/ui/dialog/ColorPickerAsyncFunction.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package blackberry.ui.dialog;
+
+import net.rim.device.api.script.Scriptable;
+import net.rim.device.api.script.ScriptableFunction;
+import net.rim.device.api.ui.UiApplication;
+import blackberry.core.FunctionSignature;
+import blackberry.core.ScriptableFunctionBase;
+import blackberry.ui.dialog.DialogRunnableFactory;
+
+/**
+ * Implementation of asynchronous color picker dialog
+ *
+ * @author jachoi
+ *
+ */
+public class ColorPickerAsyncFunction extends ScriptableFunctionBase {
+
+ public static final String NAME = "colorPickerAsync";
+ private final int HEX_BASE = 16;
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[])
+ */
+ public Object execute( Object thiz, Object[] args ) throws Exception {
+ int initialColor = stringToColor( (String) args[ 0 ] );
+ ScriptableFunction callback = (ScriptableFunction) args[ 1 ];
+
+ // create dialog
+ Runnable dr = DialogRunnableFactory.getColorPickerRunnable( initialColor, callback, thiz );
+
+ // queue
+ UiApplication.getUiApplication().invokeLater( dr );
+
+ // return value
+ return Scriptable.UNDEFINED;
+ }
+
+ private int stringToColor(String color) {
+ if ( color.startsWith( "#" ) ) {
+ return Integer.parseInt( color.substring( 1 ), HEX_BASE );
+ }
+ return Integer.parseInt( color, HEX_BASE );
+ }
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures()
+ */
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature fs = new FunctionSignature( 2 );
+ // initialColor
+ fs.addParam( String.class, true );
+ // callback
+ fs.addParam( ScriptableFunction.class, true );
+
+ return new FunctionSignature[] { fs };
+ }
+}
View
73 api/dialog/src/main/java/blackberry/ui/dialog/DateTimeAsyncFunction.java
@@ -0,0 +1,73 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package blackberry.ui.dialog;
+
+import blackberry.core.FunctionSignature;
+import blackberry.core.ScriptableFunctionBase;
+
+import net.rim.device.api.script.Scriptable;
+import net.rim.device.api.script.ScriptableFunction;
+import net.rim.device.api.ui.UiApplication;
+
+import blackberry.ui.dialog.DialogRunnableFactory;
+
+public class DateTimeAsyncFunction extends ScriptableFunctionBase {
+
+ public static final String NAME = "dateTimeAsync";
+
+ public static final int TYPE_DATE = 0;
+ public static final int TYPE_MONTH = 1;
+ public static final int TYPE_TIME = 2;
+ public static final int TYPE_DATETIME = 3;
+ public static final int TYPE_DATETIMELOCAL = 4;
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[])
+ */
+ public Object execute(Object thiz, Object[] args) throws Exception {
+ String type = (String) args[0];
+ Scriptable options = (Scriptable) args[1];
+ ScriptableFunction callback = (ScriptableFunction) args[2] ;
+
+ String value = (String)options.getField("value");
+ String min = (String)options.getField("min");
+ String max = (String)options.getField("max");
+
+ Runnable dr = DialogRunnableFactory.getDateTimeRunnable(type, value, min, max, callback, thiz);
+
+ // queue
+ UiApplication.getUiApplication().invokeLater(dr);
+
+ // return value
+ return Scriptable.UNDEFINED;
+ }
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures()
+ */
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature fs = new FunctionSignature(3);
+ // type
+ fs.addParam(String.class, true);
+ // options
+ fs.addParam(Scriptable.class, true);
+ //callback
+ fs.addParam(ScriptableFunction.class, true);
+
+ return new FunctionSignature[] { fs };
+ }
+}
View
3 api/dialog/src/main/java/blackberry/ui/dialog/DialogExtension.java
@@ -31,7 +31,7 @@
public class DialogExtension implements WidgetExtension {
public static final String FEATURE_DIALOG = "blackberry.ui.dialog";
-
+
/**
* @see net.rim.device.api.web.WidgetExtension#register(WidgetConfig, BrowserField)
*/
@@ -44,6 +44,7 @@ public void register( WidgetConfig widgetConfig, BrowserField browserField ) {
*/
public void loadFeature( final String feature, final String version, final Document document, final ScriptEngine scriptengine )
throws Exception {
+
if( feature.equals( FEATURE_DIALOG ) ) {
scriptengine.addExtension( feature, new DialogNamespace() );
}
View
4 api/dialog/src/main/java/blackberry/ui/dialog/DialogNamespace.java
@@ -17,6 +17,7 @@
import java.util.Hashtable;
+import net.rim.device.api.script.ScriptEngine;
import net.rim.device.api.script.Scriptable;
import net.rim.device.api.ui.component.Dialog;
@@ -52,6 +53,9 @@ public DialogNamespace() {
_fields.put( StandardAskFunction.NAME, new StandardAskFunction() );
_fields.put( CustomAskFunction.NAME, new CustomAskFunction() );
+ _fields.put( SelectAsyncFunction.NAME, new SelectAsyncFunction() );
+ _fields.put( DateTimeAsyncFunction.NAME, new DateTimeAsyncFunction() );
+ _fields.put( ColorPickerAsyncFunction.NAME, new ColorPickerAsyncFunction() );
_fields.put( D_OK, new Integer( Dialog.D_OK ) );
_fields.put( D_SAVE, new Integer( Dialog.D_SAVE ) );
_fields.put( D_DELETE, new Integer( Dialog.D_DELETE ) );
View
109 api/dialog/src/main/java/blackberry/ui/dialog/DialogRunnableFactory.java
@@ -0,0 +1,109 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package blackberry.ui.dialog;
+
+import java.util.Vector;
+
+import net.rim.device.api.system.DeviceInfo;
+import net.rim.device.api.script.ScriptableFunction;
+import net.rim.device.api.script.ScriptableImpl;
+
+import blackberry.ui.dialog.datetime.DateTimeDialog;
+import blackberry.ui.dialog.IWebWorksDialog;
+import blackberry.ui.dialog.select.SelectDialog;
+import blackberry.ui.dialog.color.ColorPickerDialog;
+
+public class DialogRunnableFactory {
+
+ public static Runnable getDateTimeRunnable( String type, String value, String min, String max, ScriptableFunction callback,
+ Object thiz ) {
+ IWebWorksDialog d = new DateTimeDialog( type, value, min, max );
+ return new DialogRunnable( d, callback, thiz );
+ }
+
+ public static Runnable getColorPickerRunnable( int initialColor, ScriptableFunction callback, Object thiz ) {
+ ColorPickerDialog d = new ColorPickerDialog( initialColor );
+ return new DialogRunnable( d, callback, thiz );
+ }
+
+ public static Runnable getSelectRunnable(boolean allowMultiple, String[] labels, boolean[] enabled, boolean[] selected, int[] types, ScriptableFunction callback, Object thiz) {
+ IWebWorksDialog d = new SelectDialog(allowMultiple, labels, enabled, selected, types);
+ return new DialogRunnable(d, callback, thiz);
+ }
+
+ private static class DialogRunnable implements Runnable {
+ private IWebWorksDialog _dialog;
+ private ScriptableFunction _callback;
+ private Object _context;
+
+ /**
+ * Constructs a <code>DialogRunnable</code> object.
+ *
+ * @param dialog
+ * The dialog
+ * @param callback
+ * The callback
+ * @param context
+ * The context in which the callback executes (its "this" object)
+ */
+ DialogRunnable( IWebWorksDialog dialog, ScriptableFunction callback, Object context ) {
+ _dialog = dialog;
+ _callback = callback;
+ _context = context;
+ }
+
+
+ /**
+ * Run the dialog.
+ *
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ if(_dialog.show()) {
+ Object dialogValue = _dialog.getSelectedValue();
+ Object retVal;
+
+ boolean isFive = "5".equals(DeviceInfo.getSoftwareVersion().substring(0, 1));
+
+ //we'll accept Vector-type dialog return values for arrays
+ //otherwise get object's string as all ecma primitives will return a valid string representation of themselves
+ try {
+ if (dialogValue instanceof Vector) {
+ Vector v = (Vector)dialogValue;
+ if(isFive) {
+ ScriptableImpl s = new ScriptableImpl();
+ for(int i = 0; i < v.size(); i++) {
+ s.putElement(i, v.elementAt(i));
+ }
+ retVal = s;
+ } else {
+ Object[] s = new Object[v.size()];
+ v.copyInto(s);
+ retVal = s;
+ }
+ } else {
+ retVal = dialogValue.toString();
+ }
+
+ _callback.invoke(null, new Object[] { retVal });
+ } catch (Exception e) {
+ throw new RuntimeException("Invoke callback failed: " + e.getMessage());
+ }
+ }
+ }
+ }
+}
View
21 api/dialog/src/main/java/blackberry/ui/dialog/IWebWorksDialog.java
@@ -0,0 +1,21 @@
+/*
+* Copyright 2010-2011 Research In Motion Limited.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package blackberry.ui.dialog;
+
+public interface IWebWorksDialog {
+ boolean show();
+ Object getSelectedValue();
+}
View
106 api/dialog/src/main/java/blackberry/ui/dialog/SelectAsyncFunction.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package blackberry.ui.dialog;
+
+import net.rim.device.api.script.ScriptEngine;
+import net.rim.device.api.script.Scriptable;
+import net.rim.device.api.script.ScriptableFunction;
+import net.rim.device.api.ui.UiApplication;
+import blackberry.common.util.json4j.JSONArray;
+import blackberry.core.FunctionSignature;
+import blackberry.core.ScriptableFunctionBase;
+
+import blackberry.ui.dialog.DialogRunnableFactory;
+import blackberry.ui.dialog.select.SelectDialog;
+
+/**
+ * Implementation of asynchronous selection dialog
+ *
+ * @author jachoi
+ *
+ */
+public class SelectAsyncFunction extends ScriptableFunctionBase {
+
+ public static final String NAME = "selectAsync";
+
+ public static final int POPUP_ITEM_TYPE_OPTION = 0;
+ public static final int POPUP_ITEM_TYPE_GROUP = 1;
+ public static final int POPUP_ITEM_TYPE_SEPARATOR = 2;
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#execute(Object, Object[])
+ */
+ public Object execute( Object thiz, Object[] args ) throws Exception {
+ boolean allowMultiple = ( (Boolean) args[ 0 ] ).booleanValue();
+ Scriptable choices = (Scriptable) args[ 1 ];
+ ScriptableFunction callback = (ScriptableFunction) args[ 2 ];
+
+ int numChoices = choices.getElementCount();
+ String[] labels = new String[ numChoices ];
+ boolean[] enabled = new boolean[ numChoices ];
+ boolean[] selected = new boolean[ numChoices ];
+ int[] types = new int[ numChoices ];
+
+ populateChoiceStateArrays( choices, labels, enabled, selected, types, allowMultiple );
+
+ Runnable dr = DialogRunnableFactory.getSelectRunnable(allowMultiple, labels, enabled, selected, types, callback, thiz);
+
+ // queue
+ UiApplication.getUiApplication().invokeLater(dr);
+
+ // return value
+ return Scriptable.UNDEFINED;
+ }
+
+ private void populateChoiceStateArrays( Scriptable fromScriptableChoices, String[] labels, boolean[] enabled,
+ boolean[] selected, int[] type, boolean allowMultiple ) {
+ try {
+
+ boolean firstSelected = false;
+ boolean canSelect = true;
+
+ for( int i = 0; i < fromScriptableChoices.getElementCount(); i++ ) {
+ Scriptable choice = (Scriptable) fromScriptableChoices.getElement( i );
+ labels[ i ] = (String) choice.getField( "label" );
+ enabled[ i ] = ( (Boolean) choice.getField( "enabled" ) ).booleanValue();
+
+ type[ i ] = ( (String) choice.getField( "type" ) ).equals( "group" ) ? POPUP_ITEM_TYPE_GROUP
+ : POPUP_ITEM_TYPE_OPTION;
+
+ canSelect = (type[ i ] != POPUP_ITEM_TYPE_GROUP) && (allowMultiple || !firstSelected);
+ selected[ i ] = canSelect && enabled[ i ] && ( (Boolean) choice.getField( "selected" ) ).booleanValue();
+ firstSelected = firstSelected || selected[ i ];
+ }
+ } catch( Exception e ) {
+ throw new RuntimeException( e.getMessage() );
+ }
+ }
+
+ /**
+ * @see blackberry.core.ScriptableFunctionBase#getFunctionSignatures()
+ */
+ protected FunctionSignature[] getFunctionSignatures() {
+ FunctionSignature fs = new FunctionSignature( 3 );
+ // allowMultiple
+ fs.addParam( Boolean.class, true );
+ // choices
+ fs.addParam( Scriptable.class, true );
+ // callback
+ fs.addParam( ScriptableFunction.class, true );
+
+ return new FunctionSignature[] { fs };
+ }
+}
View
694 api/dialog/src/main/java/blackberry/ui/dialog/color/ColorPickerDialog.java
@@ -0,0 +1,694 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package blackberry.ui.dialog.color;
+
+import blackberry.ui.dialog.IWebWorksDialog;
+import net.rim.device.api.system.Bitmap;
+import net.rim.device.api.system.Characters;
+import net.rim.device.api.system.KeypadListener;
+import net.rim.device.api.ui.Color;
+import net.rim.device.api.ui.Field;
+import net.rim.device.api.ui.FieldChangeListener;
+import net.rim.device.api.ui.Graphics;
+import net.rim.device.api.ui.TouchEvent;
+import net.rim.device.api.ui.UiApplication;
+import net.rim.device.api.ui.component.ButtonField;
+import net.rim.device.api.ui.container.HorizontalFieldManager;
+import net.rim.device.api.ui.container.PopupScreen;
+import net.rim.device.api.ui.container.VerticalFieldManager;
+import net.rim.device.api.util.MathUtilities;
+import net.rim.device.api.util.NumberUtilities;
+
+/**
+ * Implementation of color picker dialog
+ *
+ * @author jachoi
+ *
+ */
+public class ColorPickerDialog extends Field implements IWebWorksDialog {
+ private int _selectedColor;
+
+ public ColorPickerDialog( int initialColor ) {
+ super( Field.FOCUSABLE );
+ _selectedColor = initialColor;
+ setPadding( 0, 0, 0, 0 );
+ }
+
+ public void setColor( int color ) {
+ _selectedColor = color;
+ }
+
+ public int getPreferredWidth() {
+ return (int) Math.ceil( getFont().getHeight() * 1.618 );
+ }
+
+ public int getPreferredHeight() {
+ return getFont().getHeight();
+ }
+
+ protected void layout( int width, int height ) {
+ setExtent( getPreferredWidth(), getPreferredHeight() );
+ }
+
+ protected void paint( Graphics g ) {
+ int oldColor = g.getColor();
+ try {
+ // Color
+ g.setColor( _selectedColor );
+ g.fillRect( 0, 0, getWidth(), getHeight() );
+
+ // Border
+ g.setStrokeWidth( 1 );
+ g.setColor( 0x000000 );
+ g.drawRect( 0, 0, getWidth(), getHeight() );
+ } finally {
+ g.setColor( oldColor );
+ }
+ }
+
+ protected void drawFocus( Graphics g, boolean on ) {
+ int oldColor = g.getColor();
+ try {
+ g.setColor( 0x0000FF );
+ g.drawRect( 0, 0, getWidth(), getHeight() );
+ g.drawRect( 1, 1, getWidth() - 2, getHeight() - 2 );
+ } finally {
+ g.setColor( oldColor );
+ }
+ }
+
+ private String colorToString( int color ) throws IllegalArgumentException {
+ StringBuffer sb = new StringBuffer( 7 );
+ sb.append( "#" );
+ NumberUtilities.appendNumber( sb, color & 0x00FFFFFF, 16, 6 );
+ return sb.toString();
+ }
+
+ public boolean show() {
+ ColorPickerPopup picker = new ColorPickerPopup( _selectedColor );
+ boolean result = picker.doModal();
+ if( result ) {
+ _selectedColor = picker.getSelectedColor();
+ invalidate();
+ fieldChangeNotify( 0 );
+ }
+ return result;
+ }
+
+ public Object getSelectedValue() {
+ return colorToString( _selectedColor );
+ }
+
+ protected void paintBackground( Graphics g ) {
+ }
+
+ public void setDirty( boolean dirty ) {
+ // We never want to be dirty or muddy
+ }
+
+ public void setMuddy( boolean muddy ) {
+ // We never want to be dirty or muddy
+ }
+}
+
+class BaseColorChooser extends Field {
+ private static final int FIELD_HEIGHT = 100;
+ private static final int FIELD_WIDTH = 40;
+ private static final int NUM_COLOURS = 7;
+ private static final int FRAME_THICKNESS = 2;
+ private static final int FRAME_HEIGHT = 10;
+
+ private int _selectedColor;
+
+ private int[] _xcoords;
+ private int[] _ycoords;
+ private int[] _colors;
+ private Bitmap _rainbow;
+
+ private boolean _editing;
+ private int _y;
+
+ BaseColorChooser() {
+ _y = FRAME_THICKNESS;
+ int yStep = FIELD_HEIGHT / ( NUM_COLOURS - 1 );
+
+ _xcoords = new int[] { 0, 0, 0, 0, 0, 0, 0, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH, FIELD_WIDTH,
+ FIELD_WIDTH };
+ _ycoords = new int[] { 0, yStep, 2 * yStep, 3 * yStep, 4 * yStep, 5 * yStep, FIELD_HEIGHT, FIELD_HEIGHT, 5 * yStep,
+ 4 * yStep, 3 * yStep, 2 * yStep, yStep, 0 };
+ _colors = new int[] { 0xff0000, 0xff00ff, 0x0000ff, 0x00ffff, 0x00ff00, 0xffff00, 0xff0000, 0xff0000, 0xffff00, 0x00ff00,
+ 0x00ffff, 0x0000ff, 0xff00ff, 0xff0000 };
+ }
+
+ public int getPreferredWidth() {
+ return FIELD_WIDTH;
+ }
+
+ public int getPreferredHeight() {
+ return FIELD_HEIGHT;
+ }
+
+ public int getSelectedColor() {
+ return _selectedColor;
+ }
+
+ protected void layout( int width, int height ) {
+ width = getPreferredWidth();
+ height = getPreferredHeight();
+
+ _rainbow = new Bitmap( width, height );
+ Graphics rainbowGraphics = Graphics.create( _rainbow );
+ rainbowGraphics.drawShadedFilledPath( _xcoords, _ycoords, null, _colors, null );
+
+ setExtent( width, height );
+ }
+
+ protected void paint( Graphics g ) {
+ int oldColor = g.getColor();
+ try {
+ // Rainbow
+ g.drawBitmap( 0, 0, _rainbow.getWidth(), _rainbow.getHeight(), _rainbow, 0, 0 );
+
+ // Border
+ g.setColor( 0x000000 );
+ g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
+ if( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) {
+ g.setColor( Color.WHITE );
+ g.drawRect( 1, 1, FIELD_WIDTH - 2, FIELD_HEIGHT - 2 );
+ }
+
+ int frameY = _y - ( FRAME_HEIGHT >> 1 );
+
+ // draw the selector shadow
+ frameY++;
+ g.setColor( 0x000000 );
+ g.fillRect( 0, frameY, FIELD_WIDTH, FRAME_THICKNESS ); // top
+ g.fillRect( 0, frameY + FRAME_HEIGHT - FRAME_THICKNESS, FIELD_WIDTH, FRAME_THICKNESS ); // bottom
+ frameY--;
+
+ // draw selector foreground
+ g.setColor( Color.WHITE );
+ g.fillRect( 0, frameY, FIELD_WIDTH, FRAME_THICKNESS ); // top
+ g.fillRect( 0, frameY + FRAME_HEIGHT - FRAME_THICKNESS, FIELD_WIDTH, FRAME_THICKNESS ); // bottom
+ g.fillRect( 0, frameY, FRAME_THICKNESS, FRAME_HEIGHT ); // left
+ g.fillRect( FIELD_WIDTH - FRAME_THICKNESS, frameY, FRAME_THICKNESS, FRAME_HEIGHT ); // right
+ } finally {
+ g.setColor( oldColor );
+ }
+ }
+
+ protected void paintBackground( Graphics g ) {
+ }
+
+ protected void drawFocus( Graphics g, boolean on ) {
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ try {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ paint( g );
+ } finally {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+
+ public boolean isFocusable() {
+ return true;
+ }
+
+ protected boolean keyChar( char key, int status, int time ) {
+ if( key == Characters.ESCAPE ) {
+ if( _editing ) {
+ return handleClick();
+ }
+ } else if( key == Characters.ENTER ) {
+ return handleClick();
+ }
+ return super.keyChar( key, status, time );
+ }
+
+ protected boolean navigationMovement( int dx, int dy, int status, int time ) {
+ return handleMovement( dx, dy );
+ }
+
+ protected boolean trackwheelRoll( int amount, int status, int time ) {
+ if( ( status & KeypadListener.STATUS_ALT ) != 0 ) {
+ return handleMovement( amount, 0 );
+ } else {
+ return handleMovement( 0, amount );
+ }
+ }
+
+ private boolean handleMovement( int dx, int dy ) {
+ if( _editing ) {
+ int yMovement = dy * FIELD_HEIGHT / 20;
+
+ _y = MathUtilities.clamp( 0, _y + yMovement, FIELD_HEIGHT - 1 );
+
+ int[] argbData = new int[ 1 ];
+ _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+
+ invalidate( 0, 0, getWidth(), getHeight() );
+ fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
+ return true;
+ }
+ return false;
+ }
+
+ protected boolean navigationClick( int status, int time ) {
+ return handleClick();
+ }
+
+ protected boolean trackwheelClick( int status, int time ) {
+ return handleClick();
+ }
+
+ private boolean handleClick() {
+ _editing = !_editing;
+ invalidate( 0, 0, getWidth(), getHeight() );
+ return true;
+ }
+
+ protected boolean touchEvent( TouchEvent message ) {
+ if( message == null ) {
+ throw new IllegalArgumentException( "ColorPickerField.touchEvent: TouchEvent message is null." );
+ }
+ boolean isConsumed = false;
+ boolean isOutOfBounds = false;
+ int x = message.getX( 1 );
+ int y = message.getY( 1 );
+ int[] argbData = new int[ 1 ];
+ // Check to ensure point is within this field
+ if( x <= 0 || y <= 0 || x > ( FIELD_WIDTH - 1 ) || y > ( FIELD_HEIGHT - 1 ) ) {
+ isOutOfBounds = true;
+ }
+ switch( message.getEvent() ) {
+ case TouchEvent.CLICK:
+ case TouchEvent.MOVE:
+ if( isOutOfBounds ) {
+ return true; // consume
+ }
+ _editing = true; // Pressed effect
+ // update color
+ _y = y;
+ _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+ invalidate( 0, 0, getWidth(), getHeight() );
+ fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
+ isConsumed = true;
+ break;
+ case TouchEvent.UNCLICK:
+ if( isOutOfBounds ) {
+ _editing = false; // Reset presssed effect
+ return true;
+ }
+
+ // A field change notification is only sent on UNCLICK to allow for recovery
+ // should the user cancel, i.e. click and move off the button
+
+ _editing = false; // Reset pressed effect
+
+ // update color
+ _y = y;
+ _rainbow.getARGB( argbData, 0, 1, 0, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+ invalidate( 0, 0, getWidth(), getHeight() );
+ fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
+ isConsumed = true;
+
+ break;
+ }
+ return isConsumed;
+ }
+
+}
+
+class TintChooser extends Field {
+ private static final int FIELD_HEIGHT = 100;
+ private static final int FIELD_WIDTH = 100;
+ private static final int FRAME_SIZE = 10;
+ private static final int FRAME_THICKNESS = 2;
+
+ private int _baseColor;
+ private int _selectedColor;
+
+ private int[] _xcoords;
+ private int[] _ycoords;
+ private int[] _colors;
+ private Bitmap _backgroundBitmap;
+
+ private boolean _editing;
+
+ private int _x;
+ private int _y;
+
+ TintChooser( int baseColor ) {
+ _baseColor = baseColor;
+
+ // init cursor position
+ _x = FIELD_WIDTH - FRAME_SIZE / 2;
+ _y = FRAME_SIZE;
+ }
+
+ public int getPreferredWidth() {
+ return FIELD_WIDTH;
+ }
+
+ public int getPreferredHeight() {
+ return FIELD_HEIGHT;
+ }
+
+ protected void layout( int width, int height ) {
+ width = getPreferredWidth();
+ height = getPreferredHeight();
+
+ updateBitmap();
+
+ setExtent( width, height );
+ }
+
+ public void setColor( int newColor ) {
+ _baseColor = newColor;
+ updateBitmap();
+ invalidate();
+ }
+
+ private void updateBitmap() {
+ int width = getPreferredWidth();
+ int height = getPreferredHeight();
+
+ _xcoords = new int[] { 0, 0, width, width };
+ _ycoords = new int[] { 0, height, height, 0 };
+ _colors = new int[] { 0xFFFFFF, 0x000000, 0x000000, _baseColor };
+
+ // make new bitmap
+ _backgroundBitmap = new Bitmap( width, height );// Bitmap.ROWWISE_MONOCHROME , width, height);// Bitmap.DEFAULT_TYPE,
+ // width, height );
+ Graphics bitmapGraphics = Graphics.create( _backgroundBitmap );
+ bitmapGraphics.drawShadedFilledPath( _xcoords, _ycoords, null, _colors, null );
+
+ // Update selected color
+ int[] argbData = new int[ 1 ];
+ _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+ }
+
+ protected void paint( Graphics g ) {
+ // Rainbow
+ g.drawBitmap( 0, 0, _backgroundBitmap.getWidth(), _backgroundBitmap.getHeight(), _backgroundBitmap, 0, 0 );
+
+ // Border
+ g.setColor( 0x000000 );
+ g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
+ if( g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS ) ) {
+ g.setColor( Color.WHITE );
+ g.drawRect( 1, 1, FIELD_WIDTH - 2, FIELD_HEIGHT - 2 );
+ }
+
+ // Selector
+ int frameX = _x;
+ int frameY = _y;
+
+ int oldColor = g.getColor();
+ try {
+ // draw the selector
+ g.setColor( 0x000000 );
+ frameX++;
+ frameY++;
+
+ // Shadow Left, Right, Top, Bottom
+ g.fillRect( frameX - FRAME_SIZE / 2, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
+ g.fillRect( frameX + FRAME_THICKNESS, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
+ g.fillRect( frameX - FRAME_THICKNESS / 2, frameY - FRAME_SIZE / 2, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
+ g.fillRect( frameX - FRAME_THICKNESS / 2, frameY + FRAME_THICKNESS, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
+
+ frameX--;
+ frameY--;
+
+ g.setColor( Color.WHITE );
+ // Left, Right, Top, Bottom
+ g.fillRect( frameX - FRAME_SIZE / 2, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
+ g.fillRect( frameX + FRAME_THICKNESS, frameY - FRAME_THICKNESS / 2, FRAME_SIZE / 2 - FRAME_THICKNESS, FRAME_THICKNESS );
+ g.fillRect( frameX - FRAME_THICKNESS / 2, frameY - FRAME_SIZE / 2, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
+ g.fillRect( frameX - FRAME_THICKNESS / 2, frameY + FRAME_THICKNESS, FRAME_THICKNESS, FRAME_SIZE / 2 - FRAME_THICKNESS );
+ } finally {
+ g.setColor( oldColor );
+ }
+ }
+
+ protected void paintBackground( Graphics g ) {
+ }
+
+ protected void drawFocus( Graphics g, boolean on ) {
+ boolean oldDrawStyleFocus = g.isDrawingStyleSet( Graphics.DRAWSTYLE_FOCUS );
+ try {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, true );
+ paint( g );
+ } finally {
+ g.setDrawingStyle( Graphics.DRAWSTYLE_FOCUS, oldDrawStyleFocus );
+ }
+ }
+
+ public boolean isFocusable() {
+ return true;
+ }
+
+ protected boolean keyChar( char key, int status, int time ) {
+ if( key == Characters.ESCAPE ) {
+ if( _editing ) {
+ return handleClick();
+ }
+ } else if( key == Characters.ENTER ) {
+ return handleClick();
+ }
+ return super.keyChar( key, status, time );
+ }
+
+ protected boolean navigationMovement( int dx, int dy, int status, int time ) {
+ return handleMovement( dx, dy );
+ }
+
+ protected boolean trackwheelRoll( int amount, int status, int time ) {
+ if( ( status & KeypadListener.STATUS_ALT ) != 0 ) {
+ return handleMovement( amount, 0 );
+ } else {
+ return handleMovement( 0, amount );
+ }
+ }
+
+ private boolean handleMovement( int dx, int dy ) {
+ if( _editing ) {
+ int xMovement = dx * FIELD_WIDTH / 20;
+ int yMovement = dy * FIELD_HEIGHT / 20;
+
+ _x = MathUtilities.clamp( 0, _x + xMovement, FIELD_WIDTH - 1 );
+ _y = MathUtilities.clamp( 0, _y + yMovement, FIELD_HEIGHT - 1 );
+
+ int[] argbData = new int[ 1 ];
+ _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+
+ invalidate( 0, 0, getWidth(), getHeight() );
+ fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
+ return true;
+ }
+ return false;
+ }
+
+ public int getSelectedColor() {
+ return _selectedColor;
+ }
+
+ protected boolean navigationClick( int status, int time ) {
+ return handleClick();
+ }
+
+ protected boolean trackwheelClick( int status, int time ) {
+ return handleClick();
+ }
+
+ private boolean handleClick() {
+ _editing = !_editing;
+ invalidate( 0, 0, getWidth(), getHeight() );
+ return true;
+ }
+
+ protected boolean touchEvent( TouchEvent message ) {
+ if( message == null ) {
+ throw new IllegalArgumentException( "ButtonField.touchEvent: TouchEvent message is null." );
+ }
+ boolean isConsumed = false;
+ boolean isOutOfBounds = false;
+ int x = message.getX( 1 );
+ int y = message.getY( 1 );
+ // Check to ensure point is within this field
+ if( x <= 0 || y <= 0 || x > ( FIELD_WIDTH - 1 ) || y > ( FIELD_HEIGHT - 1 ) ) {
+ isOutOfBounds = true;
+ }
+ int[] argbData = new int[ 1 ];
+ switch( message.getEvent() ) {
+ case TouchEvent.CLICK:
+ case TouchEvent.MOVE:
+ if( isOutOfBounds ) {
+ return true; // consume
+ }
+ _editing = true; // Pressed effect
+ // update color
+ _x = x;
+ _y = y;
+ _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+ invalidate( 0, 0, getWidth(), getHeight() );
+ fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
+ isConsumed = true;
+ break;
+ case TouchEvent.UNCLICK:
+ if( isOutOfBounds ) {
+ _editing = false; // Reset presssed effect
+ return true;
+ }
+
+ // A field change notification is only sent on UNCLICK to allow for recovery
+ // should the user cancel, i.e. click and move off the button
+
+ _editing = false; // Reset pressed effect
+
+ // update state
+ _x = x;
+ _y = y;
+ _backgroundBitmap.getARGB( argbData, 0, 1, _x, _y, 1, 1 );
+ _selectedColor = argbData[ 0 ];
+ invalidate( 0, 0, getWidth(), getHeight() );
+ fieldChangeNotify( FieldChangeListener.PROGRAMMATIC );
+ isConsumed = true;
+ break;
+ }
+ return isConsumed;
+ }
+}
+
+class ColorPreviewField extends Field {
+ private static final int FIELD_WIDTH = 40;
+ private static final int FIELD_HEIGHT = 30;
+
+ private int _color;
+
+ ColorPreviewField( int color ) {
+ _color = color;
+ }
+
+ public int getPreferredWidth() {
+ return FIELD_WIDTH;
+ }
+
+ public int getPreferredHeight() {
+ return FIELD_HEIGHT;
+ }
+
+ protected void layout( int width, int height ) {
+ setExtent( getPreferredWidth(), getPreferredHeight() );
+ }
+
+ public void setColor( int color ) {
+ _color = color;
+ invalidate();
+ }
+
+ protected void paint( Graphics g ) {
+ int oldColor = g.getColor();
+ try {
+ g.setColor( _color );
+ g.fillRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
+
+ g.setColor( 0x000000 );
+ g.drawRect( 0, 0, FIELD_WIDTH, FIELD_HEIGHT );
+ } finally {
+ g.setColor( oldColor );
+ }
+ }
+}
+
+class ColorPickerPopup extends PopupScreen implements FieldChangeListener {
+ private BaseColorChooser _baseColorChooser;
+ private TintChooser _tintChooser;
+ private ColorPreviewField _previewField;
+ private ButtonField _okButton;
+
+ private final int PADDING = 4;
+ private final int PADDING_BOTTOM = 39;
+ private final String OK = "OK";
+
+ public ColorPickerPopup( int initialColor ) {
+ super( new HorizontalFieldManager() );
+ setPadding( PADDING, PADDING, PADDING, PADDING );
+ _baseColorChooser = new BaseColorChooser();
+ _baseColorChooser.setPadding( PADDING, PADDING, PADDING, PADDING );
+ _baseColorChooser.setChangeListener( this );
+ add( _baseColorChooser );
+
+ _tintChooser = new TintChooser( initialColor );
+ _tintChooser.setPadding( PADDING, PADDING, PADDING, PADDING );
+ _tintChooser.setChangeListener( this );
+ add( _tintChooser );
+
+ VerticalFieldManager previewPane = new VerticalFieldManager();
+
+ _previewField = new ColorPreviewField( initialColor );
+ _previewField.setPadding( PADDING, PADDING, PADDING + PADDING_BOTTOM, PADDING );
+ previewPane.add( _previewField );
+
+ _okButton = new ButtonField( OK );
+ _okButton.setChangeListener( this );
+ previewPane.add( _okButton );
+
+ add( previewPane );
+ }
+
+ public void fieldChanged( Field field, int context ) {
+ field.setDirty( false ); // don't want the save dialog
+ if( field == _baseColorChooser ) {
+ // Get color from base chooser
+ // Update the tint chooser
+ // Update the result color
+ _tintChooser.setColor( _baseColorChooser.getSelectedColor() );
+ _previewField.setColor( _tintChooser.getSelectedColor() );
+ } else if( field == _tintChooser ) {
+ // Update the result color
+ _previewField.setColor( _tintChooser.getSelectedColor() );
+ } else if( field == _okButton ) {
+ close();
+ }
+ }
+
+ protected boolean keyChar( char key, int status, int time ) {
+ if( key == Characters.ESCAPE ) {
+ close();
+ return true;
+ } else if( key == Characters.ENTER ) {
+ close();
+ return true;
+ }
+ return super.keyChar( key, status, time );
+ }
+
+ public int getSelectedColor() {
+ return _tintChooser.getSelectedColor();
+ }
+
+ public boolean doModal() {
+ UiApplication.getUiApplication().pushModalScreen( this );
+ return true;
+ }
+}
View
536 api/dialog/src/main/java/blackberry/ui/dialog/datetime/DateTimeDialog.java
@@ -0,0 +1,536 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package blackberry.ui.dialog.datetime;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import net.rim.device.api.i18n.SimpleDateFormat;
+import net.rim.device.api.ui.picker.DateTimePicker;
+
+import blackberry.ui.dialog.IWebWorksDialog;
+
+public class DateTimeDialog implements IWebWorksDialog {
+
+ private Html5DateTimeObject _HTML5Calendar;
+ private DateTimePicker _dateTimePicker = null;
+
+ public DateTimeDialog ( String type, String value, String min, String max ) {
+ if("date".equals(type)) {
+ _HTML5Calendar = new HTML5Date ( value );
+ } else if("month".equals(type)) {
+ _HTML5Calendar = new HTML5Month( value );
+ } else if("time".equals(type)) {
+ _HTML5Calendar = new HTML5Time( value );
+ } else if("datetime".equals(type)) {
+ _HTML5Calendar = new HTML5DateTimeGlobal( value );
+ } else if("local".equals(type)) {
+ _HTML5Calendar = new HTML5DateTimeLocal( value );
+ } else {
+ throw new IllegalArgumentException("Invalid date type.");
+ }
+
+ if ( _HTML5Calendar != null ) {
+ _HTML5Calendar.createDateTimePickerInstance();
+ if ( min != null && min.length() != 0 ) {
+ _HTML5Calendar.setMin( min );
+ }
+ if ( max != null && max.length() != 0 ) {
+ _HTML5Calendar.setMax( max );
+ }
+ }
+ }
+
+ public boolean show() {
+ return _dateTimePicker.doModal();
+ }
+
+ public Object getSelectedValue() {
+ SimpleDateFormat sdf = new SimpleDateFormat( _HTML5Calendar.getFormat().toString() );
+ StringBuffer sb = sdf.format( _dateTimePicker.getDateTime(), new StringBuffer(16), null );
+
+ return sb.toString();
+ }
+
+ private static int parseInt( String s, int from, int to ) {
+ return net.rim.device.api.util.NumberUtilities.parseInt( s, from, to, 10 );
+ }
+
+ private static void setMonth( Calendar calendar, int year, int month ) {
+ calendar.set(Calendar.DAY_OF_MONTH, 0);
+ calendar.set(Calendar.YEAR, year);
+ calendar.set(Calendar.MONTH, month);
+ }
+
+ private static void setTime( Calendar calendar, int hour, int minutes, int seconds, int milli) {
+ calendar.set(Calendar.HOUR_OF_DAY, hour);
+ calendar.set(Calendar.MINUTE, minutes);
+ calendar.set(Calendar.SECOND, seconds);
+ calendar.set(Calendar.MILLISECOND, milli);
+ }
+
+ public class HTML5Month extends Html5DateTimeObject {
+
+ public HTML5Month( String value ) {
+ if ( value != null && value.length() != 0 ) {
+ _html5Calendar = parse( value );
+ } else {
+ _html5Calendar = Calendar.getInstance();
+ }
+ }
+
+ public HTML5Month( ) {
+ }
+
+ public StringBuffer getFormat() {
+ if ( _format == null ) {
+ return new StringBuffer("yyyy-MM");
+ }
+ return _format;
+ }
+
+ public void createDateTimePickerInstance() {
+ if ( _html5Calendar == null ) {
+ _html5Calendar = Calendar.getInstance();
+ }
+ _dateTimePicker = DateTimePicker.createInstance( _html5Calendar, getFormat().toString(), null );
+ }
+
+ public void setMin( String value ) {
+ Calendar minCalendar = parse( value );
+ if ( minCalendar != null ) {
+ _dateTimePicker.setMinimumDate( minCalendar );
+ }
+ }
+
+ public void setMax( String value ) {
+ Calendar maxCalendar = parse( value );
+ if ( maxCalendar != null ) {
+ _dateTimePicker.setMaximumDate( maxCalendar );
+ }
+ }
+
+ protected Calendar parse( String text ) {
+ try {
+ _format = new StringBuffer( 7 );
<