Category Archives: code

Using the graphics class to draw a thick curve in BlackBerry applications

The Graphics class is the heart of the paint() method for BlackBerry Java applications. However, occasionally a common action such as drawing a thick curved line, is more complicated then it should be. If having a thickness of a single pixel is acceptable, you can use the following code.


byte[] pathPoints ={
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT
};
int[] xPts = {17,17,17,27,48};
int[] yPts = {39,24,14,14,14};
g.drawOutlinedPath(xPts,yPts,pathPoints,null,false);

However, trying to give this line any thickness complicates things a lot. Using the normal work around of placing a number of lines next to each other works great for the straight segments, but falls apart on the curve, where the layout is less predictable. As a result, the best way to draw a thick curve is to use the drawFilledPath() method, and essentially draw and fill a shape.

The following code draws the same line/curve/line segment as the code above, but gives it a thickness of five pixels.


byte[] pathPoints =
{
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_QUADRATIC_BEZIER_CONTROL_POINT,
Graphics.CURVEDPATH_END_POINT,
Graphics.CURVEDPATH_END_POINT
};
int[] xPts = {17,17,17,27,48,42,27,22,22,22};
int[] yPts = {39,24,14,14,14,19,19,19,24,39};
g.drawFilledPath(xPts,yPts,pathPoints,null);

Text input modal dialog for BlackBerry PlayBook

The BlackBerry PlayBook has a BaseDialog class for generating modal dialogs, but does not allow developers to extend it for their own purposes. This leaves the PlayBook without a modal dialog for asking a question and receiving a response. As such I wrote one myself below, that as a parameter on the constructor, takes the name of the function responsible for removing this child, and working with the result.

import qnx.ui.core.UIComponent
import flash.display.Graphics
import flash.events.MouseEvent
import flash.events.Event
import flash.text.TextField
import flash.text.TextFormat
import flash.text.TextFormatAlign
import qnx.ui.text.TextInput
import qnx.ui.buttons.LabelButton

public class InputDialog extends UIComponent
{
public var inputText:TextInput = new TextInput();

public function InputDialog(exitFunction:Function)
{
width = 1024
height = 600

var myFormat:TextFormat = new TextFormat()
myFormat.color = 0x000000
myFormat.size = 32
myFormat.align = "center"

var titleText:TextField = new TextField()
titleText.text = "Title"
titleText.width = 500
titleText.x = 260
titleText.y = 200
titleText.setTextFormat(myFormat)
addChild(titleText)

myFormat.size = 22
var instText:TextField = new TextField()
instText.text = "instructions"
instText.width = titleText.width
instText.x = titleText.x
instText.y = 245
instText.setTextFormat(myFormat)
addChild(instText)

inputText.width = 240
inputText.x = 392
inputText.y = 277
inputText.height = 40
inputText.prompt = "Prompt Text"
addChild(inputText)

var doneButton:LabelButton = new LabelButton()
doneButton.label = "Done"
doneButton.x = inputText.x
doneButton.y = 330
doneButton.width = 240
doneButton.height = 45
doneButton.addEventListener(MouseEvent.CLICK,exitFunction)
addChild(doneButton)
}

override protected function draw():void
{
var g:Graphics = graphics;
g.clear();
g.beginFill(0xCCCCCC,.5);
g.drawRect(0,0,1024,600);
g.endFill();
g.beginFill(0xDDDDDD,1.0);
g.drawRoundRect(262,180,500,270,10);
g.endFill();
}
}

This code was earlier posted on the Developer Forums. It should be noted, that this approach has a slightly different look then the native modal dialogs, and unlike the native dialogs, will not prevent the application from being closed or minimized.

Simpler Universal Search Demo

RIM has often made their BlackBerry sample code too complicated, and their Unified Search Demo is another such case. Implementing universal search on BlackBerry is complicated enough, and having a demo that doesn’t bring out the basics doesn’t help as much as it should. Furthermore in this case the demo is actually wrong, with two distinct issues causing the demo application to not work.

The default demo includes unnecessary GUI components, a few classes for importing data from files, and optimization tricks that obfuscate the fundamentals of the code. In response I have simplified the demo to an extreme. In the simplified demo the full GUI is removed, and even good ideas like checking for nulls, and catching exceptions is done away with. Fundamentally it highlights the process of adding Universal Search to your BlackBerry application, and does absolutely nothing else. Download the simplified source code from the link below.

Transitioning from Java to ActionScript and the BlackBerry PlayBook

As I noted earlier this week, Java is looking to be a second class language on the BlackBerry PlayBook, so most developers are going to be programing for it in ActionScript rather than in Java. This will take some adjustment, but ActionScript is not all that different. In addition to the webcasts that RIM has put together on the PlayBook, an older ActionScript for Java Developers webcast on the adobe website may be useful as well. In addition, here are a few things that have thrown me off a bit so far.

  • draw() instead of invalidate(): When updating a GUI component you call draw() where you would typically use invalidate() in Java. This is actually a bit different because the draw() method is more equivalent to Java’s paint(Graphics g) method. However, as opposed to Java where you can’t really call the paint method directly, ActionScript allows you to directly call draw() in order to refresh your components.
  • Access object variables instead of get and set methods: I’ve always been a fan of using public or protected variables instead of creating get() and set() methods for internal variables. ActionScript embraces this approach, although a little magic can be used to create get() and set() type behavior. This is even used for the default components, which can take a little getting used to.
  • Reuse variables instead of locally scoping them: Unlike Java and C#, variables are not scoped locally. So for example whenever you use for(int i=0;i<10;i++) to loop through your array in Java, in ActionScript you would use for(var i:int=0;i<10;i++) the first time it appears in the method, and then reuse the variable in the form of for(i=0;i<10;i++) for every loop after that.

Your BlackBerry Apps will not be on the PlayBook

The upcoming BlackBerry PlayBook has an operating system that is radically different from the current BlackBerry Platform. Quite simply there is not going to be any support for current BlackBerry Applications to run on the PlayBook, despite RIM’s reluctance to come out and admit it.

The BlackBerry PlayBook will support 4 main SDK’s. In order of their importance to the platform they are, Flex (Adobe Air), WebWorks (javaScript/HTML/CSS), native (C/C++), and Java. The Flex SDK is already launched, and the WebWorks will be out soon (and is mostly just an extension of WebKit). However support for the native SDK, and the Java SDK is significantly behind, with RIM unable to even confirm that they will be released before the PlayBook is available in stores. Therefore the basis of most PlayBook applications will be in Flex rather then the Java that currently runs all BlackBerry applications.

Furthermore even when the Java SDK is available on the PlayBook, most BlackBerry applications will need significant porting to bring them over to the new platform. It is possible that the PlayBook will support something closer to desktop Java, then the very special blend of J2ME that BlackBerry Java applications currently run. Even if not, in the Q and A of the last PlayBook development webcast it was revealed that the PlayBook will not have any equivalent of the current BlackBerry menu system, which will result in the underlying java being different, and the fundamental UI of many applications will need to be redesigned.

In the webcast Java developers were encouraged to wait out for the release of the Java SDK, rather then to start learning Adobe Air. However, that does not look like that option is getting the support that it needs from RIM to be viable. The fact is that the future of BlackBerry PlayBook applications is strictly in Flex and WebWorks regardless of if developers like it or not.

Right Justifying the time in a StandardTitleBar

From the start I’ve been placing the time in the title bar for most applications. This is because many people also use their phones as their primary time keeping device, and having the current time always on the screen makes this far more convenient. The code to do this has become much more optimized over time, but has remained being based upon placing a custom LabelField to the MainScreen setTitle() method.

However, with the release of OS6 the StandardTitleBar was added along with the Screen’s setTitleBar() method. This method is completely unrelated from MainScreen.setTitle(). In fact you can use both setTitle() and setTitleBar() on the same MainScreen without conflict (although it looks really bad). In addition to a title and the time the StandardTitleBar can also accommodate additional elements such as an icon, notifications, and signal information. The above image shows the StandardTitleBar with a title, the time, and signal information on the achievement screen of Liar’s Dice.

By default the time is actually left justified right after the title, while the signal indicators are placed on the right edge. The goal was instead to move the time to the right like I have been doing with the setTitle() method. Fortunately due to the way that the title gets truncated, a simple way to do this is to just pad out the title with enough spaces. This is not the prettiest solution but it gets the job done, as seen in the second image which shows the final version of the achievement screen in Liar’s Dice.

Screen s = new Screen();
StandardTitleBar titleBar = new StandardTitleBar();
titleBar.addTitle("Liar's Dice                  ");
titleBar.addClock();
titleBar.addSignalIndicator();
s.setTitleBar(titleBar);

Simple Sample Code for the ActivityIndicatorView

As part of BlackBerry operating system 6.0 RIM has added the net.rim.device.api.ui.component.progressindicator module to help with things such as displaying progress and activity indicators. Progress indicators are used to show how far along a task is when the length of the task is known (ie. 5 of 7 done; or 35% complete), while activity indicators are used when the length of time is unknown (typically displayed as a pulse or a spinning object). An activity indicator as shown below is used in version 2.0 of the Hockey Scores application while the app is waiting for the scores to initially download.

The main complication in implementing this feature was that the sample code for the feature consists of 4 java files and over 800 lines of code. Fortunately actually using this feature can be much simpler, and in fact can be simplified down to only 8 lines of code.

Screen s = new Screen();
ActivityIndicatorView view = new ActivityIndicatorView(Field.FIELD_HCENTER);
Bitmap spinImage = Bitmap.getBitmapResource("spinner.png");
view.createActivityImageField(spinImage,6,0);
LabelField label = new LabelField("Loading Hockey...");
s.add(label);
s.add(view);
pushScreen(s);

Granted this doesn’t make use of all the features that the ActivityIndicatorView can make use of. However, as soon as the data is loaded there is no need to keep the ActivityIndicatorView around anyways as the screen replaces it with real data that we were waiting for anyhow.

The limitations of the SpinBoxField

BlackBerry operating system 5.0 added the new SpinBoxField ui component. This is a slick looking and useful graphical element that also forms the basis of the DateTimePicker. An example of the DateTimePicker as used in the Twinkle application is pictured.

However the SpinBoxField has some major limitations. Unlike the ObjectChoiceField the SpinBoxField does not display over the other elements and therefore requires large buffers above and below it in order to give its intended look. As a result it can only really be used on a very sparsely populated form, or within its own popup screen, which the documentation actually suggests. This severely limits the usefulness of the object and prevents designs from using what would otherwise be a fun and good looking element.