/* * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package com.sun.lwuit.impl.blackberry; import com.sun.lwuit.BrowserComponent; import com.sun.lwuit.Component; import com.sun.lwuit.Dialog; import com.sun.lwuit.Display; import com.sun.lwuit.Form; import com.sun.lwuit.PeerComponent; import com.sun.lwuit.TextArea; import com.sun.lwuit.VideoComponent; import com.sun.lwuit.animations.Animation; import com.sun.lwuit.events.ActionEvent; import com.sun.lwuit.events.ActionListener; import com.sun.lwuit.geom.Dimension; import com.sun.lwuit.impl.LWUITImplementation; import com.sun.lwuit.plaf.UIManager; import com.sun.lwuit.util.EventDispatcher; import com.sun.lwuit.util.Resources; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Hashtable; import java.util.Vector; import javax.microedition.io.ConnectionNotFoundException; import javax.microedition.media.Manager; import javax.microedition.media.MediaException; import javax.microedition.media.Player; import javax.microedition.media.control.VideoControl; import javax.microedition.midlet.MIDlet; import net.rim.device.api.ui.Screen; import net.rim.device.api.system.Application; import net.rim.device.api.system.ApplicationDescriptor; import net.rim.device.api.system.Bitmap; //#ifdef signed //# import net.rim.device.api.system.CodeModuleGroup; //# import net.rim.device.api.system.CodeModuleGroupManager; //# import net.rim.blackberry.api.phone.Phone; //# import net.rim.device.api.browser.field2.BrowserField; //# import net.rim.device.api.browser.field2.BrowserFieldListener; //# import net.rim.device.api.script.Scriptable; //#endif import net.rim.device.api.system.DeviceInfo; import net.rim.device.api.system.GPRSInfo; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.FocusChangeListener; import net.rim.device.api.ui.Font; import net.rim.device.api.ui.FontFamily; import net.rim.device.api.ui.Graphics; import net.rim.device.api.ui.Keypad; import net.rim.device.api.ui.MenuItem; import net.rim.device.api.ui.Ui; import net.rim.device.api.ui.UiApplication; import net.rim.device.api.ui.XYRect; import net.rim.device.api.ui.component.ActiveAutoTextEditField; import net.rim.device.api.ui.component.BasicEditField; import net.rim.device.api.ui.component.Menu; import net.rim.device.api.ui.component.NullField; import net.rim.device.api.ui.component.PasswordEditField; import net.rim.device.api.ui.container.PopupScreen; import net.rim.device.api.ui.container.VerticalFieldManager; //#ifdef touch //# import net.rim.device.api.system.Branding; //# import org.w3c.dom.Document; //#endif /** * The implementation of the blackberry platform delegates the work to the underlying UI * application to allow for deep BB integration * * @author Shai Almog, Thorsten Schemm */ public class BlackBerryImplementation extends LWUITImplementation { static Hashtable fieldComponentMap = new Hashtable(); static final int INVOKE_LATER_confirmControlView = 1; static final int INVOKE_LATER_finishEdit = 2; static final int INVOKE_LATER_initComponent = 3; static final int INVOKE_LATER_deinitialize = 4; static final int INVOKE_LATER_showNativeScreen = 5; static final int INVOKE_AND_WAIT_calcPreferredSize = 6; static final int INVOKE_AND_WAIT_setFocus = 7; static final int INVOKE_LATER_dirty = 8; static final int INVOKE_LATER_startMedia = 9; private static boolean minimizeOnEnd = true; // blackberry sometimes "breaks" the drawing color... No idea why this might happen... private int color; static final int MENU_SOFT_KEY = Keypad.KEY_MENU; static final int GAME_KEY_CODE_FIRE = -90; static final int GAME_KEY_CODE_UP = -91; static final int GAME_KEY_CODE_DOWN = -92; static final int GAME_KEY_CODE_LEFT = -93; static final int GAME_KEY_CODE_RIGHT = -94; BasicEditField nativeEdit; TextArea lightweightEdit; private BlackBerryCanvas canvas = createCanvas(); private UiApplication app; private MIDlet midletInstance; static boolean midlet; private boolean initGetProperty = true; //#ifdef signed //# private static CodeModuleGroup group; //#endif private static EventDispatcher volumeListener; private NullField nullFld; BlackBerryCanvas createCanvas() { return new BlackBerryCanvas(this); } public void init(Object m) { if (m instanceof UiApplication) { app = (UiApplication) m; } else { if(m instanceof MIDlet) { midlet = true; midletInstance = (MIDlet)m; } else { midlet = false; } app = UiApplication.getUiApplication(); } app.enableKeyUpEvents(true); if (!app.isHandlingEvents()) { new Thread() { public void run() { app.enterEventDispatcher(); } }.start(); } Dialog.setCommandsAsButtons(true); UIManager.getInstance().addThemeRefreshListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { Hashtable themeProps = new Hashtable(); themeProps.put("SoftButton.margin", "0,0,0,0"); themeProps.put("SoftButton.padding", "0,0,0,0"); UIManager.getInstance().addThemeProps(themeProps); } }); } public void confirmControlView() { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_confirmControlView); i.fld = canvas; app.invokeLater(i); } protected void keyPressed(final int keyCode) { // expose the method to the canvas super.keyPressed(keyCode); } protected void keyReleased(final int keyCode) { // expose the method to the canvas super.keyReleased(keyCode); } public int getDisplayWidth() { // the alternative undeprecated API requires a signature return net.rim.device.api.ui.Graphics.getScreenWidth(); } public int getDisplayHeight() { // the alternative undeprecated API requires a signature return net.rim.device.api.ui.Graphics.getScreenHeight(); } public void editString(final Component cmp, final int maxSize, final int constraint, final String text, int keyCode) { TextArea txtCmp = (TextArea) cmp; if((txtCmp.getConstraint() & TextArea.NON_PREDICTIVE) == 0){ nativeEdit(txtCmp, txtCmp.getMaxSize(), txtCmp.getConstraint(), txtCmp.getText(), keyCode); } } public void nativeEdit(final Component cmp, final int maxSize, final int constraint, String text, int keyCode) { //#ifdef touch //# BlackBerryVirtualKeyboard.blockFolding = true; //#endif if(nativeEdit != null){ finishEdit(true); } lightweightEdit = (TextArea) cmp; if(keyCode > 0 && getKeyboardType() == Display.KEYBOARD_TYPE_QWERTY) { text += ((char)keyCode); lightweightEdit.setText(text); } class LightweightEdit implements Runnable, Animation { public void run() { long type = 0; int constraint = lightweightEdit.getConstraint(); if((constraint & TextArea.DECIMAL) == TextArea.DECIMAL) { type = BasicEditField.FILTER_REAL_NUMERIC; } else { if((constraint & TextArea.EMAILADDR) == TextArea.EMAILADDR) { type = BasicEditField.FILTER_EMAIL; } else { if((constraint & TextArea.NUMERIC) == TextArea.NUMERIC) { type = BasicEditField.FILTER_NUMERIC; } else { if((constraint & TextArea.PHONENUMBER) == TextArea.PHONENUMBER) { type = BasicEditField.FILTER_PHONE; } } } } if(lightweightEdit.isSingleLineTextArea()) { type |= BasicEditField.NO_NEWLINE; } if ((constraint & TextArea.PASSWORD) == TextArea.PASSWORD) { nativeEdit = new BBPasswordEditField(lightweightEdit, type, maxSize); } else { nativeEdit = new BBEditField(lightweightEdit, type, maxSize); } nativeEdit.setEditable(true); Font f = nativeEdit.getFont(); if (f.getHeight() > lightweightEdit.getStyle().getFont().getHeight()) { nativeEdit.setFont(f.derive(f.getStyle(), lightweightEdit.getStyle().getFont().getHeight())); } canvas.add(nativeEdit); nativeEdit.setCursorPosition(lightweightEdit.getText().length()); try { nativeEdit.setFocus(); } catch (Throwable t) { // no idea why this throws an exception sometimes //t.printStackTrace(); } } public boolean animate() { BasicEditField ef = nativeEdit; Component lw = lightweightEdit; if (lw == null || lw.getComponentForm() != Display.getInstance().getCurrent()) { Display.getInstance().getCurrent().deregisterAnimated(this); finishEdit(false); } else { if (ef != null) { if (ef.isDirty()) { lw.repaint(); } } } return false; } public void paint(com.sun.lwuit.Graphics g) { } } LightweightEdit lw = new LightweightEdit(); Display.getInstance().getCurrent().registerAnimated(lw); Application.getApplication().invokeLater(lw); } public void setCurrentForm(Form f) { super.setCurrentForm(f); nullFld = null; synchronized(UiApplication.getEventLock()) { while(canvas.getFieldCount() > 0) { canvas.delete(canvas.getField(0)); } } } void finishEdit(final boolean canceled) { // assigning the field here prevents a null pointer exception in the layout BasicEditField be = nativeEdit; if (be != null) { if (!Application.isEventDispatchThread()) { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_finishEdit); Application.getApplication().invokeLater(i); return; } if (!canceled && lightweightEdit != null) { Display.getInstance().onEditingComplete(lightweightEdit, be.getText()); } lightweightEdit = null; nativeEdit = null; canvas.delete(be); flushGraphics(); //#ifdef touch //# BlackBerryVirtualKeyboard.blockFolding = false; //#endif Display.getInstance().setShowVirtualKeyboard(false); } } public void setNativeCommands(Vector commands) { canvas.setNativeCommands(commands); } public void flushGraphics(int x, int y, int width, int height) { canvas.flush(x, y, width, height, app); } public void flushGraphics() { canvas.flush(0, 0, getDisplayWidth(), getDisplayHeight(), app); } public void getRGB(Object nativeImage, int[] arr, int offset, int x, int y, int width, int height) { Bitmap b = (Bitmap) nativeImage; b.getARGB(arr, offset, width, x, y, width, height); } public Object createImage(int[] rgb, int width, int height) { Bitmap image = new Bitmap(width, height); image.setARGB(rgb, 0, width, 0, 0, width, height); return image; } public Object createImage(String path) throws IOException { try { return createImage(com.sun.lwuit.Image.class.getResourceAsStream(path)); } catch (RuntimeException err) { throw new IOException(err.toString()); } } public Object createImage(InputStream i) throws IOException { java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream(); byte[] buf = new byte[2048]; int len; while ((len = i.read(buf)) > -1) { out.write(buf, 0, len); } out.close(); i.close(); byte[] b = out.toByteArray(); return Bitmap.createBitmapFromBytes(b, 0, b.length, 1); } public boolean isAlphaMutableImageSupported() { return true; } public Object createMutableImage(int width, int height, int fillColor) { Bitmap b = new Bitmap(width, height); Graphics g = new Graphics(b); if ((fillColor & 0xff000000) != 0xff000000) { g.setColor(fillColor & 0xffffff); int oldAlpha = g.getGlobalAlpha(); g.setGlobalAlpha((fillColor >> 24) & 0xff); g.clear(); g.setGlobalAlpha(oldAlpha); } else { g.setColor(fillColor & 0xffffff); g.fillRect(0, 0, width, height); } return b; } public Object createImage(byte[] bytes, int offset, int len) { return Bitmap.createBitmapFromBytes(bytes, offset, len, 1); } public int getImageWidth(Object i) { return ((Bitmap) i).getWidth(); } public int getImageHeight(Object i) { return ((Bitmap) i).getHeight(); } /** * @inheritDoc */ public Object scale(Object nativeImage, int width, int height) { Bitmap image = (Bitmap) nativeImage; int srcWidth = image.getWidth(); int srcHeight = image.getHeight(); // no need to scale if (srcWidth == width && srcHeight == height) { return image; } int[] currentArray = new int[srcWidth]; int[] destinationArray = new int[width * height]; scaleArray(image, srcWidth, srcHeight, height, width, currentArray, destinationArray); return createImage(destinationArray, width, height); } private void scaleArray(Bitmap currentImage, int srcWidth, int srcHeight, int height, int width, int[] currentArray, int[] destinationArray) { // Horizontal Resize int yRatio = (srcHeight << 16) / height; int xRatio = (srcWidth << 16) / width; int xPos = xRatio / 2; int yPos = yRatio / 2; // if there is more than 16bit color there is no point in using mutable // images since they won't save any memory for (int y = 0; y < height; y++) { int srcY = yPos >> 16; getRGB(currentImage, currentArray, 0, 0, srcY, srcWidth, 1); for (int x = 0; x < width; x++) { int srcX = xPos >> 16; int destPixel = x + y * width; if ((destPixel >= 0 && destPixel < destinationArray.length) && (srcX < currentArray.length)) { destinationArray[destPixel] = currentArray[srcX]; } xPos += xRatio; } yPos += yRatio; xPos = xRatio / 2; } } public int getSoftkeyCount() { return 1; } public int[] getSoftkeyCode(int index) { return new int[]{MENU_SOFT_KEY}; } public int getClearKeyCode() { return Keypad.KEY_DELETE; } public int getBackspaceKeyCode() { return Keypad.KEY_BACKSPACE; } public int getBackKeyCode() { return Keypad.KEY_ESCAPE; } public int getGameAction(int keyCode) { switch (keyCode) { // the enter key should also map to fire case '\n': case GAME_KEY_CODE_FIRE: return Display.GAME_FIRE; case GAME_KEY_CODE_UP: return Display.GAME_UP; case GAME_KEY_CODE_DOWN: return Display.GAME_DOWN; case GAME_KEY_CODE_LEFT: return Display.GAME_LEFT; case GAME_KEY_CODE_RIGHT: return Display.GAME_RIGHT; } return 0; } public int getKeyCode(int gameAction) { switch (gameAction) { case Display.GAME_FIRE: return GAME_KEY_CODE_FIRE; case Display.GAME_UP: return GAME_KEY_CODE_UP; case Display.GAME_DOWN: return GAME_KEY_CODE_DOWN; case Display.GAME_LEFT: return GAME_KEY_CODE_LEFT; case Display.GAME_RIGHT: return GAME_KEY_CODE_RIGHT; } return 0; } public boolean isTouchDevice() { return canvas.isTouchDevice(); } public int getColor(Object graphics) { if (graphics == canvas.getGlobalGraphics()) { // make sure color wasn't broken... ((Graphics) graphics).setColor(color); return color; } return ((Graphics) graphics).getColor() & 0xffffff; } public void setColor(Object graphics, int RGB) { if (graphics == canvas.getGlobalGraphics()) { color = RGB; } ((Graphics) graphics).setColor(RGB); } public boolean isAlphaGlobal() { return true; } public void setAlpha(Object graphics, int alpha) { ((Graphics) graphics).setGlobalAlpha(alpha); } public int getAlpha(Object graphics) { return ((Graphics) graphics).getGlobalAlpha(); } public void setNativeFont(Object graphics, Object font) { ((Graphics) graphics).setFont(font(font)); } public int getClipX(Object graphics) { XYRect r = new XYRect(); ((Graphics) graphics).getAbsoluteClippingRect(r); return r.x; } public int getClipY(Object graphics) { XYRect r = new XYRect(); ((Graphics) graphics).getAbsoluteClippingRect(r); return r.y; } public int getClipWidth(Object graphics) { XYRect r = new XYRect(); ((Graphics) graphics).getAbsoluteClippingRect(r); return r.width; } public int getClipHeight(Object graphics) { XYRect r = new XYRect(); ((Graphics) graphics).getAbsoluteClippingRect(r); return r.height; } public void setClip(Object graphics, int x, int y, int width, int height) { Graphics g = (net.rim.device.api.ui.Graphics) graphics; net.rim.device.api.ui.Font oldFont = g.getFont(); int oldColor = g.getColor(); int oldAlpha = g.getGlobalAlpha(); while (g.getContextStackSize() > 1) { g.popContext(); } g.pushRegion(x, y, width, height, 0, 0); g.translate(-g.getTranslateX(), -g.getTranslateY()); /** * applying a clip will automatically * reset some information that we need to keep track of * manually (it seems). */ g.setFont(oldFont == null ? (net.rim.device.api.ui.Font)getDefaultFont() : oldFont); g.setColor(oldColor); g.setGlobalAlpha(oldAlpha); } public void clipRect(Object graphics, int x, int y, int width, int height) { Graphics g = (Graphics) graphics; g.pushRegion(x, y, width, height, 0, 0); g.translate(-g.getTranslateX(), -g.getTranslateY()); } public void drawLine(Object graphics, int x1, int y1, int x2, int y2) { ((Graphics) graphics).drawLine(x1, y1, x2, y2); } public void fillRect(Object graphics, int x, int y, int width, int height) { ((Graphics) graphics).fillRect(x, y, width, height); } public void drawRect(Object graphics, int x, int y, int width, int height) { ((Graphics) graphics).drawRect(x, y, width, height); } public void drawRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight) { ((Graphics) graphics).drawRoundRect(x, y, width, height, arcWidth, arcHeight); } public void fillRoundRect(Object graphics, int x, int y, int width, int height, int arcWidth, int arcHeight) { ((Graphics) graphics).fillRoundRect(x, y, width, height, arcWidth, arcHeight); } public void fillArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle) { ((Graphics) graphics).fillArc(x, y, width, height, startAngle, arcAngle); } public void drawArc(Object graphics, int x, int y, int width, int height, int startAngle, int arcAngle) { ((Graphics) graphics).drawArc(x, y, width, height, startAngle, arcAngle); } public void drawString(Object graphics, String str, int x, int y) { ((Graphics) graphics).drawText(str, x, y); } /** * @inheritDoc */ public VideoComponent createVideoPeer(String url) throws IOException { try { Player p = Manager.createPlayer(url); p.realize(); VideoControl vidc = (VideoControl) p.getControl("VideoControl"); Field f = (Field) vidc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); RIMVideoComponent r = new RIMVideoComponent(f, p, vidc); r.putClientProperty("VideoControl", vidc); r.putClientProperty("Player", p); return r; } catch (MediaException ex) { ex.printStackTrace(); throw new IOException(ex.toString()); } } /** * @inheritDoc */ public VideoComponent createVideoPeer(InputStream stream, String type) throws IOException { try { Player p = Manager.createPlayer(stream, type); p.realize(); VideoControl vidc = (VideoControl) p.getControl("VideoControl"); Field f = (Field) vidc.initDisplayMode(VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field"); RIMVideoComponent r = new RIMVideoComponent(f, p, vidc); r.putClientProperty("VideoControl", vidc); r.putClientProperty("Player", p); return r; } catch (MediaException ex) { ex.printStackTrace(); throw new IOException(ex.toString()); } } class RIMVideoComponent extends VideoComponent { private boolean fullscreen; private Player p; private VideoControl c; private boolean started; RIMVideoComponent(Field f, Player p, VideoControl c) { super(f); this.p = p; this.c = c; } public int getMediaDuration() { return (int)(((Player) getNativePeer()).getDuration() / 1000); } public boolean isPlaying() { return ((Player) getNativePeer()).getState() == Player.STARTED; } public void setVisible(boolean b) { super.setVisible(b); try { c.setVisible(b); } catch (Throwable t) { t.printStackTrace(); } } protected void onPositionSizeChange() { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_dirty); i.fld = (Field) getNativePeer(); app.invokeLater(i); } protected void initComponent() { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_initComponent); i.fld = (Field) getNativePeer(); app.invokeLater(i); if (started) { start(); } } protected void deinitialize() { canvas.eventTarget = null; InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_deinitialize); i.fld = (Field) getNativePeer(); app.invokeLater(i); } /** * @inheritDoc */ public void paint(com.sun.lwuit.Graphics g) { /*if(isVisible()){ try { if (isFullScreen()) { c.setDisplayLocation(0, 0); c.setDisplaySize(Display.getInstance().getDisplayWidth(), Display.getInstance().getDisplayHeight()); } else { c.setDisplayLocation(getAbsoluteX(), getAbsoluteY()); int w = getWidth(); int h = getHeight(); if (c.getDisplayWidth() != w || c.getDisplayHeight() != h) { c.setDisplaySize(w, h); } } } catch (MediaException ex) { ex.printStackTrace(); } }*/ } /*public boolean animate() { Field fld = (Field)getNativePeer(); if(fld.isDirty()) { setShouldCalcPreferredSize(true); } return super.animate(); }*/ /** * @inheritDoc */ protected Dimension calcPreferredSize() { return new Dimension(c.getDisplayWidth(), c.getDisplayHeight()); } /** * Start media playback implicitly setting the component to visible */ public void start() { if (isInitialized()) { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_startMedia); i.v = p; app.invokeLater(i); } else { started = true; } } /** * Stope media playback */ public void stop() { try { p.stop(); } catch (MediaException ex) { ex.printStackTrace(); throw new RuntimeException(ex.toString()); } } /** * Set the number of times the media should loop * * @param count the number of times the media should loop */ public void setLoopCount(int count) { p.setLoopCount(count); } /** * Return the duration of the media * * @return the duration of the media */ public int getMediaTimeMS() { return (int) (p.getMediaTime() / 1000); } /** * "Jump" to a point in time within the media * * @param now the point in time to "Jump" to * @return the media time in microseconds */ public int setMediaTimeMS(int now) { try { return (int) (p.setMediaTime(now * 1000) / 1000); } catch (MediaException ex) { ex.printStackTrace(); throw new RuntimeException(ex.toString()); } } public void setFullScreen(boolean fullscreen) { this.fullscreen = fullscreen; try { c.setDisplayFullScreen(fullscreen); } catch (MediaException ex) { ex.printStackTrace(); } repaint(); } public boolean isFullScreen() { return fullscreen; } } public void drawImage(Object graphics, Object img, int x, int y) { Bitmap b = (Bitmap) img; ((Graphics) graphics).drawBitmap(x, y, b.getWidth(), b.getHeight(), b, 0, 0); } public void drawRGB(Object graphics, int[] rgbData, int offset, int x, int y, int w, int h, boolean processAlpha) { Graphics nativeGraphics = (Graphics) graphics; int rgbX = x; int rgbY = y; //if the x or y are positive simply redirect the call to midp Graphics if (rgbX >= 0) { if (processAlpha) { nativeGraphics.drawARGB(rgbData, offset, w, rgbX, rgbY, w, h); } else { nativeGraphics.drawRGB(rgbData, offset, w, rgbX, rgbY, w, h); } return; } //if the translate causes us to paint out of the bounds //we will paint only the relevant rows row by row to avoid some devices bugs //such as BB that fails to paint if the coordinates are negative. if (rgbX < 0) { if (rgbX + w > 0) { if (w < rgbData.length) { for (int i = 1; i <= rgbData.length / w; i++) { offset = -rgbX + (w * (i - 1)); rgbY++; if (rgbY >= 0) { nativeGraphics.drawARGB(rgbData, offset, (w + rgbX), 0, rgbY, w + rgbX, 1); } } } } } } public Object getNativeGraphics() { return canvas.getGlobalGraphics(); } public Object getNativeGraphics(Object image) { return new Graphics((Bitmap) image); } public boolean isAntiAliasingSupported() { return true; } public void setAntiAliased(Object graphics, boolean a) { ((Graphics) graphics).setDrawingStyle(Graphics.DRAWSTYLE_AALINES, a); ((Graphics) graphics).setDrawingStyle(Graphics.DRAWSTYLE_AAPOLYGONS, a); } public boolean isAntiAliased(Object graphics) { return ((Graphics) graphics).isDrawingStyleSet(Graphics.DRAWSTYLE_AALINES); } public boolean isAntiAliasedTextSupported() { return false; } public void setAntiAliasedText(Object graphics, boolean a) { // this method uses undocumented behavior so it won't compile on different JDE versions /*Graphics g = (Graphics)graphics; Font f = g.getFont(); if(a) { if(f.getAntialiasMode() != Font.ANTIALIAS_SUBPIXEL) { f = f.derive(f.getStyle(), f.getHeight(), Ui.UNITS_px, Font.ANTIALIAS_SUBPIXEL, f.getEffects()); g.setFont(f); } } else { if(f.getAntialiasMode() == Font.ANTIALIAS_SUBPIXEL) { f = f.derive(f.getStyle(), f.getHeight(), Ui.UNITS_px, Font.ANTIALIAS_NONE, f.getEffects()); g.setFont(f); } }*/ } public boolean isAntiAliasedText(Object graphics) { // this method uses undocumented behavior so it won't compile on different JDE versions /*Graphics g = (Graphics)graphics; Font f = g.getFont(); return f.getAntialiasMode() == Font.ANTIALIAS_SUBPIXEL;*/ return false; } public int charsWidth(Object nativeFont, char[] ch, int offset, int length) { return font(nativeFont).getAdvance(ch, offset, length); } private Font font(Object nativeFont) { if (nativeFont == null) { return Font.getDefault(); } return (Font) nativeFont; } public int stringWidth(Object nativeFont, String str) { return font(nativeFont).getAdvance(str); } public int charWidth(Object nativeFont, char ch) { return font(nativeFont).getAdvance(ch); } public int getHeight(Object nativeFont) { return font(nativeFont).getHeight(); } public Object getDefaultFont() { return Font.getDefault(); } public int getFace(Object nativeFont) { Font nf = (Font) font(nativeFont); int s = nf.getStyle(); int result = 0; if ((s & Font.BOLD) == Font.BOLD) { result |= com.sun.lwuit.Font.STYLE_BOLD; } if ((s & Font.ITALIC) == Font.ITALIC) { result |= com.sun.lwuit.Font.STYLE_ITALIC; } if ((s & Font.UNDERLINED) == Font.UNDERLINED) { result |= com.sun.lwuit.Font.STYLE_UNDERLINED; } return result; } public int getSize(Object nativeFont) { Font nf = (Font) font(nativeFont); int bbSize = Font.getDefault().getHeight(); int diff = Font.getDefault().getHeight() / 3; if (nf.getHeight() == bbSize - diff) { return com.sun.lwuit.Font.SIZE_SMALL; } if (nf.getHeight() == bbSize + diff) { return com.sun.lwuit.Font.SIZE_LARGE; } return com.sun.lwuit.Font.SIZE_MEDIUM; } public int getStyle(Object nativeFont) { Font nf = (Font) font(nativeFont); int s = nf.getStyle(); if ((s & FontFamily.MONO_BITMAP_FONT) == FontFamily.MONO_BITMAP_FONT) { return com.sun.lwuit.Font.FACE_MONOSPACE; } if ((s & FontFamily.SCALABLE_FONT) == FontFamily.SCALABLE_FONT) { return com.sun.lwuit.Font.FACE_PROPORTIONAL; } return com.sun.lwuit.Font.FACE_SYSTEM; } public Object createFont(int face, int style, int size) { Font font = Font.getDefault(); int bbSize = Font.getDefault().getHeight(); int diff = Font.getDefault().getHeight() / 3; switch (size) { case com.sun.lwuit.Font.SIZE_SMALL: bbSize -= diff; break; case com.sun.lwuit.Font.SIZE_LARGE: bbSize += diff; break; } int bbStyle = Font.PLAIN; switch (style) { case com.sun.lwuit.Font.STYLE_BOLD: bbStyle = Font.BOLD; break; case com.sun.lwuit.Font.STYLE_ITALIC: bbStyle = Font.ITALIC; break; case com.sun.lwuit.Font.STYLE_PLAIN: bbStyle = Font.PLAIN; break; case com.sun.lwuit.Font.STYLE_UNDERLINED: bbStyle = Font.UNDERLINED; break; default: // probably bold/italic bbStyle = Font.BOLD | Font.ITALIC; break; } switch (face) { case com.sun.lwuit.Font.FACE_MONOSPACE: font = font.getFontFamily().getFont(bbStyle | FontFamily.MONO_BITMAP_FONT, bbSize); break; case com.sun.lwuit.Font.FACE_PROPORTIONAL: font = font.getFontFamily().getFont(bbStyle | FontFamily.SCALABLE_FONT, bbSize); break; case com.sun.lwuit.Font.FACE_SYSTEM: font = font.derive(bbStyle, bbSize, Ui.UNITS_px, Font.ANTIALIAS_SUBPIXEL, font.getEffects()); break; } return font; } public boolean isNativeInputSupported() { return true; } public int getKeyboardType() { int keyT = Keypad.getHardwareLayout(); switch (keyT) { case Keypad.HW_LAYOUT_LEGACY: case Keypad.HW_LAYOUT_32: case Keypad.HW_LAYOUT_39: case Keypad.HW_LAYOUT_PHONE: return Display.KEYBOARD_TYPE_QWERTY; case Keypad.HW_LAYOUT_REDUCED: case Keypad.HW_LAYOUT_REDUCED_24: return Display.KEYBOARD_TYPE_HALF_QWERTY; case 1230263636: // HW_LAYOUT_ITUT return Display.KEYBOARD_TYPE_NUMERIC; //#ifdef touch //# case Keypad.HW_LAYOUT_TOUCHSCREEN_12: //# case Keypad.HW_LAYOUT_TOUCHSCREEN_24: //# case Keypad.HW_LAYOUT_TOUCHSCREEN_29: //# return Display.KEYBOARD_TYPE_VIRTUAL; //#endif } return Display.KEYBOARD_TYPE_QWERTY; } public boolean isMultiTouch() { return canvas.isMultiTouch(); } public boolean isClickTouchScreen() { return canvas.isClickTouchScreen(); } protected void pointerDragged(final int[] x, final int[] y) { super.pointerDragged(x, y); } protected void pointerPressed(final int[] x, final int[] y) { super.pointerPressed(x, y); } protected void pointerReleased(final int[] x, final int[] y) { super.pointerReleased(x, y); } protected void pointerHover(final int[] x, final int[] y) { super.pointerHover(x, y); } protected void pointerHoverPressed(final int[] x, final int[] y) { super.pointerHoverPressed(x, y); } protected void pointerHoverPressed(final int x, final int y) { super.pointerHoverPressed(x, y); } protected void pointerDragged(final int x, final int y) { super.pointerDragged(x, y); } protected void pointerPressed(final int x, final int y) { super.pointerPressed(x, y); } protected void pointerReleased(final int x, final int y) { super.pointerReleased(x, y); } protected void pointerHoverReleased(final int x, final int y) { super.pointerHoverReleased(x, y); } protected void pointerHoverReleased(final int[] x, final int[] y) { super.pointerHoverReleased(x, y); } protected void pointerHover(final int x, final int y) { super.pointerHover(x, y); } protected void sizeChanged(int w, int h) { super.sizeChanged(w, h); } public boolean minimizeApplication() { app.requestBackground(); return true; } public void restoreMinimizedApplication() { app.requestForeground(); } public boolean isThirdSoftButton() { return false; } /** * Indicates whether the application should minimize or exit when the end key is pressed * * @return the minimizeOnEnd */ public static boolean isMinimizeOnEnd() { return minimizeOnEnd; } /** * Indicates whether the application should minimize or exit when the end key is pressed * * @param aMinimizeOnEnd the minimizeOnEnd to set */ public static void setMinimizeOnEnd(boolean aMinimizeOnEnd) { minimizeOnEnd = aMinimizeOnEnd; } /** * Volume listener is invoked when the volume up/down buttons on the blackberry * device are pressed. The key event would be either Characters.CONTROL_VOLUME_UP * or Characters.CONTROL_VOLUME_DOWN * * @param al action listener callback */ public static void addVolumeListener(ActionListener al) { if (volumeListener == null) { volumeListener = new EventDispatcher(); } volumeListener.addListener(al); } /** * Remove the volume listener instance * * @param al action listener to remove */ public static void removeVolumeListener(ActionListener al) { if (volumeListener != null) { volumeListener.removeListener(al); if (volumeListener.getListenerVector() == null || volumeListener.getListenerVector().size() == 0) { volumeListener = null; } } } static EventDispatcher getVolumeListener() { return volumeListener; } /** * @inheritDoc */ public PeerComponent createNativePeer(Object nativeComponent) { if (nativeComponent instanceof Field) { if (nullFld == null) { nullFld = new NullField(); nullFld.setFocusListener(new FocusChangeListener() { public void focusChanged(Field field, int eventType) { if(lightweightEdit != null) { finishEdit(false); } } }); canvas.add(nullFld); } final Field fld = (Field) nativeComponent; final PeerComponent peer = new PeerComponent(fld) { public boolean isFocusable() { if (fld != null) { return fld.isFocusable(); } return super.isFocusable(); } public void setFocus(boolean b) { if (hasFocus() == b) { return; } if (b) { canvas.eventTarget = fld; fld.setFocusListener(new FocusChangeListener() { public void focusChanged(Field field, int eventType) { if (getNativePeer() == fld && eventType == FocusChangeListener.FOCUS_LOST) { fld.setFocusListener(null); nullFld.setFocus(); canvas.eventTarget = null; canvas.repeatLastNavigation(); } } }); } else { fld.setFocusListener(null); if (canvas.eventTarget == fld) { canvas.eventTarget = null; } } if (isInitialized()) { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_AND_WAIT_setFocus); i.val = b; i.fld = fld; app.invokeAndWait(i); } else { super.setFocus(b); } } public boolean animate() { if (fld.isDirty()) { repaint(); } return super.animate(); } protected Dimension calcPreferredSize() { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_AND_WAIT_calcPreferredSize); i.dim = new Dimension(); i.fld = fld; app.invokeAndWait(i); return i.dim; } protected void onPositionSizeChange() { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_dirty); i.fld = fld; app.invokeLater(i); } protected void initComponent() { fieldComponentMap.put(fld, this); InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_initComponent); i.fld = fld; app.invokeLater(i); setFocus(super.hasFocus()); if (hasFocus()) { canvas.eventTarget = fld; } getComponentForm().registerAnimated(this); } protected void deinitialize() { getComponentForm().deregisterAnimated(this); canvas.eventTarget = null; InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_deinitialize); i.fld = fld; app.invokeLater(i); fieldComponentMap.remove(fld); } }; fieldComponentMap.put(fld, peer); return peer; } throw new IllegalArgumentException(nativeComponent.getClass().getName()); } /** * @inheritDoc */ public void showNativeScreen(Object nativeFullScreenPeer) { InvokeLaterWrapper i = new InvokeLaterWrapper(INVOKE_LATER_showNativeScreen); i.fld = (Screen) nativeFullScreenPeer; app.invokeLater(i); } /** * ####################################################################### * ####################################################################### * * see editString() method */ private class EditPopup extends PopupScreen implements FocusChangeListener, Runnable { protected final TextArea lightweightEdit; private boolean finished = false; private boolean cancel = false; private String okString; private String cancelString; protected final BasicEditField nativeEdit; protected EditPopup(TextArea lightweightEdit, boolean password, int maxSize) { super(new VerticalFieldManager(), Field.FOCUSABLE | Field.EDITABLE | Screen.DEFAULT_MENU); UIManager m = UIManager.getInstance(); okString = m.localize("ok", "OK"); cancelString = m.localize("cancel", "Cancel"); this.lightweightEdit = lightweightEdit; long type = 0; switch (lightweightEdit.getConstraint()) { case TextArea.DECIMAL: type = BasicEditField.FILTER_REAL_NUMERIC; break; case TextArea.EMAILADDR: type = BasicEditField.FILTER_EMAIL; break; case TextArea.NUMERIC: type = BasicEditField.FILTER_NUMERIC; break; case TextArea.PHONENUMBER: type = BasicEditField.FILTER_PHONE; break; } if (password) { nativeEdit = new BBPasswordEditField(lightweightEdit, type, maxSize); } else { nativeEdit = new BBEditField(lightweightEdit, type, maxSize); } // using Field.EDITABLE flag now because of bug with DevTrack ID 354265 at // https://www.blackberry.com/jira/browse/JAVAAPI-101 //nativeEdit.setEditable(true); net.rim.device.api.ui.Font f = nativeEdit.getFont(); if (f.getHeight() > lightweightEdit.getStyle().getFont().getHeight()) { nativeEdit.setFont(f.derive(f.getStyle(), lightweightEdit.getStyle().getFont().getHeight())); } add(nativeEdit); nativeEdit.setFocus(); nativeEdit.setFocusListener(this); } protected void makeMenu(Menu menu, int arg1) { menu.add(new MenuItem(okString, 0, 99) { public void run() { finishEdit(); } }); menu.add(new MenuItem(cancelString, 1, 100) { public void run() { EditPopup.this.cancel = true; finishEdit(); } }); super.makeMenu(menu, arg1); } protected void onMenuDismissed(Menu arg0) { super.onMenuDismissed(arg0); /** * at this point the EDT is still blocked, so we repaint the * screen with our old buffer and request some fresh paint * for the textfield. */ this.invalidate(); } protected void onExposed() { super.onExposed(); /** * we reach this if the context menu opened another dialog * on top. * * at this point the EDT is still blocked, so we repaint the * screen with our old buffer and request some fresh paint * for the textfield. */ this.invalidate(); } protected boolean keyDown(int keycode, int time) { if (Keypad.key(keycode) == Keypad.KEY_ESCAPE) { this.cancel = true; finishEdit(); return true; } if (Keypad.key(keycode) == Keypad.KEY_ENTER) { /** * single line text field accept input. */ if (this.lightweightEdit.isSingleLineTextArea()) { finishEdit(); return true; } } return super.keyDown(keycode, time); } public void focusChanged(Field field, int type) { if (field == this.nativeEdit && type == FOCUS_LOST) { finishEdit(); } } protected void startEdit() { BlackBerryImplementation.this.app.invokeAndWait(this); } public void run() { UiApplication.getUiApplication().pushScreen(this); } protected void finishEdit() { if (this.finished) { return; } this.finished = true; if (!this.cancel) { Display.getInstance().onEditingComplete(lightweightEdit, nativeEdit.getText()); } if (isTouchDevice()) { UiApplication.getUiApplication().invokeLater(new Runnable() { public void run() { Display.getInstance().setShowVirtualKeyboard(false); } }); } UiApplication.getUiApplication().popScreen(this); } } /** * ####################################################################### * ####################################################################### * * see editString() method */ private class BBEditField extends ActiveAutoTextEditField { private TextArea lightweightEdit = null; private NativeEditCallback callback = new NativeEditCallback(); public BBEditField(TextArea lightweightEdit, long type, int maxSize) { super("", lightweightEdit.getText(), maxSize, Field.EDITABLE | Field.FOCUSABLE | Field.SPELLCHECKABLE | type); this.lightweightEdit = lightweightEdit; } public void paintBackground(net.rim.device.api.ui.Graphics g) { g.setBackgroundColor(lightweightEdit.getSelectedStyle().getBgColor()); g.setColor(lightweightEdit.getSelectedStyle().getBgColor()); super.paintBackground(g); g.setColor(lightweightEdit.getSelectedStyle().getBgColor()); g.fillRect(0, 0, this.getWidth(), this.getHeight()); } public void paint(net.rim.device.api.ui.Graphics g) { g.setBackgroundColor(lightweightEdit.getSelectedStyle().getBgColor()); g.setColor(lightweightEdit.getSelectedStyle().getFgColor()); super.paint(g); } protected boolean keyDown(int keycode, int time) { if (Keypad.key(keycode) == Keypad.KEY_ESCAPE) { finishEdit(true); return true; } if (Keypad.key(keycode) == Keypad.KEY_ENTER) { if (lightweightEdit.isSingleLineTextArea()) { finishEdit(false); return true; } } return super.keyDown(keycode, time); } protected boolean keyUp(int keycode, int time) { boolean b = super.keyUp(keycode, time); callback.onChanged(); return b; } protected boolean navigationMovement(int dx, int dy, int status, int time) { boolean b = super.navigationMovement(dx, dy, status, time); callback.onChanged(); return b; } } /** * ####################################################################### * ####################################################################### * * see editString() method */ private class BBPasswordEditField extends PasswordEditField { private TextArea lightweightEdit = null; private NativeEditCallback callback = new NativeEditCallback(); public BBPasswordEditField(TextArea lightweightEdit, long type, int maxSize) { super("", lightweightEdit.getText(), maxSize, Field.EDITABLE | Field.FOCUSABLE | type); this.lightweightEdit = lightweightEdit; } public void paintBackground(net.rim.device.api.ui.Graphics g) { g.setBackgroundColor(lightweightEdit.getSelectedStyle().getBgColor()); g.setColor(lightweightEdit.getSelectedStyle().getBgColor()); super.paintBackground(g); g.setColor(lightweightEdit.getSelectedStyle().getBgColor()); g.fillRect(0, 0, this.getWidth(), this.getHeight()); } public void paint(net.rim.device.api.ui.Graphics g) { g.setBackgroundColor(lightweightEdit.getSelectedStyle().getBgColor()); g.setColor(lightweightEdit.getSelectedStyle().getFgColor()); super.paint(g); } protected boolean keyDown(int keycode, int time) { if (Keypad.key(keycode) == Keypad.KEY_ESCAPE) { finishEdit(true); return true; } if (Keypad.key(keycode) == Keypad.KEY_ENTER) { if (lightweightEdit.isSingleLineTextArea()) { finishEdit(false); return true; } } return super.keyDown(keycode, time); } protected boolean keyUp(int keycode, int time) { callback.onChanged(); return super.keyUp(keycode, time); } protected boolean navigationMovement(int dx, int dy, int status, int time) { callback.onChanged(); return super.navigationMovement(dx, dy, status, time); } } class NativeEditCallback implements Runnable { private String text; private int cursorLocation; public void onChanged() { if (nativeEdit != null) { text = nativeEdit.getText(); cursorLocation = nativeEdit.getCursorPosition(); Display.getInstance().callSerially(this); } } public void run() { // prevent a race condition by copying the global scope TextArea t = lightweightEdit; if (t != null) { Dimension d = t.getPreferredSize(); t.setText(text); Dimension current = t.getPreferredSize(); Form f = t.getComponentForm(); // allows the lightweight text area to grow to fill up the screen if (d.getHeight() != current.getHeight() || d.getWidth() != current.getWidth()) { f.getComponentForm().revalidate(); } int currentLineLength = 0; int numOfChars = 0; int currentY = 0; while (numOfChars <= cursorLocation && currentY < t.getLines()) { String currentLine = t.getTextAt(currentY); currentLineLength = currentLine.length(); if (numOfChars + currentLineLength < text.length() && (text.charAt(numOfChars + currentLineLength) == '\n' || text.charAt(numOfChars + currentLineLength) == ' ')) { currentLineLength++; } numOfChars += currentLineLength; currentY++; } int cursorY = Math.max(0, currentY - 1); com.sun.lwuit.Font textFont = t.getStyle().getFont(); int rowsGap = t.getRowsGap(); int lineHeight = textFont.getHeight() + rowsGap; t.scrollRectToVisible(t.getScrollX(), cursorY * lineHeight, t.getWidth(), lineHeight, t); } } } /** * This class is here to unify multiple invocations of invoke later */ class InvokeLaterWrapper implements Runnable { public Field fld; public Dimension dim; public boolean val; private int i; public Player v; public InvokeLaterWrapper(int i) { this.i = i; } public void run() { switch (i) { case INVOKE_LATER_confirmControlView: if (app.getActiveScreen() != canvas) { app.pushScreen(canvas); } break; case INVOKE_LATER_finishEdit: finishEdit(val); break; case INVOKE_LATER_initComponent: canvas.add(fld); break; case INVOKE_LATER_deinitialize: canvas.delete(fld); break; case INVOKE_LATER_showNativeScreen: app.pushScreen((Screen) fld); break; case INVOKE_AND_WAIT_calcPreferredSize: dim.setWidth(Math.max(fld.getWidth(), fld.getPreferredWidth())); dim.setHeight(Math.max(fld.getHeight(), fld.getPreferredHeight())); break; case INVOKE_AND_WAIT_setFocus: try { // Not sure why an exception is thrown here during a touch event... if (val) { fld.setFocus(); } else { nullFld.setFocus(); } } catch (Throwable t) { //t.printStackTrace(); } break; case INVOKE_LATER_dirty: if (fld.getScreen() == canvas) { fld.setDirty(true); canvas.updateRIMLayout(); } break; case INVOKE_LATER_startMedia: try { v.start(); } catch (MediaException ex) { ex.printStackTrace(); } break; } } } public void execute(String url) { if(midlet) { try { midletInstance.platformRequest(url); } catch (ConnectionNotFoundException ex) { ex.printStackTrace(); } } else { // For some reason RIM decided to require signing for these API's // if you need this functionality and own a signature add a define to // signed //#ifdef signed //# net.rim.blackberry.api.browser.Browser.getDefaultSession().displayPage(url); //#endif } } public void exitApplication() { if(midlet) { midletInstance.notifyDestroyed(); } else { System.exit(0); } } public String getProperty(String key, String defaultValue) { String val = null; if("OS".equals(key)) { return "RIM"; } if("IMEI".equals(key)) { return GPRSInfo.imeiToString(GPRSInfo.getIMEI()); } //#ifdef touch //# if ("User-Agent".equals(key)) { //# return "Blackberry" + DeviceInfo.getDeviceName() + "/" + DeviceInfo.getPlatformVersion() //# + " Profile/" + System.getProperty("microedition.profiles") //# + " Configuration/" //# + System.getProperty("microedition.configuration") //# + " VendorID/" + Branding.getVendorId(); //# } //#endif if(midletInstance != null) { val = midletInstance.getAppProperty(key); } else { // For some reason RIM decided to require signing for these API's // if you need this functionality and own a signature add a define to // signed //#ifdef signed //# if("MSISDN".equals(key)) { //# return Phone.getDevicePhoneNumber(true); //# } //# //# if(initGetProperty) { //# initGetProperty = false; //# ApplicationDescriptor ad = ApplicationDescriptor.currentApplicationDescriptor(); //# if(ad != null) { //# String moduleName = ad.getModuleName(); //# //# if(moduleName != null) { //# CodeModuleGroup[] allGroups = CodeModuleGroupManager.loadAll(); //# if(allGroups != null) { //# for (int i = 0; i < allGroups.length; i++) { //# if (allGroups[i].containsModule(moduleName)) { //# group = allGroups[i]; //# break; //# } //# } //# } //# } //# } //# } //# if(group != null) { //# val = group.getProperty(key); //# } //#endif } if(val == null) { return defaultValue; } return val; } /** * @inheritDoc */ public void playBuiltinSound(String soundIdentifier) { if(!playUserSound(soundIdentifier)) { // todo... } } /** * @inheritDoc */ protected void playNativeBuiltinSound(Object data) { try { try { Object o = createAudio(new ByteArrayInputStream((byte[]) data), "audio/mpeg", null); playAudio(o); } catch(Exception err) { // some simulators take issue with the audio/mpeg string but the mp3 string // works fine Object o = createAudio(new ByteArrayInputStream((byte[]) data), "audio/mp3", null); playAudio(o); } } catch (IOException ex) { // not likely since the stream is a byte array input stream ex.printStackTrace(); } } /** * @inheritDoc */ public boolean isBuiltinSoundAvailable(String soundIdentifier) { if(soundIdentifier.equals(Display.SOUND_TYPE_ALARM)) { return true; } if(soundIdentifier.equals(Display.SOUND_TYPE_CONFIRMATION)) { return true; } if(soundIdentifier.equals(Display.SOUND_TYPE_ERROR)) { return true; } if(soundIdentifier.equals(Display.SOUND_TYPE_INFO)) { return true; } if(soundIdentifier.equals(Display.SOUND_TYPE_WARNING)) { return true; } return super.isBuiltinSoundAvailable(soundIdentifier); } /** * @inheritDoc */ public Object createAudio(String uri, Runnable onCompletion) throws IOException { return MMAPIPlayer.createAudio(uri, onCompletion); } /** * @inheritDoc */ public Object createAudio(InputStream stream, String mimeType, Runnable onCompletion) throws IOException { return MMAPIPlayer.createAudio(stream, mimeType, onCompletion); } /** * @inheritDoc */ public void cleanupAudio(Object handle) { ((MMAPIPlayer)handle).cleanupAudio(); } /** * @inheritDoc */ public void playAudio(Object handle) { ((MMAPIPlayer)handle).playAudio(); } /** * @inheritDoc */ public void pauseAudio(Object handle) { ((MMAPIPlayer)handle).pauseAudio(); } /** * @inheritDoc */ public int getAudioTime(Object handle) { return ((MMAPIPlayer)handle).getAudioTime(); } /** * @inheritDoc */ public void setAudioTime(Object handle, int time) { ((MMAPIPlayer)handle).setAudioTime(time); } /** * @inheritDoc */ public int getAudioDuration(Object handle) { return ((MMAPIPlayer)handle).getAudioDuration(); } /** * @inheritDoc */ public void setVolume(int vol) { MMAPIPlayer.setVolume(vol); } /** * @inheritDoc */ public int getVolume() { return MMAPIPlayer.getVolume(); } //#ifdef NewOS //# public void copyToClipboard(Object obj) { //# if(obj instanceof String || obj instanceof StringBuffer) { //# net.rim.device.api.system.Clipboard.getClipboard().put(obj); //# super.copyToClipboard(null); //# } else { //# net.rim.device.api.system.Clipboard.getClipboard().put(null); //# super.copyToClipboard(obj); //# } //# } //# //# public Object getPasteDataFromClipboard() { //# Object o = net.rim.device.api.system.Clipboard.getClipboard().get(); //# if(o != null) { //# return o; //# } //# return super.getPasteDataFromClipboard(); //# } //# //# public boolean canForceOrientation() { //# return true; //# } //# //# public void lockOrientation(boolean portrait) { //# net.rim.device.api.ui.UiEngineInstance ue; //# ue = net.rim.device.api.ui.Ui.getUiEngineInstance(); //# if(portrait) { //# ue.setAcceptableDirections(net.rim.device.api.system.Display.DIRECTION_PORTRAIT); //# } else { //# ue.setAcceptableDirections(net.rim.device.api.system.Display.DIRECTION_LANDSCAPE); //# } //# } //#endif //#ifdef NewOSSigned //# public boolean isNativeBrowserComponentSupported() { //# return true; //# } //# //# public PeerComponent createBrowserComponent(Object browserComponent) { //# synchronized(UiApplication.getEventLock()) { //# BrowserField bff = new BrowserField(); //# final BrowserComponent cmp = (BrowserComponent)browserComponent; //# bff.addListener(new BrowserFieldListener() { //# public void documentError(BrowserField browserField, Document document) throws Exception { //# super.documentError(browserField, document); //# cmp.fireWebEvent("onError", new ActionEvent(document)); //# } //# //# public void documentLoaded(BrowserField browserField, Document document) throws Exception { //# super.documentLoaded(browserField, document); //# cmp.fireWebEvent("onLoad", new ActionEvent(document)); //# } //# }); //# return PeerComponent.create(bff); //# } //# } //# //# public void setBrowserProperty(PeerComponent browserPeer, String key, Object value) { //# } //# //# public String getBrowserTitle(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# return ((BrowserField)browserPeer.getNativePeer()).getDocumentTitle(); //# } //# } //# //# public String getBrowserURL(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# return ((BrowserField)browserPeer.getNativePeer()).getDocumentUrl(); //# } //# } //# //# public void setBrowserURL(PeerComponent browserPeer, String url) { //# if(url.startsWith("jar://")) { //# //ApplicationDescriptor ad = ApplicationDescriptor.currentApplicationDescriptor(); //# //url = "cod://" + ad.getModuleName() + url.substring(6); //# //super.setBrowserURL(browserPeer, url); //# //url = "local://" + url.substring(6); //# //# // load from jar:// URL's //# try { //# InputStream i = Display.getInstance().getResourceAsStream(getClass(), url.substring(6)); //# if(i == null) { //# System.out.println("Local resource not found: " + url); //# return; //# } //# byte[] buffer = new byte[4096]; //# ByteArrayOutputStream bo = new ByteArrayOutputStream(); //# int size = i.read(buffer); //# while(size > -1) { //# bo.write(buffer, 0, size); //# size = i.read(buffer); //# } //# i.close(); //# bo.close(); //# String htmlText = new String(bo.toByteArray(), "UTF-8"); //# int pos = url.lastIndexOf('/'); //# if(pos > 6) { //# url = url.substring(6, pos); //# } else { //# url = "/"; //# } //# String baseUrl = "local://" + url; //# setBrowserPage(browserPeer, htmlText, baseUrl); //# return; //# } catch (IOException ex) { //# ex.printStackTrace(); //# } //# return; //# } //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).requestContent(url); //# } //# } //# //# public void browserReload(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).refresh(); //# } //# } //# //# public boolean browserHasBack(PeerComponent browserPeer) { //# return ((BrowserField)browserPeer.getNativePeer()).getHistory().canGoBack(); //# } //# //# public boolean browserHasForward(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# return ((BrowserField)browserPeer.getNativePeer()).getHistory().canGoForward(); //# } //# } //# //# public void browserBack(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).back(); //# } //# } //# //# public void browserForward(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).forward(); //# } //# } //# //# public void browserClearHistory(PeerComponent browserPeer) { //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).getHistory().clearHistory(); //# } //# } //# //# public void setBrowserPage(PeerComponent browserPeer, String html, String baseUrl) { //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).displayContent(html, baseUrl); //# } //# } //# //# public void browserExecute(PeerComponent browserPeer, String javaScript) { //# synchronized(UiApplication.getEventLock()) { //# ((BrowserField)browserPeer.getNativePeer()).executeScript(javaScript); //# } //# } //# //# public void browserExposeInJavaScript(PeerComponent browserPeer, Object o, String name) { //# synchronized(UiApplication.getEventLock()) { //# try { //# ((BrowserField) browserPeer.getNativePeer()).extendScriptEngine(name, (Scriptable) o); //# } catch (Exception ex) { //# ex.printStackTrace(); //# } //# } //# } //#endif private boolean testedNativeTheme; private boolean nativeThemeAvailable; public boolean hasNativeTheme() { if(!testedNativeTheme) { testedNativeTheme = true; try { InputStream is = getResourceAsStream(getClass(), "/blackberryTheme.res"); nativeThemeAvailable = is != null; is.close(); } catch (IOException ex) { ex.printStackTrace(); } } return nativeThemeAvailable; } /** * Installs the native theme, this is only applicable if hasNativeTheme() returned true. Notice that this method * might replace the DefaultLookAndFeel instance and the default transitions. */ public void installNativeTheme() { if(nativeThemeAvailable) { try { InputStream is = getResourceAsStream(getClass(), "/blackberryTheme.res"); Resources r = Resources.open(is); UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0])); is.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }