Perform specific action when any cell of TableLayoutManager clicked - blackberry

I'm new to Blackberry development. Currently, i have an instance of TableLayoutManager to add into the UI screen. How i perform a specific action when any cell of the table is selected/clicked, as the method setOnItemClick() i used in Android?
This is my code
TableLayoutManager colFMgr = new TableLayoutManager(new int[] {
TableLayoutManager.USE_PREFERRED_SIZE,
TableLayoutManager.USE_PREFERRED_SIZE }, new int[] {
TableLayoutManager.USE_PREFERRED_WIDTH_WITH_MAXIMUM,
TableLayoutManager.USE_PREFERRED_WIDTH_WITH_MAXIMUM }, 5,
Manager.HORIZONTAL_SCROLL);
for (int i = 0; i < images.length; i++) {
colFMgr.add(new BitmapField(images[i], Field.FOCUSABLE));
}
add(colFMgr);
TableLayoutManager is a class as defined here
I want to do specific action (like navigating to other screen) when any cell of the table clicked and get information about which cell is clicked.
Thank you...

I didnt tried this answer. Lets check it.
TableLayoutManager colFMgr = new TableLayoutManager(new int[] {
TableLayoutManager.USE_PREFERRED_SIZE,
TableLayoutManager.USE_PREFERRED_SIZE }, new int[] {
TableLayoutManager.USE_PREFERRED_WIDTH_WITH_MAXIMUM,
TableLayoutManager.USE_PREFERRED_WIDTH_WITH_MAXIMUM }, 5,
Manager.HORIZONTAL_SCROLL){
protected boolean navigationClick(int status, int time) {
int k=getFieldWithFocusIndex();
if(k==0){
//clicked first row
}else if(k==1){
//clicked second row
}//and so on......
return true;
}
};
for (int i = 0; i < images.length; i++) {
colFMgr.add(new BitmapField(images[i], Field.FOCUSABLE));
}
add(colFMgr);

Related

Blackberry verticalfieldmanager partial screen scrolling with label fields

I am trying to create a set of FAQ questions and answers using a bunch of LabelFields in a VFM. Issue is that when I try to scroll, it jumps to the bottom of the list and doesn't show the mid-section questions.
public class HelpTab implements ITabAreaLayout, ScrollChangeListener {
public String[] GetQandAs() {
String[] QandAs = new String[22];
QandAs[0] = "Q. ....";
QandAs[1] = "A. ....";
....
....
QandAs[20] = "Q. ...";
QandAs[21] = "A. ....";
return QandAs;
}
VerticalFieldManager _vfm;
public VerticalFieldManager GetLayout() {
_vfm = new VerticalFieldManager(Field.FIELD_LEFT
| Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
_vfm.add(UIElements.GetTitleArea(" ? FAQ"));
String[] QandAs = GetQandAs();
for (int i = 0; i < QandAs.length; i++) {
LabelField lblQandA = null;
if ((i % 2) == 0) {
lblQandA = UIElements.GetQuestionLabel(QandAs[i]);
} else {
lblQandA = UIElements.GetAnswerLabel(QandAs[i]);
}
_vfm.add(lblQandA);
}
_vfm.add(new NullField(NullField.FOCUSABLE)); // for scrolling
return _vfm;
}
public void scrollChanged(Manager manager, int newHorizontalScroll,
int newVerticalScroll) {
if (_vfm != null){
_vfm.setVerticalScroll(newVerticalScroll);
}
}
public class HomeScreen extends MainScreen
{
public HomeScreen() {
super(Manager.FIELD_HCENTER | Screen.NO_VERTICAL_SCROLL);
_vfmMain = new VerticalFieldManager();
// add header image
_vfmMain.add(UIElements
.GetBitmapField(UIElements.IMG_HEADER, false));
// add tab strip
_vfmMain.add(MakeTabStrip());
add(_vfmMain);
_vfmTabArea = new HelpTab().GetLayout();
add(_vfmTabArea);
}
}
I was not able to find much help on setVerticalScroll usage, maybe that is the reason for this issue.
Please advise.
Thanks
In your code, you added the focusable null field at the end position of the loop. so if you scroll, it will goto the last element. If you add the focusable field to- After first question, then after second question, ..... so it will scroll one by one.
Try This code -
for (int i = 0; i < QandAs.length; i++) {
LabelField lblQandA = null;
if ((i % 2) == 0) {
lblQandA = UIElements.GetQuestionLabel(QandAs[i]);
} else {
lblQandA = UIElements.GetAnswerLabel(QandAs[i]);
}
_vfm.add(lblQandA);
_vfm.add(new NullField(NullField.FOCUSABLE)); //after each element, add a focusable null field.
}
As Signare has pointed out, the issue here is probably related to your LabelFields not being focusable, which are they are not by default. One answer is to add NullFields as has been suggested. However I suspect you actually want these to be focusable, so the user can click on the one they would like more information on. So make your LabelFields Focusable, by setting the style, for example
LabelField lab = new LabelField("Label", LabelField.FOCUSABLE);
Alternatively, and to my mind preferably, use RichTextField instead of LabelField. This will give you scrolling line by line, LabelField focuses on the whole text.

Stackoverflow exception in blackberry CheckBoxField

I am implementing a simple app, where in the registration page user can select news categories. Requirements are below
All the categories are the CheckBoxField's. User have to select at least one category.
Select all CheckBox will allow to select all/deselect all categories CheckBox.
If user manually selects all checkbox fields then "Select All" checkbox must be selected.
Approaches: I have created the categories checkbox in a loop.
for(int i=0;i<interests.length;i++){
allFields[i] = new ColorCheckBoxField(interests[i], false, checkBoxStyle | USE_ALL_WIDTH);
allFields[i].setCookie(i+"");
allFields[i].setFont(bodyFont);
allFields[i].setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
ColorCheckBoxField tempChoice = (ColorCheckBoxField)field;
int index =Integer.parseInt(tempChoice.getCookie().toString().trim());
//set the selection
if(tempChoice.getChecked()){
parent.selectInterest(index);
}
boolean flag = true;
int[] intrests = parent.getSelectedInterest();
for (int i = 0; i < intrests.length; i++) {
if(intrests[i]==0){
flag = false;
}
}
if(flag==true){
selectAll.setChecked(flag); // select all is Checkbox object
}else{
selectAll.setChecked(false);
}
}
});
vfm.add(allFields[i]);
}
My selectAll checkbox logic is
selectAll = new ColorCheckBoxField("Select All", false, checkBoxStyle | USE_ALL_WIDTH);
selectAll.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
ColorCheckBoxField temp = (ColorCheckBoxField) field;
//if (context == FieldChangeListener.PROGRAMMATIC ) {
checkAll(temp.getChecked()); // it loops through all checkbox and set them checked
//}
}
});
innerHfm.add(selectAll);
I understand the problem, its due to infinite loop. I have used "FieldChangeListener.PROGRAMMATIC" but that wont help because i want the field listener to work for both pragmatically and manually. I don't have any option left to fix. Any hack will help me?
That's correct that you have to use FieldChangeListener.PROGRAMMATIC. But you have to use it with interest checkboxes instead of using it for selectAll checkbox.
Please add one defensive check to FieldChangeListener for interest checkboxes:
if ( nonProgrammaticChange(context) ) {
ColorCheckBoxField tempChoice = (ColorCheckBoxField)field;
int index = Integer.parseInt(tempChoice.getCookie().toString().trim());
...
}
Where nonProgrammaticChange is:
private boolean nonProgrammaticChange (int context) {
return (context & FieldChangeListener.PROGRAMMATIC) != FieldChangeListener.PROGRAMMATIC;
}
I see bug in your code - you don't clear interest in parent if checkbox is unchecked.
Minor improvements as for me - use Vector where you'll store indexes of selected checkboxes. This will allow to replace this code:
boolean flag = true;
int[] intrests = parent.getSelectedInterest();
for ( int i = 0; i < intrests.length; i++ ) {
if( intrests[i] == 0 ) {
flag = false;
}
}
To this code:
selectedInterestIndexes.size() == interests.length
And probably this will give you less iteration in other places.
As well I would work more on removal of duplicates and code readability.

Blackberry: Drawing TableModel focus properly

I need help with drawing the focus of the selected row properly.
Currently if I select the first item of a category the separatorrow gets highlighted too. So how can I implement my custom focus drawing so that only the selected row gets focused/highlighted?
I am using the posted source code from here: Blackberry Tablemodel gets messed up when scrolling
I am using the Eclipse IDE from RIM and JRE 7.0.0
public class ProductsScreen extends MainScreen
{
private TableModel _tableModel;
private static final int ROW_HEIGHT = 40;
public ProductsScreen(MainCategory mc)
{
super(Manager.NO_VERTICAL_SCROLL | Manager.HORIZONTAL_SCROLL);
DBManager dbman = DBManager.getInstance();
AllProductByCategory[] products = null;
try {
products = dbman.getProducts(mc.getID().intValue());
} catch (DatabaseException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setTitle(mc.getName());
_tableModel = new TableModel();//(StringComparator.getInstance(true), 0);
if(products != null)
{
for(int i = 0; i < products.length; i++)
{
ViewableData[] data = products[i].getData().getViewableData();
for(int j = 0; j < data.length; j++)
{
_tableModel.addRow(new Object[] {products[i].getCategoryName(), data[j].getTitle2()});
}
}
}
RegionStyles style = new RegionStyles(BorderFactory.createSimpleBorder(new XYEdges(1, 1, 1, 1), Border.STYLE_SOLID), null, null,
null, RegionStyles.ALIGN_LEFT, RegionStyles.ALIGN_TOP);
TableView tableView = new TableView(_tableModel);
final TableController tableController = new TableController(_tableModel, tableView);
tableController.setFocusPolicy(TableController.ROW_FOCUS);
tableController.setCommand(new Command(new CommandHandler()
{
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
}
}));
tableView.setController(tableController);
DataTemplate dataTemplate = new DataTemplate(tableView, 2, 2)
{
public Field[] getDataFields(int modelRowIndex)
{
final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);
Field[] fields = new Field[3];
String rowGroup = (String)data[0];
// we're in a new group if this is the very first row, or if this row's
// data[0] value is different from the last row's data[0] value
boolean isNewGroup = (modelRowIndex == 0) ||
(rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
if (isNewGroup) {
// make a separator row
fields[0] = new HeaderField((String)data[0],
Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
} else {
// this is in the same group as the last product, so don't add anything here
fields[0] = new NullField();
}
// now, add the actual product information
fields[1] = new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | Field.USE_ALL_HEIGHT | DrawStyle.ELLIPSIS);
fields[2] = new BitmapField(Bitmap.getBitmapResource("img/bullet_arrow_right.png"));
return fields;
}
};
dataTemplate.createRegion(new XYRect(0, 0, 2, 1)); // group separator (maybe a null field)
dataTemplate.createRegion(new XYRect(0, 1, 1, 1)); // actual rows with product information
dataTemplate.createRegion(new XYRect(1, 1, 1, 1));
dataTemplate.setColumnProperties(0, new TemplateColumnProperties(95, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setColumnProperties(1, new TemplateColumnProperties(5, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setRowProperties(0, new TemplateRowProperties(ROW_HEIGHT)); // separator
dataTemplate.setRowProperties(1, new TemplateRowProperties(ROW_HEIGHT)); // product data
dataTemplate.useFixedHeight(false);
tableView.setDataTemplate(dataTemplate);
add(tableView);
}
}
SOLUTION:
I was able to solve the problem on my own with the following approach.
I just added a overridden LabelField as headerfield and didn't implement its focus drawing. So only the "subfields" get the focus drawn.
Maybe some people would implement it in another way (take a look at the answer from Nate) but it worked for me.
So, I didn't have time to fully integrate your new code sample, which has data model code that I don't have, and which appears to have added a DataTemplate column for a BitmapField. Hopefully, you can adapt what I have to reintegrate those changes.
I'm sure there's more than one way to do this, and I'm not claiming this method to be the highest performance. However, it seems to draw the focus as you would expect, without the separator row getting highlighted when the row directly under it is focused.
What I did was abandon the concept of using multiple regions, and just made my data template 1 row by 1 column. If you want, you can probably make it 1 row by 2 columns, where the column I don't show is the BitmapField.
But, what I did was to place a VerticalFieldManager in the first row in each new group/category. That VerticalFieldManager then contained a separator/header row, a separator field (just a horizontal line), and then the actual product row. If the row was not the first in the group/category, I would just return a simple Field, not a VerticalFieldManager with three Field objects inside it.
Then, I changed the TableController focus policy to FIELD_FOCUS, not ROW_FOCUS. This allows focus to be taken by the VerticalFieldManager, when we're on the first row in a new group/category. However, inside that manager, only the actual product row is focusable. The separator row is not focusable, and will therefore not be drawn with focus.
Here's the code that changed. The rest is the same as in the previous sample I gave you:
_tableController.setFocusPolicy(TableController.FIELD_FOCUS);
_tableView.setController(_tableController);
DataTemplate dataTemplate = new DataTemplate(_tableView, 1, 1) // 1 row now!
{
public Field[] getDataFields(int modelRowIndex)
{
final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);
String rowGroup = (String)data[0];
// we're in a new group if this is the very first row, or if this row's data[0] value is
// different from the last row's data[0] value
boolean isNewGroup = (modelRowIndex == 0) ||
(rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
if (isNewGroup) {
LabelField header = new LabelField((String)data[0], Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
SeparatorField line = new SeparatorField(Field.USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.BLACK);
super.paint(g);
}
};
LabelField productRow = new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER);
VerticalFieldManager manager = new VerticalFieldManager(Field.USE_ALL_WIDTH | Field.FOCUSABLE |
Manager.NO_VERTICAL_SCROLL | Manager.NO_VERTICAL_SCROLLBAR);
manager.add(header);
manager.add(line);
manager.add(productRow);
return new Field[] { manager };
} else {
return new Field[] { new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER) };
}
}
};
// create just one region, with one row and one full-width column
dataTemplate.createRegion(new XYRect(0, 0, 1, 1), _style); // may be a product row, or a product row + separator
dataTemplate.setColumnProperties(0, new TemplateColumnProperties(100, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setRowProperties(0, new TemplateRowProperties(2 * ROW_HEIGHT)); // max height if row + separator
_tableView.setDataTemplate(dataTemplate);
dataTemplate.useFixedHeight(false);
The scrolling is a little funny when you get down to the bottom of the page, but I'm pretty sure I've built VerticalFieldManager subclasses before that acted like lists, that needed some custom scroll handling ... if I get some time tomorrow, I'll try to add that in.
One step at a time, though ...

how to select all items at a time when cliking on select all menuitem for a listfield checkbox in blackberry

I want to select all items in a listfield at a time when cliking on the select all menu item in the application.i tried with my code like this..
selectall = new MenuItem("Selectall", 200, 10){
public void run(){
int elementLength = _elements.length;
for(int count = 0; count < elementLength; ++count)
{
_listData.addElement(new ChecklistData(_elements[count], true));
listField.insert(count);
}
}
};
but iam getting the result with old list also.below the old list this new list is coming with checked.how to solve that.please give your ideas.and where iam doing the mistake.thanks in advance..
Your use of listField.insert means that you're adding new ChecklistData objects to the list. That's why you're getting a completely new list underneath your previous one. Instead of adding to _listData, go through it and set the ChecklistData to be checked.
It looks like that is a custom class, so I don't know what it will take for you to do that. If you used CheckboxFields in _listData, you could do it like this:
for (Enumeration e = _listdata.elements() ; e.hasMoreElements() ;) {
CheckboxField c = (CheckboxField)e.nextElement();
c.setChecked(true);
}
Thanks for your all suggestions. i solved my problem now..the solution is..
selectall = new MenuItem("Selectall", 200, 10){
public void run(){
int elementLength = _elements.length;
for(int count = 0; count < elementLength; ++count)
{
_listData.setElementAt(new ChecklistData(_elements[count], true), count);
}
}
};

How can I enable/disable cells using Vaadin table component?

I have a table with 2 columns: a checkbox and a textfield. I want to disable the textfield depending of the respective (same row) checkbox status. If the checkbox is checked then the textfield will be cleared and be read only. Is this possible ? Here is my code:
#SuppressWarnings("serial")
private Table filtersTable() {
final Table table = new Table();
table.setPageLength(10);
table.setSelectable(false);
table.setImmediate(true);
table.setSizeFull();
// table.setMultiSelectMode(MultiSelectMode.SIMPLE) ;
table.addContainerProperty("Tipo filtro", CheckBox.class, null);
table.addContainerProperty("Valor", String.class, null);
table.setEditable(true);
for (int i = 0; i < 15; i++) {
TextField t = new TextField();
t.setData(i);
t.setMaxLength(50);
t.setValue("valor " + i);
t.setImmediate(true);
t.setWidth(30, UNITS_PERCENTAGE);
CheckBox c = new CheckBox(" filtro " + i);
c.setWidth(30, UNITS_PERCENTAGE);
c.setData(i);
c.setImmediate(true);
c.addListener(new ValueChangeListener() {
#Override
public void valueChange(ValueChangeEvent event) {
// within this, could I access the respective row ID
// (i) then enable/disable TextField t on second column ?
System.out.println("event.getProperty().getValue()="
+ event.getProperty().getValue());
}
});
table.addItem(new Object[] { c, t }, i);
}
return table;
}
Thanks
Few changes to your code made it possible.
Not the finiest way, but te simpliest.
First,you have to set your second column (Valor) to TextField.class not String.class.
Here the change :
table.addContainerProperty("Valor", TextField.class, null);
Instead of keepin the variable i in the CheckBox.setData(), I suggest you to link your checkBox to the TextField of the same row, like this :
c.setData(t);
Finally I made little change to your listener :
c.addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
CheckBox checkBox = (CheckBox)event.getProperty();
if((Boolean) checkBox.getValue())
{
TextField associatedTextField = (TextField)checkBox.getData();
//Do all your stuff with the TextField
associatedTextField.setReadOnly(true);
}
}
});
Hope it's work for you!
Regards, Éric
public class MyCheckBox extends CheckBox {
private TextBox t;
public MyCheckBox(TextBox t) {
this.t = t;
attachLsnr();
}
private void attachLsnr()
{
addListener(new Property.ValueChangeListener() {
public void valueChange(ValueChangeEvent event) {
CheckBox checkBox = (CheckBox)event.getProperty();
if((Boolean) checkBox.getValue())
{
t.setReadOnly(true);
}
}
});
}
}

Resources