pjs/cmd/xfe/Microline3.0/examples/grid6.c

466 строки
11 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* The following source code is part of the Microline Widget Library.
* The Microline widget library is made available to Mozilla developers
* under the Netscape Public License (NPL) by Neuron Data. To learn
* more about Neuron Data, please visit the Neuron Data Home Page at
* http://www.neurondata.com.
*/
#include <Xm/Xm.h>
#include <Xm/Text.h>
#include <XmL/Grid.h>
/* DATABASE PROTOTYPE FUNCTIONS */
int dbTableNumRows = 14;
int dbTableNumColumns = 5;
typedef enum {
ID, Desc, Price, Qty, UnitPrice, Buyer
}
DbTableColumnID;
typedef struct
{
DbTableColumnID id;
char label[15];
int width;
unsigned char cellAlignment;
Boolean cellEditable;
} DbTableColumn;
DbTableColumn dbTableColumns[] =
{
{ Desc, "Description", 16, XmALIGNMENT_LEFT, True },
{ Price, "Price", 9, XmALIGNMENT_LEFT, True },
{ Qty, "Qty", 5, XmALIGNMENT_LEFT, True },
{ UnitPrice, "Unit Prc", 9, XmALIGNMENT_LEFT, False },
{ Buyer, "Buyer", 15, XmALIGNMENT_LEFT, True },
};
typedef struct
{
char key[10];
char desc[20];
float price;
int qty;
char buyer[20];
} DbTableRow;
DbTableRow dbTableRows[] =
{
{ "key01", "Staples", 1.32, 100, "Tim Pick" },
{ "key02", "Notebooks", 1.11, 4, "Mary Miner" },
{ "key03", "3-Ring Binders", 2.59, 2, "Mary Miner" },
{ "key04", "Pads", 1.23, 3, "Tim Pick" },
{ "key05", "Scissors", 4.41, 1, "Mary Miner" },
{ "key06", "Pens", .29, 4, "Mary Miner" },
{ "key07", "Pencils", .10, 5, "Tim Pick" },
{ "key08", "Markers", .95, 3, "Mary Miner" },
{ "key09", "Fax Paper", 3.89, 100, "Bob Coal" },
{ "key10", "3.5\" Disks", 15.23, 30, "Tim Pick" },
{ "key11", "8mm Tape", 32.22, 2, "Bob Coal" },
{ "key12", "Toner", 35.69, 1, "Tim Pick" },
{ "key13", "Paper Cups", 4.25, 3, "Bob Coal" },
{ "key14", "Paper Clips", 2.09, 3, "Tim Pick" },
};
DbTableRow *dbFindRow(rowKey)
char *rowKey;
{
int i;
for (i = 0; i < dbTableNumRows; i++)
if (!strcmp(rowKey, dbTableRows[i].key))
return &dbTableRows[i];
return 0;
}
int dbCompareRowKeys(userData, l, r)
void *userData;
void *l;
void *r;
{
DbTableRow *dbRow1, *dbRow2;
float u1, u2;
dbRow1 = dbFindRow(*(char **)l);
dbRow2 = dbFindRow(*(char **)r);
switch ((int)userData)
{
case Desc:
return strcmp(dbRow1->desc, dbRow2->desc);
case Price:
u1 = dbRow1->price - dbRow2->price;
if (u1 < 0)
return -1;
else if (u1 == 0)
return 0;
return 1;
case Qty:
return dbRow1->qty - dbRow2->qty;
case UnitPrice:
u1 = dbRow1->price / (float)dbRow1->qty;
u2 = dbRow2->price / (float)dbRow2->qty;
if (u1 < u2)
return -1;
else if (u1 == u2)
return 0;
else
return 1;
case Buyer:
return strcmp(dbRow1->buyer, dbRow2->buyer);
}
return (int)(dbRow1 - dbRow2);
}
char **dbGetRowKeysSorted(sortColumnID)
int sortColumnID;
{
char **keys;
int i;
keys = (char **)malloc(sizeof(char *) * dbTableNumRows);
for (i = 0; i < dbTableNumRows; i++)
keys[i] = dbTableRows[i].key;
XmLSort(keys, dbTableNumRows, sizeof(char *),
dbCompareRowKeys, (void *)sortColumnID);
return keys;
}
/* GRID FUNCTIONS */
void setRowKeysInGridSorted(grid, sortColumnID)
Widget grid;
int sortColumnID;
{
char **keys;
int i;
keys = dbGetRowKeysSorted(sortColumnID);
/* Place a pointer to each row key in each rows userData */
for (i = 0; i < dbTableNumRows; i++)
XtVaSetValues(grid,
XmNrow, i,
XmNrowUserData, (XtPointer)keys[i],
NULL);
free((char *)keys);
}
void cellSelect(w, clientData, callData)
Widget w;
XtPointer clientData;
XtPointer callData;
{
XmLGridCallbackStruct *cbs;
XmLGridColumn column;
XtPointer columnUserData;
cbs = (XmLGridCallbackStruct *)callData;
if (cbs->rowType != XmHEADING)
return;
/* Cancel any edits in progress */
XmLGridEditCancel(w);
column = XmLGridGetColumn(w, cbs->columnType, cbs->column);
XtVaGetValues(w,
XmNcolumnPtr, column,
XmNcolumnUserData, &columnUserData,
NULL);
XtVaSetValues(w,
XmNcolumn, cbs->column,
XmNcolumnSortType, XmSORT_ASCENDING,
NULL);
setRowKeysInGridSorted(w, (DbTableColumnID)columnUserData);
XmLGridRedrawAll(w);
}
void cellDraw(w, clientData, callData)
Widget w;
XtPointer clientData;
XtPointer callData;
{
XmLGridCallbackStruct *cbs;
XmLGridDrawStruct *ds;
XmLGridRow row;
XmLGridColumn column;
XtPointer rowUserData, columnUserData;
DbTableRow *dbRow;
XRectangle cellRect;
int horizMargin, vertMargin;
XmString str;
char buf[50];
cbs = (XmLGridCallbackStruct *)callData;
if (cbs->rowType != XmCONTENT)
return;
ds = cbs->drawInfo;
/* Retrieve userData from the cells row */
row = XmLGridGetRow(w, cbs->rowType, cbs->row);
XtVaGetValues(w,
XmNrowPtr, row,
XmNrowUserData, &rowUserData,
NULL);
/* Retrieve userData from cells column */
column = XmLGridGetColumn(w, cbs->columnType, cbs->column);
XtVaGetValues(w,
XmNcolumnPtr, column,
XmNcolumnUserData, &columnUserData,
NULL);
/* Retrieve the cells value from the database */
dbRow = dbFindRow((char *)rowUserData);
switch ((DbTableColumnID)columnUserData)
{
case Desc:
sprintf(buf, "%s", dbRow->desc);
break;
case Price:
sprintf(buf, "$%4.2f", dbRow->price);
break;
case Qty:
sprintf(buf, "%d", dbRow->qty);
break;
case UnitPrice:
sprintf(buf, "$%4.2f", dbRow->price / (float)dbRow->qty);
break;
case Buyer:
sprintf(buf, "%s", dbRow->buyer);
break;
}
/* Compensate for cell margins */
cellRect = *ds->cellRect;
horizMargin = ds->leftMargin + ds->rightMargin;
vertMargin = ds->topMargin + ds->bottomMargin;
if (horizMargin >= (int)cellRect.width ||
vertMargin >= (int)cellRect.height)
return;
cellRect.x += ds->leftMargin;
cellRect.y += ds->topMargin;
cellRect.width -= horizMargin;
cellRect.height -= vertMargin;
/* Draw the string */
str = XmStringCreateSimple(buf);
if (ds->drawSelected == True)
XSetForeground(XtDisplay(w), ds->gc, ds->selectForeground);
else
XSetForeground(XtDisplay(w), ds->gc, ds->foreground);
XmLStringDraw(w, str, ds->stringDirection, ds->fontList,
ds->alignment, ds->gc, &cellRect, cbs->clipRect);
XmStringFree(str);
}
void cellEdit(w, clientData, callData)
Widget w;
XtPointer clientData;
XtPointer callData;
{
XmLGridCallbackStruct *cbs;
XmLGridRow row;
XmLGridColumn column;
XtPointer rowUserData, columnUserData;
DbTableRow *dbRow;
Widget text;
float f;
int i;
char *value;
Boolean redrawRow;
cbs = (XmLGridCallbackStruct *)callData;
/* For a production version, this function should also
handle XmCR_EDIT_INSERT by retrieving the current value
from the database and performing an XmTextSetString on
the text widget in the grid with that value. This allows
a user to hit insert or F2 to modify an existing cell value */
if (cbs->reason != XmCR_EDIT_COMPLETE)
return;
/* Get the value the user just typed in */
XtVaGetValues(w,
XmNtextWidget, &text,
NULL);
value = XmTextGetString(text);
if (!value)
return;
/* Retrieve userData from the cells row */
row = XmLGridGetRow(w, cbs->rowType, cbs->row);
XtVaGetValues(w,
XmNrowPtr, row,
XmNrowUserData, &rowUserData,
NULL);
/* Retrieve userData from cells column */
column = XmLGridGetColumn(w, cbs->columnType, cbs->column);
XtVaGetValues(w,
XmNcolumnPtr, column,
XmNcolumnUserData, &columnUserData,
NULL);
/* Set new value in the database */
redrawRow = False;
dbRow = dbFindRow((char *)rowUserData);
switch ((DbTableColumnID)columnUserData)
{
case Desc:
if ((int)strlen(value) < 20)
strcpy(dbRow->desc, value);
break;
case Price:
if (sscanf(value, "%f", &f) == 1)
{
dbRow->price = f;
redrawRow = True;
}
break;
case Qty:
if (sscanf(value, "%d", &i) == 1)
{
dbRow->qty = i;
redrawRow = True;
}
break;
case Buyer:
if ((int)strlen(value) < 20)
strcpy(dbRow->buyer, value);
break;
}
/* Redraw the row if we need to redisplay unit price */
if (redrawRow == True)
XmLGridRedrawRow(w, cbs->rowType, cbs->row);
/* Set the cellString to NULL - its is set to the value the
user typed in the text widget at this point */
XtVaSetValues(w,
XmNrow, cbs->row,
XmNcolumn, cbs->column,
XmNcellString, NULL,
NULL);
XtFree(value);
}
main(argc, argv)
int argc;
char *argv[];
{
XtAppContext app;
Widget shell, grid;
XmString str;
int i;
shell = XtAppInitialize(&app, "Grid6", NULL, 0,
&argc, argv, NULL, NULL, 0);
grid = XtVaCreateManagedWidget("grid",
xmlGridWidgetClass, shell,
XmNhorizontalSizePolicy, XmVARIABLE,
XmNvisibleRows, 10,
XmNvsbDisplayPolicy, XmSTATIC,
XmNselectionPolicy, XmSELECT_NONE,
XmNshadowThickness, 0,
XtVaTypedArg, XmNbackground, XmRString, "#C0C0C0", 8,
XtVaTypedArg, XmNforeground, XmRString, "black", 6,
NULL);
XtAddCallback(grid, XmNcellDrawCallback, cellDraw, NULL);
XtAddCallback(grid, XmNeditCallback, cellEdit, NULL);
XtAddCallback(grid, XmNselectCallback, cellSelect, NULL);
XtVaSetValues(grid,
XmNlayoutFrozen, True,
NULL);
XmLGridAddColumns(grid, XmCONTENT, -1, dbTableNumColumns);
/* Setup columns and column cell defaults based on */
/* database description */
for (i = 0; i < dbTableNumColumns; i++)
{
/* Set the width and the id on the column */
XtVaSetValues(grid,
XmNcolumn, i,
XmNcolumnUserData, (XtPointer)dbTableColumns[i].id,
XmNcolumnWidth, dbTableColumns[i].width,
NULL);
/* Set the default cell alignment and editibility for */
/* cells in the column */
XtVaSetValues(grid,
XmNcellDefaults, True,
XmNcolumn, i,
XmNcellAlignment, dbTableColumns[i].cellAlignment,
XmNcellEditable, dbTableColumns[i].cellEditable,
NULL);
}
/* Add the heading row */
XmLGridAddRows(grid, XmHEADING, -1, 1);
/* Set the column headings */
for (i = 0; i < dbTableNumColumns; i++)
{
/* Set the column heading label */
str = XmStringCreateSimple(dbTableColumns[i].label);
XtVaSetValues(grid,
XmNrowType, XmHEADING,
XmNrow, 0,
XmNcolumn, i,
XmNcellString, str,
NULL);
XmStringFree(str);
}
/* Set cell defaults for content rows */
XtVaSetValues(grid,
XmNcellDefaults, True,
XtVaTypedArg, XmNcellBackground, XmRString, "white", 6,
XmNcellLeftBorderType, XmBORDER_NONE,
XmNcellRightBorderType, XmBORDER_NONE,
XmNcellTopBorderType, XmBORDER_NONE,
XmNcellBottomBorderType, XmBORDER_NONE,
XmNcellMarginLeft, 1,
XmNcellMarginRight, 1,
NULL);
XmLGridAddRows(grid, XmCONTENT, -1, dbTableNumRows);
XtVaSetValues(grid,
XmNlayoutFrozen, False,
NULL);
/* Set the row keys in the rows */
setRowKeysInGridSorted(grid, Desc);
XtRealizeWidget(shell);
XtAppMainLoop(app);
}