/*
 * File:        wb_item.cc
 * Purpose:     Panel items implementation: base (platform-independent) code
 * Author:      Julian Smart
 * Created:     1993
 * Updated:	March 1995
 * RCS_ID:      $Id: wb_item.cc,v 1.3 1994/08/14 21:34:01 edz Exp $
 * Copyright:   (c) 1993, AIAI, University of Edinburgh
 */

// #include "wx.h" // Uncomment this line for Borland precomp. headers to work

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

#ifdef __GNUG__
#pragma implementation

#pragma implementation "wb_item.h"
#pragma implementation "wb_lbox.h"
#pragma implementation "wb_rbox.h"
#pragma implementation "wb_buttn.h"
#pragma implementation "wb_choic.h"
#pragma implementation "wb_check.h"
#pragma implementation "wb_messg.h"
#pragma implementation "wb_slidr.h"
#pragma implementation "wb_slidr.h"
#pragma implementation "wb_menu.h"
#pragma implementation "wb_mnuit.h"
#pragma implementation "wb_txt.h"
#pragma implementation "wb_mtxt.h"
#pragma implementation "wb_menu.h"
#pragma implementation "wb_group.h"
#pragma implementation "wb_gauge.h"
#endif

#include "common.h"
#include "wx_setup.h"

#include "wx_item.h"
#include "wx_lbox.h"
#include "wx_rbox.h"
#include "wx_buttn.h"
#include "wx_choic.h"
#include "wx_check.h"
#include "wx_messg.h"
#include "wx_slidr.h"
#include "wx_group.h"
#include "wx_menu.h"
#include "wx_txt.h"
#include "wx_mtxt.h"

#if USE_GAUGE
#include "wx_gauge.h"
#endif

#include "wx_stdev.h"
#include "wx_utils.h"

// If not MS C++, don't include wx.h: we'll just include
// the minimum set of files.
// If MS C++, we'll use a precompiled header instead.
#if !defined(_MSC_VER) && !defined(wx_wxh)
#define wx_wxh
#endif

#include "wx.h"

#include "wx_stdev.h"
#include "math.h"
#include "stdlib.h"

/* When implementing a new item, be sure to:

 * - add the item to the parent panel
 * - set window_parent to the parent
 * - NULL any extra child window pointers not created for this item
 *   (e.g. label control that wasn't needed)
 * - delete any extra child windows in the destructor (e.g. label control)
 * - implement GetSize and SetSize
 * - to find panel position if coordinates are (-1, -1), use GetPosition
 * - call AdvanceCursor after creation, for panel layout mechanism.
 *
 */

/*
   Motif notes

   A panel is a form.
   Each item is created on a RowColumn or Form of its own, to allow a label to
   be positioned. wxListBox and wxMultiText have forms, all the others have RowColumns.
   This is to allow labels to be positioned to the top left (can't do it with a
   RowColumn as far as I know).
   AttachWidget positions widgets relative to one another (left->right, top->bottom)
   unless the x, y coordinates are given (more than -1).
 */

// Item members
wxbItem::wxbItem (void)
{
  __type = wxTYPE_ITEM;

  handleSize = 6;
  handleMargin = 1;
  isSelected = FALSE;
  dragOffsetX = 0;
  dragOffsetY = 0;
  centreX = 0;
  centreY = 0;
}

wxbItem::~wxbItem (void)
{
  wxPanel *parent = (wxPanel *) GetParent ();
  if (parent)
  {
    // parent is not always a wxPanel: can be a wxMenu...
    if (wxSubType(parent->__type,wxTYPE_PANEL))
    {
      if (parent->defaultItem == this)
        parent->defaultItem = NULL;
    }
  }
}

void wxbItem::SetClientSize (int width, int height)
{
  SetSize (-1, -1, width, height);
}

int wxbItem::GetLabelPosition (void)
{
  return labelPosition;
}

void wxbItem::SetLabelPosition (int pos)
{
  labelPosition = pos;
}

void wxbItem::Centre (int direction)
{
  int x, y, width, height, panel_width, panel_height, new_x, new_y;

  wxPanel *panel = (wxPanel *) GetParent ();
  if (!panel)
    return;

  panel->GetClientSize (&panel_width, &panel_height);
  GetSize (&width, &height);
  GetPosition (&x, &y);

  new_x = x;
  new_y = y;

  if (direction & wxHORIZONTAL)
    new_x = (int) ((panel_width - width) / 2);

  if (direction & wxVERTICAL)
    new_y = (int) ((panel_height - height) / 2);

  SetSize (new_x, new_y, width, height);
  int temp_x, temp_y;
  GetPosition (&temp_x, &temp_y);
  GetPosition (&temp_x, &temp_y);
}

/*
 * Manipulation and drawing of items in Edit Mode
 */
 
void wxbItem::SelectItem(Bool select)
{
  isSelected = select;
}

// Returns TRUE or FALSE
Bool wxbItem::HitTest(int x, int y)
{
  int xpos, ypos, width, height;
  GetPosition(&xpos, &ypos);
  GetSize(&width, &height);

  return ((x >= xpos) && (x <= (xpos + width)) && (y >= ypos) && (y <= (ypos + height)));
}

// Calculate position of the 8 handles
void wxbItem::CalcSelectionHandles(int *hx, int *hy)
{
  int xpos, ypos, width, height;
  GetPosition(&xpos, &ypos);
  GetSize(&width, &height);
  int middleX = (int)(xpos + (width/2));
  int middleY = (int)(ypos + (height/2));

  // Start from top middle, clockwise.
/*
  7      0      1

  6             2

  5      4      3
*/

  hx[0] = (int)(middleX - (handleSize/2));
  hy[0] = ypos - handleSize - handleMargin;

  hx[1] = xpos + width + handleMargin;
  hy[1] = ypos - handleSize - handleMargin;

  hx[2] = xpos + width + handleMargin;
  hy[2] = (int)(middleY - (handleSize/2));

  hx[3] = xpos + width + handleMargin;
  hy[3] = ypos + height + handleMargin;

  hx[4] = (int)(middleX - (handleSize/2));
  hy[4] = ypos + height + handleMargin;

  hx[5] = xpos - handleSize - handleMargin;
  hy[5] = ypos + height + handleMargin;

  hx[6] = xpos - handleSize - handleMargin;
  hy[6] = (int)(middleY - (handleSize/2));

  hx[7] = xpos - handleSize - handleMargin;
  hy[7] = ypos - handleSize - handleMargin;
}

// Returns 0 (no hit), 1 - 8 for which selection handle
// (clockwise from top middle)
int wxbItem::SelectionHandleHitTest(int x, int y)
{
  // Handle positions
  int hx[8];
  int hy[8];
  CalcSelectionHandles(hx, hy);

  for (int i = 0; i < 8; i++)
  {
    if ((x >= hx[i]) && (x <= (hx[i] + handleSize)) && (y >= hy[i]) && (y <= (hy[i] + handleSize)))
      return (i + 1);
  }
  return 0;
}

void wxbItem::DrawSelectionHandles(wxPanelDC *dc, Bool erase)
{
//  wxPanel *panel = (wxPanel *)GetParent();
  
  dc->SetOptimization(FALSE);

  dc->SetLogicalFunction(wxCOPY);
  dc->SetPen(wxBLACK_PEN);
  dc->SetBrush(wxBLACK_BRUSH);

  dc->SetOptimization(TRUE);

  // Handle positions
  int hx[8];
  int hy[8];
  CalcSelectionHandles(hx, hy);

  for (int i = 0; i < 8; i++)
  {
    dc->DrawRectangle((float)hx[i], (float)hy[i], (float)handleSize, (float)handleSize);
  }
}

void wxbItem::DrawBoundingBox(wxPanelDC *dc, int x, int y, int w, int h)
{
  dc->DrawRectangle(x, y, w, h);
}

// If selectionHandle is zero, not dragging the selection handle.
void wxbItem::OnDragBegin(int x, int y, int keys, wxPanelDC *dc, int selectionHandle)
{
  int xpos, ypos, width, height;
  GetPosition(&xpos, &ypos);
  GetSize(&width, &height);

  dc->BeginDrawing();

//  dc->DestroyClippingRegion();

  wxPanel *panel = (wxPanel *)GetParent();

  // Erase selection handles
//  DrawSelectionHandles(dc, TRUE);

  if (panel->GetSlowDrag())
  {
    dc->SetOptimization(FALSE);

    dc->SetLogicalFunction(wxXOR);

    dc->SetPen(wxBLACK_DASHED_PEN);
    dc->SetBrush(wxTRANSPARENT_BRUSH);

    dc->SetOptimization(TRUE);
  }

  if (selectionHandle > 0)
  {
    // Initialise centre memo
    centreX = (int)(xpos + (width/2));
    centreY = (int)(ypos + (height/2));

    GetParent()->Refresh();

    if (panel->GetSlowDrag())
    {
      DrawBoundingBox(dc, xpos, ypos, width, height);
    }
  }
  else
  {
    GetParent()->Refresh();

    dragOffsetX = (x - xpos);
    dragOffsetY = (y - ypos);

    if (panel->GetSlowDrag())
    {
      DrawBoundingBox(dc, xpos, ypos, width, height);
    }
  }
  dc->EndDrawing();
}

void wxbItem::OnDragContinue(Bool paintIt, int x, int y, int keys, wxPanelDC *dc, int selectionHandle)
{
  wxPanel *panel = (wxPanel *)GetParent();

  if (!panel->GetSlowDrag() && !paintIt)
    return;
    
  int xpos, ypos, width, height;
  GetPosition(&xpos, &ypos);
  GetSize(&width, &height);

  if (selectionHandle > 0)
  {
/*
  8      1      2

  7             3

  6      5      4
*/

    Bool moveHorizontally = FALSE;
    Bool moveVertically = FALSE;
    switch (selectionHandle)
    {
      case 1:
      case 5:
        moveVertically = TRUE;
        break;
      case 3:
      case 7:
        moveHorizontally = TRUE;
        break;
      case 2:
      case 4:
      case 6:
      case 8:
        moveHorizontally = TRUE;
        moveVertically = TRUE;
        break;
    }

    if (moveVertically)
    {
      // This is half the height of the item
      int absY = (int)abs(y - centreY);

      ypos = centreY - absY;
      height = 2*absY;
    }
    if (moveHorizontally)
    {
      // This is half the width of the item
      int absX = (int)abs(x - centreX);

      xpos = centreX - absX;
      width = 2*absX;
    }
    if (panel->GetSlowDrag())
    {
      dc->BeginDrawing();
      
      dc->SetLogicalFunction(wxXOR);
      dc->SetPen(wxBLACK_DASHED_PEN);
      dc->SetBrush(wxTRANSPARENT_BRUSH);

      DrawBoundingBox(dc, xpos, ypos, width, height);

      dc->EndDrawing();
    }
    else
      SetSize(xpos, ypos, width, height);
  }
  else
  {
//    SetSize((int)(x - dragOffsetX), (int)(y - dragOffsetY), width, height);
    if (panel->GetSlowDrag())
    {
      dc->BeginDrawing();

      dc->SetLogicalFunction(wxXOR);
      dc->SetPen(wxBLACK_DASHED_PEN);
      dc->SetBrush(wxTRANSPARENT_BRUSH);

      DrawBoundingBox(dc, (int)(x - dragOffsetX), (int)(y - dragOffsetY), width, height);
      dc->EndDrawing();
    }
    else
      Move((int)(x - dragOffsetX), (int)(y - dragOffsetY));
  }
}

void wxbItem::OnDragEnd(int x, int y, int keys, wxPanelDC *dc, int selectionHandle)
{
  wxPanel *panel = (wxPanel *)GetParent();
  dc->BeginDrawing();

  if (selectionHandle > 0)
  {
    if (panel->GetSlowDrag())
    {
      int xpos, ypos, width, height;
      GetPosition(&xpos, &ypos);
      GetSize(&width, &height);

      Bool moveHorizontally = FALSE;
      Bool moveVertically = FALSE;
      switch (selectionHandle)
      {
      case 1:
      case 5:
        moveVertically = TRUE;
        break;
      case 3:
      case 7:
        moveHorizontally = TRUE;
        break;
      case 2:
      case 4:
      case 6:
      case 8:
        moveHorizontally = TRUE;
        moveVertically = TRUE;
        break;
      }

      if (moveVertically)
      {
        // This is half the height of the item
        int absY = (int)abs(y - centreY);

        ypos = centreY - absY;
        height = 2*absY;
      }
      if (moveHorizontally)
      {
        // This is half the width of the item
        int absX = (int)abs(x - centreX);

        xpos = centreX - absX;
        width = 2*absX;
      }
      SetSize(xpos, ypos, width, height);
    }
  }
  else
  {
    Move((int)(x - dragOffsetX), (int)(y - dragOffsetY));
    GetEventHandler()->OnMove((int)(x - dragOffsetX), (int)(y - dragOffsetY));
  }

  dc->SetOptimization(FALSE);

  dc->SetLogicalFunction(wxCOPY);
  dc->SetPen(wxBLACK_PEN);
  dc->SetBrush(wxBLACK_BRUSH);

  dc->SetOptimization(TRUE);

  // Force it to repaint the selection handles (if any)
  // since the panel thinks we're still within a drag and
  // won't paint the handles.
  if (IsSelected())
    DrawSelectionHandles(dc);

  dc->EndDrawing();

  GetParent()->Refresh();
}

// These functions call OnItemEvent, OnItemMove and OnItemSize
// by default.
void wxbItem::OnEvent(wxMouseEvent& event)
{
  if ((event.eventType == wxEVENT_TYPE_LEFT_DCLICK) ||
      (event.eventType == wxEVENT_TYPE_RIGHT_DCLICK))
    return;
    
  wxWindow *theParent = this->GetParent();
  ((wxPanel *)theParent)->GetEventHandler()->OnItemEvent((wxItem *)this, event);
}

void wxbItem::OnMove(int x, int y)
{
  wxWindow *theParent = GetParent();
  ((wxPanel *)theParent)->GetEventHandler()->OnItemMove((wxItem *)this, x, y);
}

void wxbItem::OnSize(int w, int h)
{
  wxWindow *theParent = GetParent();
  ((wxPanel *)theParent)->GetEventHandler()->OnItemSize((wxItem *)this, w, h);
}

void wxbItem::OnSelect(Bool select)
{
  wxWindow *theParent = GetParent();
  ((wxPanel *)theParent)->GetEventHandler()->OnItemSelect((wxItem *)this, select);
}

void wxbItem::OnLeftClick(int x, int y, int keys)
{
  wxWindow *theParent = GetParent();
  ((wxPanel *)theParent)->GetEventHandler()->OnItemLeftClick((wxItem *)this, x, y, keys);
}

void wxbItem::OnRightClick(int x, int y, int keys)
{
  wxWindow *theParent = GetParent();
  ((wxPanel *)theParent)->GetEventHandler()->OnItemRightClick((wxItem *)this, x, y, keys);
}


/*
 * Button
 */
 
wxbButton::wxbButton (void)
{
  __type = wxTYPE_BUTTON;
  window_parent = NULL;
  labelPosition = wxHORIZONTAL;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbButton::wxbButton (wxPanel * panel, wxFunction Function, char *label,
	   int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_BUTTON;
  windowStyle = style;
  window_parent = panel;
  labelPosition = wxHORIZONTAL;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbButton::wxbButton (wxPanel * panel, wxFunction Function, wxBitmap * bitmap,
	   int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_BUTTON;
  windowStyle = style;
  window_parent = panel;
  labelPosition = wxHORIZONTAL;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbButton::~wxbButton (void)
{
}

void wxbButton::Command (wxCommandEvent & event)
{
  ProcessCommand (event);
}

void wxbButton::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }

  wxNotifyEvent (event, FALSE);
}

/*
 * Menu
 */

// Construct a menu with optional title (then use append)
wxbMenu::wxbMenu (char *Title, wxFunction func)
{
  __type = wxTYPE_MENU;
  no_items = 0;
  menu_bar = NULL;
  WXGC_IGNORE(menu_bar);
  WXGC_IGNORE(top_level_menu);
  if (Title)
    title = copystring (Title);
  else
    title = NULL;
}

// The wxWindow destructor will take care of deleting the submenus.
wxbMenu::~wxbMenu (void)
{
  if (title)
    delete[]title;
}

// Finds the item id matching the given string, -1 if not found.
int wxbMenu::FindItem (char *itemString)
{
  char buf1[200];
  char buf2[200];
  wxStripMenuCodes (itemString, buf1);

  for (wxNode * node = menuItems.First (); node; node = node->Next ())
    {
      wxMenuItem *item = (wxMenuItem *) node->Data ();
      if (item->subMenu)
	{
	  int ans = item->subMenu->FindItem (itemString);
	  if (ans > -1)
	    return ans;
	}
      if ((item->itemId > -1) && item->itemName)
	{
	  wxStripMenuCodes (item->itemName, buf2);
	  if (strcmp (buf1, buf2) == 0)
	    return item->itemId;
	}
    }

  return -1;
}

wxMenuItem *wxbMenu::FindItemForId (int itemId, wxMenu ** itemMenu)
{
  if (itemMenu)
    *itemMenu = NULL;
  for (wxNode * node = menuItems.First (); node; node = node->Next ())
    {
      wxMenuItem *item = (wxMenuItem *) node->Data ();

      if (item->itemId == itemId)
	{
	  if (itemMenu)
	    *itemMenu = (wxMenu *) this;
	  return item;
	}

      if (item->subMenu)
	{
	  wxMenuItem *ans = item->subMenu->FindItemForId (itemId, itemMenu);
	  if (ans)
	    return ans;
	}
    }

  if (itemMenu)
    *itemMenu = NULL;
  return NULL;
}

void wxbMenu::SetHelpString (int itemId, char *helpString)
{
  wxMenuItem *item = FindItemForId (itemId);
  if (item)
    {
      if (item->helpString)
	delete[]item->helpString;
      item->helpString = copystring (helpString);
    }
}

char *wxbMenu::GetHelpString (int itemId)
{
  wxMenuItem *item = FindItemForId (itemId);
  if (item)
    return item->helpString;
  else
    return NULL;
}

void wxbMenu::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }

  wxNotifyEvent (event, FALSE);
}

/*
 * Menu Bar
 */

wxbMenuBar::wxbMenuBar (void)
{
  __type = wxTYPE_MENU_BAR;
  n = 0;
  menus = NULL;
  titles = NULL;
  menu_bar_frame = NULL;
  WXGC_IGNORE(menu_bar_frame);
}

wxbMenuBar::wxbMenuBar (int N, wxMenu * Menus[], char *Titles[])
{
  __type = wxTYPE_MENU_BAR;
  n = N;
  menus = Menus;
  titles = Titles;
  menu_bar_frame = NULL;
  for (int i = 0; i < N; i++)
    menus[i]->menu_bar = (wxMenuBar *) this;
  WXGC_IGNORE(menu_bar_frame);
}

wxbMenuBar::~wxbMenuBar (void)
{
}

void wxbMenuBar::Append (wxMenu * menu, char *title)
{
  n++;
  wxMenu **new_menus = new wxMenu *[n];
  char **new_titles = new char *[n];

  int i;
  for (i = 0; i < n - 1; i++)
    {
      new_menus[i] = menus[i];
      menus[i] = NULL;
      new_titles[i] = titles[i];
      titles[i] = NULL;
    }
  if (menus)
    {
      delete[]menus;
      delete[]titles;
    }
  menus = new_menus;
  titles = new_titles;

  menus[n - 1] = menu;
  titles[n - 1] = copystring (title);

  menu->menu_bar = (wxMenuBar *) this;
}

// Find the menu menuString, item itemString, and return the item id.
// Returns -1 if none found.
int wxbMenuBar::FindMenuItem (char *menuString, char *itemString)
{
  char buf1[200];
  char buf2[200];
  wxStripMenuCodes (menuString, buf1);
  for (int i = 0; i < n; i++)
    {
      wxStripMenuCodes (titles[i], buf2);
      if (strcmp (buf1, buf2) == 0)
	return menus[i]->FindItem (itemString);
    }
  return -1;
}

wxMenuItem *wxbMenuBar::FindItemForId (int Id, wxMenu ** itemMenu)
{
  if (itemMenu)
    *itemMenu = NULL;

  wxMenuItem *item = NULL;
  for (int i = 0; i < n; i++)
    if (item = menus[i]->FindItemForId (Id, itemMenu))
      return item;
  return NULL;
}

void wxbMenuBar::SetHelpString (int Id, char *helpString)
{
  for (int i = 0; i < n; i++)
    {
      if (menus[i]->FindItemForId (Id))
	{
	  menus[i]->SetHelpString (Id, helpString);
	  return;
	}
    }
}

char *wxbMenuBar::GetHelpString (int Id)
{
  for (int i = 0; i < n; i++)
    {
      if (menus[i]->FindItemForId (Id))
	return menus[i]->GetHelpString (Id);
    }
  return NULL;
}

/*
 * Single check box item
 */
 
wxbCheckBox::wxbCheckBox (void)
{
  __type = wxTYPE_CHECK_BOX;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbCheckBox::wxbCheckBox (wxPanel * panel, wxFunction func, char *Title,
	     int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_CHECK_BOX;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbCheckBox::wxbCheckBox (wxPanel * panel, wxFunction func, wxBitmap * bitmap,
	     int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_CHECK_BOX;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbCheckBox::~wxbCheckBox (void)
{
}

void wxbCheckBox::Command (wxCommandEvent & event)
{
  SetValue (event.commandInt);
  ProcessCommand (event);
}

void wxbCheckBox::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }

  wxNotifyEvent (event, FALSE);
}

/*
 * Choice
 */
 
wxbChoice::wxbChoice (void)
{
  __type = wxTYPE_CHOICE;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbChoice::wxbChoice (wxPanel * panel, wxFunction func, char *Title,
	   int x, int y, int width, int height, int N, char **Choices,
	   long style, char *name)
{
  __type = wxTYPE_CHOICE;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  no_strings = N;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbChoice::~wxbChoice (void)
{
}

char *wxbChoice::GetStringSelection (void)
{
  int sel = GetSelection ();
  if (sel > -1)
    return this->GetString (sel);
  else
    return NULL;
}

Bool wxbChoice::SetStringSelection (char *s)
{
  int sel = FindString (s);
  if (sel > -1)
    {
      SetSelection (sel);
      return TRUE;
    }
  else
    return FALSE;
}

void wxbChoice::Command (wxCommandEvent & event)
{
  SetSelection (event.commandInt);
  ProcessCommand (event);
}

void wxbChoice::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }

  wxNotifyEvent (event, FALSE);
}

/*
 * Listbox
 */
 
wxbListBox::wxbListBox (void)
{
  __type = wxTYPE_LIST_BOX;
  selected = -1;
  selections = 0;
  no_items = 0;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbListBox::wxbListBox (wxPanel * panel, wxFunction func,
	    char *Title, Bool Multiple,
	    int x, int y, int width, int height,
	    int N, char **Choices, long style, char *name)
{
  __type = wxTYPE_LIST_BOX;
  windowStyle = style;
  selected = -1;
  selections = 0;
  multiple = Multiple;
  window_parent = panel;
  no_items = 0;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbListBox::~wxbListBox (void)
{
}

int wxbListBox::Number (void)
{
  return no_items;
}

// For single selection items only
char *wxbListBox::GetStringSelection (void)
{
  int sel = GetSelection ();
  if (sel > -1)
    return this->GetString (sel);
  else
    return NULL;
}

Bool wxbListBox::SetStringSelection (char *s)
{
  int sel = FindString (s);
  if (sel > -1)
    {
      SetSelection (sel);
      return TRUE;
    }
  else
    return FALSE;
}

// Is this the right thing? Won't setselection generate a command
// event too? No! It'll just generate a setselection event.
// But we still can't have this being called whenever a real command
// is generated, because it sets the selection, which will already
// have been done! (Unless we have an optional argument for calling
// by the actual window system, or a separate function, ProcessCommand)
void wxbListBox::Command (wxCommandEvent & event)
{
  if (event.extraLong)
    SetSelection (event.commandInt);
  else
    {
      Deselect (event.commandInt);
      return;
    }
  ProcessCommand (event);
}

void wxbListBox::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;

  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }


  wxNotifyEvent (event, FALSE);
}

/*
 * Radiobox item
 */
 
wxbRadioBox::wxbRadioBox (void)
{
  __type = wxTYPE_RADIO_BOX;
  selected = -1;
  no_items = 0;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbRadioBox::wxbRadioBox (wxPanel * panel, wxFunction func,
	     char *Title,
	     int x, int y, int width, int height,
	     int N, char **Choices,
	     int majorDim, long style, char *name)
{
  __type = wxTYPE_RADIO_BOX;
  windowStyle = style;
  selected = -1;
  window_parent = panel;
  no_items = 0;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

#ifndef __BORLANDC__
wxbRadioBox::wxbRadioBox (wxPanel * panel, wxFunction func,
	     char *Title,
	     int x, int y, int width, int height,
	     int N, wxBitmap ** Choices,
	     int majorDim, long style, char *name)
{
  __type = wxTYPE_RADIO_BOX;
  windowStyle = style;
  selected = -1;
  window_parent = panel;
  no_items = 0;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}
#endif

wxbRadioBox::~wxbRadioBox (void)
{
}

int wxbRadioBox::Number (void)
{
  return no_items;
}

// For single selection items only
char *wxbRadioBox::GetStringSelection (void)
{
  int sel = GetSelection ();
  if (sel > -1)
    return this->GetString (sel);
  else
    return NULL;
}

Bool wxbRadioBox::SetStringSelection (char *s)
{
  int sel = FindString (s);
  if (sel > -1)
    {
      SetSelection (sel);
      return TRUE;
    }
  else
    return FALSE;
}

void wxbRadioBox::Command (wxCommandEvent & event)
{
  SetSelection (event.commandInt);
  ProcessCommand (event);
}

void wxbRadioBox::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;

  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }

  wxNotifyEvent (event, FALSE);
}

/*
 * Message
 */
 
wxbMessage::wxbMessage (void)
{
  __type = wxTYPE_MESSAGE;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbMessage::wxbMessage (wxPanel * panel, char *label, int x, int y, long style, char *name)
{
  __type = wxTYPE_MESSAGE;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

#if USE_BITMAP_MESSAGE
wxbMessage::wxbMessage (wxPanel * panel, wxBitmap *image, int x, int y, long style, char *name)
{
  __type = wxTYPE_MESSAGE;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}
#endif

wxbMessage::~wxbMessage (void)
{
}

/*
 * Text item
 */
 
wxbText::wxbText (void)
{
  __type = wxTYPE_TEXT;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbText::wxbText (wxPanel * panel, wxFunction Function, char *label, char *value,
	 int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_TEXT;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbText::~wxbText (void)
{
}


void wxbText::Command (wxCommandEvent & event)
{
  SetValue (event.commandString);
  ProcessCommand (event);
}

void wxbText::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }

  wxNotifyEvent (event, FALSE);
}

/*
 * Multi-line Text item
 */
 
wxbMultiText::wxbMultiText (void)
{
  __type = wxTYPE_MULTI_TEXT;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbMultiText::wxbMultiText (wxPanel * panel, wxFunction Function, char *label, char *value,
	      int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_MULTI_TEXT;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

void wxbMultiText::Command (wxCommandEvent & event)
{
  SetValue (event.commandString);
  ProcessCommand (event);
}

void wxbMultiText::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }
  wxNotifyEvent (event, FALSE);
}

/*
 * Slider
 */
 
wxbSlider::wxbSlider (void)
{
  __type = wxTYPE_SLIDER;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbSlider::wxbSlider (wxPanel * panel, wxFunction func, char *label, int value,
	   int min_value, int max_value, int width, int x, int y, long style, char *name)
{
  __type = wxTYPE_SLIDER;
  windowStyle = style;
  window_parent = panel;
  labelPosition = panel->label_position;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbSlider::~wxbSlider (void)
{
}

void wxbSlider::Command (wxCommandEvent & event)
{
  SetValue (event.commandInt);
  ProcessCommand (event);
}

void wxbSlider::ProcessCommand (wxCommandEvent & event)
{
  if (wxNotifyEvent (event, TRUE))
    return;

  wxFunction fun = callback;
  if (fun)
    {
      (void) (*(fun)) (*this, event);
    }
    else
    {
      GetEventHandler()->OnCommand(*this, event);
    }
  wxNotifyEvent (event, FALSE);
}

/*
 * Group box
 */
 
wxbGroupBox::wxbGroupBox (void)
{
  __type = wxTYPE_GROUP_BOX;
  window_parent = NULL;
  labelPosition = wxHORIZONTAL;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbGroupBox::wxbGroupBox (wxPanel * panel, char *label,
	   int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_GROUP_BOX;
  windowStyle = style;
  window_parent = panel;
  labelPosition = wxHORIZONTAL;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbGroupBox::~wxbGroupBox (void)
{
}

/*
 * Gauge
 */
 
#if USE_GAUGE
wxbGauge::wxbGauge (void)
{
  __type = wxTYPE_GAUGE;
  window_parent = NULL;
  labelPosition = wxHORIZONTAL;
  buttonFont = NULL;
  labelFont = NULL;
  backColour = NULL;
  labelColour = NULL;
  buttonColour = NULL;
}

wxbGauge::wxbGauge (wxPanel * panel, char *label,
	   int range, int x, int y, int width, int height, long style, char *name)
{
  __type = wxTYPE_GAUGE;
  windowStyle = style;
  window_parent = panel;
  labelPosition = wxHORIZONTAL;
  buttonFont = panel->buttonFont;
  labelFont = panel->labelFont;
  backColour = panel->backColour;
  labelColour = panel->labelColour;
  buttonColour = panel->buttonColour;
}

wxbGauge::~wxbGauge (void)
{
}
#endif
