home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / WXWIN140.ZIP / SRC / WX_FORM.CC < prev    next >
C/C++ Source or Header  |  1993-04-18  |  27KB  |  1,155 lines

  1. /*
  2.  * File:     wx_form.cc
  3.  * Purpose:  Form handling code
  4.  *
  5.  *                       wxWindows 1.40
  6.  * Copyright (c) 1993 Artificial Intelligence Applications Institute,
  7.  *                   The University of Edinburgh
  8.  *
  9.  *                     Author: Julian Smart
  10.  *                       Date: 18-4-93
  11.  *
  12.  * Permission to use, copy, modify, and distribute this software and its
  13.  * documentation for any purpose is hereby granted without fee, provided
  14.  * that the above copyright notice, author statement and this permission
  15.  * notice appear in all copies of this software and related documentation.
  16.  *
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS,
  18.  * IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
  19.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  20.  *
  21.  * IN NO EVENT SHALL THE ARTIFICIAL INTELLIGENCE APPLICATIONS INSTITUTE OR THE
  22.  * UNIVERSITY OF EDINBURGH BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR
  23.  * CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER RESULTING FROM
  24.  * LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF
  25.  * DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
  26.  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <windows.h>
  30. #include <iostream.h>
  31. #include <stdio.h>
  32. #include <stdarg.h>
  33. #include "common.h"
  34. #include "wx_utils.h"
  35. #include "wx_dialg.h"
  36. #include "wx_form.h"
  37.  
  38. // Helper function
  39. wxFormItemConstraint *wxFormConstraintsContains(int type, wxList *constraints);
  40.  
  41. // Display items and callback functions
  42. class wxFormButton: public wxButton
  43. {
  44.  public:
  45.   wxForm *form;
  46.   wxFormButton(wxPanel *panel, wxFunction func, char *label,
  47.                int x = -1, int y = -1, int width = -1, int height = -1);
  48. };
  49.  
  50. void wxFormOk(wxFormButton& button, wxEvent& event);
  51. void wxFormRevert(wxFormButton& button, wxEvent& event);
  52. void wxFormCancel(wxFormButton& button, wxEvent& event);
  53. void wxFormUpdate(wxFormButton& button, wxEvent& event);
  54.  
  55. /*
  56.  * Range
  57.  *
  58.  */
  59.  
  60. wxRealRange::wxRealRange(float the_lo, float the_hi)
  61. {
  62.   lo = the_lo;
  63.   hi = the_hi;
  64. }
  65.  
  66. /*
  67.  * Form item constraint
  68.  *
  69.  */
  70.  
  71. wxFormItemConstraint::wxFormItemConstraint(int type)
  72. {
  73.   Type = type;
  74. }
  75.  
  76. wxFormItemConstraint::~wxFormItemConstraint(void)
  77. {
  78.   switch (Type)
  79.   {
  80.     case wxFORM_CONSTRAINT_ONE_OF:
  81.     {
  82.       wxNode *node = Constraint.OneOf->First();
  83.       while (node)
  84.       {
  85.         char *s = (char *)node->Data();
  86.         wxNode *next = node->Next();
  87.         delete s;
  88.         delete node;
  89.         node = next;
  90.       }
  91.       break;
  92.     }
  93.     default:
  94.       break;
  95.   }
  96. }
  97.  
  98. /*
  99.  * Form item
  100.  *
  101.  */
  102.  
  103. wxFormItem::wxFormItem(int type, int item_type)
  104. {
  105.   Id = 0;
  106.   Type = type;
  107.   ItemType = item_type;
  108.   PanelItem = NULL;
  109.   Constraints = NULL;
  110.   CustomEditor = NULL;
  111.   HelpString = NULL;
  112.   Label = NULL;
  113.   Height = -1;
  114.   Width = -1;
  115. }
  116.  
  117. wxFormItem::~wxFormItem(void)
  118. {
  119.   if (HelpString)
  120.     delete HelpString;
  121.   if (Label)
  122.     delete Label;
  123.  
  124.   Form->FormItems.DeleteObject(this);
  125.  
  126.   if (Constraints)
  127.   {
  128.     wxNode *node = Constraints->First();
  129.     while (node)
  130.     {
  131.       wxFormItemConstraint *constraint = (wxFormItemConstraint *)node->Data();
  132.       delete constraint;
  133.       node = node->Next();
  134.     }
  135.     delete Constraints;
  136.   }
  137. }
  138.  
  139. void wxFormItem::MakePanelItem(wxPanel *panel)
  140. {
  141.   switch (Type)
  142.   {
  143.     case wxFORM_STRING:
  144.     {
  145.       switch (ItemType)
  146.       {
  147.         case wxFORM_SINGLE_LIST:
  148.         {
  149.           PanelItem = new wxListBox(panel, (wxFunction)NULL, Label, wxSINGLE,
  150.                                     -1, -1, Width, Height);
  151.           wxListBox *listbox = (wxListBox *)PanelItem;
  152.           wxFormItemConstraint *constraint =
  153.             wxFormConstraintsContains(wxFORM_CONSTRAINT_ONE_OF, Constraints);
  154.           if (constraint)
  155.           {
  156.             wxNode *node = constraint->Constraint.OneOf->First();
  157.             while (node)
  158.             {
  159.               char *s = (char *)node->Data();
  160.               listbox->Append(s);
  161.               node = node->Next();
  162.             }
  163.           }
  164.           break;
  165.         }
  166.         case wxFORM_CHOICE:
  167.         {
  168.           PanelItem = new wxChoice(panel, (wxFunction)NULL, Label,
  169.                                     -1, -1, Width, Height);
  170.           wxChoice *choice = (wxChoice *)PanelItem;
  171.           wxFormItemConstraint *constraint =
  172.             wxFormConstraintsContains(wxFORM_CONSTRAINT_ONE_OF, Constraints);
  173.           if (constraint)
  174.           {
  175.             wxNode *node = constraint->Constraint.OneOf->First();
  176.             while (node)
  177.             {
  178.               char *s = (char *)node->Data();
  179.               choice->Append(s);
  180.               node = node->Next();
  181.             }
  182.           }
  183.           break;
  184.         }
  185.         case wxFORM_TEXT:
  186.         {
  187.           PanelItem = new wxText(panel, (wxFunction)NULL, Label, "", -1, -1,
  188.                                  Width, Height);
  189.           break;
  190.         }
  191.         default:
  192.           break;
  193.       }
  194.       break;
  195.     }
  196.     case wxFORM_DUMB_MESSAGE:
  197.     {
  198.       PanelItem = new wxMessage(panel, Label);
  199.       break;
  200.     }
  201.     case wxFORM_BUTTON:
  202.     {
  203.       PanelItem = new wxButton(panel, ButtonFunc, Label, -1, -1, Width, Height);
  204.       break;
  205.     }
  206.     case wxFORM_NEWLINE:
  207.     {
  208.       panel->NewLine();
  209.       break;
  210.     }
  211.     case wxFORM_SHORT:
  212.     case wxFORM_LONG:
  213.     {
  214.       switch (ItemType)
  215.       {
  216.         case wxFORM_SLIDER:
  217.         {
  218.           int lo = -100;
  219.           int hi = 100;
  220.           int width = 230;
  221.           wxFormItemConstraint *constraint =
  222.             wxFormConstraintsContains(wxFORM_CONSTRAINT_RANGE, Constraints);
  223.           if (constraint)
  224.           {
  225.             wxRealRange *range = constraint->Constraint.Range;
  226.             lo = (int)range->lo;
  227.             hi = (int)range->hi;
  228.           }
  229.           int default_value;
  230.           if (Type == wxFORM_SHORT)
  231.             default_value = *(ValuePtr.ShortIntValuePtr);
  232.           else
  233.             default_value = (int)*(ValuePtr.LongIntValuePtr);
  234.  
  235.           PanelItem = new wxSlider(panel, (wxFunction)NULL, Label,
  236.                                    default_value, lo, hi, width);
  237.           break;
  238.         }
  239.         case wxFORM_TEXT:
  240.         default:
  241.         {
  242.           PanelItem = new wxText(panel, (wxFunction)NULL, Label, "", -1, -1,
  243.                                  Width, Height);
  244.           break;
  245.         }
  246.       }
  247.       break;
  248.     }
  249.  
  250.     case wxFORM_BOOL:
  251.     {
  252.       switch (ItemType)
  253.       {
  254.         case wxFORM_CHECKBOX:
  255.         default:
  256.         {
  257.           PanelItem = new wxCheckBox(panel, (wxFunction)NULL, Label, -1, -1,
  258.                                  Width, Height);
  259.           break;
  260.         }
  261.       }
  262.       break;
  263.     }
  264.     case wxFORM_FLOAT:
  265.     {
  266.       switch (ItemType)
  267.       {
  268.         case wxFORM_TEXT:
  269.         default:
  270.         {
  271.           PanelItem = new wxText(panel, (wxFunction)NULL, Label, "", -1, -1,
  272.                                  Width, Height);
  273.           break;
  274.         }
  275.       }
  276.       break;
  277.     }
  278.     case wxFORM_LIST_OF_STRINGS:
  279.     {
  280.       break;
  281.     }
  282.     case wxFORM_LIST_OF_LONGS:
  283.     {
  284.       break;
  285.     }
  286.  
  287.     default:
  288.       break;
  289.   }
  290. }
  291.  
  292. Bool wxFormItem::CheckLongValue(long val)
  293. {
  294.   char msg_buf[300];
  295.   if (Constraints)
  296.   {
  297.     wxNode *node = Constraints->First();
  298.     Bool ok = TRUE;
  299.     while (node && ok)
  300.     {
  301.       wxFormItemConstraint *constraint = (wxFormItemConstraint *)node->Data();
  302.       switch (constraint->Type)
  303.       {
  304.         case wxFORM_CONSTRAINT_RANGE:
  305.         {
  306.           wxRealRange *range = constraint->Constraint.Range;
  307.           if ((range->lo > (float)val) || (range->hi < (float)val))
  308.           {
  309.             sprintf(msg_buf, "%s should be in range %.0f to %.0f",
  310.                     Label, range->lo, range->hi);
  311.             ok = FALSE;
  312.           }
  313.           break;
  314.         }
  315.         case wxFORM_CONSTRAINT_FUNCTION:
  316.         {
  317.           ok = (*(constraint->Constraint.ConstraintFunc))(Type, (char *)&val, Label, msg_buf);
  318.           break;
  319.         }
  320.         default:
  321.           break;
  322.       }
  323.       if (!ok)
  324.       {
  325.         (void)wxMessageBox(msg_buf, "Constraint violation", wxOK);
  326.       }
  327.       node = node->Next();
  328.     }
  329.     return ok;
  330.   }
  331.   else return TRUE;
  332. }
  333.  
  334. Bool wxFormItem::CheckBoolValue(Bool val)
  335. {
  336.   char msg_buf[300];
  337.   if (Constraints)
  338.   {
  339.     wxNode *node = Constraints->First();
  340.     Bool ok = TRUE;
  341.     while (node && ok)
  342.     {
  343.       wxFormItemConstraint *constraint = (wxFormItemConstraint *)node->Data();
  344.       switch (constraint->Type)
  345.       {
  346.         case wxFORM_CONSTRAINT_FUNCTION:
  347.         {
  348.           ok = (*(constraint->Constraint.ConstraintFunc))(Type, (char *)&val, Label, msg_buf);
  349.           break;
  350.         }
  351.         default:
  352.           break;
  353.       }
  354.       if (!ok)
  355.       {
  356.         (void)wxMessageBox(msg_buf, "Constraint violation", wxOK);
  357.       }
  358.       node = node->Next();
  359.     }
  360.     return ok;
  361.   }
  362.   else return TRUE;
  363. }
  364.  
  365. Bool wxFormItem::CheckStringValue(char *val)
  366. {
  367.   char msg_buf[300];
  368.   if (Constraints)
  369.   {
  370.     wxNode *node = Constraints->First();
  371.     Bool ok = TRUE;
  372.     while (node && ok)
  373.     {
  374.       wxFormItemConstraint *constraint = (wxFormItemConstraint *)node->Data();
  375.       switch (constraint->Type)
  376.       {
  377.         case wxFORM_CONSTRAINT_FUNCTION:
  378.         {
  379.           ok = (*(constraint->Constraint.ConstraintFunc))(Type, val, Label, msg_buf);
  380.           break;
  381.         }
  382.         default:
  383.           break;
  384.       }
  385.       if (!ok)
  386.       {
  387.         (void)wxMessageBox(msg_buf, "Constraint violation", wxOK);
  388.       }
  389.       node = node->Next();
  390.     }
  391.     return ok;
  392.   }
  393.   else return TRUE;
  394. }
  395.  
  396. Bool wxFormItem::CheckFloatValue(float val)
  397. {
  398.   char msg_buf[300];
  399.   if (Constraints)
  400.   {
  401.     wxNode *node = Constraints->First();
  402.     Bool ok = TRUE;
  403.     while (node && ok)
  404.     {
  405.       wxFormItemConstraint *constraint = (wxFormItemConstraint *)node->Data();
  406.       switch (constraint->Type)
  407.       {
  408.         case wxFORM_CONSTRAINT_RANGE:
  409.         {
  410.           wxRealRange *range = constraint->Constraint.Range;
  411.           if ((range->lo > val) || (range->hi < val))
  412.           {
  413.             sprintf(msg_buf, "%s should be in range %.2f to %.2f",
  414.                     Label, range->lo, range->hi);
  415.             ok = FALSE;
  416.           }
  417.           break;
  418.         }
  419.         case wxFORM_CONSTRAINT_FUNCTION:
  420.         {
  421.           ok = (*(constraint->Constraint.ConstraintFunc))(Type, (char *)&val, Label, msg_buf);
  422.           break;
  423.         }
  424.         default:
  425.           break;
  426.       }
  427.       if (!ok)
  428.       {
  429.         (void)wxMessageBox(msg_buf, "Constraint error", wxOK);
  430.       }
  431.       node = node->Next();
  432.     }
  433.     return ok;
  434.   }
  435.   else return TRUE;
  436. }
  437.  
  438. void wxFormItem::RevertValue(void)
  439. {
  440.   switch (Type)
  441.   {
  442.     case wxFORM_SHORT:
  443.     {
  444.       switch (ItemType)
  445.       {
  446.         case wxFORM_TEXT:
  447.         {
  448.           wxText *text_item = (wxText *)PanelItem;
  449.           char *svalue = IntToString(*(ValuePtr.ShortIntValuePtr));
  450.           if (svalue)
  451.           {
  452.             text_item->SetValue(svalue);
  453.             delete svalue;
  454.           }
  455.           break;
  456.         }
  457.         case wxFORM_SLIDER:
  458.         {
  459.           wxSlider *slider_item = (wxSlider *)PanelItem;
  460.           slider_item->SetValue(*(ValuePtr.ShortIntValuePtr));
  461.           break;
  462.         }
  463.         default:
  464.           break;
  465.       }
  466.       break;
  467.     }
  468.     case wxFORM_LONG:
  469.     {
  470.       switch (ItemType)
  471.       {
  472.         case wxFORM_TEXT:
  473.         {
  474.           wxText *text_item = (wxText *)PanelItem;
  475.           char *svalue = LongToString(*(ValuePtr.LongIntValuePtr));
  476.           if (svalue)
  477.           {
  478.             text_item->SetValue(svalue);
  479.             delete svalue;
  480.           }
  481.           break;
  482.         }
  483.         case wxFORM_SLIDER:
  484.         {
  485.           wxSlider *slider_item = (wxSlider *)PanelItem;
  486.           slider_item->SetValue((int)*(ValuePtr.LongIntValuePtr));
  487.           break;
  488.         }
  489.         default:
  490.           break;
  491.       }
  492.       break;
  493.     }
  494.     case wxFORM_FLOAT:
  495.     {
  496.       switch (ItemType)
  497.       {
  498.         case wxFORM_TEXT:
  499.         {
  500.           wxText *text_item = (wxText *)PanelItem;
  501.           char *svalue = FloatToString(*(ValuePtr.FloatValuePtr));
  502.           if (svalue)
  503.           {
  504.             text_item->SetValue(svalue);
  505.             delete svalue;
  506.           }
  507.           break;
  508.         }
  509.         default:
  510.           break;
  511.       }
  512.       break;
  513.     }
  514.     case wxFORM_BOOL:
  515.     {
  516.       switch (ItemType)
  517.       {
  518.         case wxFORM_CHECKBOX:
  519.         {
  520.           wxCheckBox *check_item = (wxCheckBox *)PanelItem;
  521.           check_item->SetValue(*(ValuePtr.BoolValuePtr));
  522.           break;
  523.         }
  524.         default:
  525.           break;
  526.       }
  527.       break;
  528.     }
  529.     case wxFORM_STRING:
  530.     {
  531.       switch (ItemType)
  532.       {
  533.         case wxFORM_TEXT:
  534.         {
  535.           wxText *text_item = (wxText *)PanelItem;
  536.           char *svalue = *(ValuePtr.StringValuePtr);
  537.           if (svalue)
  538.           {
  539.             text_item->SetValue(svalue);
  540.           }
  541.           break;
  542.         }
  543.         case wxFORM_SINGLE_LIST:
  544.         {
  545.           wxListBox *list_item = (wxListBox *)PanelItem;
  546.           char *svalue = *(ValuePtr.StringValuePtr);
  547.           if (svalue)
  548.           {
  549.             int pos = list_item->FindString(svalue);
  550.             if (pos > -1)
  551.               list_item->SetSelection(pos);
  552.             else
  553.               list_item->SetSelection(0);
  554.           }
  555.           else
  556.             list_item->SetSelection(0);
  557.           break;
  558.         }
  559.         case wxFORM_CHOICE:
  560.         {
  561.           wxChoice *choice_item = (wxChoice *)PanelItem;
  562.           char *svalue = *(ValuePtr.StringValuePtr);
  563.           if (svalue)
  564.           {
  565.             int pos = choice_item->FindString(svalue);
  566.             if (pos > -1)
  567.               choice_item->SetSelection(pos);
  568.             else
  569.               choice_item->SetSelection(0);
  570.           }
  571.           else
  572.             choice_item->SetSelection(0);
  573.           break;
  574.         }
  575.         default:
  576.           break;
  577.       }
  578.       break;
  579.     }
  580.     default:
  581.       break;
  582.   }
  583. }
  584.  
  585. Bool wxFormItem::UpdateValue(void)
  586. {
  587.   switch (Type)
  588.   {
  589.     case wxFORM_SHORT:
  590.     {
  591.       int short_value = 0;
  592.       switch (ItemType)
  593.       {
  594.         case wxFORM_TEXT:
  595.         {
  596.           wxText *text_item = (wxText *)PanelItem;
  597.           char *svalue = text_item->GetValue();
  598.           StringToInt(svalue, &short_value);
  599.           break;
  600.         }
  601.         case wxFORM_SLIDER:
  602.         {
  603.           wxSlider *slider_item = (wxSlider *)PanelItem;
  604.           short_value = slider_item->GetValue();
  605.           break;
  606.         }
  607.         default:
  608.           break;
  609.       }
  610.       if (CheckLongValue((long)short_value))
  611.         *(ValuePtr.ShortIntValuePtr) = short_value;
  612.       else
  613.         return FALSE;
  614.       break;
  615.     }
  616.     case wxFORM_LONG:
  617.     {
  618.       long long_value;
  619.       switch (ItemType)
  620.       {
  621.         case wxFORM_TEXT:
  622.         {
  623.           wxText *text_item = (wxText *)PanelItem;
  624.           char *svalue = text_item->GetValue();
  625.           StringToLong(svalue, &long_value);
  626.           break;
  627.         }
  628.         case wxFORM_SLIDER:
  629.         {
  630.           wxSlider *slider_item = (wxSlider *)PanelItem;
  631.           long_value = slider_item->GetValue();
  632.           break;
  633.         }
  634.         default:
  635.           break;
  636.       }
  637.       if (CheckLongValue(long_value))
  638.         *(ValuePtr.LongIntValuePtr) = long_value;
  639.       else
  640.         return FALSE;
  641.       break;
  642.     }
  643.     case wxFORM_FLOAT:
  644.     {
  645.       float float_value;
  646.       switch (ItemType)
  647.       {
  648.         case wxFORM_TEXT:
  649.         {
  650.           wxText *text_item = (wxText *)PanelItem;
  651.           char *svalue = text_item->GetValue();
  652.           StringToFloat(svalue, &float_value);
  653.           break;
  654.         }
  655.         default:
  656.           break;
  657.       }
  658.       if (CheckFloatValue(float_value))
  659.         *(ValuePtr.FloatValuePtr) = float_value;
  660.       else
  661.         return FALSE;
  662.       break;
  663.     }
  664.     case wxFORM_BOOL:
  665.     {
  666.       Bool bool_value;
  667.       switch (ItemType)
  668.       {
  669.         case wxFORM_CHECKBOX:
  670.         {
  671.           wxCheckBox *check_item = (wxCheckBox *)PanelItem;
  672.           bool_value = check_item->GetValue();
  673.           break;
  674.         }
  675.         default:
  676.           break;
  677.       }
  678.       if (CheckBoolValue(bool_value))
  679.         *(ValuePtr.BoolValuePtr) = bool_value;
  680.       else
  681.         return FALSE;
  682.       break;
  683.     }
  684.     case wxFORM_STRING:
  685.     {
  686.       char *string_value = NULL;
  687.       switch (ItemType)
  688.       {
  689.         case wxFORM_TEXT:
  690.         {
  691.           wxText *text_item = (wxText *)PanelItem;
  692.           string_value = text_item->GetValue();
  693.           break;
  694.         }
  695.         case wxFORM_SINGLE_LIST:
  696.         {
  697.           wxListBox *list_item = (wxListBox *)PanelItem;
  698.           string_value = list_item->GetStringSelection();
  699.           break;
  700.         }
  701.         case wxFORM_CHOICE:
  702.         {
  703.           wxChoice *choice_item = (wxChoice *)PanelItem;
  704.           string_value = choice_item->GetStringSelection();
  705.           break;
  706.         }
  707.         default:
  708.           break;
  709.       }
  710.       if (CheckStringValue(string_value))
  711.       {
  712.         if (*ValuePtr.StringValuePtr)
  713.           delete (*ValuePtr.StringValuePtr);
  714.         *(ValuePtr.StringValuePtr) = copystring(string_value);
  715.       }
  716.       else return FALSE;
  717.       break;
  718.     }
  719.     default:
  720.       break;
  721.   }
  722.   return TRUE;
  723. }
  724.  
  725. /*
  726.  * Form
  727.  *
  728.  */
  729.  
  730. wxForm::wxForm(void)
  731. {
  732.   wx_form_panel = NULL;
  733.   wx_editable = TRUE;
  734. }
  735.  
  736. wxForm::~wxForm(void)
  737. {
  738.   wxNode *node = FormItems.First();
  739.   while (node)
  740.   {
  741.     wxFormItem *item = (wxFormItem *)node->Data();
  742.     wxNode *next = node->Next();
  743.     delete item;
  744.     node = next;
  745.   }
  746. }
  747.  
  748. void wxForm::Add(wxFormItem *item, long id)
  749. {
  750.   if (id < 0)
  751.     id = NewId();
  752.   item->Id = id;
  753.   item->Form = this;
  754.   FormItems.Append(item);
  755. }
  756.  
  757. wxNode *wxForm::FindItem(long id)
  758. {
  759.   wxNode *node = FormItems.First();
  760.   wxNode *found = NULL;
  761.   while (node && !found)
  762.   {
  763.     wxFormItem *item = (wxFormItem *)node->Data();
  764.     if (item->Id == id)
  765.       found = node;
  766.     else node = node->Next();
  767.   }
  768.   return found;
  769. }
  770.  
  771.  
  772. Bool wxForm::Set(long id, wxFormItem *item)
  773. {
  774.   wxNode *found = FindItem(id);
  775.   if (found)
  776.   {
  777.     wxNode *next = found->Next();
  778.     wxFormItem *old_item = (wxFormItem *)found->Data();
  779.     delete old_item;
  780.     FormItems.Insert(next, item);
  781.     return TRUE;
  782.   }
  783.   else return FALSE;
  784. }
  785.  
  786. Bool wxForm::Delete(long id)
  787. {
  788.   wxNode *found = FindItem(id);
  789.   if (found)
  790.   {
  791.     wxFormItem *old_item = (wxFormItem *)found->Data();
  792.     delete old_item;
  793.     return TRUE;
  794.   }
  795.   else return FALSE;
  796. }
  797.  
  798. void wxForm::AssociatePanel(wxPanel *panel)
  799. {
  800.   wx_form_panel = panel;
  801.  
  802.   wxFormButton *ok_button = new wxFormButton(panel, (wxFunction)wxFormOk, "Ok");
  803.   ok_button->form = this;
  804.  
  805.   if (wx_editable)
  806.   {
  807.     wxFormButton *update_button = new wxFormButton(panel, (wxFunction)wxFormUpdate, "Update");
  808.     update_button->form = this;
  809.   }
  810.  
  811.   wxFormButton *revert_button = new wxFormButton(panel, (wxFunction)wxFormRevert, "Revert");
  812.   revert_button->form = this;
  813.  
  814.   if (wx_editable)
  815.   {
  816.     wxFormButton *cancel_button = new wxFormButton(panel, (wxFunction)wxFormCancel, "Cancel");
  817.     cancel_button->form = this;
  818.   }
  819.  
  820.   panel->NewLine();
  821.  
  822.   wxNode *node = FormItems.First();
  823.   while (node)
  824.   {
  825.     wxFormItem *item = (wxFormItem *)node->Data();
  826.     item->MakePanelItem(panel);
  827.     item->RevertValue();
  828.     node = node->Next();
  829.   }
  830.  
  831.   panel->Fit();
  832. }
  833.  
  834. void wxForm::DisassociatePanel(void)
  835. {
  836. }
  837.  
  838. Bool wxForm::UpdateValues(void)
  839. {
  840.   wxNode *node = FormItems.First();
  841.   Bool success = TRUE;
  842.   while (node && success)
  843.   {
  844.     wxFormItem *item = (wxFormItem *)node->Data();
  845.     if (!(item->UpdateValue()))
  846.       success = FALSE;
  847.     node = node->Next();
  848.   }
  849.   return success;
  850. }
  851.  
  852. void wxForm::RevertValues(void)
  853. {
  854.   wxNode *node = FormItems.First();
  855.   while (node)
  856.   {
  857.     wxFormItem *item = (wxFormItem *)node->Data();
  858.     item->RevertValue();
  859.     node = node->Next();
  860.   }
  861. }
  862.  
  863. void wxForm::OnOk(void)
  864. {
  865.   if (wx_form_panel)
  866.   {
  867.     wx_form_panel->Show(FALSE);
  868.     delete wx_form_panel;
  869.   }
  870.   delete this;
  871. }
  872.  
  873. void wxForm::OnCancel(void)
  874. {
  875.   if (wx_form_panel)
  876.   {
  877.     wx_form_panel->Show(FALSE);
  878.     delete wx_form_panel;
  879.   }
  880.   delete this;
  881. }
  882.  
  883. void wxForm::OnRevert(void)
  884. {
  885. }
  886.  
  887. void wxForm::OnUpdate(void)
  888. {
  889. }
  890.  
  891. /*
  892.  * Functions for creating items
  893.  *
  894.  */
  895.  
  896. wxFormItem *wxMakeFormString(char *label, char **var,
  897.   int item_type, wxList *constraints,
  898.   char *help_string, wxEditFunction editor, int width, int height)
  899. {
  900.   if (item_type == wxFORM_DEFAULT)
  901.   {
  902.     // Must decide what type of item to use.
  903.     // If constraint list contains a OneOf, use a single-choice list box.
  904.     // Else use a simple Text item
  905.     if (wxFormConstraintsContains(wxFORM_CONSTRAINT_ONE_OF, constraints))
  906.       item_type = wxFORM_SINGLE_LIST;
  907.     else
  908.       item_type = wxFORM_TEXT;
  909.   }
  910.   wxFormItem *item = new wxFormItem(wxFORM_STRING, item_type);
  911.   item->Constraints = constraints;
  912.   item->CustomEditor = editor;
  913.   if (help_string)
  914.     item->HelpString = copystring(help_string);
  915.   item->ValuePtr.StringValuePtr = var;
  916.   if (label)
  917.     item->Label = copystring(label);
  918.   item->Value.StringValue = NULL;
  919.   item->Height = height;
  920.   item->Width = width;
  921.   return item;
  922. }
  923.  
  924. wxFormItem *wxMakeFormMessage(char *label)
  925. {
  926.   wxFormItem *item = new wxFormItem(wxFORM_DUMB_MESSAGE, wxFORM_DUMB_MESSAGE);
  927.   if (label)
  928.     item->Label = copystring(label);
  929.   return item;
  930. }
  931.  
  932. wxFormItem *wxMakeFormButton(char *label, wxFunction func)
  933. {
  934.   wxFormItem *item = new wxFormItem(wxFORM_BUTTON, wxFORM_BUTTON);
  935.   if (label)
  936.     item->Label = copystring(label);
  937.   item->ButtonFunc = func;
  938.   return item;
  939. }
  940.  
  941. wxFormItem *wxMakeFormNewLine(void)
  942. {
  943.   return new wxFormItem(wxFORM_NEWLINE, wxFORM_NEWLINE);
  944. }
  945.  
  946. wxFormItem *wxMakeFormLong(char *label, long *var,
  947.   int item_type, wxList *constraints,
  948.   char *help_string, wxEditFunction editor,
  949.   int width, int height)
  950. {
  951.   if (item_type == wxFORM_DEFAULT)
  952.   {
  953.     if (wxFormConstraintsContains(wxFORM_CONSTRAINT_RANGE, constraints))
  954.       item_type = wxFORM_SLIDER;
  955.     else item_type = wxFORM_TEXT;
  956.   }
  957.   wxFormItem *item = new wxFormItem(wxFORM_LONG, item_type);
  958.   item->Constraints = constraints;
  959.   item->CustomEditor = editor;
  960.   if (help_string)
  961.     item->HelpString = copystring(help_string);
  962.   item->ValuePtr.LongIntValuePtr = var;
  963.   if (label)
  964.     item->Label = copystring(label);
  965.   item->Value.LongIntValue = 0;
  966.   item->Height = height;
  967.   item->Width = width;
  968.   return item;
  969. }
  970.  
  971. wxFormItem *wxMakeFormShort(char *label, int *var,
  972.   int item_type, wxList *constraints,
  973.   char *help_string, wxEditFunction editor,
  974.   int width, int height)
  975. {
  976.   if (item_type == wxFORM_DEFAULT)
  977.   {
  978.     if (wxFormConstraintsContains(wxFORM_CONSTRAINT_RANGE, constraints))
  979.       item_type = wxFORM_SLIDER;
  980.     else item_type = wxFORM_TEXT;
  981.   }
  982.   wxFormItem *item = new wxFormItem(wxFORM_SHORT, item_type);
  983.   item->Constraints = constraints;
  984.   item->CustomEditor = editor;
  985.   if (help_string)
  986.     item->HelpString = copystring(help_string);
  987.   item->ValuePtr.ShortIntValuePtr = var;
  988.   if (label)
  989.     item->Label = copystring(label);
  990.   item->Value.ShortIntValue = 0;
  991.   item->Height = height;
  992.   item->Width = width;
  993.   return item;
  994. }
  995.  
  996. wxFormItem *wxMakeFormFloat(char *label, float *var,
  997.   int item_type, wxList *constraints,
  998.   char *help_string, wxEditFunction editor,
  999.   int width, int height)
  1000. {
  1001.   if (item_type == wxFORM_DEFAULT)
  1002.   {
  1003.     item_type = wxFORM_TEXT;
  1004.   }
  1005.   wxFormItem *item = new wxFormItem(wxFORM_FLOAT, item_type);
  1006.   item->Constraints = constraints;
  1007.   item->CustomEditor = editor;
  1008.   if (help_string)
  1009.     item->HelpString = copystring(help_string);
  1010.   item->ValuePtr.FloatValuePtr = var;
  1011.   if (label)
  1012.     item->Label = copystring(label);
  1013.   item->Value.FloatValue = 0.0;
  1014.   item->Height = height;
  1015.   item->Width = width;
  1016.   return item;
  1017. }
  1018.  
  1019. wxFormItem *wxMakeFormBool(char *label, Bool *var,
  1020.   int item_type, wxList *constraints,
  1021.   char *help_string, wxEditFunction editor,
  1022.   int width, int height)
  1023. {
  1024.   if (item_type == wxFORM_DEFAULT)
  1025.   {
  1026.     item_type = wxFORM_CHECKBOX;
  1027.   }
  1028.   wxFormItem *item = new wxFormItem(wxFORM_BOOL, item_type);
  1029.   item->Constraints = constraints;
  1030.   item->CustomEditor = editor;
  1031.   if (help_string)
  1032.     item->HelpString = copystring(help_string);
  1033.   item->ValuePtr.BoolValuePtr = var;
  1034.   if (label)
  1035.     item->Label = copystring(label);
  1036.   item->Value.BoolValue = 0;
  1037.   item->Height = height;
  1038.   item->Width = width;
  1039.   return item;
  1040. }
  1041.  
  1042. /*
  1043.  * Functions for creating constraints
  1044.  *
  1045.  */
  1046.  
  1047. wxFormItemConstraint *wxMakeConstraintStrings(wxList *list)
  1048. {
  1049.   wxFormItemConstraint *constraint =
  1050.     new wxFormItemConstraint(wxFORM_CONSTRAINT_ONE_OF);
  1051.   constraint->Constraint.OneOf = list;
  1052.   return constraint;
  1053. }
  1054.  
  1055. wxFormItemConstraint *wxMakeConstraintStrings(char *first ...)
  1056. {
  1057.   wxList *list = new wxList;
  1058.   va_list ap;
  1059.  
  1060.   va_start(ap, first);
  1061.   list->Append((wxObject *)copystring(first));
  1062.  
  1063.   for (;;)
  1064.   {
  1065.     char *s = va_arg(ap, char *);
  1066.     if (((int)s) == 0)
  1067.       break;
  1068.     else list->Append((wxObject *)copystring(s));
  1069.   }
  1070.   va_end(ap);
  1071.  
  1072.   wxFormItemConstraint *constraint =
  1073.     new wxFormItemConstraint(wxFORM_CONSTRAINT_ONE_OF);
  1074.   constraint->Constraint.OneOf = list;
  1075.   return constraint;
  1076. }
  1077.  
  1078. wxFormItemConstraint *wxMakeConstraintRange(float lo, float hi)
  1079. {
  1080.   wxFormItemConstraint *constraint =
  1081.     new wxFormItemConstraint(wxFORM_CONSTRAINT_RANGE);
  1082.   constraint->Constraint.Range = new wxRealRange(lo, hi);
  1083.   return constraint;
  1084. }
  1085.  
  1086. wxFormItemConstraint *wxMakeConstraintFunction(wxConstraintFunction func)
  1087. {
  1088.   wxFormItemConstraint *constraint =
  1089.     new wxFormItemConstraint(wxFORM_CONSTRAINT_FUNCTION);
  1090.   constraint->Constraint.ConstraintFunc = func;
  1091.   return constraint;
  1092. }
  1093.  
  1094. /*
  1095.  * Helper functions
  1096.  *
  1097.  */
  1098.  
  1099. wxFormItemConstraint *wxFormConstraintsContains(int type, wxList *constraints)
  1100. {
  1101.   if (!constraints)
  1102.     return NULL;
  1103.  
  1104.   wxFormItemConstraint *found = NULL;
  1105.   wxNode *node = constraints->First();
  1106.   while (node && !found)
  1107.   {
  1108.     wxFormItemConstraint *constraint = (wxFormItemConstraint *)node->Data();
  1109.     if (constraint->Type == type)
  1110.       found = constraint;
  1111.     else node = node->Next();
  1112.   }
  1113.   return found;
  1114. }
  1115.  
  1116. /*
  1117.  * Form display items and helper functions
  1118.  *
  1119.  */
  1120.  
  1121. wxFormButton::wxFormButton(wxPanel *panel, wxFunction func, char *label,
  1122.              int x, int y, int width, int height):
  1123.   wxButton(panel, func, label, x, y, width, height)
  1124. {
  1125. }
  1126.  
  1127. void wxFormOk(wxFormButton& button, wxEvent& event)
  1128. {
  1129.   Bool success = TRUE;
  1130.  
  1131.   if (button.form->wx_editable)
  1132.     success = button.form->UpdateValues();
  1133.  
  1134.   if (success)
  1135.     button.form->OnOk();
  1136. }
  1137.  
  1138. void wxFormUpdate(wxFormButton& button, wxEvent& event)
  1139. {
  1140.   Bool success = button.form->UpdateValues();
  1141.   if (success)
  1142.     button.form->OnUpdate();
  1143. }
  1144.  
  1145. void wxFormRevert(wxFormButton& button, wxEvent& event)
  1146. {
  1147.   button.form->RevertValues();
  1148.   button.form->OnRevert();
  1149. }
  1150.  
  1151. void wxFormCancel(wxFormButton& button, wxEvent& event)
  1152. {
  1153.   button.form->OnCancel();
  1154. }
  1155.