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

    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 __OXFRAME_H
#define __OXFRAME_H

#include <X11/Xproto.h>

#include <xclass/OXWindow.h>
#include <xclass/ODimension.h>
#include <xclass/OXSList.h>
#include <xclass/OTimer.h>
#include <xclass/OLayout.h>


//---- frame states

#define IS_VISIBLE       (1<<0)
#define IS_MAPPED        IS_VISIBLE
#define IS_ARRANGED      (1<<1)

//---- types of frames (and borders)

#define CHILD_FRAME      0
#define MAIN_FRAME       (1<<0)
#define VERTICAL_FRAME   (1<<1)
#define HORIZONTAL_FRAME (1<<2)
#define SUNKEN_FRAME     (1<<3)
#define RAISED_FRAME     (1<<4)
#define DOUBLE_BORDER    (1<<5)
#define FIT_WIDTH        (1<<6)
#define FIXED_WIDTH      (1<<7)
#define FIT_HEIGHT       (1<<8)
#define FIXED_HEIGHT     (1<<9)
#define FIXED_SIZE       (FIXED_WIDTH | FIXED_HEIGHT)
#define OWN_BKGND        (1<<10)

//---- MWM Hints stuff

// hints

#define MWM_HINTS_FUNCTIONS     (1L << 0)
#define MWM_HINTS_DECORATIONS   (1L << 1)
#define MWM_HINTS_INPUT_MODE    (1L << 2)

// functions

#define MWM_FUNC_ALL            (1L << 0)
#define MWM_FUNC_RESIZE         (1L << 1)
#define MWM_FUNC_MOVE           (1L << 2)
#define MWM_FUNC_MINIMIZE       (1L << 3)
#define MWM_FUNC_MAXIMIZE       (1L << 4)
#define MWM_FUNC_CLOSE          (1L << 5)       

// input mode

#define MWM_INPUT_MODELESS                   0
#define MWM_INPUT_PRIMARY_APPLICATION_MODAL  1
#define MWM_INPUT_SYSTEM_MODAL               2
#define MWM_INPUT_FULL_APPLICATION_MODAL     3         

// decorations

#define MWM_DECOR_ALL                 (1L << 0)
#define MWM_DECOR_BORDER              (1L << 1)
#define MWM_DECOR_RESIZEH             (1L << 2)
#define MWM_DECOR_TITLE               (1L << 3)
#define MWM_DECOR_MENU                (1L << 4)
#define MWM_DECOR_MINIMIZE            (1L << 5)
#define MWM_DECOR_MAXIMIZE            (1L << 6)

#define PROP_MOTIF_WM_HINTS_ELEMENTS  4
#define PROP_MWM_HINTS_ELEMENTS       PROP_MOTIF_WM_HINTS_ELEMENTS


//--------------------------------------------------------------------
// This class subclasses OXWindow, used as base class for some simple
// widgets (buttons, labels, etc.).
// It provides:
//  - position & dimension fields
//  - an 'options' attribute (see #defines above)
//  - a generic event handler
//  - a generic layout mechanism
//  - a generic border

class OXTip;

class OXFrame : public OXWindow {
protected:
  static const OPicture * _defaultBackgroundPicture;
  static unsigned long _defaultFrameBackground;
  static unsigned long _defaultSelectedBackground;
  static unsigned long _whitePixel;
  static unsigned long _blackPixel;
  static GC _blackGC, _whiteGC;
  static GC _hilightGC;
  static GC _shadowGC;
  static GC _bckgndGC;
  static Time _lastclick;
  static unsigned int _lastbutton, _dbx, _dby, _dbw;

public:
  OXFrame(const OXWindow *p, int w, int h,
          unsigned int options = 0,
          unsigned long back = _defaultFrameBackground);

  virtual int HandleEvent(XEvent *event);
  virtual int HandleConfigureNotify(XConfigureEvent *event);
  virtual int HandleButton(XButtonEvent */*event*/); 
  virtual int HandleDoubleClick(XButtonEvent */*event*/) { return False; }
  virtual int HandleCrossing(XCrossingEvent */*event*/);
  virtual int HandleMotion(XMotionEvent */*event*/) { return False; }
  virtual int HandleKey(XKeyEvent */*event*/) { return False; }
  virtual int HandleFocusChange(XFocusChangeEvent */*event*/) { return False; }
  virtual int HandleClientMessage(XClientMessageEvent *event);
  virtual int HandleSelection(XSelectionEvent */*event*/) { return False; }
  virtual int HandleSelectionRequest(XSelectionRequestEvent */*event*/) { return False; }
  virtual int HandleSelectionClear(XSelectionClearEvent */*event*/) { return False; }
  virtual int HandlePropertyChange(XPropertyEvent */*event*/) { return False; }

  virtual void SendMessage(const OXWindow *w, long msg, long parm1, long parm2);
  virtual int ProcessMessage(long /*msg*/, long /*parm1*/, long /*parm2*/)
              { return False; }

  virtual void Move(int x, int y);
  virtual void Resize(int w, int h);
  virtual void Resize(ODimension size);
  virtual void MoveResize(int x, int y, int w, int h);
  virtual int  GetDefaultWidth() const { return GetDefaultSize().w; }
  virtual int  GetDefaultHeight() const { return GetDefaultSize().h; }
  virtual ODimension GetDefaultSize() const 
          { return ODimension(_w, _h); }

  virtual unsigned int GetOptions() const { return _options; }
  virtual void ChangeOptions(unsigned int options);
  virtual void Layout() {}
  virtual void MapSubwindows() {}  // Simple frames do not have subwindows 
                                   // Redefine this in OXCompositeFrame!
  virtual void DrawBorder();

  int GetWidth() const { return _w; }
  int GetHeight() const { return _h; }
  ODimension GetSize() const { return ODimension(_w, _h); }
  int GetX() const { return _x; }
  int GetY() const { return _y; }
  int GetBorderWidth() const { return _bw; }

  // Modifiers (without graphic update)
  void SetWidth(int w) { _w = w; }
  void SetHeight(int h) { _h = h; }
  void SetSize(const ODimension &s) { _w = s.w; _h = s.h; }

  void SetTip(char * text);
  void RemoveTip();

  void ShowTip();
  void HideTip();

  friend class OXClient;

protected:
  virtual void _DoRedraw();
  virtual const OXWindow *_GetMainFrame() const { return OXWindow::_GetMainFrame(); }

  int _x, _y, _w, _h, _bw;
  unsigned int _options;

  OXTip * _tip;
  OString * _tip_text;
};


//--------------------------------------------------------------------
// This class is the base class for composite widgets 
// (menu bars, list boxes, etc.).
//
// It provides:
//  - a layout manager
//  - a frame container (SListFrameElt *)

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

//  virtual void Resize(int w, int h);
//  virtual void Resize(ODimension size);
//  virtual void MoveResize(int x, int y, int w, int h);
  virtual int  GetDefaultWidth() const 
                 { return GetDefaultSize().w; }
  virtual int  GetDefaultHeight() const
                 { return GetDefaultSize().h; }
  virtual ODimension GetDefaultSize() const 
                 { return _layoutManager->GetDefaultSize(); }

  virtual void MapSubwindows();
  virtual void Layout();

  virtual void ChangeOptions(unsigned int options);

  OLayoutManager *GetLayoutManager() const { return _layoutManager; }
  void            SetLayoutManager(OLayoutManager *l);

  void AddFrame(OXFrame *f, OLayoutHints *l = NULL);
  void RemoveFrame(OXFrame *f);
  void ShowFrame(OXFrame *f);
  void HideFrame(OXFrame *f);
  int  GetState(OXFrame *f) const;
  int  IsVisible(OXFrame *f) const;
  int  IsVisible(SListFrameElt *ptr) const { return (ptr->state & IS_VISIBLE); }
  int  IsArranged(OXFrame *f) const;
  int  IsArranged(SListFrameElt *ptr) const { return (ptr->state & IS_ARRANGED); }
  SListFrameElt **GetListAddr() { return &_flist; }

protected:
  SListFrameElt *_flist;

private:
  OLayoutManager *_layoutManager;
};

class OXVerticalFrame : public OXCompositeFrame {
public:
  OXVerticalFrame(const OXWindow *p, int w, int h,
		  unsigned int options = CHILD_FRAME,
                  unsigned long back = _defaultFrameBackground) :
    OXCompositeFrame(p, w, h, options | VERTICAL_FRAME, back) {}
};

class OXHorizontalFrame : public OXCompositeFrame {
public:
  OXHorizontalFrame(const OXWindow *p, int w, int h,
		  unsigned int options = CHILD_FRAME,
                  unsigned long back = _defaultFrameBackground) :
    OXCompositeFrame(p, w, h, options | HORIZONTAL_FRAME, back) {}
};

//--------------------------------------------------------------------
// For top-level windows:

class OXMainFrame : public OXCompositeFrame {
public:
  OXMainFrame(const OXWindow *p, int w, int h,
	      unsigned long options = MAIN_FRAME | VERTICAL_FRAME);
  virtual ~OXMainFrame();

  virtual int HandleKey(XKeyEvent *event);
  virtual int HandleClientMessage(XClientMessageEvent *event);
  virtual void CloseWindow();

  void SetWindowName(char *Name);
  void SetIconName(char *Name);
  void SetClassHints(char *ClassName, char *ResourceName);
  void SetMWMHints(unsigned int value, unsigned int funcs, unsigned int input);
  void SetWMPosition(int x, int y);
  void SetWMSize(int w, int h);
  void SetWMSizeHints(int wmin, int hmin, int wmax, int hmax, 
                      int winc, int hinc);
  void SetWMState(int state);

  virtual int BindKey(const OXWindow *w, int keycode, int modifier) const;
  virtual void RemoveBind(const OXWindow *w, int keycode, int modifier) const;

protected:
  virtual const OXWindow *_GetMainFrame() const { return this; }
  typedef struct _MWMHintsProperty {
    CARD32 flags;
    CARD32 functions;
    CARD32 decorations;
    INT32  inputMode;
  } MWMHintsProperty;
  OXSList *_bindlist;
};

//--------------------------------------------------------------------
// For dialog (transient) windows:

class OXTransientFrame : public OXMainFrame {
public:
  OXTransientFrame(const OXWindow *p, const OXWindow *main, int w, int h,
	      unsigned long options = MAIN_FRAME | VERTICAL_FRAME) :
    OXMainFrame(p, w, h, options) {
      if (main)
        XSetTransientForHint(GetDisplay(), _id, main->GetId());
  }

  virtual void CloseWindow();
};


#endif  // __OXFRAME_H
