home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / xfe / Microline3.0 / examples / grid6.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  11.5 KB  |  462 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * The following source code is part of the Microline Widget Library.
  21.  * The Microline widget library is made available to Mozilla developers
  22.  * under the Netscape Public License (NPL) by Neuron Data.  To learn
  23.  * more about Neuron Data, please visit the Neuron Data Home Page at
  24.  * http://www.neurondata.com.
  25.  */
  26.  
  27.  
  28. #include <Xm/Xm.h>
  29. #include <Xm/Text.h>
  30. #include <XmL/Grid.h>
  31.  
  32. /* DATABASE PROTOTYPE FUNCTIONS */
  33.  
  34. int dbTableNumRows = 14;
  35. int dbTableNumColumns = 5;
  36.  
  37. typedef enum {
  38.     ID, Desc, Price, Qty, UnitPrice, Buyer 
  39. }
  40. DbTableColumnID;
  41.  
  42. typedef struct
  43.     {
  44.     DbTableColumnID id;
  45.     char label[15];
  46.     int width;
  47.     unsigned char cellAlignment;
  48.     Boolean cellEditable;
  49. } DbTableColumn;
  50.  
  51. DbTableColumn dbTableColumns[] =
  52. {
  53.     { Desc,      "Description", 16, XmALIGNMENT_LEFT,  True  },
  54.     { Price,     "Price",       9,  XmALIGNMENT_RIGHT, True  },
  55.     { Qty,       "Qty",         5,  XmALIGNMENT_RIGHT, True  },
  56.     { UnitPrice, "Unit Prc",    9,  XmALIGNMENT_RIGHT, False },
  57.     { Buyer,     "Buyer",       15, XmALIGNMENT_LEFT,  True  },
  58. };
  59.  
  60. typedef struct
  61.     {
  62.     char key[10];
  63.     char desc[20];
  64.     float price;
  65.     int qty;
  66.     char buyer[20];
  67. } DbTableRow;
  68.  
  69. DbTableRow dbTableRows[] =
  70. {
  71.     { "key01", "Staples",        1.32, 100, "Tim Pick"   },
  72.     { "key02", "Notebooks",      1.11,   4, "Mary Miner" },
  73.     { "key03", "3-Ring Binders", 2.59,   2, "Mary Miner" },
  74.     { "key04", "Pads",           1.23,   3, "Tim Pick"   },
  75.     { "key05", "Scissors",       4.41,   1, "Mary Miner" },
  76.     { "key06", "Pens",            .29,   4, "Mary Miner" },
  77.     { "key07", "Pencils",         .10,   5, "Tim Pick"   },
  78.     { "key08", "Markers",         .95,   3, "Mary Miner" },
  79.     { "key09", "Fax Paper",      3.89, 100, "Bob Coal"   },
  80.     { "key10", "3.5\" Disks",   15.23,  30, "Tim Pick"   },
  81.     { "key11", "8mm Tape",      32.22,   2, "Bob Coal"   },
  82.     { "key12", "Toner",         35.69,   1, "Tim Pick"   },
  83.     { "key13", "Paper Cups",     4.25,   3, "Bob Coal"   },
  84.     { "key14", "Paper Clips",    2.09,   3, "Tim Pick"   },
  85. };
  86.  
  87. DbTableRow *dbFindRow(rowKey)
  88. char *rowKey;
  89. {
  90.     int i;
  91.  
  92.     for (i = 0; i < dbTableNumRows; i++)
  93.         if (!strcmp(rowKey, dbTableRows[i].key))
  94.             return &dbTableRows[i];
  95.     return 0;
  96. }
  97.  
  98. int dbCompareRowKeys(userData, l, r)
  99. void *userData;
  100. void *l;
  101. void *r;
  102. {
  103.     DbTableRow *dbRow1, *dbRow2;
  104.     float u1, u2;
  105.  
  106.     dbRow1 = dbFindRow(*(char **)l);
  107.     dbRow2 = dbFindRow(*(char **)r);
  108.     switch ((int)userData)
  109.     {
  110.     case Desc:
  111.         return strcmp(dbRow1->desc, dbRow2->desc);
  112.     case Price:
  113.         u1 = dbRow1->price - dbRow2->price;
  114.         if (u1 < 0)
  115.             return -1;
  116.         else if (u1 == 0)
  117.             return 0;
  118.         return 1;
  119.     case Qty:
  120.         return dbRow1->qty - dbRow2->qty;
  121.     case UnitPrice:
  122.         u1 = dbRow1->price / (float)dbRow1->qty;
  123.         u2 = dbRow2->price / (float)dbRow2->qty;
  124.         if (u1 < u2)
  125.             return -1;
  126.         else if (u1 == u2)
  127.             return 0;
  128.         else
  129.             return 1;
  130.     case Buyer:
  131.         return strcmp(dbRow1->buyer, dbRow2->buyer);
  132.     }
  133.     return (int)(dbRow1 - dbRow2);
  134. }
  135.  
  136. char **dbGetRowKeysSorted(sortColumnID)
  137. int sortColumnID;
  138. {
  139.     char **keys;
  140.     int i;
  141.  
  142.     keys = (char **)malloc(sizeof(char *) * dbTableNumRows);
  143.     for (i = 0; i < dbTableNumRows; i++)
  144.         keys[i] = dbTableRows[i].key;
  145.     XmLSort(keys, dbTableNumRows, sizeof(char *),
  146.         dbCompareRowKeys, (void *)sortColumnID);
  147.     return keys;
  148. }
  149.  
  150. /* GRID FUNCTIONS */
  151.  
  152. void setRowKeysInGridSorted(grid, sortColumnID)
  153. Widget grid;
  154. int sortColumnID;
  155. {
  156.     char **keys;
  157.     int i;
  158.  
  159.     keys = dbGetRowKeysSorted(sortColumnID);
  160.     /* Place a pointer to each row key in each rows userData */
  161.     for (i = 0; i < dbTableNumRows; i++)
  162.         XtVaSetValues(grid,
  163.             XmNrow, i,
  164.             XmNrowUserData, (XtPointer)keys[i],
  165.             NULL);
  166.     free((char *)keys);
  167. }
  168.  
  169. void cellSelect(w, clientData, callData)
  170. Widget w;
  171. XtPointer clientData;
  172. XtPointer callData;
  173. {
  174.     XmLGridCallbackStruct *cbs;
  175.     XmLGridColumn column;
  176.     XtPointer columnUserData;
  177.  
  178.     cbs = (XmLGridCallbackStruct *)callData;
  179.  
  180.     if (cbs->rowType != XmHEADING)
  181.         return;
  182.  
  183.     /* Cancel any edits in progress */
  184.     XmLGridEditCancel(w);
  185.  
  186.     column = XmLGridGetColumn(w, cbs->columnType, cbs->column);
  187.     XtVaGetValues(w,
  188.         XmNcolumnPtr, column,
  189.         XmNcolumnUserData, &columnUserData,
  190.         NULL);
  191.     setRowKeysInGridSorted(w, (DbTableColumnID)columnUserData);
  192.     XmLGridRedrawAll(w);
  193. }
  194.  
  195. void cellDraw(w, clientData, callData)
  196. Widget w;
  197. XtPointer clientData;
  198. XtPointer callData;
  199. {
  200.     XmLGridCallbackStruct *cbs;
  201.     XmLGridDrawStruct *ds;
  202.     XmLGridRow row;
  203.     XmLGridColumn column;
  204.     XtPointer rowUserData, columnUserData;
  205.     DbTableRow *dbRow;
  206.     XRectangle cellRect;
  207.     int horizMargin, vertMargin;
  208.     XmString str;
  209.     char buf[50];
  210.  
  211.     cbs = (XmLGridCallbackStruct *)callData;
  212.     if (cbs->rowType != XmCONTENT)
  213.         return;
  214.  
  215.     ds = cbs->drawInfo;
  216.  
  217.     /* Retrieve userData from the cells row */
  218.     row = XmLGridGetRow(w, cbs->rowType, cbs->row);
  219.     XtVaGetValues(w,
  220.         XmNrowPtr, row,
  221.         XmNrowUserData, &rowUserData,
  222.         NULL);
  223.  
  224.     /* Retrieve userData from cells column */
  225.     column = XmLGridGetColumn(w, cbs->columnType, cbs->column);
  226.     XtVaGetValues(w,
  227.         XmNcolumnPtr, column,
  228.         XmNcolumnUserData, &columnUserData,
  229.         NULL);
  230.  
  231.     /* Retrieve the cells value from the database */
  232.     dbRow = dbFindRow((char *)rowUserData);
  233.     switch ((DbTableColumnID)columnUserData)
  234.     {
  235.     case Desc:
  236.         sprintf(buf, "%s", dbRow->desc);
  237.         break;
  238.     case Price:
  239.         sprintf(buf, "$%4.2f", dbRow->price);
  240.         break;
  241.     case Qty:
  242.         sprintf(buf, "%d", dbRow->qty);
  243.         break;
  244.     case UnitPrice:
  245.         sprintf(buf, "$%4.2f", dbRow->price / (float)dbRow->qty);
  246.         break;
  247.     case Buyer:
  248.         sprintf(buf, "%s", dbRow->buyer);
  249.         break;
  250.     }
  251.  
  252.     /* Compensate for cell margins */
  253.     cellRect = *ds->cellRect;
  254.     horizMargin = ds->leftMargin + ds->rightMargin;
  255.     vertMargin = ds->topMargin + ds->bottomMargin;
  256.     if (horizMargin >= (int)cellRect.width ||
  257.         vertMargin >= (int)cellRect.height)
  258.         return;
  259.     cellRect.x += ds->leftMargin;
  260.     cellRect.y += ds->topMargin;
  261.     cellRect.width -= horizMargin;
  262.     cellRect.height -= vertMargin;
  263.  
  264.     /* Draw the string */
  265.     str = XmStringCreateSimple(buf);
  266.     if (ds->drawSelected == True)
  267.         XSetForeground(XtDisplay(w), ds->gc, ds->selectForeground);
  268.     else
  269.         XSetForeground(XtDisplay(w), ds->gc, ds->foreground);
  270.     XmLStringDraw(w, str, ds->stringDirection, ds->fontList,
  271.         ds->alignment, ds->gc, &cellRect, cbs->clipRect);
  272.     XmStringFree(str);
  273. }
  274.  
  275. void cellEdit(w, clientData, callData)
  276. Widget w;
  277. XtPointer clientData;
  278. XtPointer callData;
  279. {
  280.     XmLGridCallbackStruct *cbs;
  281.     XmLGridRow row;
  282.     XmLGridColumn column;
  283.     XtPointer rowUserData, columnUserData;
  284.     DbTableRow *dbRow;
  285.     Widget text;
  286.     float f;
  287.     int i;
  288.     char *value;
  289.     Boolean redrawRow;
  290.  
  291.     cbs = (XmLGridCallbackStruct *)callData;
  292.  
  293.     /* For a production version, this function should also
  294.        handle XmCR_EDIT_INSERT by retrieving the current value
  295.        from the database and performing an XmTextSetString on
  296.        the text widget in the grid with that value.  This allows
  297.        a user to hit insert or F2 to modify an existing cell value */
  298.  
  299.     if (cbs->reason != XmCR_EDIT_COMPLETE)
  300.         return;
  301.  
  302.     /* Get the value the user just typed in */
  303.     XtVaGetValues(w,
  304.         XmNtextWidget, &text,
  305.         NULL);
  306.     value = XmTextGetString(text);
  307.     if (!value)
  308.         return;
  309.  
  310.     /* Retrieve userData from the cells row */
  311.     row = XmLGridGetRow(w, cbs->rowType, cbs->row);
  312.     XtVaGetValues(w,
  313.         XmNrowPtr, row,
  314.         XmNrowUserData, &rowUserData,
  315.         NULL);
  316.  
  317.     /* Retrieve userData from cells column */
  318.     column = XmLGridGetColumn(w, cbs->columnType, cbs->column);
  319.     XtVaGetValues(w,
  320.         XmNcolumnPtr, column,
  321.         XmNcolumnUserData, &columnUserData,
  322.         NULL);
  323.  
  324.     /* Set new value in the database */
  325.     redrawRow = False;
  326.     dbRow = dbFindRow((char *)rowUserData);
  327.     switch ((DbTableColumnID)columnUserData)
  328.     {
  329.     case Desc:
  330.         if ((int)strlen(value) < 20)
  331.             strcpy(dbRow->desc, value);
  332.         break;
  333.     case Price:
  334.         if (sscanf(value, "%f", &f) == 1)
  335.         {
  336.             dbRow->price = f;
  337.             redrawRow = True;
  338.         }
  339.         break;
  340.     case Qty:
  341.         if (sscanf(value, "%d", &i) == 1)
  342.         {
  343.             dbRow->qty = i;
  344.             redrawRow = True;
  345.         }
  346.         break;
  347.     case Buyer:
  348.         if ((int)strlen(value) < 20)
  349.             strcpy(dbRow->buyer, value);
  350.         break;
  351.     }
  352.  
  353.     /* Redraw the row if we need to redisplay unit price */
  354.     if (redrawRow == True)
  355.         XmLGridRedrawRow(w, cbs->rowType, cbs->row);
  356.  
  357.     /* Set the cellString to NULL - its is set to the value the
  358.            user typed in the text widget at this point */
  359.     XtVaSetValues(w,
  360.         XmNrow, cbs->row,
  361.         XmNcolumn, cbs->column,
  362.         XmNcellString, NULL,
  363.         NULL);
  364.  
  365.     XtFree(value);
  366. }
  367.  
  368. main(argc, argv)
  369. int argc;
  370. char *argv[];
  371. {
  372.     XtAppContext app;
  373.     Widget shell, grid;
  374.     XmString str;
  375.     int i;
  376.  
  377.     shell =  XtAppInitialize(&app, "Grid6", NULL, 0,
  378.         &argc, argv, NULL, NULL, 0);
  379.  
  380.     grid = XtVaCreateManagedWidget("grid",
  381.         xmlGridWidgetClass, shell,
  382.         XmNhorizontalSizePolicy, XmVARIABLE,
  383.         XmNvisibleRows, 10,
  384.         XmNvsbDisplayPolicy, XmSTATIC,
  385.         XmNselectionPolicy, XmSELECT_NONE,
  386.         XmNshadowThickness, 0,
  387.         XtVaTypedArg, XmNbackground, XmRString, "#C0C0C0", 8,
  388.         XtVaTypedArg, XmNforeground, XmRString, "black", 6,
  389.         NULL);
  390.     XtAddCallback(grid, XmNcellDrawCallback, cellDraw, NULL);
  391.     XtAddCallback(grid, XmNeditCallback, cellEdit, NULL);
  392.     XtAddCallback(grid, XmNselectCallback, cellSelect, NULL);
  393.  
  394.     XtVaSetValues(grid,
  395.         XmNlayoutFrozen, True,
  396.         NULL);
  397.  
  398.     XmLGridAddColumns(grid, XmCONTENT, -1, dbTableNumColumns);
  399.  
  400.     /* Setup columns and column cell defaults based on */
  401.     /* database description */
  402.     for (i = 0; i < dbTableNumColumns; i++)
  403.     {
  404.         /* Set the width and the id on the column */
  405.         XtVaSetValues(grid,
  406.             XmNcolumn, i,
  407.             XmNcolumnUserData, (XtPointer)dbTableColumns[i].id,
  408.             XmNcolumnWidth, dbTableColumns[i].width,
  409.             NULL);
  410.  
  411.         /* Set the default cell alignment and editibility for */
  412.         /* cells in the column */
  413.         XtVaSetValues(grid,
  414.             XmNcellDefaults, True,
  415.             XmNcolumn, i,
  416.             XmNcellAlignment, dbTableColumns[i].cellAlignment,
  417.             XmNcellEditable, dbTableColumns[i].cellEditable,
  418.             NULL);
  419.     }
  420.  
  421.     /* Add the heading row */
  422.     XmLGridAddRows(grid, XmHEADING, -1, 1);
  423.  
  424.     /* Set the column headings */
  425.     for (i = 0; i < dbTableNumColumns; i++)
  426.     {
  427.         /* Set the column heading label */
  428.         str = XmStringCreateSimple(dbTableColumns[i].label);
  429.         XtVaSetValues(grid,
  430.             XmNrowType, XmHEADING,
  431.             XmNrow, 0,
  432.             XmNcolumn, i,
  433.             XmNcellString, str,
  434.             NULL);
  435.         XmStringFree(str);
  436.     }
  437.  
  438.     /* Set cell defaults for content rows */
  439.     XtVaSetValues(grid,
  440.         XmNcellDefaults, True,
  441.         XtVaTypedArg, XmNcellBackground, XmRString, "white", 6,
  442.         XmNcellLeftBorderType, XmBORDER_NONE,
  443.         XmNcellRightBorderType, XmBORDER_NONE,
  444.         XmNcellTopBorderType, XmBORDER_NONE,
  445.         XmNcellBottomBorderType, XmBORDER_NONE,
  446.         XmNcellMarginLeft, 1,
  447.         XmNcellMarginRight, 1,
  448.         NULL);
  449.  
  450.     XmLGridAddRows(grid, XmCONTENT, -1, dbTableNumRows);
  451.  
  452.     XtVaSetValues(grid,
  453.         XmNlayoutFrozen, False,
  454.         NULL);
  455.  
  456.     /* Set the row keys in the rows */
  457.     setRowKeysInGridSorted(grid, Desc);
  458.  
  459.     XtRealizeWidget(shell);
  460.     XtAppMainLoop(app);
  461. }
  462.