You are on page 1of 6

Creating Custom Table Items Under Palm OS

Tables (or grids) are very useful controls when you need to display and edit multiple data columns. 
Especially if column's types are different like checkboxes, text fields or popup triggers. In addition to 
standard cell types (described in Table.h) Table API provides an opportunity to create custom cells. This 
article highlights some aspects of custom table development.
Getting started

Let's cover shortly the basics of tables. Usual working flow is as follows:

• type of column in table's row
• a value to integer or pointer data of the cell if needed
• desired columns usable
• set custom procedures for loading, saving and drawing if needed
• set ID and Data values for row (each one is of two bytes length) if needed 
Note that by default columns are unusable, so you should explicitly set them into visible state. The 
following illustrates all of these concepts:

FormPtr frmP = FrmGetActiveForm();
TablePtr tableP = FrmGetObjectPtr( frmP,
FrmGetObjectIndex(frmP,TestTableTable));
UInt nNumRows = TblGetNumberOfRows(tableP);
UInt i = 0;

for (i = 0; i < i =" 0;" nvalue =" TblGetItemInt(tableP,row,column);" nvalue ="="" bitmaph =" 
DmGetResource('Tbmp'," bitmaph =" DmGetResource('Tbmp'," bitmapp =" (BitmapPtr)">topLeft.x, 
bounds­>topLeft.y);
MemHandleUnlock (bitmapH);
}

All this function does is load the appropriate bitmap resource according to stored value and then draw it 
inside the cell bounds. Just avoid time consuming operations when the cell is being drawn, otherwise 
users will not understand you!

Responding to events

The Table API provides more opportunities to display data than to edit data. One more point where you 
may customize your control is in handling some events. Applying to tables, it will be tblEnterEvent and 
tblSelectEvent. We need to create field in cell's bounds and then redirect events to this control. This is just 
a very simple and schematical implementation of what was presented above:
*********************************************************************
Global variables
*********************************************************************/

FieldPtr g_InPlaceField;
UInt16 g_wCurrRow, g_wCurrCol;
MemHandle g_hText;
Boolean g_bSelected;
static void SaveValue(TablePtr table);
static void HandleTapInCell(EventType* eventP,
TablePtr tableP,
UInt16 wCol,
UInt16 wRow,
Boolean& bHandled);
..................................
static void MainFormInit(FormType *frmP)
{
.......................
g_wCurrRow = g_wCurrCol = ­1;
g_bSelected = false;
g_InPlaceField =
(FieldPtr)FrmGetObjectPtr(frmP,FrmGetObjectIndex(frmP,MainInPlaceEdit));
.......................
}
static Boolean MainFormHandleEvent(EventType * eventP)
{
Boolean handled = false;
FormType * frmP;

switch (eventP­>eType)
{
// other events
......................
case tblEnterEvent:
{
frmP = FrmGetActiveForm();
TablePtr tableP = eventP­>data.tblEnter.pTable;
UInt16 wRow = eventP­>data.tblEnter.row;
UInt16 wCol = eventP­>data.tblEnter.column;
HandleTapInCell(eventP, tableP, wCol, wRow, handled);
g_wCurrRow = wRow;
g_wCurrCol = wCol;
}
break;
}
return handled;
}
/*********************************************************************
 Internal Functions
*********************************************************************/
static void SaveValue(TablePtr table)
{
Boolean dirty;

if (!g_InPlaceField)
return;

dirty = FldDirty(g_InPlaceField);

if (dirty)
{
CharPtr textP = FldGetTextPtr(g_InPlaceField);
Int nInt;

if (textP)
nInt = StrAToI(textP);
else
nInt = 0;
TblSetItemInt(table,g_wCurrRow,0,nInt);
}

FldReleaseFocus(g_InPlaceField);
FldSetSelection(g_InPlaceField, 0, 0);
}

static void HandleTapInCell( EventType* eventP,
TablePtr tableP,
UInt16 wCol,
UInt16 wRow,
Boolean& bHandled)
{
FormPtr frmP = FrmGetActiveForm();

// if user tapped on new row then deselect current one
if ( g_bSelected &&
(wCol != g_wCurrCol || wRow != g_wCurrRow) )
{
SaveValue(tableP);
FrmHideObject(frmP,FrmGetObjectIndex(frmP,MainInPlaceEdit));
TblMarkRowInvalid(tableP,g_wCurrRow);
g_bSelected = false;
}
TblRedrawTable(tableP);

if ( wCol > 0 )
{
g_bSelected = false;
bHandled = false;
return;
}

// show field at new position if needed
RectangleType r;
TblGetItemBounds(tableP,wRow,wCol,&r);

if ( (wCol == 0 && wCol != g_wCurrCol) || (wRow != g_wCurrRow) )
{
TblGetItemBounds(tableP,wRow,wCol,&r);
Int16 nInt = TblGetItemInt(tableP,wRow,wCol);

FrmSetObjectBounds(frmP,FrmGetObjectIndex(frmP,MainInPlaceEdit),&r);
FrmShowObject(frmP,FrmGetObjectIndex(frmP,MainInPlaceEdit));

char szBuffer[10];
StrPrintF(szBuffer,"%d",nInt);

char* pText = (char*)MemHandleLock(g_hText);
StrCopy(pText,szBuffer);
MemHandleUnlock(g_hText);
FldSetTextHandle(g_InPlaceField,g_hText);
FrmSetFocus(frmP,FrmGetObjectIndex(frmP,MainTestTable));
{
// Convert tblEnter event to fldEnter event
EventType newEvent;
EvtCopyEvent(eventP,&newEvent);
newEvent.eType = fldEnterEvent;
newEvent.data.fldEnter.fieldID = 1971;
newEvent.data.fldEnter.pField = g_InPlaceField;

FldHandleEvent(g_InPlaceField, &newEvent);
}
FldDrawField(g_InPlaceField);
g_bSelected = true;
bHandled = true;
}
FrmDrawForm(frmP);
}

Such solution is really simple yet effective enough. You create field control once; then you just need to 
move it to correct position of edited cell or hide field control if no cells are required to be edited. An 
important point in this sample is that you should convert and redirect tblEnter event to FldHandleEvent 
function in order to support natural field functionality. Once you are done with it, saving/assigning values 
of cells are just trivial things! The only additional step ought to be noted here is that usually you need to 
save data in frmCloseEvent handler.

Where to go
As we have seen, Table API manager gives us several opportunities to customize our tables. For most of 
relatively simple cases it's more than enough. But if you're requested to implement more complex 
behavior, next possible area of thinking is Gadget control. We will discuss it in next article.

Article Source: Developer.Com

To inquire more about Palm applications, mobile application development services please visit 
www.palmphone.com or Call 888­284­0858
Palm Pre Apps | Palm Apps Development | Palm Software Programming

You might also like