/*
 * File:	bitem.cc
 * Purpose:	wxWindows GUI builder - panel items
 * Author:	Julian Smart
 * Created:	1993
 * Updated:	
 * Copyright:	(c) 1993, AIAI, University of Edinburgh
 */

static const char sccsid[] = "%W% %G%";

#include "wx.h"
#include "wx_form.h"

#ifdef wx_msw
#include "dib.h"
#else
#include "wx_image.h"
#endif

#include <ctype.h>
#include <stdlib.h>

#include "wxbuild.h"
#include "bapp.h"
#include "namegen.h"
#include "bframe.h"
#include "bsubwin.h"
#include "bitem.h"
#include "bactions.h"

BuildItemData::BuildItemData(BuildPanelData *theParent):
  BuildWindowData(theParent)
{
  labelPosition = TRUE;
  autoSize = TRUE;
  functionName = NULL;
}

BuildItemData::~BuildItemData(void)
{
  BuildSelections.DeleteObject(this);
}

Bool BuildItemData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildWindowData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValue("label_position", &labelPosition);
  expr->AssignAttributeValue("auto_size", &autoSize);
  return TRUE;
}

Bool BuildItemData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildWindowData::WritePrologAttributes(expr, database);
  expr->AddAttributeValue("label_position", (long)labelPosition);
  expr->AddAttributeValue("auto_size", (long)autoSize);
  return TRUE;
}

void BuildItemData::FindScreenPosition(int *sx, int *sy)
{
  if (!userWindow)
  {
    *sx = x; *sy = y; return;
  }

  if (buildParent)
  {
    userWindow->GetPosition(sx, sy);
    buildParent->userWindow->ClientToScreen(sx, sy);
  }
}

void BuildItemData::FindClientPosition(int sx, int sy, int *cx, int *cy)
{
  if (buildParent)
  {
    *cx = sx;
    *cy = sy;
    buildParent->userWindow->ScreenToClient(cx, cy);
    x = *cx; y = *cy;
  }
}

// Generation
void BuildItemData::WriteClassImplementation(ostream& stream)
{
}

void BuildItemData::WriteClassDeclaration(ostream& stream)
{
}

void BuildItemData::GenerateWindowStyleString(char *buf)
{
  buf[0] = 0;

  if (windowStyle & wxALWAYS_SB)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxALWAYS_SB");
  }
  if (windowStyle & wxVSCROLL)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxVSCROLL");
  }
  if (windowStyle & wxHSCROLL)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxHSCROLL");
  }
  if (windowStyle & wxHORIZONTAL)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxHORIZONTAL");
  }
  if (windowStyle & wxVERTICAL)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxVERTICAL");
  }
  if (windowStyle & wxVERTICAL_LABEL)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxVERTICAL_LABEL");
  }
  if (windowStyle & wxPROCESS_ENTER)
  {
    if (strlen(buf) > 0)
      strcat(buf, " | ");
    strcat(buf, "wxPROCESS_ENTER");
  }
  if (strlen(buf) == 0)
    strcat(buf, "0");
}

// Do any common pre-constructor stuff, such as setting the
// label orientation and fonts.
void BuildItemData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  Bool defaultIsHorizontal = ((BuildPanelData *)buildParent)->horizLabelPosition;
  if (labelPosition == wxVERTICAL)
  {
    if (defaultIsHorizontal)
      stream << indentation << "SetLabelPosition(wxVERTICAL);\n";
  }
  else if (labelPosition == wxHORIZONTAL)
  {
    if (!defaultIsHorizontal)
      stream << indentation << "SetLabelPosition(wxHORIZONTAL);\n";
  }
}

void BuildItemData::GenerateWindowInitialisationPost(ostream& stream, char *instanceName, char *indentation)
{
  // Reset to default.
  Bool defaultIsHorizontal = ((BuildPanelData *)buildParent)->horizLabelPosition;
  if (labelPosition == wxVERTICAL)
  {
    if (defaultIsHorizontal)
      stream << indentation << "SetLabelPosition(wxHORIZONTAL);\n";
  }
  else if (labelPosition == wxHORIZONTAL)
  {
    if (!defaultIsHorizontal)
      stream << indentation << "SetLabelPosition(wxVERTICAL);\n";
  }
}

Bool BuildItemData::EditAttributes(void)
{
  char nameBuf[200];
  sprintf(nameBuf, "Properties for %s", name);
  wxDialogBox *dialog = new wxDialogBox(NULL, nameBuf, TRUE, 10, 10);
  dialog->SetLabelFont(SmallLabelFont);
  dialog->SetButtonFont(SmallButtonFont);

  BuildForm *form = new BuildForm;

  if (!(wxSubType(windowType, wxTYPE_BUTTON) ||
        wxSubType(windowType, wxTYPE_MESSAGE)))
  {
    if (labelPosition == wxHORIZONTAL)
      labelPositionString = copystring("Horizontal");
    else if (labelPosition == wxVERTICAL)
      labelPositionString = copystring("Vertical");
    else
      labelPositionString = copystring("Default");
  }
  
  AddFormItems(form);

  form->AssociatePanel(dialog);
  form->dialog = dialog;
  AddDialogItems(dialog);

  dialog->Fit();
  dialog->Centre(wxBOTH);

//  form->RevertValues();

  dialog->Show(TRUE);

  if (!(wxSubType(windowType, wxTYPE_BUTTON) ||
        wxSubType(windowType, wxTYPE_MESSAGE)))
  {
    if (strcmp(labelPositionString, "Horizontal") == 0)
      labelPosition = wxHORIZONTAL;
    else if (strcmp(labelPositionString, "Vertical") == 0)
      labelPosition = wxVERTICAL;
    else
      labelPosition = wxDEFAULT_POSITION;
  }

  // An empty title/label string should be NULLed
  if (title && (strcmp(title, "") == 0))
  {
    delete[] title;
    title = NULL;
  }

  return TRUE;
}

// Add class-specific items to form
void BuildItemData::AddFormItems(wxForm *form)
{
  SetHelpTopic("Procedures");
  form->Add(wxMakeFormString("Name", &name, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               300));
  form->Add(wxMakeFormNewLine());
  form->Add(wxMakeFormString("Description", &description, wxFORM_MULTITEXT, NULL, NULL, wxVERTICAL,
               300, 100));
  form->Add(wxMakeFormNewLine());
  form->Add(wxMakeFormString("Label", &title, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               300));
  form->Add(wxMakeFormNewLine());
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
void BuildItemData::AddDialogItems(wxDialogBox *dialog)
{
}

// Write .wxr resource information for this window
void BuildItemData::GenerateWXResourceData(ostream& stream)
{
  stream << "  control = [";
  char buf[300];
  if (labelPosition == wxVERTICAL)
  {
    if ((windowStyle & wxVERTICAL_LABEL) != wxVERTICAL_LABEL)
      windowStyle |= wxVERTICAL_LABEL;
  }
  GenerateWindowStyleString(buf);
  if (buf[0] == '0')
    buf[0] = 0;
    
  switch (windowType)
  {
    case wxTYPE_BUTTON:
    {
      BuildButtonData *buttonData  = (BuildButtonData *)this;
      stream << "wxButton, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      if (buttonData->bitmapData)
        stream << ", '" << buttonData->bitmapData->GetBitmapName() << "_resource'" ;
      break;
    }
    case wxTYPE_MESSAGE:
    {
      BuildMessageData *messageData  = (BuildMessageData *)this;
      stream << "wxMessage, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      if (messageData->bitmapData)
        stream << ", '" << messageData->bitmapData->GetBitmapName() << "_resource'" ;
      break;
    }
    case wxTYPE_CHECK_BOX:
    {
      BuildCheckBoxData *checkBoxData = (BuildCheckBoxData *)this;
      stream << "wxCheckBox, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      break;
    }
    case wxTYPE_GROUP_BOX:
    {
      BuildGroupBoxData *groupBoxData = (BuildGroupBoxData *)this;
      stream << "wxGroupBox, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      break;
    }
    case wxTYPE_TEXT:
    {
      BuildTextData *textData = (BuildTextData *)this;
      stream << "wxText, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      break;
    }
    case wxTYPE_MULTI_TEXT:
    {
      BuildMultiTextData *textData = (BuildMultiTextData *)this;
      stream << "wxMultiText, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      break;
    }
    case wxTYPE_GAUGE:
    {
      BuildGaugeData *gaugeData = (BuildGaugeData *)this;
      stream << "wxGauge, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      stream << ", " << gaugeData->gaugeValue << ", " << gaugeData->maxValue;
      break;
    }
    case wxTYPE_SLIDER:
    {
      BuildSliderData *sliderData = (BuildSliderData *)this;
      stream << "wxSlider, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      stream << ", " << sliderData->sliderValue << ", " << sliderData->minValue << ", " << sliderData->maxValue;
      break;
    }
    case wxTYPE_LIST_BOX:
    {
      BuildListBoxData *listBoxData = (BuildListBoxData *)this;
      stream << "wxListBox, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      // Default list of values
      stream << ", [";
      wxNode *node = listBoxData->strings.First();
      while (node)
      {
        char *s = (char *)node->Data();
        stream << SafeWord(s);
        if (node->Next())
          stream << ", ";
        node = node->Next();
      }
      stream << "], ";
      if (listBoxData->multipleSel)
        stream << "wxMULTIPLE";
      else
        stream << "wxSINGLE";

      break;
    }
    case wxTYPE_CHOICE:
    {
      BuildChoiceData *choiceData = (BuildChoiceData *)this;
      stream << "wxChoice, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      // Default list of values
      stream << ", [";
      wxNode *node = choiceData->strings.First();
      while (node)
      {
        char *s = (char *)node->Data();
        stream << SafeWord(s);
        if (node->Next())
          stream << ", ";
        node = node->Next();
      }
      stream << "]";

      break;
    }
    case wxTYPE_RADIO_BOX:
    {
      BuildRadioBoxData *radioBoxData = (BuildRadioBoxData *)this;
      stream << "wxRadioBox, " << SafeWord(title) << ", '" << buf << "', ";
      stream << SafeWord(name) << ", ";
      stream << x << ", " << y << ", " << width << ", " << height;
      // Default list of values
      stream << ", [";
      wxNode *node = radioBoxData->strings.First();
      while (node)
      {
        char *s = (char *)node->Data();
        stream << SafeWord(s);
        if (node->Next())
          stream << ", ";
        node = node->Next();
      }
      stream << "]";

      break;
    }
  }
  stream << "]";
}

/*
 * Button
 *
 */
  
BuildButtonData::BuildButtonData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = -1;
  height = -1;
  name = copystring(GetNewObjectName("button"));
  memberName = copystring(name);
  className = copystring("wxButton");
  title = copystring("untitled");
  windowStyle = 0;
  windowType = wxTYPE_BUTTON;
  functionName = copystring(GetNewObjectName("ButtonProc"));

//  bitmapFile = NULL;
//  buttonBitmap = NULL;
  bitmapData = NULL;
}

BuildButtonData::~BuildButtonData(void)
{
  if (bitmapData)
    delete bitmapData;    
}

Bool BuildButtonData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
// Handles for us to associate the wxButton with client data
// AddFormItems
void BuildButtonData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));

  SetHelpTopic("Creating a button item");
/*
#if defined(wx_x) || FAFA_LIB
  form->Add(wxMakeFormNewLine());
  form->Add(wxMakeFormString("Bitmap name", &bitmapFile, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL, 300));
#endif
*/
}

static wxButton *ButtonBitmapButton = NULL;

static void ButtonBitmapCheckBoxProc(wxCheckBox& check, wxCommandEvent& event)
{
  MakeModified();
  BuildButtonData *data = (BuildButtonData *)check.GetClientData();
  if (check.GetValue())
  {
    data->autoSize = TRUE;
    data->width = -1;
    data->height = -1;
    ButtonBitmapButton->Enable(TRUE);
    if (!data->bitmapData)
      data->bitmapData = new BuildBitmapData;
    data->bitmapData->Edit(check.GetParent());
    if (data->bitmapData->CreateBitmap())
      ((wxButton *)data->userWindow)->SetLabel(data->bitmapData->GetBitmap());
  }
  else
  {
    if (data->userWindow)
      ((wxButton *)data->userWindow)->SetLabel(data->title);

    ButtonBitmapButton->Enable(FALSE);
    if (data->bitmapData)
      delete data->bitmapData;
  }
}

static void ButtonBitmapButtonProc(wxButton& but, wxCommandEvent& event)
{
  MakeModified();
  BuildButtonData *data = (BuildButtonData *)but.GetClientData();
  wxBitmap *oldBitmap = data->bitmapData->GetBitmap();
  data->bitmapData->Edit(but.GetParent());
  data->bitmapData->SetBitmap(NULL);
  if (data->bitmapData->CreateBitmap())
  {
    ((wxButton *)data->userWindow)->SetLabel(data->bitmapData->GetBitmap());
    delete oldBitmap;
  }
  else
    data->bitmapData->SetBitmap(oldBitmap);
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
void BuildButtonData::AddDialogItems(wxDialogBox *dialog)
{
  dialog->NewLine();
  wxCheckBox *checkBox = new wxCheckBox(dialog, (wxFunction)ButtonBitmapCheckBoxProc, "Use bitmap");
  checkBox->SetClientData((char *)this);
  ButtonBitmapButton = new wxButton(dialog, (wxFunction)ButtonBitmapButtonProc, "Edit bitmap properties");
  ButtonBitmapButton->SetClientData((char *)this);
  if (bitmapData)
  {
    checkBox->SetValue(TRUE);
  }
  else
  {
    checkBox->SetValue(FALSE);
    ButtonBitmapButton->Enable(FALSE);
  }
}

Bool BuildButtonData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
//  expr->AssignAttributeValue("bitmap_file", &bitmapFile);
  if (expr->AttributeValue("bitmap"))
  {
    bitmapData = new BuildBitmapData;
    bitmapData->ReadPrologAttributes(expr);
  }
  else
  {
    // Backward compatibility
    char *bitmapFilename = NULL;
    expr->AssignAttributeValue("bitmap_file", &bitmapFilename);
    if (bitmapFilename)
    {
      if (strlen(bitmapFilename) > 0)
      {
        bitmapData = new BuildBitmapData;
        bitmapData->SetBitmapName(bitmapFilename);
      }
      delete[] bitmapFilename;
    }
  }
  return TRUE;
}

Bool BuildButtonData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
//  expr->AddAttributeValueString("bitmap_file", bitmapFile);
  if (bitmapData)
    bitmapData->WritePrologAttributes(expr);
  return TRUE;
}

Bool BuildButtonData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }
  
  UserButton *button = NULL;

#if defined(wx_x) || FAFA_LIB
  if (bitmapData && bitmapData->CreateBitmap())
  {
    button = new UserButton((wxPanel *)buildParent->userWindow,
                 (wxFunction)UserButtonCallback, bitmapData->GetBitmap(), x, y,
                 width, height, windowStyle);
  }
  else
#endif  
    button = new UserButton((wxPanel *)buildParent->userWindow,
                 (wxFunction)UserButtonCallback, title, x, y,
                 width, height, windowStyle);


  userWindow = button;
  button->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildButtonData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildButtonData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxButton& but, wxCommandEvent& event);\n\n";
}

// Generation
void BuildButtonData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxButton& but, wxCommandEvent& event)\n";
    stream << "{\n";
    wxNode *node = buildActions.First();
    while (node)
    {
      BuildAction *action = (BuildAction *)node->Data();
      action->GenerateActionCPP(stream, "  ", this);
      node = node->Next();
    }
    stream << "}\n\n";
  }
}

void BuildButtonData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxButton" << "(" << parentName;
  stream << ", (wxFunction)" << (functionName ? functionName : "NULL") << ", ";

  if (bitmapData)
  {
    // Generate name for the bitmap
    char buf1[50];
    strcpy(buf1, bitmapData->GetBitmapName());
    strcat(buf1, "Bitmap");
    stream << buf1 << ", ";
  }
  else
    stream << SafeString(title) << ", ";
  stream << x << ", " << y << ", ";
  stream << width << ", " << height << ", ";
  
  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

// Generate bitmap, icon etc. resource entries for RC file.
void BuildButtonData::GenerateResourceEntries(ostream &stream)
{
  if (bitmapData)
    bitmapData->GenerateResourceEntry(stream);
}

void BuildButtonData::GenerateWXResourceBitmaps(ostream& stream)
{
  if (bitmapData)
    bitmapData->GenerateWXResourceBitmap(stream);
}

void BuildButtonData::GenerateWXResourceBitmapRegistration(ostream& stream)
{
  if (bitmapData)
    bitmapData->GenerateWXResourceBitmapRegistration(stream);
}

void BuildButtonData::GenerateResourceLoading(ostream &stream)
{
  if (bitmapData)
    bitmapData->GenerateResourceLoading(stream);
}

void BuildButtonData::GenerateBitmapDataIncludes(ostream& stream)
{
  if (bitmapData)
    bitmapData->GenerateBitmapDataInclude(stream);
}

/*
 * Checkbox
 *
 */
  
BuildCheckBoxData::BuildCheckBoxData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = -1;
  height = -1;
  name = copystring(GetNewObjectName("checkbox"));
  memberName = copystring(name);
  className = copystring("wxCheckBox");
  title = copystring("untitled");
  windowStyle = 0;
  windowType = wxTYPE_CHECK_BOX;
  functionName = copystring(GetNewObjectName("CheckBoxProc"));

  intValue = 0;
}

BuildCheckBoxData::~BuildCheckBoxData(void)
{
}

Bool BuildCheckBoxData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildCheckBoxData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  SetHelpTopic("Creating a checkbox item");
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
void BuildCheckBoxData::AddDialogItems(wxDialogBox *dialog)
{
}

Bool BuildCheckBoxData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValue("value", &intValue);
  return TRUE;
}

Bool BuildCheckBoxData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValue("value", (long)intValue);
  return TRUE;
}

Bool BuildCheckBoxData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }
  
  UserCheckBox *button = new UserCheckBox((wxPanel *)buildParent->userWindow,
                 (wxFunction)NULL, title, x, y,
                 width, height, windowStyle);
  userWindow = button;
  button->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildCheckBoxData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildCheckBoxData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxCheckBox& check, wxCommandEvent& event);\n\n";
}

// Generation
void BuildCheckBoxData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxCheckBox& but, wxCommandEvent& event)\n";
    stream << "{\n";
    stream << "}\n\n";
  }
}

void BuildCheckBoxData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxCheckBox" << "(" << parentName;
  stream << ", (wxFunction)" << (functionName ? functionName : "NULL") << ", ";
  stream << SafeString(title) << ", " << x << ", " << y << ", ";
  stream << width << ", " << height << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

/*
 * Message
 *
 */
  
BuildMessageData::BuildMessageData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = -1;
  height = -1;
  name = copystring(GetNewObjectName("message"));
  memberName = copystring(name);
  className = copystring("wxMessage");
  title = copystring("untitled");
  windowStyle = 0;
  windowType = wxTYPE_MESSAGE;
  bitmapData = NULL;
}

BuildMessageData::~BuildMessageData(void)
{
  if (bitmapData)
    delete bitmapData;
}

Bool BuildMessageData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

static wxButton *MessageBitmapButton = NULL;

static void MessageBitmapCheckBoxProc(wxCheckBox& check, wxCommandEvent& event)
{
  MakeModified();
  BuildMessageData *data = (BuildMessageData *)check.GetClientData();
  if (check.GetValue())
  {
    data->autoSize = TRUE;
    data->width = -1;
    data->height = -1;
    MessageBitmapButton->Enable(TRUE);
    if (!data->bitmapData)
      data->bitmapData = new BuildBitmapData;
    data->bitmapData->Edit(check.GetParent());
    if (data->bitmapData->CreateBitmap())
      ((wxMessage *)data->userWindow)->SetLabel(data->bitmapData->GetBitmap());
  }
  else
  {
    if (data->userWindow)
      ((wxMessage *)data->userWindow)->SetLabel(data->title);

    MessageBitmapButton->Enable(FALSE);
    if (data->bitmapData)
      delete data->bitmapData;
  }
}

static void MessageBitmapButtonProc(wxButton& but, wxCommandEvent& event)
{
  MakeModified();
  BuildMessageData *data = (BuildMessageData *)but.GetClientData();
  wxBitmap *oldBitmap = data->bitmapData->GetBitmap();
  data->bitmapData->Edit(but.GetParent());
  data->bitmapData->SetBitmap(NULL);
  if (data->bitmapData->CreateBitmap())
  {
    ((wxMessage *)data->userWindow)->SetLabel(data->bitmapData->GetBitmap());
    delete oldBitmap;
  }
  else
    data->bitmapData->SetBitmap(oldBitmap);
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
void BuildMessageData::AddDialogItems(wxDialogBox *dialog)
{
  dialog->NewLine();
  wxCheckBox *checkBox = new wxCheckBox(dialog, (wxFunction)MessageBitmapCheckBoxProc, "Use bitmap");
  checkBox->SetClientData((char *)this);
  MessageBitmapButton = new wxButton(dialog, (wxFunction)MessageBitmapButtonProc, "Edit bitmap properties");
  MessageBitmapButton->SetClientData((char *)this);
  if (bitmapData)
  {
    checkBox->SetValue(TRUE);
  }
  else
  {
    checkBox->SetValue(FALSE);
    MessageBitmapButton->Enable(FALSE);
  }
}

// Add class-specific items to form
void BuildMessageData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  SetHelpTopic("Creating a message item");
}

Bool BuildMessageData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  if (expr->AttributeValue("bitmap"))
  {
    bitmapData = new BuildBitmapData;
    bitmapData->ReadPrologAttributes(expr);
  }
  return TRUE;
}

Bool BuildMessageData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  if (bitmapData)
    bitmapData->WritePrologAttributes(expr);
  return TRUE;
}

Bool BuildMessageData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  UserMessage *message = NULL;
#if defined(wx_x) || FAFA_LIB
  if (bitmapData && bitmapData->CreateBitmap())
  {
    message = new UserMessage((wxPanel *)buildParent->userWindow,
                 bitmapData->GetBitmap(), x, y,
                 windowStyle);
  }
  else
#endif  
    message = new UserMessage((wxPanel *)buildParent->userWindow,
                 title, x, y,
                 windowStyle);
  userWindow = message;
  message->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildMessageData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildMessageData::WriteClassDeclaration(ostream& stream)
{
}

// Generation
void BuildMessageData::WriteClassImplementation(ostream& stream)
{
}

void BuildMessageData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxMessage" << "(" << parentName;
  stream << ", ";

  if (bitmapData)
  {
    // Generate name for the bitmap
    char buf1[50];
    strcpy(buf1, bitmapData->GetBitmapName());
    strcat(buf1, "Bitmap");
    stream << buf1 << ", ";
  }
  else
    stream << SafeString(title) << ", ";
  stream << x << ", " << y << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}


// Generate bitmap, icon etc. resource entries for RC file.
void BuildMessageData::GenerateResourceEntries(ostream &stream)
{
  if (bitmapData)
    bitmapData->GenerateResourceEntry(stream);
}

void BuildMessageData::GenerateWXResourceBitmaps(ostream& stream)
{
  if (bitmapData)
    bitmapData->GenerateWXResourceBitmap(stream);
}

void BuildMessageData::GenerateWXResourceBitmapRegistration(ostream& stream)
{
  if (bitmapData)
    bitmapData->GenerateWXResourceBitmapRegistration(stream);
}

void BuildMessageData::GenerateResourceLoading(ostream &stream)
{
  if (bitmapData)
    bitmapData->GenerateResourceLoading(stream);
}

void BuildMessageData::GenerateBitmapDataIncludes(ostream& stream)
{
  if (bitmapData)
    bitmapData->GenerateBitmapDataInclude(stream);
}

/*
 * Text item
 *
 */
 
BuildTextData::BuildTextData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = -1;
  height = -1;
  name = copystring(GetNewObjectName("text"));
  memberName = copystring(name);
  className = copystring("wxText");
  title = NULL;
  windowStyle = 0;
  windowType = wxTYPE_TEXT;
  stringValue = NULL;
  functionName = copystring(GetNewObjectName("TextProc"));
}

BuildTextData::~BuildTextData(void)
{
}

Bool BuildTextData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildTextData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));
  form->Add(wxMakeFormNewLine());

  form->Add(wxMakeFormString("Label position", &labelPositionString, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));

  SetHelpTopic("Creating a text item");
  form->Add(wxMakeFormNewLine());
  form->Add(wxMakeFormString("Value", &stringValue, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               300));
}

// Add class-specific items to dialog, since forms can't
// cope with everything.

void BuildTextData::AddDialogItems(wxDialogBox *dialog)
{
}

Bool BuildTextData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValue("value", &stringValue);
  return TRUE;
}

Bool BuildTextData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValueString("value", stringValue);
  return TRUE;
}

Bool BuildTextData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition  ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  UserText *text = new UserText((wxPanel *)buildParent->userWindow, (wxFunction)NULL,
                 title, stringValue, x, y,
                 width, height, windowStyle);
  userWindow = text;
  text->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildTextData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildTextData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxText& text, wxCommandEvent& event);\n\n";
}

// Generation
void BuildTextData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxText& text, wxCommandEvent& event)\n";
    stream << "{\n";
    stream << "}\n\n";
  }
}

void BuildTextData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxText" << "(" << parentName;
  stream << ", (wxFunction)" << (functionName ? functionName : "NULL") << ", ";
  stream << SafeString(title) << ", ";
  stream << SafeString(stringValue) << ", ";
  stream << x << ", " << y << ", ";
  stream << width << ", " << height << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

/*
 * MultiText item
 *
 */
 
BuildMultiTextData::BuildMultiTextData(BuildPanelData *theParent):
  BuildTextData(theParent)
{
  x = -1;
  y = -1;
  width = 300;
  height = 150;

  autoSize = FALSE;
  name = copystring(GetNewObjectName("multitext"));
  memberName = copystring(name);
  className = copystring("wxMultiText");
  title = NULL;
  windowStyle = 0;
  windowType = wxTYPE_MULTI_TEXT;
  stringValue = NULL;
  functionName = copystring(GetNewObjectName("MultiTextProc"));
}

BuildMultiTextData::~BuildMultiTextData(void)
{
}

void BuildMultiTextData::AddFormItems(wxForm *form)
{
  BuildTextData::AddFormItems(form);
  SetHelpTopic("Create a multi-line text item");
}

Bool BuildMultiTextData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition  ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  UserMultiText *text = new UserMultiText((wxPanel *)buildParent->userWindow, (wxFunction)NULL,
                 title, stringValue, x, y,
                 width, height, windowStyle);
  userWindow = text;
  text->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

void BuildMultiTextData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxMultiText" << "(" << parentName;
  stream << ", (wxFunction)" << (functionName ? functionName : "NULL") << ", ";
  stream << SafeString(title) << ", ";
  stream << SafeString(stringValue) << ", ";
  stream << x << ", " << y << ", ";
  stream << width << ", " << height << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

/*
 * List box
 *
 */
 
BuildListBoxData::BuildListBoxData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = 200;
  height = 100;

  autoSize = FALSE;
  name = copystring(GetNewObjectName("listbox"));
  memberName = copystring(name);
  className = copystring("wxListBox");
  title = NULL;
  windowStyle = 0;
  windowType = wxTYPE_LIST_BOX;

  multipleSel = FALSE;
  scrollAlways = FALSE;
  functionName = copystring(GetNewObjectName("ListBoxProc"));
  tmpStringArray = NULL;
}

BuildListBoxData::~BuildListBoxData(void)
{
}

Bool BuildListBoxData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildListBoxData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormString("Label position", &labelPositionString, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));

  SetHelpTopic("Creating a listbox item");
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
static void ListBoxStringsCallback(wxListBox& lbox, wxCommandEvent& event)
{
}

static void ListBoxAddCallback(wxButton& but, wxCommandEvent& event)
{
  BuildListBoxData *data = (BuildListBoxData *)but.GetClientData();
  char *s = (data->currentTextBox->GetValue());
  if (s && (strlen(s) > 0))
  {
    wxNode *node = data->strings.Add(s);
    data->currentStringsBox->Append(s, (char *)node);
    data->currentTextBox->SetValue("");
  }
}

static void ListBoxDeleteCallback(wxButton& but, wxCommandEvent& event)
{
  BuildListBoxData *data = (BuildListBoxData *)but.GetClientData();
  int sel = data->currentStringsBox->GetSelection();
  if (sel > -1)
  {
    wxNode *node = (wxNode *)data->currentStringsBox->GetClientData(sel);
    delete[] (char *)node->Data();
    delete node;
    data->currentStringsBox->Delete(sel);
  }
}

void BuildListBoxData::AddDialogItems(wxDialogBox *dialog)
{
  dialog->NewLine();
  dialog->SetLabelPosition(wxVERTICAL);
  currentStringsBox = new wxListBox(dialog, (wxFunction)ListBoxStringsCallback,
                           "Values", wxSINGLE,-1, -1, 300, 100);
  currentStringsBox->wxWindow::SetClientData((char *)this);
  wxNode *node = strings.First();
  while (node)
  {
    char *s = (char *)node->Data();
    currentStringsBox->Append(s, (char *)node);
    node = node->Next();
  }
  dialog->NewLine();
  dialog->SetLabelPosition(wxHORIZONTAL);
  currentTextBox = new wxText(dialog, (wxFunction)NULL, "Value", "", -1, -1, 200);
//  dialog->NewLine();
  wxButton *addBut = new wxButton(dialog, (wxFunction)ListBoxAddCallback, "Add");
  wxButton *deleteBut = new wxButton(dialog, (wxFunction)ListBoxDeleteCallback, "Delete");
  addBut->SetClientData((char *)this);
  deleteBut->SetClientData((char *)this);
}

Bool BuildListBoxData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValue("multiple_sel", &multipleSel);
  expr->AssignAttributeValue("scroll_always", &scrollAlways);
  expr->AssignAttributeValueStringList("values", &strings);
  return TRUE;
}

Bool BuildListBoxData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValue("multiple_sel", (long)multipleSel);
  expr->AddAttributeValue("scroll_always", (long)scrollAlways);
  expr->AddAttributeValueStringList("values", &strings);
  return TRUE;
}

Bool BuildListBoxData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  windowStyle = 0;
  if (scrollAlways)
    windowStyle |= wxALWAYS_SB;

  char **theStrings = new char*[strings.Number()];
  for (int i = 0; i < strings.Number(); i++)
    theStrings[i] = (char *)(strings.Nth(i))->Data();

  UserListBox *listbox = new UserListBox((wxPanel *)buildParent->userWindow,
                 (wxFunction)NULL, title, (multipleSel ? wxMULTIPLE : wxSINGLE), x, y,
                 width, height, strings.Number(), theStrings, windowStyle);

  delete[] theStrings;

  userWindow = listbox;
  listbox->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildListBoxData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildListBoxData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxListBox& lbox, wxCommandEvent& event);\n\n";
}

// Generation
void BuildListBoxData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxListBox& lbox, wxCommandEvent& event)\n";
    stream << "{\n";
    stream << "}\n\n";
  }
}

void BuildListBoxData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxListBox" << "(" << parentName;
  stream << ", " << "(wxFunction)" << (functionName ? functionName : "NULL") << ", " << SafeString(title) << ", ";
  stream << (multipleSel ? "wxMULTIPLE" : "wxSINGLE") << ", " << x << ", " << y << ", ";
  stream << width << ", " << height << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << strings.Number() << ", " << ((strings.Number() == 0) ? "NULL" : tmpStringArray)
         << ", " << buf << ", " << "\"" << name << "\")";
}

void BuildListBoxData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  BuildItemData::GenerateWindowInitialisationPre(stream, instanceName, indentation);
  if (strings.Number() != 0)
  {
    if (tmpStringArray) delete[] tmpStringArray;
    tmpStringArray = GetNewObjectName("stringArray");
    stream << indentation << "char *" << tmpStringArray << "[] = { ";
    wxNode *node = strings.First();
    while (node)
    {
      char *s = (char *)node->Data();
      stream << "\"" << s << "\"";
      node = node->Next();
      if (node) stream << ", "; else stream << " ";
    }
    stream << "};\n";
  }
}

/*
 * Choice
 *
 */

BuildChoiceData::BuildChoiceData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = 200;
  height = 100;
  name = copystring(GetNewObjectName("choice"));
  memberName = copystring(name);
  className = copystring("wxChoice");
  title = NULL;
  windowStyle = 0;
  windowType = wxTYPE_CHOICE;
  functionName = copystring(GetNewObjectName("ChoiceProc"));
  tmpStringArray = NULL;
}

BuildChoiceData::~BuildChoiceData(void)
{
}

Bool BuildChoiceData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildChoiceData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));
  form->Add(wxMakeFormNewLine());

  form->Add(wxMakeFormString("Label position", &labelPositionString, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));
  SetHelpTopic("Creating a choice item");
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
static void ChoiceStringsCallback(wxListBox& lbox, wxCommandEvent& event)
{
}

static void ChoiceAddCallback(wxButton& but, wxCommandEvent& event)
{
  BuildChoiceData *data = (BuildChoiceData *)but.GetClientData();
  char *s = (data->currentTextBox->GetValue());
  if (s && (strlen(s) > 0))
  {
    wxNode *node = data->strings.Add(s);
    data->currentStringsBox->Append(s, (char *)node);
    data->currentTextBox->SetValue("");
  }
}

static void ChoiceDeleteCallback(wxButton& but, wxCommandEvent& event)
{
  BuildChoiceData *data = (BuildChoiceData *)but.GetClientData();
  int sel = data->currentStringsBox->GetSelection();
  if (sel > -1)
  {
    wxNode *node = (wxNode *)data->currentStringsBox->GetClientData(sel);
    delete[] (char *)node->Data();
    delete node;
    data->currentStringsBox->Delete(sel);
  }
}

void BuildChoiceData::AddDialogItems(wxDialogBox *dialog)
{
  dialog->NewLine();
  dialog->SetLabelPosition(wxVERTICAL);
  currentStringsBox = new wxListBox(dialog, (wxFunction)ChoiceStringsCallback,
                           "Values", wxSINGLE,-1, -1, 300, 100);
  wxNode *node = strings.First();
  while (node)
  {
    char *s = (char *)node->Data();
    currentStringsBox->Append(s, (char *)node);
    node = node->Next();
  }
  currentStringsBox->wxWindow::SetClientData((char *)this);
  dialog->NewLine();
  dialog->SetLabelPosition(wxHORIZONTAL);
  currentTextBox = new wxText(dialog, (wxFunction)NULL, "Value", "", -1, -1, 200);
//  dialog->NewLine();
  wxButton *addBut = new wxButton(dialog, (wxFunction)ChoiceAddCallback, "Add");
  wxButton *deleteBut = new wxButton(dialog, (wxFunction)ChoiceDeleteCallback, "Delete");
  addBut->SetClientData((char *)this);
  deleteBut->SetClientData((char *)this);
}

Bool BuildChoiceData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValueStringList("values", &strings);
  return TRUE;
}

Bool BuildChoiceData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValueStringList("values", &strings);
  return TRUE;
}

Bool BuildChoiceData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  windowStyle = 0;

  char **theStrings = new char*[strings.Number()];
  for (int i = 0; i < strings.Number(); i++)
    theStrings[i] = (char *)(strings.Nth(i))->Data();

  UserChoice *choice = new UserChoice((wxPanel *)buildParent->userWindow,
                 (wxFunction)NULL, title, x, y,
                 width, -1, strings.Number(), theStrings, windowStyle);

  delete[] theStrings;

  userWindow = choice;
  choice->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildChoiceData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildChoiceData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxChoice& choice, wxCommandEvent& event);\n\n";
}

// Generation
void BuildChoiceData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxChoice& choice, wxCommandEvent& event)\n";
    stream << "{\n";
    stream << "}\n\n";
  }
}

void BuildChoiceData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxChoice" << "(" << parentName;
  stream << ", " << "(wxFunction)" << (functionName ? functionName : "NULL") << ", " << SafeString(title) << ", " << x << ", " << y << ", ";
  stream << "-1" << ", " << "-1" << ", ";

  stream << strings.Number() << ", " << ((strings.Number() == 0) ? "NULL" : tmpStringArray) << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

void BuildChoiceData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  BuildItemData::GenerateWindowInitialisationPre(stream, instanceName, indentation);
  if (strings.Number() != 0)
  {
    if (tmpStringArray) delete[] tmpStringArray;
    tmpStringArray = GetNewObjectName("stringArray");
    stream << indentation << "char *" << tmpStringArray << "[] = { ";
    wxNode *node = strings.First();
    while (node)
    {
      char *s = (char *)node->Data();
      stream << "\"" << s << "\"";
      node = node->Next();
      if (node) stream << ", "; else stream << " ";
    }
    stream << "};\n";
  }
}

/*
 * RadioBox
 *
 */

BuildRadioBoxData::BuildRadioBoxData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = 200;
  height = 100;
  name = copystring(GetNewObjectName("radiobox"));
  memberName = copystring(name);
  className = copystring("wxRadioBox");
  title = copystring("untitled");
  windowStyle = 0;
  windowType = wxTYPE_RADIO_BOX;
  functionName = copystring(GetNewObjectName("RadioBoxProc"));
  noRowsCols = 2;
  tmpStringArray = NULL;
}

BuildRadioBoxData::~BuildRadioBoxData(void)
{
}

Bool BuildRadioBoxData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildRadioBoxData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));
  form->Add(wxMakeFormNewLine());

  form->Add(wxMakeFormString("Label position", &labelPositionString, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));
  form->Add(wxMakeFormShort("Rows/cols", &noRowsCols, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               100));
  
  SetHelpTopic("Creating a radiobox item");
}

// Add class-specific items to dialog, since forms can't
// cope with everything.
static void RadioBoxStringsCallback(wxListBox& lbox, wxCommandEvent& event)
{
}

static void RadioBoxAddCallback(wxButton& but, wxCommandEvent& event)
{
  BuildRadioBoxData *data = (BuildRadioBoxData *)but.GetClientData();
  char *s = (data->currentTextBox->GetValue());
  if (s && (strlen(s) > 0))
  {
    wxNode *node = data->strings.Add(s);
    data->currentStringsBox->Append(s, (char *)node);
    data->currentTextBox->SetValue("");
  }
}

static void RadioBoxDeleteCallback(wxButton& but, wxCommandEvent& event)
{
  BuildRadioBoxData *data = (BuildRadioBoxData *)but.GetClientData();
  int sel = data->currentStringsBox->GetSelection();
  if (sel > -1)
  {
    wxNode *node = (wxNode *)data->currentStringsBox->GetClientData(sel);
    delete[] (char *)node->Data();
    delete node;
    data->currentStringsBox->Delete(sel);
  }
}

void BuildRadioBoxData::AddDialogItems(wxDialogBox *dialog)
{
  dialog->NewLine();
  dialog->SetLabelPosition(wxVERTICAL);
  currentStringsBox = new wxListBox(dialog, (wxFunction)RadioBoxStringsCallback,
                           "Values", wxSINGLE,-1, -1, 300, 100);
  currentStringsBox->wxWindow::SetClientData((char *)this);
  wxNode *node = strings.First();
  while (node)
  {
    char *s = (char *)node->Data();
    currentStringsBox->Append(s, (char *)node);
    node = node->Next();
  }
  dialog->NewLine();
  dialog->SetLabelPosition(wxHORIZONTAL);
  currentTextBox = new wxText(dialog, (wxFunction)NULL, "Value", "", -1, -1, 200);
//  dialog->NewLine();
  wxButton *addBut = new wxButton(dialog, (wxFunction)RadioBoxAddCallback, "Add");
  wxButton *deleteBut = new wxButton(dialog, (wxFunction)RadioBoxDeleteCallback, "Delete");
  addBut->SetClientData((char *)this);
  deleteBut->SetClientData((char *)this);
}

Bool BuildRadioBoxData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValueStringList("values", &strings);
  expr->AssignAttributeValue("rows_or_cols", &noRowsCols);
  return TRUE;
}

Bool BuildRadioBoxData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValueStringList("values", &strings);
  expr->AddAttributeValue("rows_or_cols", (long)noRowsCols);
  return TRUE;
}

Bool BuildRadioBoxData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  windowStyle = 0;

  char **theStrings = new char*[strings.Number()];
  for (int i = 0; i < strings.Number(); i++)
    theStrings[i] = (char *)(strings.Nth(i))->Data();

  UserRadioBox *radiobox = new UserRadioBox((wxPanel *)buildParent->userWindow,
                 (wxFunction)NULL, title, x, y,
                 -1, -1, strings.Number(), theStrings, noRowsCols, windowStyle);

  delete[] theStrings;
  
  userWindow = radiobox;
  radiobox->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildRadioBoxData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildRadioBoxData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxRadioBox& radioBox, wxCommandEvent& event);\n\n";
}

// Generation
void BuildRadioBoxData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxRadioBox& radioBox, wxCommandEvent& event)\n";
    stream << "{\n";
    stream << "}\n\n";
  }
}

void BuildRadioBoxData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxRadioBox" << "(" << parentName;
  stream << ", " << "(wxFunction)" << (functionName ? functionName : "NULL") << ", " << SafeString(title) << ", " << x << ", " << y << ", ";
  stream << "-1" << ", " << "-1" << ", ";
  stream << strings.Number() << ", " << ((strings.Number() == 0) ? "NULL" : tmpStringArray) << ", ";
  stream << noRowsCols << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

void BuildRadioBoxData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  BuildItemData::GenerateWindowInitialisationPre(stream, instanceName, indentation);
  if (strings.Number() != 0)
  {
    if (tmpStringArray) delete[] tmpStringArray;
    tmpStringArray = GetNewObjectName("stringArray");
    stream << indentation << "char *" << tmpStringArray << "[] = { ";
    wxNode *node = strings.First();
    while (node)
    {
      char *s = (char *)node->Data();
      stream << "\"" << s << "\"";
      node = node->Next();
      if (node) stream << ", "; else stream << " ";
    }
    stream << "};\n";
  }
}

/*
 * Slider
 *
 */

BuildSliderData::BuildSliderData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = 200;
  height = -1;
  minValue = 0;
  maxValue = 100;
  sliderValue = 0;
  
  name = copystring(GetNewObjectName("slider"));
  memberName = copystring(name);
  className = copystring("wxSlider");
  title = copystring("untitled");
  windowStyle = 0;
  windowType = wxTYPE_SLIDER;
  functionName = copystring(GetNewObjectName("SliderProc"));
}

BuildSliderData::~BuildSliderData(void)
{
}

Bool BuildSliderData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildSliderData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));
  form->Add(wxMakeFormNewLine());

  form->Add(wxMakeFormString("Label position", &labelPositionString, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));
  form->Add(wxMakeFormShort("Min value", &minValue, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               100));
  form->Add(wxMakeFormNewLine());
  form->Add(wxMakeFormShort("Max value", &maxValue, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               100));
  
  SetHelpTopic("Creating a slider item");
}

void BuildSliderData::AddDialogItems(wxDialogBox *dialog)
{
}

Bool BuildSliderData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValue("min_value", &minValue);
  expr->AssignAttributeValue("max_value", &maxValue);
  expr->AssignAttributeValue("slider_value", &sliderValue);
  return TRUE;
}

Bool BuildSliderData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  if (userWindow)
    sliderValue = ((wxSlider *)userWindow)->GetValue();

  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValue("min_value", (long)minValue);
  expr->AddAttributeValue("max_value", (long)maxValue);
  expr->AddAttributeValue("slider_value", (long)sliderValue);
  return TRUE;
}

Bool BuildSliderData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  windowStyle = 0;

  UserSlider *slider = new UserSlider((wxPanel *)buildParent->userWindow,
                 (wxFunction)NULL, title, sliderValue, minValue, maxValue, width, x, y,
                 windowStyle);

  userWindow = slider;
  slider->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildSliderData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    sliderValue = ((wxSlider *)userWindow)->GetValue();
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildSliderData::WriteClassDeclaration(ostream& stream)
{
  if (!buildApp.useResourceMethod)
    stream << "void " << functionName << "(wxSlider& slider, wxCommandEvent& event);\n\n";
}

// Generation
void BuildSliderData::WriteClassImplementation(ostream& stream)
{
  if (!buildApp.useResourceMethod)
  {
    stream << "void " << functionName << "(wxSlider& slider, wxCommandEvent& event)\n";
    stream << "{\n";
    stream << "}\n\n";
  }
}

void BuildSliderData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  if (userWindow)
  {
    sliderValue = ((wxSlider *)userWindow)->GetValue();
  }
  stream << "new ";
  stream << "wxSlider" << "(" << parentName;
  stream << ", " << "(wxFunction)" << (functionName ? functionName : "NULL") << ", " << SafeString(title) << ", ";
  stream << sliderValue << ", " << minValue << ", " << maxValue << ", " << width << ", ";
  stream << x << ", " << y << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

void BuildSliderData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  BuildItemData::GenerateWindowInitialisationPre(stream, instanceName, indentation);
}

/*
 * Gauge
 *
 */

BuildGaugeData::BuildGaugeData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = 200;
  height = 30;
  maxValue = 100;
  gaugeValue = 0;
  orientation = copystring("Horizontal");
  autoSize = FALSE;
  
  name = copystring(GetNewObjectName("gauge"));
  memberName = copystring(name);
  className = copystring("wxGauge");
//  title = copystring("untitled");
  windowStyle = wxHORIZONTAL;
  windowType = wxTYPE_GAUGE;
}

BuildGaugeData::~BuildGaugeData(void)
{
  if (orientation)
    delete[] orientation;
}

Bool BuildGaugeData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildGaugeData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  form->Add(wxMakeFormBool("Auto size", &autoSize, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL));
  form->Add(wxMakeFormNewLine());

  form->Add(wxMakeFormString("Label position", &labelPositionString, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));
  form->Add(wxMakeFormString("Orientation", &orientation, wxFORM_CHOICE,
              new wxList(wxMakeConstraintStrings("Horizontal", "Vertical", "Default", NULL), NULL),
      NULL, wxVERTICAL));
//  form->Add(wxMakeFormNewLine());
  form->Add(wxMakeFormShort("Range", &maxValue, wxFORM_DEFAULT, NULL, NULL, wxVERTICAL,
               100));
  
  SetHelpTopic("Creating a gauge item");
}

void BuildGaugeData::AddDialogItems(wxDialogBox *dialog)
{
}

Bool BuildGaugeData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  expr->AssignAttributeValue("max_value", &maxValue);
  expr->AssignAttributeValue("gauge_value", &gaugeValue);
  expr->AssignAttributeValue("orientation", &orientation);
  return TRUE;
}

Bool BuildGaugeData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
//  if (userWindow)
//    gaugeValue = ((wxGauge *)userWindow)->GetValue();

  BuildItemData::WritePrologAttributes(expr, database);
  expr->AddAttributeValue("max_value", (long)maxValue);
  expr->AddAttributeValue("gauge_value", (long)gaugeValue);
  expr->AddAttributeValueString("orientation", orientation);
  return TRUE;
}

Bool BuildGaugeData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);

  if (strcmp(orientation, "Horizontal") == 0)
    windowStyle = wxHORIZONTAL;
  else
    windowStyle = wxVERTICAL;

  if (autoSize)
  {
    width = -1;
    height = -1;
  }

  UserGauge *gauge = new UserGauge((wxPanel *)buildParent->userWindow,
                 title, maxValue, x, y, width, height, windowStyle);
  gauge->SetValue(gaugeValue);

  userWindow = gauge;
  gauge->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildGaugeData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildGaugeData::WriteClassDeclaration(ostream& stream)
{
}

// Generation
void BuildGaugeData::WriteClassImplementation(ostream& stream)
{
}

void BuildGaugeData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxGauge" << "(" << parentName;
  stream << ", " << SafeString(title) << ", ";
  stream << maxValue << ", " << x << ", " << y << ", " << width << ", " << height << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

void BuildGaugeData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  BuildItemData::GenerateWindowInitialisationPre(stream, instanceName, indentation);
}

/*
 * Group box
 *
 */

BuildGroupBoxData::BuildGroupBoxData(BuildPanelData *theParent):
  BuildItemData(theParent)
{
  x = -1;
  y = -1;
  width = 200;
  height = 200;

  autoSize = FALSE;  
  name = copystring(GetNewObjectName("groupbox"));
  memberName = copystring(name);
  className = copystring("wxGroupBox");
  title = copystring("untitled");
  windowStyle = 0;
  windowType = wxTYPE_GROUP_BOX;
}

BuildGroupBoxData::~BuildGroupBoxData(void)
{
}

Bool BuildGroupBoxData::EditAttributes(void)
{
  return BuildItemData::EditAttributes();
}

// Add class-specific items to form
void BuildGroupBoxData::AddFormItems(wxForm *form)
{
  BuildItemData::AddFormItems(form);
  SetHelpTopic("Creating a groupbox item");
}

void BuildGroupBoxData::AddDialogItems(wxDialogBox *dialog)
{
}

Bool BuildGroupBoxData::ReadPrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::ReadPrologAttributes(expr, database);
  return TRUE;
}

Bool BuildGroupBoxData::WritePrologAttributes(PrologExpr *expr, PrologDatabase *database)
{
  BuildItemData::WritePrologAttributes(expr, database);
  return TRUE;
}

Bool BuildGroupBoxData::MakeRealWindow(void)
{
  if (!(buildParent && buildParent->userWindow)) return FALSE;

  wxPanel *panel = (wxPanel *)buildParent->userWindow;
  if (labelPosition == wxDEFAULT_POSITION)
    panel->SetLabelPosition((((BuildPanelData *)buildParent)->horizLabelPosition ? wxHORIZONTAL : wxVERTICAL));
  else
    panel->SetLabelPosition(labelPosition);
/*
  if (autoSize)
  {
    width = -1;
    height = -1;
  }
*/
  windowStyle = 0;

  UserGroupBox *group = new UserGroupBox((wxPanel *)buildParent->userWindow,
                 title, x, y, width, height, windowStyle);

  userWindow = group;
  group->buildWindow = this;

  userWindow->Show(TRUE);
  return TRUE;
}

Bool BuildGroupBoxData::DestroyRealWindow(void)
{
  if (userWindow)
  {
    userWindow->GetPosition(&x, &y);
    userWindow->GetSize(&width, &height);
    delete userWindow;
    userWindow = NULL;
  }
  return TRUE;
}

void BuildGroupBoxData::WriteClassDeclaration(ostream& stream)
{
}

// Generation
void BuildGroupBoxData::WriteClassImplementation(ostream& stream)
{
}

void BuildGroupBoxData::GenerateConstructorCall(ostream& stream, char *parentName)
{
  stream << "new ";
  stream << "wxGroupBox" << "(" << parentName;
  stream << ", " << SafeString(title) << ", ";
  stream << x << ", " << y << ", " << width << ", " << height << ", ";

  char buf[400];
  GenerateWindowStyleString(buf);
  stream << buf << ", \"" << name << "\")";
}

void BuildGroupBoxData::GenerateWindowInitialisationPre(ostream& stream, char *instanceName, char *indentation)
{
  BuildItemData::GenerateWindowInitialisationPre(stream, instanceName, indentation);
}

/*
 * Callbacks
 *
 */
 
void UserButtonCallback(UserButton& but, wxCommandEvent& event)
{
  wxNode *node = but.buildWindow->buildActions.First();
  if (buildApp.TestMode())
  {
    if (node)
    {
      BuildAction *action = (BuildAction *)node->Data();
      action->DoAction();
    }
  }
  else
  {
    BuildAction *action = NULL;
    
    if (!node)
    {
      action = CreateNewAction();
      if (!action) return;
    }
    else
      action = (BuildAction *)node->Data();

    Bool ok = action->EditAction();
    if (ok)
    {
      if (!node)
        but.buildWindow->AddAction(action);
    }
    else
    {
      but.buildWindow->DeleteAction(action);
    }
  }
}
 
