http://www.developer.com/ws/palm/article.php/3294191/Creating-Custom-Table-Items-Under-Palm-OS.htm
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. Let's cover shortly the basics of tables. Usual working flow is as follows:
Note that by default columns are unusable, so you should explicitly set them into visible state. The following illustrates all of these concepts:
The LoadDataProc function has following signature:
You return the same values for dataH, dataOffset, and dataSize that you would pass to FldSetText. That is, you can use this function to point the table cell's text field to a string in a database record so that you can edit that string directly
using text field routines. To do so, return the handle to a database record in dataH, the offset from the start of the record to the start of the string in dataOffset, and the allocated size of the string in dataSize. Finally, custom cell has its own drawing procedure CustomDrawProc defined as:
Thus you may supply any possible look and feel to your custom cell. We will take a look at some sample implementation in the very next section. Now it's time to take a look at custom drawing. Our procedure will draw a bitmap depending on integer value stored for particular cell. It may be implemented as follows: All this function does is load the appropriate bitmap resource according to stored value and then draw it inside the cell bounds. You may freely apply your imagination here and implement almost any behavior. Just avoid time consuming operations when the cell is being drawn, otherwise users will not understand you!
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. You may process them in HandleEvent function. As an example we'll implement in-place edit. The main idea is simple. We need to create field in cell's bounds and then redirect events to this control. For example, in case of in-place edit you may write something like following code sample. This is just a very simple and schematical implementation of what was presented above:
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. 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.
Alex Gusev started to play with mainframes in the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler. # # #
Creating Custom Table Items Under Palm OS
December 31, 2003
Getting started
FormPtr frmP = FrmGetActiveForm();
TablePtr tableP = FrmGetObjectPtr( frmP,
FrmGetObjectIndex(frmP,TestTableTable));
UInt nNumRows = TblGetNumberOfRows(tableP);
UInt i = 0;
for (i = 0; i < nNumRows; i++)
{
TblSetItemStyle(tableP, i, 0, numericTableItem);
TblSetItemInt(tableP, i, 0, i);
TblSetItemStyle(tableP, i, 1, textTableItem);
TblSetItemStyle(tableP, i, 2, checkboxTableItem);
TblSetItemInt(tableP, i, 2, i % 2);
TblSetItemStyle(tableP, i, 3, customTableItem);
TblSetItemInt(tableP, i, 2, i % 2 + 1);
}
for (i = 0; i < 4; i++)
{
TblSetColumnUsable(tableP,i,true);
}
TblSetLoadDataProcedure(tableP,1,LoadDataProc);
TblSetCustomDrawprocedure(tableP,3,CustomDrawProc);
Err TableLoadDataFuncType (void *tableP,
Int16 row,
Int16 column,
Boolean editable,
MemHandle *dataH,
Int16 *dataOffset,
Int16 *dataSize,
FieldPtr fld);
void TableDrawItemFuncType (void *tableP,
Int16 row,
Int16 column,
RectangleType *bounds);
Custom drawing procedure
void CustomDrawProc (void *tableP,
Int16 row,
Int16 column,
RectangleType *bounds)
{
Int16 nValue = TblGetItemInt(tableP,row,column);
MemHandle bitmapH;
BitmapPtr bitmapP;
if ( nValue == 1 )
bitmapH = DmGetResource('Tbmp', resBitmapIDEven);
else
bitmapH = DmGetResource('Tbmp', resBitmapIDOdd);
if ( !bitmapH )
return;
bitmapP = (BitmapPtr) MemHandleLock (bitmapH);
WinDrawBitmap (bitmapP, bounds->topLeft.x, bounds->topLeft.y);
MemHandleUnlock (bitmapH);
}
Responding to events
/*********************************************************************
* 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);
}

Where to go
About the Author