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;
}
}