📄 sugarmemobrowse.c
字号:
#include <PalmOS.h>
#include "SugarMemo.h"
#include "SugarMemoRsc.h"
#include "SugarMemoBrowse.h"
#include "SugarMemoDB.h"
#include "SugarMemoTools.h"
#define statusColumn 0
#define entryColumn 1
#define arrowColumn 2
#define statusColumnWidth 11
#define arrowColumnWidth 13
#define columnSpacing 2
UInt16 CurrentCategory = dmAllCategories;
Char CategoryName[dmCategoryLength];
UInt16 TopVisibleRecord = 0;
Boolean ShowAllCategories = true;
Int16 VisibleRows = 0;
//*******************************************************************
// Internal variables
//*******************************************************************
TabSelected tabCurrentSelected = StudyListTab;
UInt16 TopVisibleBackup[TabCounts] = {0, FirstWordRecord, FirstWordRecord};
const Int16 RowsInTable = 11;
Header HeaderMask;
UInt32 SearchFieldTicks = 0;
Boolean SearchFieldTicking = false;
extern void EditNewRecord();
//*******************************************************************
// Internal functions
//*******************************************************************
static void BrowseFormLoadTable( FormType* frmP );
static void WordListDrawRecord (void * table, Int16 row, Int16 column, RectanglePtr bounds);
static void BrowseFormInit( FormType* frmP );
static void ClearWordListTable();
Boolean SeekNextRecord(UInt16 * indexP, Int16 direction);
static void WordListForward(Boolean byline);
static void WordListBackward(Boolean byline);
static UInt16 WordListSelectCategory (void);
static void ToolsChangeCategory (UInt16 category);
static void ChangeTab(TabSelected tab);
static void DrawTitleBar();
static void MoveToStudyList(Int16 row);
static void MoveToRawList(Int16 row);
static void BatchMoveToStudyList();
static void BatchMoveToRawList();
static void UpdateSearchField();
static void InstantLookup(EventType * event);
static void SearchFieldIdle(FieldType* fldP);
static void SortStudyList();
static void DetectPenDown(EventType* event);
static void ShuffleStudyList();
static Char WordQueueToChar(HeaderQueue queue);
/////////////////////////////////////////////////
//
// event handler
//
/////////////////////////////////////////////////
Boolean BrowseFormHandleEvent(EventType * event){
FormType* frmP = FrmGetActiveForm();
FormType* form;
Boolean handled = false;
Char* p;
UInt32 x;
frmP = FrmGetActiveForm();
switch (event->eType){
case frmOpenEvent:
BrowseFormInit(frmP);
handled = true;
break;
case ctlSelectEvent:
switch (event->data.ctlSelect.controlID){
case BrowseCategoryPopTrigger:
WordListSelectCategory();
handled = true;
break;
case BrowseQuitButton:
//close database if possible
if (CurrentDB != NULL) {
if (errNone != DmCloseDatabase(CurrentDB))
DoCustomDialog("错误", "无法关闭数据库", false, 0, NULL, false);
}
FrmGotoForm(MainForm);
handled = true;
break;
case BrowseNewButton:
EditNewRecord();
handled = true;
break;
case BrowseShuffleButton:
ShuffleStudyList();
handled = true;
break;
//case BrowseSortButton:
// SortStudyList();
// handled = true;
// break;
case BrowseAddAllButton:
BatchMoveToStudyList();
handled = true;
break;
case BrowseRemoveAllButton:
BatchMoveToRawList();
handled = true;
break;
case BrowseStudyListPushButton:
ChangeTab(StudyListTab);
break;
case BrowseRawPushButton:
ChangeTab(RawTab);
break;
case BrowseAllPushButton:
ChangeTab(AllTab);
break;
//case BrowseGoButton:
// RandomNewRecord();
// break;
default:
break;
}
break;
case ctlRepeatEvent:
switch(event->data.ctlSelect.controlID){
case BrowseScrollUpRepeating:
WordListBackward(false);
break;
case BrowseScrollDownRepeating:
WordListForward(false);
break;
}
break;
case tblSelectEvent:
TblUnhighlightSelection(event->data.tblSelect.pTable);
CurrentRecord = TblGetRowID(event->data.tblSelect.pTable, event->data.tblSelect.row);
switch(event->data.tblSelect.column){
case statusColumn:
FrmPopupForm(DetailForm);
break;
case entryColumn:
TopVisibleFieldIndex = 0;
EditRowIDWhichHadFocus = FirstFieldIndex;
EditFieldPosition = 0;
FrmGotoForm(EditForm);
break;
case arrowColumn:
switch(tabCurrentSelected){
case StudyListTab:
MoveToRawList(event->data.tblSelect.row);
break;
case RawTab:
MoveToStudyList(event->data.tblSelect.row);
break;
case AllTab:
form = FrmInitForm(StatusForm);
FrmDoDialog(form);
FrmDeleteForm(form);
break;
}
break;
}
handled = true;
break;
case penDownEvent:
//capture pen down only if raw tab is displayed
if (tabCurrentSelected == RawTab){
DetectPenDown(event);
}
break;
case keyDownEvent:
//if (TxtCharIsHardKey(event->data.keyDown.modifiers, event->data.keyDown.chr))
//{
//}
if (EvtKeydownIsVirtual(event))
{
if (event->data.keyDown.chr == pageUpChr){
//ctl = GetObjectPtr(BrowseScrollUpRepeating);
//if (CtlGetValue(ctl) != 0)
WordListBackward(false);
if (!(event->data.keyDown.modifiers & autoRepeatKeyMask)) handled = true;
}
else if (event->data.keyDown.chr == pageDownChr){
//ctl = GetObjectPtr(BrowseScrollDownRepeating);
//if (CtlGetValue(ctl) != 0)
WordListForward(false);
if (!(event->data.keyDown.modifiers & autoRepeatKeyMask)) handled = true;
}
}
else if (event->data.keyDown.chr == linefeedChr)
{
handled = true;
}
else {
InstantLookup(event);
handled = true;
}
break;
case fldEnterEvent:
FldHandleEvent(event->data.fldEnter.pField, event);
p = FldGetTextPtr(event->data.fldEnter.pField);
if ((p != NULL) && (StrLen(p) > 0))
FldSetSelection(event->data.fldEnter.pField, 0, StrLen(p));
if (tabCurrentSelected == RawTab){
SearchFieldTicking = true;
SearchFieldTicks = TimGetTicks();
}
handled = true;
break;
case fldChangedEvent:
InstantLookup(event);
handled = true;
break;
case nilEvent:
x = TimGetTicks();
if ((tabCurrentSelected == RawTab) &&
SearchFieldTicking && (( x - SearchFieldTicks) > 500)){
SearchFieldTicking = false;
UpdateSearchField();
}
break;
default:
break;
}
return handled;
}
static void BrowseFormInit( FormType* frmP ){
Int16 row;
TableType* tblP;
ControlPtr ctl;
if (ShowAllCategories) CurrentCategory = dmAllCategories;
// Initialize the word list table.
tblP = GetObjectPtr(BrowseWordListTable);
for (row = 0; row < RowsInTable; row++)
{
TblSetItemStyle(tblP, row, statusColumn, customTableItem);
TblSetItemStyle(tblP, row, entryColumn, customTableItem);
TblSetItemStyle(tblP, row, arrowColumn, customTableItem);
TblSetRowUsable(tblP, row, false);
}
TblSetColumnUsable(tblP, statusColumn, true);
TblSetColumnUsable(tblP, entryColumn, true);
TblSetColumnUsable(tblP, arrowColumn, true);
TblSetColumnSpacing(tblP, statusColumn, columnSpacing);
// Set the callback routine that will draw the records.
TblSetCustomDrawProcedure (tblP, statusColumn, WordListDrawRecord);
TblSetCustomDrawProcedure (tblP, entryColumn, WordListDrawRecord);
TblSetCustomDrawProcedure (tblP, arrowColumn, WordListDrawRecord);
// Set the label of the category trigger.
ctl = GetObjectPtr(BrowseCategoryPopTrigger);
CategoryGetName (CurrentDB, CurrentCategory, CategoryName);
CategorySetTriggerLabel (ctl, CategoryName);
ChangeTab(tabCurrentSelected);
}
static void BrowseFormLoadTable( FormType* frmP )
{
Int16 row = 0;
TableType* tblP;
UInt16 cursor = 0;
Boolean full = false;
Boolean reachedEnd = false;
Boolean reachedHead = false;
Int16 i;
UInt16 studyNums;
UInt16 index = 0, recordIndex;
HeaderItem item;
Boolean detecting = true;
UInt32 ticks, ticksPerSecond;
Err error;
tblP = GetObjectPtr(BrowseWordListTable);
// first branch: load study list
if (tabCurrentSelected == StudyListTab){
//Validation
studyNums = GetHeaderItemNumber(CurrentDB, LearningRecordIndex);
if (studyNums == 0){
TopVisibleRecord = 0;
index = 0;
row = 0;
}
else {
if (TopVisibleRecord + 10 > studyNums - 1){
if (studyNums < 11) TopVisibleRecord = 0;
else TopVisibleRecord = studyNums - 11;
}
if (studyNums > RowsInTable) VisibleRows = RowsInTable;
else VisibleRows = studyNums;
for (index = TopVisibleRecord; index < TopVisibleRecord + VisibleRows; index ++){
GetHeaderItem(CurrentDB, LearningRecordIndex, &item, index);
error = DmFindRecordByID(CurrentDB, item, &recordIndex);
if (error) ErrAlert(error);
TblSetRowID(tblP, row, recordIndex);
TblSetRowUsable(tblP, row, true);
row ++;
}
}
// hide empty row
while(row < RowsInTable){
TblSetRowUsable(tblP, row, false);
row ++;
}
// draw table
TblDrawTable(tblP);
// update search/count field
UpdateSearchField();
// update scrollers
reachedHead = (TopVisibleRecord == 0);
reachedEnd = ((TopVisibleRecord + RowsInTable) >= studyNums);
FrmUpdateScrollers(frmP, FrmGetObjectIndex(frmP, BrowseScrollUpRepeating),
FrmGetObjectIndex(frmP, BrowseScrollDownRepeating), !reachedHead, !reachedEnd);
return;
}
ticks = TimGetTicks();
ticksPerSecond = (UInt32)SysTicksPerSecond();
// For each row in the table, store the record number as the row id.
// first, check if table full
if (VisibleRows == RowsInTable) full = true;
// forward search to fill table
if (!full){
if (VisibleRows == 0) cursor = TopVisibleRecord;
else cursor = TblGetRowID(tblP, VisibleRows - 1) + 1;
while (SeekNextRecord(&cursor, dmSeekForward)){
if (detecting && ((TimGetTicks() - ticks) > ticksPerSecond / 2)){
FntSetFont(largeBoldFont);
WinDrawChars("Searching....", 9, 50, 70);
detecting = false;
}
TblSetRowID(tblP, VisibleRows, cursor);
TblSetRowUsable(tblP, VisibleRows, true);
VisibleRows ++;
cursor ++;
if (VisibleRows == RowsInTable){
full = true;
break;
}
}
}
// backward search to fill table
if (!full) {
reachedEnd = true;
if (VisibleRows == 0) cursor = TopVisibleRecord - 1;
else cursor = TblGetRowID(tblP, 0) - 1;
while (SeekNextRecord(&cursor, dmSeekBackward)){
if (detecting && ((TimGetTicks() - ticks) > ticksPerSecond / 2)){
FntSetFont(largeBoldFont);
WinDrawChars("Searching....", 9, 50, 70);
detecting = false;
}
for (i = VisibleRows; i > 0; i--)
TblSetRowID(tblP, i, TblGetRowID(tblP, i-1));
TblSetRowID(tblP, 0, cursor);
TblSetRowUsable(tblP, VisibleRows, true);
VisibleRows ++;
cursor --;
if (VisibleRows == RowsInTable){
full = true;
break;
}
}
if (!full) reachedHead = true;
}
if (VisibleRows == 0){
reachedHead = true;
reachedEnd = true;
}
if (!reachedHead) {
cursor = TblGetRowID(tblP, 0) - 1;
reachedHead = !SeekNextRecord(&cursor, dmSeekBackward);
}
if (!reachedEnd) {
cursor = TblGetRowID(tblP, VisibleRows - 1) + 1;
reachedEnd = !SeekNextRecord(&cursor, dmSeekForward);
}
// Hide the item that don't have any data.
row = VisibleRows;
while (row < RowsInTable)
{
TblSetRowUsable (tblP, row, false);
row++;
}
TblDrawTable(tblP);
//update scrollers
FrmUpdateScrollers(frmP, FrmGetObjectIndex(frmP, BrowseScrollUpRepeating),
FrmGetObjectIndex(frmP, BrowseScrollDownRepeating), !reachedHead, !reachedEnd);
//update top visible record
if (VisibleRows) TopVisibleRecord = TblGetRowID(tblP, 0);
// update search field if
// 2. raw tab and search field not focused
if ((tabCurrentSelected == RawTab) && (!SearchFieldTicking))
UpdateSearchField();
}
static void WordListDrawRecord (void * table, Int16 row, Int16 column, RectanglePtr bounds){
UInt16 recordNum;
Err error;
WordRecordType record;
MemHandle recordH;
Int16 strWidth = 75; //75 pixel at most for question field
Int16 strLength = 0;
Int16 offset = 0;
Boolean fitWithinWidth = true;
char* strP;
char arrowChar;
char infoChar;
HeaderQueue queue;
// Get the record number that corresponds to the table item to draw.
// The record number is stored in the "intValue" field of the item.
recordNum = TblGetRowID (table, row);
error = GetWordRecord (CurrentDB, recordNum, &record, &recordH);
if (error)
{
ErrNonFatalDisplay ("Record not found");
return;
}
switch (column)
{
case entryColumn:
if (record.field[WordFieldQuestion] != NULL) {
strP = record.field[WordFieldQuestion];
FntSetFont(boldFont);
strLength = StrLen(strP);
FntCharsInWidth(strP, &strWidth, &strLength, &fitWithinWidth);
WinDrawChars(strP, strLength, bounds->topLeft.x, bounds->topLeft.y);
}
if (record.field[WordFieldAnswer] != NULL){
strP = record.field[WordFieldAnswer];
FntSetFont(stdFont);
strLength = StrLen(strP);
offset = strWidth + 10;
strWidth = TblGetColumnWidth(table, entryColumn) - offset;
FntCharsInWidth(strP, &strWidth, &strLength, &fitWithinWidth);
WinDrawChars(strP, strLength, bounds->topLeft.x +
TblGetColumnWidth(table, entryColumn) - strWidth, bounds->topLeft.y);
}
break;
case statusColumn:
FntSetFont(symbolFont);
infoChar = 10;
WinDrawChars(&infoChar, 1, bounds->topLeft.x + 2, bounds->topLeft.y);
FntSetFont(stdFont);
break;
case arrowColumn:
switch(tabCurrentSelected){
case StudyListTab:
arrowChar = 187;
break;
case RawTab:
arrowChar = 171;
break;
case AllTab:
queue = GetQueue(CurrentDB, TblGetRowID(table, row));
arrowChar = WordQueueToChar(queue);
break;
}
FntSetFont(boldFont);
WinDrawChars(&arrowChar, 1, bounds->topLeft.x + 1, bounds->topLeft.y);
FntSetFont(stdFont);
break;
}
MemHandleUnlock(recordH);
}
UInt16 WordListSelectCategory (void)
{
FormType* frmP;
UInt16 category;
Boolean categoryEdited;
// Process the category popup list.
category = CurrentCategory;
frmP = FrmGetActiveForm();
categoryEdited = CategorySelect (CurrentDB, frmP, BrowseCategoryPopTrigger,
BrowseWordCategoryList, true, &category, CategoryName, 1, categoryDefaultEditCategoryString);
if (category == dmAllCategories)
ShowAllCategories = true;
else
ShowAllCategories = false;
if ( categoryEdited || (category != CurrentCategory))
{
ToolsChangeCategory (category);
// Display the new category.
VisibleRows = 0;
BrowseFormLoadTable(frmP);
// By changing the category the current record is lost.
CurrentRecord = noRecord;
}
return (category);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -