Archive for Tag "blackberry"

ImagePickerDialog Blackberry

// an image picker dialog, for blackberry JDE
// usage:
// String result = ImagePickerDialog.getInstance().show();

public class ImagePickerDialog extends PopupScreen {
  private static final String FILE_SEPARATOR = System.getProperty("file.separator");
  private static final String PARENT_DIRECTORY = "..";
  private static final String FILE_PROTOCOL = "file://";
  private static ImagePickerDialog instance = null;
  
  private ListField listField;
  private ImageListFieldCallback listFieldCallback;
  private String currentDir = null;
  private String rootDir = null;
  protected volatile boolean keepRunning = true;
  
  private Bitmap folderBitmap = Bitmap.getBitmapResource("folder.png");
  private Bitmap fileBitmap = Bitmap.getBitmapResource("file.png");
  private Bitmap defaultBitmap = Bitmap.getPredefinedBitmap(Bitmap.QUESTION);
  private BitmapField preview = new BitmapField(defaultBitmap);
  
  private String result = null;
  private PreviewWorker previewWorker = null;
  
  class PreviewWorker implements Runnable {
    private Vector queue = new Vector();
    private Bitmap bitmap;
    private volatile Thread thread = null;
    
    public void start() {
      thread = new Thread(this);
      thread.setPriority(Thread.MIN_PRIORITY);
      thread.start();
    }
    
    public void stop() {
      thread = null;
    }
    
    public void preview( String filename ) {
      queue.addElement(filename);
    }
    
    public void run() {
      while (thread != null) {
        if ( queue.isEmpty() ) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          continue;
        }
        
        String selected = (String)queue.elementAt(queue.size()-1);
        if ( selected == null ) {
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            //e.printStackTrace();
          }
          continue;
        }
        
        queue.removeAllElements();
        
        try {
          bitmap = readBitmapFromFile(selected, defaultBitmap.getWidth(), defaultBitmap.getHeight());
        } catch (IOException e) {
          bitmap = defaultBitmap;
        }
        
        UiApplication.getUiApplication().invokeLater(new Runnable() {
          public void run() {
            preview.setBitmap(bitmap);
          }
        });
        
        try {
          Thread.sleep(50);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
  }
  
  private ImagePickerDialog() {
    super(new HorizontalFieldManager(Field.USE_ALL_HEIGHT|Field.USE_ALL_WIDTH|Manager.NO_HORIZONTAL_SCROLL));
    
    rootDir = "file:///" + getCurrentRoot();
    int height = Font.getDefault().getHeight();
    int thumbSize = Math.max(height, 24);
    int ypadding = 2;
    int padding = 2;
    
    previewWorker = new PreviewWorker();
    
    listField = new ListField() {
      protected boolean navigationClick(int status, int time) {
        selectField();
        return super.navigationClick(status, time);
      }

      protected int moveFocus(int amount, int status, int time) {
        int r = super.moveFocus(amount, status, time);
        previewSelected();
        return r;
      }

    };
    listField.setRowHeight(thumbSize+(ypadding*2));
    

    VerticalFieldManager vfm = new VerticalFieldManager( Manager.USE_ALL_HEIGHT|Manager.VERTICAL_SCROLL|Manager.NO_HORIZONTAL_SCROLL) {
      protected void sublayout(int width, int height) {
        Log.info( Display.getWidth() + ", " + getManager().getWidth() + ", " + defaultBitmap.getWidth() );
        
        int w = getManager().getWidth() - ( 20 + defaultBitmap.getWidth() + preview.getMarginLeft() + preview.getMarginRight());
        super.sublayout(w, height);
        setExtent(w, height);
      }
    };
    vfm.add(listField);
    
    add(vfm);
    add(preview);
    preview.setPadding(5, 5, 5, 5);
    
    
    listFieldCallback = new ImageListFieldCallback(listField);
    listFieldCallback.setImageHeight(thumbSize);
    listFieldCallback.setImageWidth(thumbSize);
    listFieldCallback.setPadding(padding);
    listFieldCallback.setYPadding(ypadding);
  }
  
  public static ImagePickerDialog getInstance() {
    if ( instance == null )
      instance = new ImagePickerDialog();
    return instance;
  }
  
  public String show() {
    listFiles( rootDir );
    
    //started
    result = null;
    previewWorker.start();
    
    UiApplication.getUiApplication().pushModalScreen(this);
    
    //dismissed
    previewWorker.stop();

    return result;
  }
  
  protected boolean keyDown(int keycode, int status) {
    if (Keypad.key(keycode) == Keypad.KEY_ESCAPE) {
      result = null;
      if ( currentDir.equals(rootDir) ) {
        close();
      } else {
        int pos = currentDir.lastIndexOf('/', currentDir.length()-2);
        String dir = new String( currentDir.substring(0, pos+1) );
        listFiles( dir );
      }
    }
    return super.keyDown(keycode, status);
  }
  
  protected void previewSelected() {
    int index = listField.getSelectedIndex();
    int size = listField.getSize();
    if ( index >= 0 && index < size ) {
      final String selected = (String)listFieldCallback.get(listField, index);
      if ( selected.endsWith(".gif") || selected.endsWith(".png") || selected.endsWith(".jpg") || selected.endsWith(".bmp") ) {
        previewWorker.preview(selected);
        ImagePickerDialog.this.result = selected;
      } else {
        ImagePickerDialog.this.result = null;
      }
    } else {
      UiApplication.getUiApplication().invokeLater(new Runnable() {
        public void run() {
          preview.setBitmap(defaultBitmap);
        }
      });
    }
  }
  
  protected Thread listThread = null;
  
  protected void listFiles(String dir) {
    keepRunning = false;
    if ( listThread != null ) {
      Log.info( "waiting to stop.." );
      try { listThread.join(); }
      catch(InterruptedException ie) {}
    }
    
    currentDir = dir;
    keepRunning = true;
    
    UiApplication.getUiApplication().invokeLater(new Runnable() {
      public void run() {
        preview.setBitmap(defaultBitmap);
      }
    });
    
    Log.info( "currentDir="+currentDir+", root="+rootDir );
    
    listThread = new Thread() {
      public void run() {
        FileConnection fc = null;
        try {
          fc = (FileConnection)Connector.open(currentDir, Connector.READ);
          if ( fc.exists() ) {
            recurseDirectory( fc );
          }
        } catch(IOException ioe) {
          Log.error(ioe, "listing directory");
        } finally {
          if ( fc != null ) {
            try { fc.close(); }
            catch(Exception ex) {}
          }
        }
      }
    };
    listThread.setPriority(Thread.MIN_PRIORITY);
    listThread.start();
  }
  
  protected void recurseDirectory(FileConnection dir) throws IOException {
    listFieldCallback.clear();
    
    if ( !currentDir.equals(rootDir) ) {
      listFieldCallback.add(folderBitmap, PARENT_DIRECTORY);
    }
    
    SimpleSortingVector sv = new SimpleSortingVector();
    sv.setSortComparator(new Comparator() {
      public int compare(Object arg0, Object arg1) {
        FileItem f1 = (FileItem)arg0;
        FileItem f2 = (FileItem)arg1;
        
        if ( f1.type < f2.type ) {
          return -1;
        } else if ( f1.type > f2.type ) {
          return 1;
        } else if ( f1.timestamp < f2.timestamp ) {
          return 1;
        } else if ( f1.timestamp > f2.timestamp ) {
          return -1;
        } else {
          return f1.name.compareTo(f2.name);
        }
      }
    });
    sv.setSort(false);
    
    Enumeration list = dir.list();
    while (list.hasMoreElements() && keepRunning) {
      String file = (String) list.nextElement();
      String fl = file.toLowerCase();
      if (fl.endsWith(FILE_SEPARATOR) || fl.endsWith(".jpg") || fl.endsWith(".gif") || fl.endsWith(".bmp") || fl.endsWith(".png") ) {
        try {
          StringBuffer filename = new StringBuffer();
          filename.append(FILE_PROTOCOL).append(dir.getPath()).append(dir.getName()).append(file);
          FileItem item = new FileItem(filename.toString());
          sv.addElement(item);
        } catch(Exception ex) {
          //
        }
      }
      
      /*
      if (file.endsWith(FILE_SEPARATOR)) {
        StringBuffer filename = new StringBuffer();
        filename.append(FILE_PROTOCOL).append(dir.getPath()).append(dir.getName()).append(file);
        listFieldCallback.add(folderBitmap, filename.toString());
      } else {
        String fl = file.toLowerCase();
        if ( fl.endsWith(".jpg") || fl.endsWith(".gif") || fl.endsWith(".bmp") || fl.endsWith(".png") ) {
          StringBuffer filename = new StringBuffer();
          filename.append(FILE_PROTOCOL).append(dir.getPath()).append(dir.getName()).append(file);
          listFieldCallback.add(fileBitmap, filename.toString());
        }
      }
      */
    }
    
    sv.reSort();
    Enumeration sorted = sv.elements();
    while( sorted.hasMoreElements() && keepRunning ) {
      FileItem item = (FileItem)sorted.nextElement();
      if ( item.type == 0 ) {
        listFieldCallback.add(folderBitmap, item.name);
      } else {
        listFieldCallback.add(fileBitmap, item.name);
      }
    }
  }
  
  class FileItem {
    public int type;
    public String name;
    public long timestamp;
    
    public FileItem(String name) throws IOException {
      this.name = name;
      if ( name.endsWith(FILE_SEPARATOR) ) {
        type = 0;
      } else {
        type = 1;
        FileConnection fc = null;
        try {
          fc = (FileConnection)Connector.open(name, Connector.READ);
          timestamp = fc.lastModified();
        } finally {
          if (fc != null) fc.close();
        }
      }
    }
  }
  
  protected void selectField() {
    int index = listField.getSelectedIndex();
    int size = listField.getSize();
    if ( index >= 0 && index < size ) {
      String selected = (String)listFieldCallback.get(listField, index);
      if ( selected.endsWith(FILE_SEPARATOR) ) {
        listFiles( selected );
      } else if ( selected.equals(PARENT_DIRECTORY) ) {
        int pos = currentDir.lastIndexOf('/', currentDir.length()-2);
        String dir = new String( currentDir.substring(0, pos+1) );
        listFiles( dir );
      } else {
        close();
      }
    }
  }
    
  public static String getCurrentRoot() {
    Enumeration rootEnum = FileSystemRegistry.listRoots();
    String currentRoot = null;
    while (rootEnum.hasMoreElements()) {
      String root = (String) rootEnum.nextElement();
      if (root.endsWith("CFCard/") || root.endsWith("SDCard/") || root.endsWith("MemoryStick/")) {
        currentRoot = root;
        break;
      }
    }
    return currentRoot;
  }
    
  public static Bitmap readBitmapFromFile(String filename, int width, int height) throws IOException {
    Bitmap bitmap = null;
    byte[] data;
    if (filename != null) {
      FileConnection file = (FileConnection) Connector.open(filename, Connector.READ);
      int fileSize = (int) file.fileSize();
      if (fileSize > 0) {
        data = new byte[fileSize];
        InputStream input = file.openInputStream();
        input.read(data);
        input.close();
        
        EncodedImage image = EncodedImage.createEncodedImage(data, 0, data.length);
        EncodedImage result = resizeImage(image, width, height);
        bitmap = result.getBitmap();
      }
      file.close();
    }
    return bitmap;
  }
    
  public static EncodedImage resizeImage(EncodedImage image, int width, int height) {
    if (image == null || (image.getWidth() == width && image.getHeight() == height)) {
      return image;
      }
    
      double scaleHeight, scaleWidth;

      if (image.getWidth() > width && image.getHeight() > height) {  //actual image is bigger than scale size
        if (image.getWidth() > image.getHeight()) {  //actual image width is more that height then scale with width
          scaleWidth = width;
          scaleHeight = (double)width / image.getWidth() * image.getHeight();
        } else { //scale with height
          scaleHeight = height;
          scaleWidth = (double)height / image.getHeight() * image.getWidth();
        }
      } else if (width < image.getWidth()) { //scale with scale width or height
        scaleWidth = width;
        scaleHeight = (double)width / image.getWidth() * image.getHeight();
      } else {
        scaleHeight = height;
        scaleWidth = (double)height / image.getHeight() * image.getWidth();
      }
      int w = Fixed32.div(Fixed32.toFP(image.getWidth()), Fixed32.toFP((int)scaleWidth));
      int h = Fixed32.div(Fixed32.toFP(image.getHeight()), Fixed32.toFP((int)scaleHeight));
      return image.scaleImage32(w, h);
  }

}

//ListFieldCallback with Images


import java.io.UnsupportedEncodingException;
import java.util.Vector;

import orca.bb.log.Log;
import orca.bb.text.TextUtil;

import net.rim.device.api.system.Application;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;

public class ImageListFieldCallback implements ListFieldCallback {
  private Vector listitems = new Vector();
  private Vector thumbnail = new Vector();
  private ListField list;
  
  private int imageWidth = 50;
  private int imageHeight = 50;
  private int padding = 2;
  private int ypadding = 2;

  public ImageListFieldCallback(ListField list) {
    this.list = list;
    this.list.setCallback(this);
  }
  
  public void clear() {
    listitems.removeAllElements();
    thumbnail.removeAllElements();
    synchronized(Application.getEventLock()) {
      list.setSize(0);
    }
  }

  public int add( Bitmap bitmap, Object text ) {
    Log.info( "listitems.add: text="+text );
    listitems.addElement(text);
    thumbnail.addElement(bitmap);
    synchronized(Application.getEventLock()) {
      int size = listitems.size()-1;
      list.insert(listitems.size()-1);
      return size;
    }
  }
  
  public void insert( int index, Bitmap bitmap, Object text ) {
    Log.info( "listitems.insert: index="+index+",text="+text );
    listitems.insertElementAt(text, index);
    thumbnail.insertElementAt(bitmap, index);
    synchronized(Application.getEventLock()) {
      list.insert(index);
    }
  }
  
  public void delete( Object o ) {
    int index = listitems.indexOf( o );
    Log.info("listitems.delete, index="+index+",object="+o);
    if ( index >= 0 ) {
      delete(index);
    }
  }
  
  public void delete( int index ) {
    listitems.removeElementAt(index);
    thumbnail.removeElementAt(index);
    synchronized(Application.getEventLock()) {
      list.delete(index);
    }
  }
  
  public void update( int index, Bitmap bitmap, Object text ) {
    listitems.setElementAt(text, index);
    thumbnail.setElementAt(bitmap, index);
    synchronized(Application.getEventLock()) {
      list.invalidate(index);
    }
  }
  
  public int size() {
    return thumbnail.size();
  }

  public void drawListRow(ListField listField, Graphics g, int index, int y, int w) {
     Object object = listitems.elementAt(index);
     Bitmap thumb = (Bitmap) thumbnail.elementAt(index); 
     
     String filepath = object.toString();
     String text = filepath;
     int pos = filepath.lastIndexOf('/');
     
     if ( filepath.endsWith("/") ) {
       pos = filepath.lastIndexOf('/', pos-1);
     }
     
     try {
      text = TextUtil.urlDecode( new String( filepath.substring(pos+1) ), "UTF-8" );
     } catch (UnsupportedEncodingException e) {
      //Log.error("");
     }
     
     int padding = getPadding();
     int ypadding = getYPadding();
     int imageWidth = getImageWidth();

     g.drawText(text, imageWidth + padding, y+ypadding, DrawStyle.LEADING | DrawStyle.ELLIPSIS, w - imageWidth - padding);
     g.drawBitmap(0, y+ypadding, thumb.getWidth(), thumb.getHeight(), thumb, 0, 0);
     
  }

  public Object get(ListField listField, int index) {
    return listitems.elementAt(index);
  }

  public int getPreferredWidth(ListField listField) {
    return listField.getPreferredWidth();
  }

  public int indexOfList(ListField listField, String prefix, int start) {
    return -1;
  }

  public int getImageWidth() {
    return imageWidth;
  }

  public void setImageWidth(int imageWidth) {
    this.imageWidth = imageWidth;
  }

  public int getImageHeight() {
    return imageHeight;
  }

  public void setImageHeight(int imageHeight) {
    this.imageHeight = imageHeight;
  }

  public int getPadding() {
    return padding;
  }

  public void setPadding(int padding) {
    this.padding = padding;
  }
  
  public int getYPadding() {
    return ypadding;
  }

  public void setYPadding(int padding) {
    this.ypadding = padding;
  }
}

Blackberry JDE Animated GIF

// display animated gif on blackberry device

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.system.GIFEncodedImage;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.BitmapField;

/**
 * A BitmapField that displays an animated GIF. This Class extends BitmapField
 * to create a new class called AnimatedGIFField. This class can be added to a
 * Screen and accepts a GIFEncodedImage, which it will animate.
 */
public class AnimatedGIFField extends BitmapField {
    private GIFEncodedImage _image; // The image to draw.
    private int _currentFrame; // The current frame in the animation sequence.
    private int _width; // The width of the image (background frame).
    private int _height; // The height of the image (background frame).
    private AnimatorThread _animatorThread;

    public AnimatedGIFField(GIFEncodedImage image) {
        this(image, 0);
    }

    public AnimatedGIFField(GIFEncodedImage image, long style) {
        // Call super to setup the field with the specified style.
        // The image is passed in as well for the field to
        // configure its required size.
        super(image.getBitmap(), style);

        // Store the image and it's dimensions.
        _image = image;
        _width = image.getWidth();
        _height = image.getHeight();

        // Start the animation thread.
        _animatorThread = new AnimatorThread(this);
        _animatorThread.start();
    }

    protected void paint(Graphics graphics) {
        // Call super.paint. This will draw the first background
        // frame and handle any required focus drawing.
        super.paint(graphics);

        // Don't redraw the background if this is the first frame.
        if (_currentFrame != 0) {
            // Draw the animation frame.
            graphics
                    .drawImage(_image.getFrameLeft(_currentFrame), _image
                            .getFrameTop(_currentFrame), _image
                            .getFrameWidth(_currentFrame), _image
                            .getFrameHeight(_currentFrame), _image,
                            _currentFrame, 0, 0);
        }
    }

    // Stop the animation thread when the screen the field is on is
    // popped off of the display stack.
    protected void onUndisplay() {
        _animatorThread.stop();
        super.onUndisplay();
    }

    // A thread to handle the animation.
    private class AnimatorThread extends Thread {
        private AnimatedGIFField _theField;
        private boolean _keepGoing = true;
        private int _totalFrames; // The total number of frames in the image.
        private int _loopCount; // The number of times the animation has looped
                                // (completed).
        private int _totalLoops; // The number of times the animation should
                                    // loop (set in the image).

        public AnimatorThread(AnimatedGIFField theField) {
            _theField = theField;
            _totalFrames = _image.getFrameCount();
            _totalLoops = _image.getIterations();

        }

        public synchronized void stop() {
            _keepGoing = false;
        }

        public void run() {
            while (_keepGoing) {
                // Invalidate the field so that it is redrawn.
                UiApplication.getUiApplication().invokeAndWait(new Runnable() {
                    public void run() {
                        _theField.invalidate();
                    }
                });

                try {
                    // Sleep for the current frame delay before
                    // the next frame is drawn.
                    sleep(_image.getFrameDelay(_currentFrame) * 10);
                } catch (InterruptedException iex) {
                } // Couldn't sleep.

                // Increment the frame.
                ++_currentFrame;

                if (_currentFrame == _totalFrames) {
                    // Reset back to frame 0 if we have reached the end.
                    _currentFrame = 0;

                    ++_loopCount;

                    // Check if the animation should continue.
                    if (_loopCount == _totalLoops) {
                        _keepGoing = false;
                    }
                }
            }
        }
    }

    public int getAnimatedImageWidth() {
        return _width;
    }

    public int getAnimatedImageHeight() {
        return _height;
    }
}