BlackBerry menu ordinals and priorities – Part 2: System menu items

Part 1 explained basically how BlackBerry menus are ordered. In part 2 we’ll look at where system menu items (such as Close, Copy and Paste) fit, and how to work with them.

The interesting stuff

Built-in menu items

Built in menu items all have priorities and ordinals too. We can use the following bit of code (with the right kinds of controls on screen) to get the values:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     super.makeMenu(menu, instance);
  3.     for(int i = 0; i < menu.getSize(); i++) {
  4.         MenuItem menuItem = menu.getItem(i);
  5.         System.out.println(“Name: “ + menuItem.toString() + ” Ordinal: “ + menuItem.getOrdinal() + ” Priority: “ + menuItem.getPriority());
  6.     }
  7.        }

So we get the following values:

Menu Item Ordinal Priority Id
Select 196720 500 7
Copy 196672 200 3
Cut 196688 300 4
Cancel Selection 196736 350 10
Paste 196704 400 6
Clear Field 219392 2147483647 2
Show Symbols 50680656 2147483647 10065
Enable Multitap 50680656 2147483647 0
Switch Input Language 50680656 2147483647 10089
Close 268501008 1073741823 9

So the priorities for some of the items (Clear Field, Show Symbols, Enable Multitap, and Switch Input Language) are Integer.MAX_INT, so they’ll always be the lowest priority. Other than that, there’s plenty of room in between all of those numbers to put other menu items wherever you want.

Say you wanted something to appear below the Close menu item. Just create a menu item like:

new MenuItem("Below Close", 300000000, 100) ... // etc

 

Also notice the Id value – this is obtained from MenuItem.getId() and won’t change, even if the device language changes the label of the item. These do not correspond to the constants in MenuItem (MenuItem.CLOSE, etc) – though some aren’t represented there.
The value comes in handy for these next tricks.

Removing built-in menu items

Always hated that Switch Input Language menu item? Here’s how to get rid of it!

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     super.makeMenu(menu, instance);
  3.     for(int i = 0; i < menu.getSize(); i++) {
  4.         MenuItem menuItem = menu.getItem(i);
  5.         if (menuItem.getId() == 10089) { // ID for Switch Input Language
  6.             menu.deleteItem(i);
  7.             break;
  8.         }
  9.     }
  10.        }

BlackBerry menu ordinals and priorities, illustrated – Part 1: Basics

This is an article aimed at beginners (though it might be useful for a refresher for experienced BlackBerry coders too). If all of this seems like old hat though, check out Part 2 of this mini-series to get more in-depth with BlackBerry system menu item values, altering the system menus, removing unwanted system menu items, etc.

Most BlackBerry menus I’ve seen have been constructed something like this:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”100100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”100100) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”100100) { public void run() {}});
  5. }

Nothing wrong with that – it’s valid in many circumstances. But what are those two numbers for?

The javadocs say that the first is the ordinal and the second the priority of the menu item.

The basics of MenuItem ordinals and priorities

Ordinal

Ordinal is straightforward, it’s the position of the item in the menu. Menu items with equal ordinals appear in the order that they were added, top to bottom. The first example gives this:

Changing the ordinals to be in ascending order:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”100100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”200100) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”300100) { public void run() {}});
  5. }

Gives the same thing:

Changing them to be in descending order:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”300100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”200100) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”100100) { public void run() {}});
  5. }

Gives:

Priority

Priority is just what menu item is selected when you initially open the menu. The menu item with the lowest priority will be selected initially. As the above examples show, if there are several items which all share the lowest priority in the menu, the topmost of those will be selected:

Changing the priority:

view plaincopy to clipboardprint?
  1. protected void makeMenu(Menu menu, int instance) {
  2.     menu.add(new MenuItem(“Item A”100100) { public void run() {}});
  3.     menu.add(new MenuItem(“Item B”1000) { public void run() {}});
  4.     menu.add(new MenuItem(“Item C”100100) { public void run() {}});
  5. }

BlackBerry UI – Creating a basic field manager

If you build apps using RIM’s BlackBerry user interface classes (and if you’re trying to build professional applications on BlackBerry, you should be using them) sooner or later you’ll have to start building your own field managers.

Creating managers is actually very easy. I’ll proceed by way of illustrative example – how to code a manager from scratch.

Centering

My previous post created a simple Hello World app – containing one screen with a single LabelField.

That label field appears at the top-left of the screen. What if we wanted to center it at the top of the screen?

We could try changing a couple of things. First, by reading the BlackBerry Javadocs, you might notice that the MainScreen (from which our screen is derived) automatically uses a VerticalFieldManager – maybe what we want to do is to embed our LabelField into a HorizontalFieldManager, set the style of our LabelField to FIELD_HCENTER and add that to the screen? We’ll make the HorizontalFieldManager use all width just to be on the safe side.

Try it:

view plaincopy to clipboardprint?
  1. LabelField lf = new LabelField(“Hello World!”, Field.FIELD_HCENTER);
  2. HorizontalFieldManager hfm = new HorizontalFieldManager(Manager.USE_ALL_WIDTH);
  3. hfm.add(labelField);
  4. add(hfm);

What gives? USE_ALL_WIDTH doesn’t seem to do what it should do.

Now, I can tell you that HorizontalFieldManager can be tweaked to make it center the field in the screen, but since we’re talking about managers, let’s instead fix this problem by creating our own.

Managers

Manager is an abstract class, with one abstract method – sublayout(int width, int height)

What sublayout is passed in are the width and height of its parent – the manager that contains it, which continues up to the top level screen. This is another thing about BlackBerry UIs – you’ll probably end up dealing with nested managers, so try to visualize which manager contains which.

A little exploratory coding tells us that when we add a manager directly to the screen, it is indeed passed the full screen width. So our task is pretty easy. We have to:

1. Get our centered field (for simplicity, we’ll assume we’re only going to ever add one field to this manager)
2. Get the width and height of the field to be centered
3. Figure out where to position the field to center it, based on the field’s width
4. Make our manager take up the entire available width

The code to do this is straightforward:

Getting started with BlackBerry development in Eclipse

After using the BlackBerry JDE plugin for Eclipse for the past couple of months (yes, a bit late on that – I was in a non-develoment job for most of the past year), I can say that – while not perfect – it is currently the best way to develop applications for BlackBerry.

And even with its flaws, RIM has finally delivered something approaching a world class BlackBerry development environment. So if you are thinking of dipping your toes in BlackBerry development, there has never been a better time.

I’ll describe setup in a bit, but first a bit of history:

A (very brief and abridged) history of BlackBerry development

The very first BlackBerry handhelds – the 95x and 85x devices – had to be programmed using C++.  RIM made the great choice of using Microsoft Visual Studio as their development environment, which although missing some features VS.NET has today, was still one of the best environments 7 years ago – and definitely (as today) one of the best debuggers around.

When the first Java based BlackBerry handhelds shipped (also the first to run on the mobile phone networks, so the first to function as phones), they shipped a home-grown IDE called the BlackBerry JDE (Java Development Environment).  To their credit, they had a great simulator, good debugger and a rich class library, but the editor itself left more than a little bit to be desired.  Given the availability even then of open-source 3rd party tools like Eclipse, there were constant requests for integration with something else.

With the release of the 4.1 JDE, RIM sort-of answered those requests.  They released a standalone simulator launcher which used JDWP, and so could be integrated with Eclipse (or NetBeans) and the availability of 3rd party BlackBerry Ant tasks meant that you could cobble together a reasonable development environment around Eclipse.  It wasn’t quite as seamless as the JDE, and much harder to setup, but the superiority of the Eclipse environment meant that a lot of developers (including myself) started using this kind of setup for BlackBerry development.  Most developers though – including some of the best BlackBerry developers that I know – continued using the JDE.

Finally in March of 2008, RIM released a plug-in for Eclipse that replicated all the functionality of the JDE in an easy-to-use package.   A lot of people haven’t looked back since. I’m one of them. So let’s get started.

Setting up the JDE Plug-in

As I implied, setup is very easy.
1. Get and install the JDK from Sun (but you probably already have that, right?)
2. Download and setup (i.e. unzip) Eclipse 3.4 (the regular Java version is fine for BlackBerry development)
3. Download one of the JDE plug-in packages from RIM’s BlackBerry Developer Zone (I recommend the one that includes all the JDE versions – at minimum you’ll want something that includes 4.3 to maintain compatibility with the largest installed base of devices, but probably also 4.7 so you can develop some touch-aware functionality for the sexy new touch-screen Storm)
4. Install the JDE plug-in.  Don’t worry about which workspace you use to install the plugin, it’ll always appear in every eclipse workspace once installed in on.  There’s a Word Doc on the BlackBerry site with instructions (Word?  Ah, RIM), but also a Google-docced version here

And you’re ready to go!

Your first BlackBerry project

This will be very quick, I’m focusing on the mechanics of project setup, and so won’t explain the code at all (look for lots of other posts about that!)

Creating the project

1. Create a new BlackBerry project (from the Eclipse menu choose File->New->Project)
2. Choose BlackBerry->BlackBerry Project
3. Click Next, and Name your new project (I called mine HelloWorldBB) and finish the new project wizard

What a basic project looks like

You’ll see a couple of things listed under your project.  One is a folder called src, this is the default name for Eclipse source directories.  The other is a link to a library called NET_RIM_BLACKBERRY.  This is the BlackBerry runtime library, which includes the all the Java ME classes.