Here it is. I use this only as a gimmick in my current project (the normal 
search is in a fulltext index). But it works quite well. DoDatabaseListAction() 
checks currently only for the first key pressed. You can change that easily in 
place.
If you haven't dealt with tables, it should be easier (but not better) if you 
change it to deal with lists.
Best practice should be to put this code into the Memo example that comes with 
PODS and CW and later include the table code into your own project.


- ListTable is my table id.
- RecordDBRecordPtr is a pointer to my database database record structure.
- RecordDB is my database (change this name to MemoDB for use with the Memo 
example)

First, add a few global variables to your project:

// This is used to indicate if the table has the focus.
// If it hasn't the focus we don't want to handle a keyDown event 
// there of course
Boolean    OneHandedTableHasFocus = true;
// CurrentRecord is the record which the custom table draw
// callback draws and is used to scroll to the record. Naming is the
// same as in the Memo example
UInt16      CurrentRecord = noRecordSelected;

(Actually, in my project I set OneHandedTableHasFocus to false initially. If 
you have multiple input fields on your form and want to support this navigation 
on older devices below OS ? where frmObjectFocusTakeEvent isn't available, you 
have to check yourself if your list/table has the focus. You can do this by 
checking for object focus (check the API docs) each time a key is pressed for 
example).


Then, in your form event handler you need to add a few things:

// BEGIN OF FORM HANDLER SECTION. Include this appropriately in your form 
handler

/* Check if the table has the object focus. If your form isn't in object focus 
mode or you want to support older deviced (AFAIK OS < 5) make sure you set 
OneHandedTableHasFocus by hand appropriately (refer to the API docs)
*/
if (event->eType == frmObjectFocusTakeEvent)
{
    frm = FrmGetActiveForm();
    if (event->data.frmObjectFocusTake.objectID == ListTable)
    {   
        OneHandedTableHasFocus = true;
    }
    else
    {
        OneHandedTableHasFocus = false;
    }
}

// Handle Key events if a key is pressed and the table has the focus
if (event->eType == keyDownEvent)
{
            if ((!TxtCharIsHardKey(event->data.keyDown.modifiers, 
event->data.keyDown.chr)) && OneHandedTableHasFocus)
            {
                if (TxtGlueCharIsPrint (event->data.keyDown.chr))
                    handled = DoDatabaseListAction (frm, 
event->data.keyDown.chr, RecordDB);
            }
}

// END OF FORM HANDLER SECTION



/***********************************************************************
 *
 * FUNCTION:    ListViewScrollTo
 *
 * Scrolls to a specific redord number (the record that matches the key)
 *
 * -- snip Fuer Five-Way Navigation verwendet --- snip
 *
 ***********************************************************************/
static void ListViewScrollTo (Int16 row)
{
    UInt16 attr;
    TablePtr table;
   //  RectangleType rect;
   
    DmRecordInfo(RecordDB, row, &attr, NULL, NULL);
     if (!(attr & dmRecAttrSecret))
     {
         table = GetObjectPtr (ListTable);
        /* snipped. That's for One handed table navigation  
         // Falls vorige selektion auf gleicher seite vorhanden, loeschen
        if (OneHandedSelectedRow  >= 0)
        {
            TblGetItemBounds (table, OneHandedSelectedRow, 0, &rect);
            WinEraseRectangle(&rect, 0);
            ListViewDrawRecord(table, OneHandedSelectedRow, 0, &rect);
        }
        */
       
         // Set the current record to the record that matched our key
        CurrentRecord = row;
        // Redraw the table.
        ListViewLoadRecords (FrmGetActiveForm());
        TblRedrawTable(table);
       
        /* snip.
        if (TblFindRowID (table, row, &OneHandedSelectedRow))
        {
            FrmGlueNavRemoveFocusRing (FrmGetActiveForm());
            ListViewSelectTableItem(true, table, OneHandedSelectedRow, 0, 
&rect);
            OneHandedRecordSelected = true;
        }
       */
     }
}


/* This function is called by the form event handler when a key is pressed.
    Note that only one chracter at a time is processed here. You can easily 
change
    this behaviour at this place, SetDatabaseListSelection() will already 
handle it.
*/
static Boolean DoDatabaseListAction (FormPtr frmP, UInt16 c, DmOpenRef dbP)
{
  Boolean handled = false;
  TablePtr tblP;
  Boolean selection;
  Int16 row, column;

  column = 0;
  tblP = FrmGetObjectPtr (frmP, FrmGetObjectIndex (frmP, ListTable));

    // Check for printable character and perform a search
    if ((((Char)c & ~0x20) >= 'A') && (((Char)c & ~0x20)<= 'Z'))
    {
        Char buf[2] = {c, 0};
        SetDatabaseListSelection (tblP, buf, 1, false, dbP);
        handled = true;
     }
 
  return handled;
}

static Int16 SetDatabaseListSelection (TablePtr tblP, Char *name, Int32 len, 
Boolean caseSensitive, DmOpenRef dbP)
{
  SysDBListItemType* arrayP;
  //Int16 selection;
  Int16 row, column;
  Int16 val;
  MemHandle recH;
  RecordDBRecordPtr recP;  // Pointer to my database structure
  UInt16 attr;
  UInt16 numRecs;
 
// row = INTERNALRECS;

 // Top visible record in your database
  row = 0;
  column = 0;
 
  numRecs = DmNumRecords(dbP);

  if (len == 0)
    {
      len = StrLen (name);
      if (len == 0)
        {
          goto Exit;
        }
    }

  if (caseSensitive)
    {
      while (row < (numRecs-1))
        {
          DmRecordInfo(dbP, row, &attr, NULL, NULL);
          if (!(attr & dmRecAttrSecret)) // only visible records
          {
            recH = DmQueryRecord (dbP, row);
            if (recH == 0)
            {
              //MemHandleUnlock (recH);
              break;
            }
            recP = MemHandleLock (recH);
            if (recP->title == 0)
            {
                MemHandleUnlock (recH);
                break;
            }
            val = StrNCompare (name, &recP->title, len);
            if(val == 0)
              {
                  MemHandleUnlock (recH);
                break; // match
              }
            else if (val < 0)
              {
                  MemHandleUnlock (recH);
                row--;
                break;
              }
              MemHandleUnlock (recH);
          }
          row++;
        }
    }
  else
    {
      while (row < (numRecs-1))
        {
          DmRecordInfo(dbP, row, &attr, NULL, NULL);
          if (!(attr & dmRecAttrSecret)) // nur sichtbare records
          {
            recH = DmQueryRecord (dbP, row);
            if (recH == 0)
            {
              //MemHandleUnlock (recH);
              break;
            }
            recP = MemHandleLock (recH);
            if (recP->title == 0)
            {
              MemHandleUnlock (recH);
                break;
            }
            val = StrNCaselessCompare (name, &recP->title, len);
            if(val == 0)
              {
                  MemHandleUnlock (recH);
                break; // match
              }
            else if (val < 0)
              {
                row--;
                MemHandleUnlock (recH);
                break;
              }
              MemHandleUnlock (recH);
          }
          row++;
        }
    }


Exit:

  ListViewScrollTo (row);
  return row;
 
}



Regards,
Benjamin Stadin
-- 
For information on using the PalmSource Developer Forums, or to unsubscribe, 
please see http://www.palmos.com/dev/support/forums/

Reply via email to