/**************************************************************************

    This file is part of Xclass95, a Win95-looking GUI toolkit.
    Copyright (C) 1996, 1997 David Barth, Hector Peraza.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************/

#ifndef __OXWIDGETS_H
#define __OXWIDGETS_H

#include <X11/Xlib.h>

#include <xclass/OXFrame.h>
#include <xclass/ODimension.h>
#include <xclass/OString.h>
#include <xclass/OTextBuffer.h>
#include <xclass/OPicture.h>

#ifndef min
#define min(a,b) (((a)<(b)) ? (a) : (b))
#endif

#ifndef max
#define max(a,b) (((a)>(b)) ? (a) : (b))
#endif


//--- Text justification modes

#define TEXT_LEFT         (1<<0)
#define TEXT_RIGHT        (1<<1)
#define TEXT_CENTER_X     (1<<2)

#define TEXT_TOP          (1<<3)
#define TEXT_BOTTOM       (1<<4)
#define TEXT_CENTER_Y     (1<<5)

//--- Widget messages and submessages
//    (these should be on a separate include file)

#define XC_COMMAND        1
#define   CM_MENU           1
#define   CM_MENUSELECT     2
#define   CM_BUTTON         3
#define   CM_CHECKBUTTON    4
#define   CM_RADIOBUTTON    5
#define   CM_LISTBOX        6
#define   CM_DDLISTBOX      7
#define XC_HSCROLL        2
#define XC_VSCROLL        3
#define   SB_LINEUP         1
#define   SB_LINEDOWN       2
#define   SB_PAGEUP         3
#define   SB_PAGEDOWN       4
#define   SB_SLIDERTRACK    5
#define   SB_SLIDERPOS      6
#define XC_TEXTENTRY      4
#define   TE_TEXTCHANGED    1
#define XC_CONTAINER      5
#define   CT_ITEMCLICK      1
#define   CT_ITEMDBLCLICK   2
#define   CT_SELCHANGED     3
#define XC_HSLIDER        6
#define XC_VSLIDER        7
#define   SL_POS            1
#define   SL_TRACK          2

#define XC_MSGMAX         7

#define MK_MSG(msg, submsg) ((msg << 8) + submsg)
#define GET_MSG(val)        ((val >> 8) & 255)
#define GET_SUBMSG(val)     (val & 255)

#define DISABLED	  0
#define ENABLED		  1

//-----------------------------------------------------------------

#define WIDGET_WANT_FOCUS  (1<<0)
#define WIDGET_HAS_FOCUS   (1<<1)
#define WIDGET_IS_ENABLED  (1<<2)

class OXWidget {
public:
  OXWidget() {}
  OXWidget(int ID, char *type) { _widgetID = ID; _widgetType = type; }

  int  WidgetID() const { return _widgetID; }
  char *WidgetType() const { return _widgetType; }
  int  HasFocus() const { return (_widgetFlags & WIDGET_HAS_FOCUS); }
  int  WantFocus() const { return (_widgetFlags & WIDGET_WANT_FOCUS); }
  void Associate(const OXWindow *w) { _msgWindow = w; }

protected:
  int _SetFlags(int flags) { return _widgetFlags |= flags; }
  int _ClearFlags(int flags) { return _widgetFlags &= ~flags; }

  int _widgetID;
  int _widgetFlags;
  char *_widgetType;
  const OXWindow *_msgWindow;
};

#include <xclass/OXButton.h>
#include <xclass/OXMenu.h>
#include <xclass/OXScrollBar.h>
#include <xclass/OXCanvas.h>
#include <xclass/OXTab.h>

//-----------------------------------------------------------------

class OXIcon : public OXFrame {
public:
  OXIcon(const OXWindow *p, const OPicture *pic, int w, int h,
         unsigned int options = CHILD_FRAME,
         unsigned long back = _defaultFrameBackground) :
    OXFrame(p, w, h, options, back) { _pic = pic; }

  const OPicture *GetPicture() const { return _pic; }
  virtual void SetPicture(const OPicture *pic);

  virtual ODimension GetDefaultSize() const;

protected:
  virtual void _DoRedraw();

  const OPicture *_pic;
};

//-----------------------------------------------------------------

class OXLabel : public OXFrame {
protected:
  static GC _defaultGC;
  static XFontStruct *_defaultFontStruct;
  XFontStruct *_fontStruct;
  GC _normGC;

public:
  OXLabel(const OXWindow *p, OString *text,
          GC norm = _defaultGC,
          XFontStruct *font = _defaultFontStruct,
          unsigned int options = CHILD_FRAME,
          unsigned long back = _defaultFrameBackground);
  OXLabel(const OXWindow *p, char *text,
          GC norm = _defaultGC,
          XFontStruct *font = _defaultFontStruct,
          unsigned int options = CHILD_FRAME,
          unsigned long back = _defaultFrameBackground);
  virtual ~OXLabel();

  virtual ODimension GetDefaultSize() const { return ODimension(_tw, _th+1); }
  const OString *GetText() const { return _text; }
  void SetText(OString *new_text);
  void SetTextJustify(const int tmode) { _tmode = tmode; } 

  friend class OXClient;

protected:
  virtual void _DoRedraw();
     
  OString *_text;
  int _tmode, _tw, _th;
};

//-----------------------------------------------------------------

class OXTextEntry : public OXFrame, public OXWidget {
protected:
  int _state;
  static Cursor _defaultCursor;
  static GC _defaultGC;
  static GC _defaultSelectedGC, _defaultSelectedBackgroundGC;
  GC _normGC, _selGC, _selbackGC;
  static XFontStruct *_defaultFontStruct;
  XFontStruct *_fontStruct;

public:
  OXTextEntry(const OXWindow *p, OTextBuffer *text, int ID = -1,
              GC norm = _defaultGC,
	      XFontStruct *font = _defaultFontStruct,
              unsigned int option = SUNKEN_FRAME | DOUBLE_BORDER,
              unsigned long back = _whitePixel);
  virtual ~OXTextEntry();
  virtual void SetState(int state);
  virtual int GetState(){return _state;}
  virtual int HandleButton(XButtonEvent *event);
  virtual int HandleDoubleClick(XButtonEvent *event);
  virtual int HandleMotion(XMotionEvent *event);
  virtual int HandleKey(XKeyEvent *event);
  virtual int HandleFocusChange(XFocusChangeEvent *event);
  virtual int HandleSelection(XSelectionEvent *event);
  virtual int HandleTimer(OTimer *t);
  virtual void DrawBorder();

  friend class OXClient;

protected:
  virtual void _DoRedraw();
  int _GetCharacterIndex(int xcoord);
  void _PastePrimary(Window wid, Atom property, int Delete);

  OTextBuffer *_text;
  OTimer *_curblink;
  // selection
  int _start_ix, _start_x, _end_ix, _end_x, _selection_on;
  // cursor
  int _cursor_x, _cursor_ix, _cursor_on;
};

//-----------------------------------------------------------------

class OXGroupFrame : public OXCompositeFrame {
protected:
  static GC _defaultGC;
  static XFontStruct *_defaultFontStruct;
  XFontStruct *_fontStruct;
  GC _normGC;

public:
  OXGroupFrame(const OXWindow *p, OString *title,
               unsigned int options = VERTICAL_FRAME,
               GC norm = _defaultGC,
               XFontStruct *font = _defaultFontStruct,
               unsigned long back = _defaultFrameBackground);
  virtual ~OXGroupFrame();

  virtual void DrawBorder();

  friend class OXClient;

protected:
  OString *_text;
};


//-------------------- Listbox (text strings only)

//---- base class for listbox entries:

class OXLBEntry : public OXFrame {
public:
  OXLBEntry(const OXWindow *p, int ID,
            unsigned int options = HORIZONTAL_FRAME,
            unsigned long back = _whitePixel) :
    OXFrame(p, 10, 10, options | OWN_BKGND, back) 
      { _active = False; _ID = ID; _bkcolor = back; }

  virtual void Activate(int a);
  virtual void UpdateEntry(OXLBEntry *e) {}  // this is needed on OXDDListBoxes :(
  int ID() const { return _ID; }
  int IsActive() const { return _active; }

  friend class OXClient;

protected:
  virtual void _DoRedraw() {}

  int _active, _ID, _bkcolor;
};

//---- text string entries

class OXTextLBEntry : public OXLBEntry {
protected:
  static unsigned long _selPixel;
  static GC _defaultGC;
  GC _normGC;
  static XFontStruct *_defaultFontStruct;
  XFontStruct *_fontStruct;

public:
  OXTextLBEntry(const OXWindow *p, OString *s, int ID,
                GC norm = _defaultGC, XFontStruct *font = _defaultFontStruct,
                unsigned int options = HORIZONTAL_FRAME,
                unsigned long back = _whitePixel);
  virtual ~OXTextLBEntry();

  virtual ODimension GetDefaultSize() const { return ODimension(_tw, _th+1); }
  const OString *GetText() const { return _text; }
  void SetText(OString *new_text);
  virtual void UpdateEntry(OXLBEntry *e)
    { SetText(new OString(((OXTextLBEntry *)e)->GetText())); }

  friend class OXClient;

protected:
  virtual void _DoRedraw();

  OString *_text;
  int _tw, _th;
};

class OXLBContainer : public OXCompositeFrame {
public:
  OXLBContainer(const OXWindow *p, int w, int h,
                unsigned int options = SUNKEN_FRAME,
                unsigned long back = _defaultFrameBackground);
  virtual ~OXLBContainer();

  virtual void AddEntry(OXLBEntry *lbe, OLayoutHints *lhints);
  virtual void InsertEntry(OXLBEntry *lbe, OLayoutHints *lhints, int afterID);
  virtual void RemoveEntry(int ID);
  virtual void RemoveEntries(int from_ID, int to_ID);
  virtual void RemoveAllEntries();

  virtual void Associate(const OXWindow *w) { _msgWindow = w; }
  virtual int  HandleButton(XButtonEvent *event);
  virtual int  HandleMotion(XMotionEvent *event);
  virtual int  GetSelected() const;
  virtual OXLBEntry *GetSelectedEntry() const { return _last_active; }

  virtual void SelectAll();
  virtual void UnSelectAll();
  virtual OXLBEntry *Select(int ID);
  virtual OXLBEntry *FindEntry(int ID);

  void SetMultipleSelect(int mode) { _multipleSelect = mode; }

protected:
  OXLBEntry *_last_active;
  const OXWindow *_msgWindow;
  int _dragging, _multipleSelect;
};

class OXListBox : public OXCompositeFrame {
public:
  OXListBox(const OXWindow *p, int ID,
            unsigned int options = SUNKEN_FRAME | DOUBLE_BORDER,
            unsigned long back = _whitePixel);
  virtual ~OXListBox();

  virtual void AddEntry(OString *s, int ID);
  virtual void AddEntry(OXLBEntry *lbe, OLayoutHints *lhints);
  virtual void InsertEntry(OString *s, int ID, int afterID);
  virtual void InsertEntry(OXLBEntry *lbe, OLayoutHints *lhints, int afterID);
  virtual void RemoveEntry(int ID);
  virtual void RemoveEntries(int from_ID, int to_ID);
  virtual void RemoveAllEntries();

  OXWindow *GetContainer() const
    { return ((OXWindow *) _vport->GetContainer()); }
  OXWindow *GetViewPort() const
    { return ((OXWindow *) _vport); }
  virtual void DrawBorder();
  virtual void Resize(int w, int h);
  virtual void MoveResize(int x, int y, int w, int h);
  virtual void Layout();
  virtual void IntegralHeight(int mode) { _integralHeight = mode; }
  virtual ODimension GetDefaultSize() const;

  virtual int  ProcessMessage(long msg, long parm1, long parm2);

  virtual void Associate(const OXWindow *w) { _msgWindow = w; }
  virtual OXLBEntry *Select(int ID) { return _lbc->Select(ID); }
  virtual OXLBEntry *FindEntry(int ID) { return _lbc->FindEntry(ID); }
  virtual int  GetSelected() const;
  virtual OXLBEntry *GetSelectedEntry() const
    { return _lbc->GetSelectedEntry(); }

  virtual void SetMultipleSelect(int mode)
    { _lbc->SetMultipleSelect(mode); }

  void AutoUpdate(int mode) { _autoUpdate = mode; }
  virtual void Update();

protected:
  void _SetContainer(OXFrame *f) { _vport->SetContainer(f); }

  const OXWindow *_msgWindow;
  OXLBContainer *_lbc;
  OXViewPort *_vport;
  OXVScrollBar *_vscrollbar;
  int _ID, _itemVsize, _integralHeight, _autoUpdate;
};

//-------------------- Drop-down listbox (combo box)

class OXDDPopup : public OXCompositeFrame {
protected:
  static Cursor _defaultCursor;

public:
  OXDDPopup(const OXWindow *p, int w, int h,
            unsigned int options = VERTICAL_FRAME,
            unsigned long back = _whitePixel);

  virtual int HandleButton(XButtonEvent *);
  void PlacePopup(int x, int y, int w, int h);
  void EndPopup();

  friend class OXClient;
};

class OXDDListBox : public OXCompositeFrame {
protected:
  static const OPicture *_bpic;

public:
  OXDDListBox(const OXWindow *p, int ID,
              unsigned int options = HORIZONTAL_FRAME | SUNKEN_FRAME | DOUBLE_BORDER,
              unsigned long back = _whitePixel);
  virtual ~OXDDListBox();

  virtual void DrawBorder();
  virtual ODimension GetDefaultSize() const { return ODimension (_w, _h); }

  virtual void Associate(const OXWindow *w) { _msgWindow = w; }
  virtual int  HandleButton(XButtonEvent *event);
  virtual int  ProcessMessage(long msg, long parm1, long parm2);

  virtual void AddEntry(OString *s, int ID)
    { _lb->AddEntry(s, ID); }
  virtual void AddEntry(OXLBEntry *lbe, OLayoutHints *lhints)
    { _lb->AddEntry(lbe, lhints); }
  virtual void InsertEntry(OString *s, int ID, int afterID)
    { _lb->InsertEntry(s, ID, afterID); }
  virtual void InsertEntry(OXLBEntry *lbe, OLayoutHints *lhints, int afterID)
    { _lb->InsertEntry(lbe, lhints, afterID); }
  virtual void RemoveEntry(int ID)
    { _lb->RemoveEntry(ID); }
  virtual void RemoveEntries(int from_ID, int to_ID)
    { _lb->RemoveEntries(from_ID, to_ID); }
  virtual void RemoveAllEntries()
    { _lb->RemoveAllEntries(); }

  virtual const OXListBox *GetListBox() const { return _lb; }
  virtual void Select(int ID);
  virtual int  GetSelected() const { return _lb->GetSelected(); }
  virtual OXLBEntry *GetSelectedEntry() const
    { return _lb->GetSelectedEntry(); }

  virtual void SetTopEntry(OXLBEntry *e, OLayoutHints *lh);

  friend class OXClient;

protected:
  const OXWindow *_msgWindow;
  OXLBEntry *_selentry;
  OXScrollBarElt *_ddbutton;
  OXDDPopup *_ddframe;
  OXListBox *_lb;
  int _ID;
  OLayoutHints *_lhs, *_lhb, *_lhdd;
};

//-------------------- Spin buttons

/*

//--- abstract

class OXSpin : public OXCompositeFrame {
public:
  OXSpin(
};

class OXHSpin : public OXSpin {
};

class OXVSpin : public OXSpin {
};
*/

#endif  // __OXWIDGETS_H
