Difference between revisions of "Teams Winter 2011/team4/project"

From CDOT Wiki
Jump to: navigation, search
(Drawing Application)
(Drawing Application)
 
Line 7: Line 7:
 
[[File:T4_1.png]]
 
[[File:T4_1.png]]
 
*Set the title of the project
 
*Set the title of the project
[[File:T4_3.png]]
+
[[File:T4p1.png]]
 
===Add Elements on Main Screen===
 
===Add Elements on Main Screen===
 
*Place a applications icon into ''res->image''
 
*Place a applications icon into ''res->image''
 
*Open ''BlackBerry_App_Descriptor''
 
*Open ''BlackBerry_App_Descriptor''
 
*Select the icon, click the ''Add'' button
 
*Select the icon, click the ''Add'' button
[[File:T4_2.png]]
+
[[File:T4p2.png]]
 
===Define the Application===
 
===Define the Application===
 
*Create a class called Menu.  This will provide the user with an interface to navigate between screens.
 
*Create a class called Menu.  This will provide the user with an interface to navigate between screens.

Latest revision as of 18:06, 10 April 2011

Drawing Application

Create BlackBerry Project

  • Download and install BlackBerry Java Plug-in for Eclipse
  • Repeat the above for BlackBerry Torch 9800 simulator
  • Launch Eclipse
  • Create new BlackBerry Project: File->New->BlackBerry Project

T4 1.png

  • Set the title of the project

T4p1.png

Add Elements on Main Screen

  • Place a applications icon into res->image
  • Open BlackBerry_App_Descriptor
  • Select the icon, click the Add button

T4p2.png

Define the Application

  • Create a class called Menu. This will provide the user with an interface to navigate between screens.
public class Menu extends UiApplication {
...
}
  • This allows the user to view Screen 1(our start screen) and then ultimately begin drawing on Screen2 (drawing screen).
  • It allows us to push screens onto the stack in order get them to be displayed.
  • The code to implement the Menu class is as follows:
// Push a screen onto the UI stack for rendering.
ButtonField start = new ButtonField( "Start", ButtonField.CONSUME_CLICK | ButtonField.FIELD_HCENTER);
ButtonField about = new ButtonField( "About", ButtonField.CONSUME_CLICK | ButtonField.FIELD_HCENTER);
HorizontalFieldManager horizontalFieldManager = getFieldManager();
VerticalFieldManager innerManager = new VerticalFieldManager(HorizontalFieldManager.USE_ALL_WIDTH | HorizontalFieldManager.USE_ALL_HEIGHT);
screen.add(horizontalFieldManager);

horizontalFieldManager.add( innerManager );
innerManager.add(start);
innerManager.add(about);
innerManager.setPadding((Display.getHeight()/2)-30, 0, 0, 0);
       
start.setChangeListener( new FieldChangeListener() {
     public void fieldChanged( Field arg0, int arg1 ) {
           pushScreen(new Screen2());
     }
} );
pushScreen( screen);
  • Next we will be implementing Screen1 which will provide the user with a nice background image, as well as two buttons (one to view the about information, and one to begin drawing).
  • The code is as follows:
public class Screen1 extends MainScreen {
    public Screen1() {
        setTitle( "Drawsy" );
    }
    public void close(){
        super.close();
    }
}
  • The 3rd class is Screen2, which does the bulk of the work in our application.
  • Upon instantiation, numerous managers are created for various different tasks.
  • GridFieldManagers are used to align data neatly and quickly (used for the menu at the bottom of the screen).
  • AbsoluteFieldManagers enable us to draw bitmaps at a specified x and y coordinate on the screen, something other FieldManagers are unable to perform.
public Screen2() {
    //Define private attributes
    screen = new AbsoluteFieldManager();
    bitmap = Bitmap.getBitmapResource("icon.png");
    screenHolder = new AbsoluteFieldManager();
    tempScreenHolder = null;
    grid = new GridFieldManager(1,4,0);
    colorGrid = new GridFieldManager(8,6,0);
    bmf2 = null;
    alphaSwitch = draw = added = false;
    tbX = tbY = currentColour = width = height = 0;
    counter = 4;
    displayHeight = Display.getHeight();
    displayWidth = Display.getWidth();
    //Startup code
    Border border = BorderFactory.createSimpleBorder(new XYEdges(6, 6, 6, 6));
    setColorGrid(colorGrid);
    screenHolder.setMargin(0, 0, 0, 0);
    grid.setBorder(border);
    grid.setBackground(BackgroundFactory.createSolidBackground(Color.GRAY));
    grid.add(new NullField());
    grid.getFieldAtIndex(0).setPadding(bitmap.getHeight()-10, bitmap.getWidth()-10, 0, 0);
    grid.getFieldAtIndex(0).setBorder(BorderFactory.createSimpleBorder(new XYEdges(2, 2, 2, 2)));
    grid.getFieldAtIndex(0).setBackground(BackgroundFactory.createSolidBackground(Color.GREEN));
    grid.add(new BitmapField(Bitmap.getBitmapResource("paint.png")));
    grid.add(new BitmapField(Bitmap.getBitmapResource("clear.png")));
    grid.add(new BitmapField(Bitmap.getBitmapResource("circle.png")));
    this.setStatus(grid);
    Bitmap bitmap2 = Bitmap.getBitmapResource("square.png");
    width = bitmap2.getWidth()/20;
    height = bitmap2.getHeight()/20;
    this.add(screen);
   
    int columnWidth = (displayWidth / 4) -
    (grid.getColumnPadding()+(grid.getBorder().getLeft())/2);
    for(int i = 0; i < 4; i++) {
        grid.setColumnProperty(i, GridFieldManager.FIXED_SIZE, columnWidth);
    }
}
  • All menu interaction is done through screen positions which we figure out using some math depending on the devices screen width and height (all of which are available to developers).
  • We create the color screen by creating another GridFieldManager and setting each square to a different hex value to acheive the look and amount of colors we wanted. Example code below:
private final int [] colours = {
    0x000000,0x000033,0x000066,0x000099,0x0000CC,0x0000FF,
    0x003300,0x003333,0x003366,0x003399,0x0033CC,0x0033FF,
    0x00FF00,0x00FF33,0x00FF66,0x00FF99,0x00FFCC,0x00FFFF,
    0x660000,0x660033,0x660066,0x660099,0x6600CC,0x6600FF,
    0x666600,0x666633,0x666666,0x666699,0x6666CC,0x6666FF,
    0xFF0000,0xFF0033,0xFF0066,0xFF0099,0xFF00CC,0xFF00FF,
    0xFF9900,0xFF9933,0xFF9966,0xFF9999,0xFF99CC,0xFF99FF,
    0xFFFF00,0xFFFF33,0xFFFF66,0xFFFF99,0xFFFFCC,0xFFFFFF
};
public void setColorGrid(GridFieldManager cg){
    int i, h,w, rows = 10, cols = 6, rh = 3, rw = 2;
    h = displayHeight;
    w = displayWidth;
    cg.setEditable(true);
    for (i = 0; i < colours.length; i++){
        cg.add(new ButtonField( "", ButtonField.CONSUME_CLICK | ButtonField.FIELD_HCENTER));
        cg.getFieldAtIndex(i).setPadding(h/(rows*rh), w/(cols*rw), h/(rows*rh), w/(cols*rw));
        cg.getFieldAtIndex(i).setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
        cg.getFieldAtIndex(i).setBackground(BackgroundFactory.createSolidBackground(colours[i]));
        cg.setColumnPadding(0);
        cg.setRowPadding(0);
    }
}
  • The screen is saved between color choices by saving the manager in a temp variable, deleting it from the screen, then adding the gridFieldManager holding the color choices, waiting for user interaction, then deleting and re-adding the drawing screen.
  • Trackball event:
int top = 0, bottom = (displayHeight-(grid.getHeight()-(bitmap.getHeight()+12)))/9,
left = 0, right = displayWidth/6;

if(dx > 0)
    tbX += dx*10;
else
    tbX += dx*10;
if(dy > 0)
    tbY += dy*10;
else
    tbY += dy*10;

if(added){
    for(int i = 0;i < colours.length;i++){
        if(tbX > left && tbX < right && tbY > top && tbY < bottom){
            grid.getFieldAtIndex(0).setBackground(BackgroundFactory.createSolidBackground(colours[i]));
            currentColour = colours[i];
        }
        if((i+1)%6 == 0){
            top = bottom;
            bottom +=(displayHeight-(grid.getHeight()-(bitmap.getHeight()+12)))/9;
            left = 0;
            right = displayWidth/6;
        }
        else{
            left = right;
            right += displayWidth/6;
        }
       
    }
}

Bitmap bm = Bitmap.getBitmapResource("square.png");
BitmapField bmf = new BitmapField(bm){
    protected void paint(Graphics g){
    }
};
doMenuEvent(menuEvent(tbX, tbY));
bmf.setPadding(0, 0, height, width);
if(draw && !added){
    drawsy(bmf, tbX, tbY);
}
else{
    if(bmf2 != null){
        screen.delete(bmf2);
        drawsy(bmf, tbX, tbY);
        bmf2 = bmf;
    }
    else{
        drawsy(bmf, tbX, tbY);
        bmf2 = bmf;
    }
}
return true;
  • Touch event:
final int touchX =  message.getX(1);
final int touchY =  message.getY(1);
int top = 0, bottom = (displayHeight-(grid.getHeight()-(bitmap.getHeight()+12)))/9,
left = 0, right = displayWidth/6;

if(added){
    for(int i = 0;i < colours.length;i++){
        if(touchX > left && touchX < right && touchY > top && touchY < bottom){
            grid.getFieldAtIndex(0).setBackground(BackgroundFactory.createSolidBackground(colours[i]));
            currentColour = colours[i];
        }
        if((i+1)%6 == 0){
            top = bottom;
            bottom +=(displayHeight-(grid.getHeight()-(bitmap.getHeight()+12)))/9;
            left = 0;
            right = displayWidth/6;
        }
        else{
            left = right;
            right += displayWidth/6;
        }
       
    }
}

Bitmap bm = Bitmap.getBitmapResource("square.png");
BitmapField bmf = new BitmapField(bm){
    protected void paint(Graphics g){
    }
};
doMenuEvent(menuEvent(touchX, touchY));

if(!added){
    bmf.setPadding(0, 0, height, width);
    drawsy(bmf, touchX, touchY);

}
return true;
  • Clearing the screen is simply deleting all the fields in the manager
  • Resizing the brush is done by simply dividing our original bitmap size(or multiplying).
  • Setting the brush to a marker (translucent colors) or paintbrush was done with a simple global flag checking if it was true or false.
  • Usage
doMenuEvent(menuEvent(touchX, touchY));
  • MenuEvent
private int menuEvent(int x, int y){
    int rc = -1;
    for(int i = 0;i < 4; i++){
        if( x > grid.getFieldAtIndex(i).getContentLeft() &&
            x < (grid.getFieldAtIndex(i).getContentLeft() + bitmap.getWidth()) &&
            y > (displayHeight -(grid.getFieldAtIndex(0).getContentTop())) &&
            y < (displayHeight)){
            rc = i;
            break;
        }
    }
    return rc;
}
  • doMenuEvent
private boolean doMenuEvent(int n){
    boolean rc = false;
    if(n == 0){
        rc = true;
        if(!added){
            tempScreenHolder = screen;
            super.delete(screen);
            screenHolder.insert(colorGrid, 0);
            super.insert(screenHolder, 0);
            added = !added;
        }
        else{
            screenHolder.delete(colorGrid);
            super.delete(screenHolder);
            super.insert(tempScreenHolder, 0);
            added = !added;
        }
    }
    else if(n == 1){
        rc = true;
        alphaSwitch = !alphaSwitch;
        grid.delete(0, 1);
        if(alphaSwitch)
            grid.insert(new BitmapField(Bitmap.getBitmapResource("marker.png")),1);
        else
            grid.insert(new BitmapField(Bitmap.getBitmapResource("paint.png")),1);
       
        int columnWidth = (displayWidth / 4) -
        (grid.getColumnPadding()+(grid.getBorder().getLeft())/2);
        for(int j = 0; j < 4; j++) {
            grid.setColumnProperty(j, GridFieldManager.FIXED_SIZE, columnWidth);
        }
    }
    else if(n == 2){
        rc = true;
        screen.deleteAll();
    }
    else if(n == 3){
        rc = true;
        Bitmap bm = Bitmap.getBitmapResource("square.png");
        if(counter > 2){   
            height = bm.getHeight();
            width = bm.getWidth();
            counter--;
        }
        else if(counter > 0){
            height = bm.getHeight()/2;
            width = bm.getWidth()/2;
            counter--;
        }
        else{
            counter = 4;
            height = bm.getHeight()/12;
            width = bm.getWidth()/12;
        }
    }
    return rc;
}
  • Drawing was done in an odd way. The simplest solution we came up with, was to use a square bitmap and recolor its background if any different colors were chosen, and resized accordingly. This worked well for the most part, tho we do run into some performance issues if there are too many bitmaps on the screen at once
private void drawsy(BitmapField bmf, int x, int y){
    if(alphaSwitch)
        bmf.setBackground(BackgroundFactory.createSolidTransparentBackground(currentColour == 0 ? Color.GREEN : currentColour, 50));
    else
        bmf.setBackground(grid.getFieldAtIndex(0).getBackground());
    screen.add(bmf, x-(bmf.getBitmapWidth()/2), y-(bmf.getBitmapHeight()/2));
}
  • The program works with both touch events and scroll wheel events, tho scroll wheel events are still buggy.

Using the program

  • Our program, dubbed Drawsy, allows the user to create works of art on most blackberrys (Above version 5.0.0)
  • First select start to begin drawing

Bbprj1.png

  • You are then provided with a blank canvas and some options to work with

Bbprj2.png

  • You can change the color of your brush

Bbprj3.png

  • You can change the size of a brush

Bbprj4.png

  • You can clear the screen

Bbprj5.png

  • You can switch between a marker and a paintbrush to achieve translucent colors.

Bbprj6.png

  • This being said, our program provides the user with an open ended experience which is only limited by their imagination

Bbprj7.png

  • Enjoy!

Demonstration Video

http://www.youtube.com/watch?v=YH7tTBwM1fE