class ColumnList : public Ctrl, private CtrlFrame {
public:
	virtual void  Serialize(Stream& s);
	virtual void  Paint(Draw& w);
	virtual void  Layout();
	virtual Image CursorImage(Point p, dword);
	virtual void  LeftDown(Point p, dword);
	virtual void  LeftUp(Point p, dword);
	virtual void  LeftDouble(Point p, dword);
	virtual void  RightDown(Point p, dword);
	virtual void  LeftDrag(Point p, dword keyflags);
	virtual void  MouseMove(Point p, dword);
	virtual void  MouseLeave();
	virtual void  MouseWheel(Point p, int zdelta, dword keyflags);
	virtual bool  Key(dword key, int count);
	virtual void  GotFocus();
	virtual void  LostFocus();
	virtual void  CancelMode();
	virtual void  DragEnter();
	virtual void  DragAndDrop(Point p, PasteClip& d);
	virtual void  DragRepeat(Point p);
	virtual void  DragLeave();

private:
	virtual void  FrameLayout(Rect& r);
	virtual void  FrameAddSize(Size& sz);
	virtual void  FramePaint(Draw& draw, const Rect& r);

private:
	int        ncl;
	int        cy;
	int        cursor, anchor;
	int        dx;
	int        ci;
	int        mpos;
	ScrollBar  sb;
	Scroller   scroller;
	CtrlFrame *frame;
	int        dropitem;
	bool       insert;
	bool       clickkill;
	bool       nobg;
	bool       popupex;

	bool       selclick;

	DisplayPopup info;

	const Display *display;

	struct Item {
		bool           sel;
		bool           canselect;
		Value          value;
		const Display *display;
	};

	Array<Item> item;
	int         selcount;
	bool        multi;

	struct  ItemOrder;
	friend struct ItemOrder;

	void    SetSb();
	void    Scroll();
	int     GetDragColumn(int x) const;
	int     RoundedCy();
	void    Page(bool down);
	void    PointDown(Point p);
	void    DoClick(Point p, dword flags);
	void    ShiftSelect();
	void    RefreshItem(int i, int ex = 0);
	void    RefreshCursor()                    { RefreshItem(cursor); }
	void    GetItemStyle(int i, Color& ink, Color& paper, dword& style);
	dword   PaintItem(Draw& w, int i, const Rect& r);
	void    SyncInfo();
	void    SetCursor0(int c, bool sel);
	void    UpdateSelect();
	void    RefreshSel();
	void    DoLeftDown(Point p, dword);

	bool    DnDInsert(int i, int py, PasteClip& d, int q);
	void    DnD(int _drop, bool _insert);

public:
	Callback         WhenLeftClick;
	Callback1<Point> WhenLeftClickPos;
	Callback         WhenLeftDouble;
	Callback1<Bar&>  WhenBar;
	Callback         WhenSel;

	Callback                     WhenDrag;
	Callback2<int, PasteClip&>   WhenDropItem;
	Callback2<int, PasteClip&>   WhenDropInsert;
	Callback1<PasteClip&>        WhenDrop;



	// depracated - use WhenSel
	Callback         WhenSelection;
	Callback         WhenEnterItem;
	Callback         WhenKillCursor;

	int     GetColumnItems() const;
	int     GetColumnCx(int i = 0) const;
	int     GetPageItems() const;

	int     GetItem(Point p);
	Rect    GetItemRect(int i) const;

	int     GetCursor() const                          { return cursor; }
	void    SetCursor(int c);
	void    KillCursor();
	bool    IsCursor() const                           { return cursor >= 0; }

	int     GetSbPos() const                           { return sb; }
	void    SetSbPos(int y);

	void    SetFrame(CtrlFrame& frame);

	void         Clear();
	void         Add(const Value& val, bool canselect = true);
	void         Add(const Value& val, const Display& display, bool canselect = true);
	int          GetCount() const                     { return item.GetCount();; }
	const Value& Get(int i) const                     { return item[i].value; }
	const Value& operator[](int i) const              { return item[i].value; }

	void         Set(int ii, const Value& val, bool canselect = true);
	void         Set(int ii, const Value& val, const Display& display, bool canselect = true);

	void         Insert(int ii, const Value& val, bool canselect = true);
	void         Insert(int ii, const Value& val, const Display& display, bool canselect = true);
	void         Remove(int ii);

	void         RemoveSelection();

	bool         IsSelection() const                  { return selcount > 0; }
	void         ClearSelection();
	void         SelectOne(int i, bool sel);
	bool         IsSelected(int i) const;
	bool         IsSel(int i) const;

	void         Sort(const ValueOrder& order);

	Image        GetDragSample();

	void         InsertDrop(int ii, const Vector<Value>& data, PasteClip& d, bool self);
	void         InsertDrop(int ii, const ColumnList& src, PasteClip& d);
	void         InsertDrop(int ii, PasteClip& d);

	ColumnList&  Columns(int _n)                      { ncl = _n; Refresh(); return *this; }
	int          GetColumns() const                   { return ncl; }
	ColumnList&  ItemHeight(int _cy)                  { cy = _cy; RefreshLayout(); Refresh(); return *this; }
	int          GetItemHeight() const                { return cy; }
	ColumnList&  RoundSize(bool b = true);
	ColumnList&  NoRoundSize()                        { return RoundSize(false); }
	ColumnList&  ClickKill(bool b = true)             { clickkill = b; return *this; }
	ColumnList&  NoClickKill()                        { return ClickKill(false); }
	ColumnList&  SetDisplay(const Display& d)         { display = &d; return *this; }
	ColumnList&  NoBackground(bool b = true)          { nobg = b; Transparent(); Refresh(); return *this; }
	ColumnList&  Multi(bool b = true)                 { multi = b; return *this; }
	bool         IsMulti() const                      { return multi; }
	ColumnList&  MultiSelect(bool b = true)           { multi = b; return *this; }
	bool         IsMultiSelect() const                { return multi; }
	ColumnList&  PopUpEx(bool b = true)               { popupex = b; return *this; }
	ColumnList&  NoPopUpEx()                          { return PopUpEx(false); }

	ColumnList&  SetScrollBarStyle(const ScrollBar::Style& s) { sb.SetStyle(s); return *this; }

	typedef ColumnList CLASSNAME;

	ColumnList();
	virtual ~ColumnList();
};
