/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas (email: alex@soften.ktu.lt)
// Modified by:
// Created:     2000/02/18
// RCS-ID:      $Id: outlctrl.h,v 1.1 2001/04/03 20:10:28 aleksandras Exp $
// Copyright:   (c) PM-Soft
// RCS-ID:      $Id: outlctrl.h,v 1.1 2001/04/03 20:10:28 aleksandras Exp $
/////////////////////////////////////////////////////////////////////////////

#ifndef __OUTLCTRL_G__
#define __OUTLCTRL_G__

/*---- TAB-size 4 ----*/

#include "wx/list.h"
#include "wx/dynarray.h"
#include "wx/window.h"

// NOTE:: prefix OL - indocates relation to wxOutlookListCtrl
//         OB - indocates relation to wxOutlookBarCtrl

// class hierarchy

class wxObject;

  class wxOLGlyph;
    class wxOLItem;
    class wxOLImage;

    class wxOLContainer;
      class wxOLBoxContainer;
      class wxOLDecorator;

  class wxOBFolder;

class wxWindow;
  class wxOutlookListCtrl;
  class wxOutlookBarCtrl;

// arrays

WX_DEFINE_ARRAY(wxBitmap*,  OLBitmapListT);
WX_DEFINE_ARRAY(wxOLImage*, OLImageListT );
WX_DEFINE_ARRAY(wxOLGlyph*, OLGlyphListT );
WX_DEFINE_ARRAY(wxPoint*,   OLPointListT );

// "missing" constants from "wx/defs.h"

#define wxLEFT  0x400
#define wxRIGHT 0x800

class wxParagraphLineInfo
{
public:
  wxString mText;
  wxSize   mSize;
};

WX_DEFINE_ARRAY(wxParagraphLineInfo*, ParagraphLineInfoT);

/*
 * General helper class for layouting/drawing of given
 * text with alignment and word-wrap options
 */

class wxTextParagraph
{
public:
  wxTextParagraph();
  wxTextParagraph(const wxString& text);
  virtual ~wxTextParagraph();

  virtual void SetWordWrap(bool on);
  virtual void SetAlignment(int align); // wxLEFT or wxRIGHT or wxCENTER
  virtual void SetVertical(bool isVertical);
  virtual bool IsVertical();

  virtual void SetText(const wxString& text);

  virtual void SetDc(wxDC* pDc);
  virtual void LayoutText(int outterWidth);
  virtual wxSize& GetPreferedSize();

  virtual void DrawText(wxDC& dc, const wxRect& rect);

protected:
  virtual void GetWords(const wxString& text, wxStringList& lst);
  virtual void GetStringDim(const wxString& text, int* w, int* h);
  virtual int  GetSpaceCharWidth();

protected:
  int      mAlign;
  bool       mIsVertical;
  wxString   mText;
  bool       mWordWrap;
  wxSize     mPrefSize;

  // set up temporarely while layouting
  wxDC*  mpDc;

  // chached data when orienting text vertically
  // uses wxImage to roate pixels 90-degrees
  wxString  mCachedText;
  wxSize    mCachedPrefSize;
  wxBitmap* mpCachedVertBmp;

  ParagraphLineInfoT mLines;
};

// couple of global layouting helpers

int wxGetCenterPos(int outterWidth, int innerWidth);
int wxGetAlignedPos(long align, int outterWidth, int innerWidth);
int wxGetHorizCenterPos(const wxSize& outterSize, const wxSize& innerSize);
int wxGetVertCenterPos(const wxSize& outterSize, const wxSize& innerSize);
void wxGetMutalCenter(int* pos1, int width1, int* pos2, int width2);
void DrawThin3DOutline(wxDC& dc, wxRect rect, bool isPressed);
void DrawThick3DOutline(wxDC& dc, const wxRect& rect, bool isPressed);
void Fill3DInterior(wxDC& dc, const wxRect& rect, bool isPressed);

// helper classes for wxOutlookListCtrl, can be subclassed
// to provide custom look and behaviour 

/*
 * Base class for all "owner-drawn" components
 * which make up the content of wxOutlookListCtrl
 */

class wxOLGlyph : public wxObject
{
public:
  wxOLGlyph();
  ~wxOLGlyph();

  // ID of the command-event which will
  // be triggered when this glyph is pressed/activated.
   // Event wont occure if it is -1.
  void SetId(int commandId);
  int  GetId();

  // sets up back-reference to the window-bound control
  virtual void SetControl(wxOutlookListCtrl* pCtrl);
  virtual wxOutlookListCtrl& GetControl();

  virtual void SetBounds(const wxRect& bounds);
  virtual wxRect& GetBounds();
  virtual bool HitTest(const wxPoint& point);

  // called first CalcPreferedSize() 
  virtual wxSize CalcPreferedSize(const wxSize& outterSize);
  
  // then called Layout()
  virtual void Layout();

  // after layouting done, Draw() is called
  virtual void Draw(wxDC& dc);

  // can be overriden by animated glyphs
  virtual void OnTimerTick(wxDC& dc, int tickNo);

  virtual bool IsAnimated(); // returns FALSE by default

  // mouse events notifications
  virtual bool OnLeftDown(const wxPoint& pos);
  virtual bool OnLeftUp(const  wxPoint& pos);
  virtual bool OnRightDown(const wxPoint& pos);
  virtual bool OnRightUp(const wxPoint& pos);
  virtual bool OnMotion(const wxPoint& pos);

  // NULL, if this glyph has no child-glyphs
  virtual OLGlyphListT* GetChildren();

protected:
  virtual bool DoDispatchEvent(int evtType, const wxPoint& pos);

protected:
  wxRect mBounds;
  wxOutlookListCtrl* mpCtrl;

  int    mCommandId;
};

class wxOLImage : public wxOLGlyph
{
public:
  wxOLImage();
  wxOLImage(const wxBitmap& largeBitmap);
  wxOLImage(const wxBitmap& largeBitmap, const wxBitmap& smallBitmap);

  ~wxOLImage();

  void AddSmallImage(const wxBitmap& smallBmp);
  void AddLargeImage(const wxBitmap& largeBmp);

  void SetupAnimation(wxPoint* jumpOffsets, int nOffsets,
             int animationRate, int framesetDelay);

  // 4 overriden methods of wxOLGlyph
  virtual void Draw(wxDC& dc);
  virtual wxSize CalcPreferedSize(const wxSize& outterSize);
  virtual void OnTimerTick(wxDC& dc, int tickNo); // does anymation if any
  virtual bool IsAnimated();
  virtual bool IsWiggling();

protected:
  wxSize GetBitmapSize(const wxBitmap& bmp);
  wxBitmap& GetCurrentBitmap(size_t index);
  wxBitmap& GetCurrentBitmap();
  OLBitmapListT& GetCurrentList();

  wxBitmap* CloneBitmap(const wxBitmap& bmp);

protected:

  OLBitmapListT mSmallBitmaps;
  OLBitmapListT mLargeBitmaps;

  // animation preferences
  int      mAnimationRate;
  int      mFramesetDelay;
  OLPointListT mJumpPoints;

  // animation state
  int mCurrentFrame;
  int mFirstTick;
};

class wxOLItem : public wxOLGlyph
{
public:
  wxOLItem(const wxString& text, int commandId = -1); // text without image

  wxOLItem(wxOLImage* pImage, const wxString& text, int commandId = -1);
  ~wxOLItem();

  virtual void SetImage(wxOLImage* pImage);
  virtual wxOLImage* GetImage();

  virtual void SetControl(wxOutlookListCtrl* pCtrl);

  virtual void SetText(const wxString& text);
  virtual wxString& GetText();

  virtual void HideText(bool hide);

  virtual void SetIsFocused(bool focused);
  virtual bool GetIsFocused();
  virtual void SetIsPressed(bool pressed);
  virtual bool GetIsPressed();

  virtual wxRect& GetTextBounds();

  // 5 overriden methods of wxOLGlyph
  virtual wxSize CalcPreferedSize(const wxSize& outterSize);
  virtual void Layout();
  virtual void Draw(wxDC& dc);
  virtual void OnTimerTick(wxDC& dc, int tickNo);
  virtual bool HitTest(const wxPoint& point);

  // mouse events notifications
  virtual bool OnLeftDown(const wxPoint& pos);
  virtual bool OnLeftUp(const  wxPoint& pos);
  virtual bool OnRightDown(const wxPoint& pos);
  virtual bool OnRightUp(const wxPoint& pos);
  virtual bool OnMotion(const wxPoint& pos);

protected:
  wxString    mText;
  wxTextParagraph mParagraph;
  wxOLImage*    mpImage; // NULL, if none

  // current state
  bool          mIsFocused;
  bool          mIsPressed;

  // cached info
  wxRect mTextRect;
  bool   mTextHidden; // set TRUE, when item's being edited
};

class wxOLContainer : public wxOLGlyph
{
public:
  wxOLContainer();
  ~wxOLContainer();

  virtual void Add(wxOLGlyph* pItem);
  virtual void Remove(wxOLGlyph* pItem);
  virtual bool RemoveById(int commandId);

  virtual void Scroll(int nItems);
  virtual size_t GetPageTopItemIndex();
  virtual void SetPageTopItem(size_t index);

  virtual void RefreshNow();

  // overridable
  virtual size_t GetItemsInPage();

  // overriden method of wxOLGlyph
  virtual OLGlyphListT* GetChildren();

protected:
  OLGlyphListT mChildren;
  size_t       mCurPageTop;
};

class wxOLBoxContainer : public wxOLContainer
{
public:
  wxOLBoxContainer();
  ~wxOLBoxContainer();

  // 4 overriden methods of wxOLGlyph
  virtual wxSize CalcPreferedSize(const wxSize& outterSize);
  virtual void Layout();
  virtual void Draw(wxDC& dc);
  virtual size_t GetItemsInPage();

protected:
  int mItemsInPage;
};

class wxOLDecorator : public wxOLContainer
{
public:
  wxOLDecorator();

  virtual void SetContainer(wxOLContainer* pContainer);

  // 3 overriden methods of wxOLGlyph
  virtual void Layout();
  virtual wxSize CalcPreferedSize(const wxSize& outterSize);
  virtual void Draw(wxDC& dc);

  // overridables (for possible subclasses of wxOLContainer)
  virtual void DrawButtonFrame(wxDC& dc, const wxPoint& at, bool pressed);
  virtual void DrawButtonShaft(wxDC& dc, const wxPoint& at, bool pressed, int dir);

  virtual void SetInnserPadding(const wxSize& padding);
  virtual void SetButtonPadding(const wxSize& padding);
  virtual void SetButtonSize(const wxSize& btnSize);

  bool HitsButton(const wxPoint& atPos, const wxPoint& btnPos);
  int  GetHittedButtonNo(const wxPoint& atPos);
  bool ButtonShown(int index);
  wxPoint GetCornerPos(int cornerNo);

  // mouse events notifications
  virtual bool OnLeftDown(const wxPoint& pos);
  virtual bool OnLeftUp(const  wxPoint& pos);
  virtual bool OnRightDown(const wxPoint& pos);
  virtual bool OnRightUp(const wxPoint& pos);

protected:
  wxOLContainer* mpContainer;
  wxSize         mBtnSize;
  wxSize         mInnerPadding;
  wxSize         mBtnPadding;

  int            mPressedBtnNo;
  wxPoint        mFirstBtnPos;
  wxPoint        mSecondBtnPos;

  // timer is used while scrolling while holding shaft-button down
  int            mFirstTick; 
};

class wxOLMarginInfo
{
public:
  int mTop;
  int mBottom;
  int mLeft;
  int mRight;
  int mTextToImageGap;
};

/*
 * wxOutlookListCtrl implements container-control for all
 * custom "owner-drawn" derivatives of wxOLGlyph which make 
 * up the content of this control
 */

// window styles for wxOutlookListCtrl

const int wxOL_HORIZONTAL  = 0x01;
const int wxOL_VERTICAL    = 0x02;
const int wxOL_LARGE_ITEMS = 0x04;
const int wxOL_SMALL_ITEMS = 0x08;
const int wxOL_ITEM_DRAG   = 0x10;

// other lower-level styles, which can be "assembled"
// to provide those obove

enum wxOL_AGLIGNMENT // applies for positioning of scroll-shafts
           // as well as item-text
{
  wxOL_ALIGN_TOP,
  wxOL_ALIGN_BOTTOM,
  wxOL_ALIGN_LEFT,
  wxOL_ALIGN_RIGHT
};

enum wxOL_ITEM_ALIGNMENT
{
  wxOL_ITEM_CENTERED      = wxCENTER,
  wxOL_ITEM_LEFT_ALIGNED  = wxLEFT,
  wxOL_ITEM_RIGHT_ALIGNED = wxRIGHT
};

enum wxOL_ITEM_TYPE
{
  wxOL_SMALL_ITEM,
  wxOL_LARGE_ITEM
};

const int wxOL_DEFAULT_STYLE = wxOL_VERTICAL    | 
                 wxOL_LARGE_ITEMS |
                 wxOL_ITEM_DRAG;



class wxOutlookListCtrl : public wxPanel
{
public:
  wxOutlookListCtrl() {}; 
  wxOutlookListCtrl(wxWindow* pWindow, wxWindowID id = -1, 
             const wxPoint& pos =wxDefaultPosition, 
             const wxSize& size =wxDefaultSize, 
             long style = wxOL_DEFAULT_STYLE, 
             const wxString& name = "wxOutlookListCtrl");

  ~wxOutlookListCtrl();

  /***** public (cutomization) interface *****/

  // item management

  virtual void AddItem(const wxString& text, const wxBitmap& largeBitmap, 
              int commandId = -1);

  virtual void AddItem(const wxString& text, 
              const wxBitmap& largeBitmap, const wxBitmap& smallBitmap, 
              int commandId = -1);

  virtual void AddItem(wxOLGlyph* pItem);
  virtual void RemoveItem(wxOLGlyph* pItem);
  virtual bool RemoveItemById(int commandId);

  virtual void ChangeStyle(int newWindowStyle, bool refreshNow = TRUE);
  virtual void RefreshNow();

  // setup for lower-level styles

  virtual void SetScrollShaftAlign(int align);
  virtual long GetScrollShaftAlign();
  virtual void SetItemTextAlign(int align);
  virtual long GetItemTextAlign();
  virtual void SetItemType(long itemType);
  virtual long GetItemType();
  virtual void SetItemAlign(long align);
  virtual long GetItemAlign();
  virtual void SetOrientation(long orient);
  virtual long GetOrientation();
  virtual bool IsVertical();

  virtual void SetWordWrap(bool on);
  virtual bool GetWordWrap();

  // other attributes
  virtual void SetBgColor(const wxColour& bg);
  virtual wxColour& GetBgColor();
  virtual void SetTextColor(const wxColour& col);
  virtual wxColour& GetTextColor();
  virtual void SetBgImage(wxOLImage* pImage);
  virtual wxOLImage* GetBgImage();
  virtual void SetGenerateMasks(bool on);
  virtual bool GetGenerateMasks();
  virtual void SetMaskColor(const wxColour& col);
  virtual wxColour& GetMaskColor();

  virtual void SetSmallItemMargins(const wxOLMarginInfo& info);
  virtual wxOLMarginInfo& GetSmallItemMargins();
  virtual void SetLargeItemMargins(const wxOLMarginInfo& info);
  virtual wxOLMarginInfo& GetLargeItemMargins();
  virtual wxOLMarginInfo& GetItemMargins(); // returns them according to the current style

  virtual void SetWigglingItem(wxOLItem* pItem);
  virtual wxOLItem* GetWigglingItem();

  // notification received from wxOLItem
  virtual void OnTrackItemMenu(wxOLItem* pItem, const wxPoint& pos);
  virtual void OnTrackListMenu(const wxPoint& pos);

  // -1 if timer-events are not generated (no animations at all),
   // otherwise indicates interval between ticks in milliseconds

  virtual void SetTimerRate(long rateMills);
  virtual long GetTimerRate();

  // setup for custom onwer-drawn components (optional)

  virtual void SetDecorator(wxOLDecorator* pDecorator);
  virtual void SetContainer(wxOLContainer* pContainer);
  wxOLDecorator* GetDecorator();
  wxOLContainer* GetContainer();

  // notifications received from external timer

  virtual void OnTimer(int millsElapsed);

  // utilities

  wxDC& GetCurrentDc();
  virtual void CaptureEventsForGlyph(wxOLGlyph* pReceiver);
  virtual void ReleaseEvents(wxOLGlyph* pPrevReceiver);

  DECLARE_CLASS(wxOutlookListCtrl); // for wxized RTTI
  DECLARE_EVENT_TABLE()

protected: /*** protected itnerface ***/

  /*** event handlers ***/

  void OnPaint(wxPaintEvent& event);
  void OnEraseBackground(wxEraseEvent& event);

  void OnLeftDown(wxMouseEvent& event);
  void OnLeftUp(wxMouseEvent& event);
  void OnMotion(wxMouseEvent& event);
  void OnRightDown(wxMouseEvent& event);
  void OnRightUp(wxMouseEvent& event);
  void OnLeftDblClick(wxMouseEvent& event);

  // command's handled by this control:

  enum OUTLOOK_LISTCTRL_COMMAND_IDS
  {
    ID_LIST_VIEW = 100,
    ID_ICON_VIEW,
    ID_ALIGN_VERTICAL,
    ID_ALIGN_HORIZONTAL,
    ID_ALIGN_TEXT_TOP,
    ID_ALIGN_TEXT_BOTTOM,
    ID_ALIGN_TEXT_LEFT,
    ID_ALIGN_TEXT_RIGHT,
    ID_ALIGN_ITEMS_LEFT,
    ID_ALIGN_ITEMS_RIGHT,
    ID_ALIGN_ITEMS_CENTER,
    ID_ALIGN_SCROLLER_TOP,
    ID_ALIGN_SCROLLER_BOTTOM,
    ID_ALIGN_SCROLLER_LEFT,
    ID_ALIGN_SCROLLER_RIGTH,
    ID_RENAME_ITEM,
    ID_REMOVE_ITEM,
    ID_WORD_WRAP_ON,
    ID_WORD_WRAP_OFF,
    ID_EDITOR_CTRL,
  };

  void OnCmdAlignTextTop(wxCommandEvent& event);
  void OnCmdAlignTextBottom(wxCommandEvent& event);
  void OnCmdAlignTextLeft(wxCommandEvent& event);
  void OnCmdAlignTextRight(wxCommandEvent& event);

  void OnCmdAlignVertical(wxCommandEvent& event);
  void OnCmdAlignHorizontal(wxCommandEvent& event);

  void OnCmdAlignItemsLeft(wxCommandEvent& event);
  void OnCmdAlignItemsRight(wxCommandEvent& event);
  void OnCmdAlignItemsCenter(wxCommandEvent& event);

  void OnCmdAlignScrollerTop(wxCommandEvent& event);
  void OnCmdAlignScrollerBottom(wxCommandEvent& event);
  void OnCmdAlignScrollerLeft(wxCommandEvent& event);
  void OnCmdAlignScrollerRight(wxCommandEvent& event);

  void OnCmdListView(wxCommandEvent& event);
  void OnCmdIconView(wxCommandEvent& event);
  void OnCmdWordWrapOn(wxCommandEvent& event);
  void OnCmdWordWrapOff(wxCommandEvent& event);
  void OnCmdRemoveItem(wxCommandEvent& event);
  void OnCmdRenameItem(wxCommandEvent& event);

  void OnTextUpdated(wxCommandEvent& event);

  // overridable for drawing risded or sunken 3d border
  // around iteml
  virtual void Draw3DOutline(wxDC& dc, const wxRect& rect, bool isPressed);
  virtual void DoRefresh(wxDC& dc);
  virtual void DoDispatchEvent(wxMouseEvent& event, int subType);

  // override this to add custom menu items to the popup-menu
  virtual void DoTrackPopupMenu(const wxPoint& pos, bool forItem);

protected:
  long mScrollShaftAlign;
  long mItemTextAlign;
  long mItemAlign;
  long mOrientation;
  long mIsVertical;
  long mScrollingStyle;
  long mItemType;
  bool mWordWrap;

  bool     mGenerateMasks; // default: TRUE;
  wxColour mMaskColor;   // default: wxWHITE

  wxColour  mTextColor;  // default: wxWHITE (MS-Outlook's color)
  wxColour  mBgColor;    // default: wxBLACK -/-
  long      mTimerRate;  // default: 100mills
  int       mTickCounter;

  wxOLImage*     mpBgImage;
  wxOLContainer* mpContainer;
  wxOLDecorator* mpDecorator; // top-level object in the containment 
                // hierarchy of wxOLGlyph derivatives

  wxOLGlyph* mpCapturedGlyph; // glyph which has currently captured
                // all mouse input, or NULL if none
  wxDC* mpCurrentDc;
  wxOLItem* mpSelectedItem; // item for which the pop-up menu is
                // currently being shown

  wxOLMarginInfo mSmallItemMargins;
  wxOLMarginInfo mLargeItemMargins;

  wxOLItem* mpWigglingItem;
  wxTextCtrl* mpEditor;   // textctrl in which item's label is edited
};


#endif // __OUTLCTRL_G__
