Wednesday, June 30, 2010

Ginga-J Approval Process

As you may know the Ginga-J specification for DTV (Digital Television) is becoming a national standard in Brazil by ABNT. Just in case you don't remember Ginga-J uses LWUIT for its component UI layer.
The specification is now in the public comments phase, looking for feedback from the community/public.
If you would like to see Ginga-J become a finalized standard for ABNT you can vote for that matter by:
1. Going to http://www.abntonline.com.br/consultanacional/default.aspx
2. A list of Commissions will be presented. Choose "ABNT - CEE85 - Televisao >>> Digital"
3. The project of Standard "85:000.00-006/6" will be presented (JavaDTV 1.3)
4. An email / password data request will be required. With this done, you >>> will be able to vote.
5. Vote

Wednesday, June 23, 2010

Headon That Table



A couple of important news before I begin, Terrence Barr has written a great new LWUIT introductory article for java.net and its at the top of java.sun.com... Great for introducing people to LWUIT!



Ofir has just passed a significant milestone of 1000 commits into our java.net SVN repository, take into consideration that we had an internal repository where we are passed the 56k version number... Its not strictly LWUIT commits though ;-)



The main subject of this post though is fixed table headers. The default LWUIT table implementation scrolls the title together with the table body, we made that choice since we assume small tables as the main use case. Fixing a column or a row (such as the titles of the table) into place isn't trivial in an efficient way. However, its possible to do something like that by using two tables and keeping their scrolling in sync.



This works great and pretty seamlessly for touch/keyboard usages however the approach has one major drawback that the size of the title might differ from the size of the cells thus causing the table titles to be misaligned from the table columns.



The solution I chose was to hardcode the cell sizes based on the size of the titles, you can obviously adapt that approach to something more appropriate for your need.



public class FixedTableDemo extends MIDlet {

private static final String[] TITLES = {"Title 1", "Title 2", "Title 3", "Title 4", "Title 5", "Title 6", "Title 7", "Title 8", "Title 9"};

private static final int ROWS = 100;

private static Dimension[] TITLE_SIZES;



static class MirroredTable extends Table {

private MirroredTable mirrorTo;

public MirroredTable(TableModel m) {

super(m);

}



public MirroredTable(TableModel m, boolean b) {

super(m, b);

}



public void setScrollX(int x) {

super.setScrollX(x);

if(isDragActivated()) {

mirrorTo.setScrollX(x);

}

}



/**

* @param mirrorTo the mirrorTo to set

*/


public void setMirrorTo(MirroredTable mirrorTo) {

this.mirrorTo = mirrorTo;

}



public Component createCell(Object value, int row, int column, boolean editable) {

Component c = super.createCell(value, row, column, editable);

if(TITLE_SIZES != null && TITLE_SIZES[column] != null) {

c.setPreferredSize(TITLE_SIZES[column]);

}

return c;

}

}



public void startApp() {

Display.init(this);

Resources r;

try {

r = Resources.open("/LWUITtheme.res");

UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));

} catch (IOException ex) {

ex.printStackTrace();

}

Form f = new Form("Table Title");

MirroredTable titlesTable = new MirroredTable(new DefaultTableModel(TITLES, new Object[0][0]));

TITLE_SIZES = new Dimension[TITLES.length];

for(int iter = 0 ; iter < TITLES.length ; iter++) {

TITLE_SIZES[iter] = titlesTable.createCell(TITLES[iter], -1, iter, false).getPreferredSize();

}



Object[][] body = new Object[ROWS][TITLES.length];

for(int rows = 0 ; rows < body.length ; rows++) {

for(int cols = 0 ; cols < body[rows].length ; cols++) {

body[rows][cols] = "" + rows + ", " + cols;

}

}

MirroredTable bodyTable = new MirroredTable(new DefaultTableModel(TITLES, body), false);

bodyTable.setMirrorTo(titlesTable);

titlesTable.setMirrorTo(bodyTable);

bodyTable.setScrollable(true);

titlesTable.setScrollableX(true);

f.setScrollable(false);

f.setLayout(new BorderLayout());

titlesTable.setTensileDragEnabled(false);

bodyTable.setTensileDragEnabled(false);

titlesTable.setIsScrollVisible(false);

f.addComponent(BorderLayout.NORTH, titlesTable);

f.addComponent(BorderLayout.CENTER, bodyTable);

f.show();

}



public void pauseApp() {

}



public void destroyApp(boolean unconditional) {

}

}





Sunday, June 6, 2010

Pimp the VirtualKeyboard - by Chen Fishbein

LWUIT 1.4 is just around the corner, before the release I wanted to share
Some of the VirtualKeyboard enhancements/improvements that will be released as part of 1.4.

Since the VirtualKeyboard is a pure LWUIT component it can be customized in various ways:

1. Changing the Virtual Keyboard look – All Virtual Keyboard items can be customized from the resource editor, the associated ui id's are:

VKB – this id is used to style the Virtual Keyboard body.
VKBtooltip – this id is used to style the popup tooltip.
VKBButton – this id is used to style a regular button on the virtual keyboard (usually a char or a string).
VKBSpecialButton – this id is used to style the special buttons such as: 'Space', 'SH', ...
VKBTextInput – this id is used to style the textfield on the virtual keyboard.






















2. Adding a language -

The example below demonstrates how to add an input mode that supports hebrew:
Create an array of String arrays, each array represents a buttons column.
private static final String[][] DEFAULT_HEBREW = new String[][]{       
{"\u05e7", "\u05e8", "\u05d0", "\u05d8", "\u05d5", "\u05df", "\u05dd", "\u05e4", "$Delete$"}, 
{"\u05e9", "\u05d3", "\u05d2", "\u05db", "\u05e2", "\u05d9", "\u05d7", "\u05dc", "\u05da"}, 
{"\u05d6", "\u05e1", "\u05d1", "\u05d4", "\u05e0", "\u05de", "\u05e6", "\u05ea", "\u05e5"}, 
{"$Mode$", "$Space$", "\u05E3", "$OK$"}   };

Now extends the VirtualKeyboard and make sure when the VirtualKeyboard is initialized the new language mode is added.

public static class HebrewK extends VirtualKeyboard {  
public HebrewK() {    
   addInputMode("\u05d0\u05d1\u05d2", DEFAULT_HEBREW);    
   setInputModeOrder(new String[]{"\u05d0\u05d1\u05d2", QWERTY_MODE,    
   NUMBERS_SYMBOLS_MODE, NUMBERS_MODE, SYMBOLS_MODE   
  }
 );  
} 
}
Now you need to make sure the new HebrewK will be used as the default virtual keyboard.
Call this:
VKBImplementationFactory.init(HebrewK.class);
instead of the regular
VKBImplementationFactory.init();



3. Binding a VirtualKeyboard to a TextField – Now we have a use case where a TextField should accept only numbers, therefore launching the regular VirtualKeyboard will be a mistake.
What we need to do is to create a 'numbers only' VirtualKeyboard and launch it on a specific TextField.

TextField txt = new TextField(); 
txt.setConstraint(TextField.NUMERIC); 
txt.setInputModeOrder(new String[]{"123"}); 
txt.setInputMode("123");  
VirtualKeyboard vkb = new VirtualKeyboard(); 
vkb.setInputModeOrder(new String[]{VirtualKeyboard.NUMBERS_MODE});  
VirtualKeyboard.bindVirtualKeyboard(txt, vkb);

4. Adding your own button to a TextField – There are several use cases where you would want to place your own buttons on a specific Virtual Keyboard, for example if you are asking the user to insert input for a search field you might want a “search” command instead of the regular “ok” command that will automatically when pressed will invoke a submit action to the network.
To accomplish this you need to create a new virtual keyboard, declare your own input buttons and to add your own special button to be part of the virtual keyboard.



Declare a new input with a new special button “Search” (By default Virtual Keyboard is able to understand only the following special keys: "Shift", "Delete", "T9", “Mode”, “Space”, “OK”):

String[][] SEARCH_QWERTY = new String[][]{ 
{"q", "w", "e", "r", "t", "y", "u", "i", "o", "p"}, 
{"a", "s", "d", "f", "g", "h", "j", "k", "l"}, 
{"$Shift$", "z", "x", "c", "v", "b", "n", "m", "$Delete$"}, 
{"$Mode$", "$Space$", "$Search$"} };  

VirtualKeyboard vkb = new VirtualKeyboard(); 
//add the new input mode 
vkb.addInputMode("ABC_S", SEARCH_QWERTY); 
vkb.setInputModeOrder(new String[]{"ABC_S"}); 
//add the new special button to the vkb 
vkb.addSpecialButton("Search", new Command("Search") {  
public void actionPerformed(ActionEvent evt) { 
  //search logic
... 
} 
});  
//bind the vkb to the textfield 
VirtualKeyboard.bindVirtualKeyboard(txt, vkb); 
f.addComponent(txt);