From: Robin Dunn Date: Tue, 25 May 2004 04:59:23 +0000 (+0000) Subject: Switch to the TreeListCtrl from the wxCode project. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/28eab81fdc83fdc69da113f13d6d5e65c8ad1ba2 Switch to the TreeListCtrl from the wxCode project. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@27422 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/wxPython/contrib/gizmos/_gizmos_rename.i b/wxPython/contrib/gizmos/_gizmos_rename.i index 9b04bf8d01..27ee081966 100644 --- a/wxPython/contrib/gizmos/_gizmos_rename.i +++ b/wxPython/contrib/gizmos/_gizmos_rename.i @@ -25,6 +25,11 @@ %rename(TL_ALIGN_RIGHT) wxTL_ALIGN_RIGHT; %rename(TL_ALIGN_CENTER) wxTL_ALIGN_CENTER; %rename(TREE_HITTEST_ONITEMCOLUMN) wxTREE_HITTEST_ONITEMCOLUMN; +%rename(TL_SEARCH_VISIBLE) wxTL_SEARCH_VISIBLE; +%rename(TL_SEARCH_LEVEL) wxTL_SEARCH_LEVEL; +%rename(TL_SEARCH_FULL) wxTL_SEARCH_FULL; +%rename(TL_SEARCH_PARTIAL) wxTL_SEARCH_PARTIAL; +%rename(TL_SEARCH_NOCASE) wxTL_SEARCH_NOCASE; %rename(TreeListColumnInfo) wxTreeListColumnInfo; #endif diff --git a/wxPython/contrib/gizmos/gizmos.i b/wxPython/contrib/gizmos/gizmos.i index d35cb4f0be..6f48b39f4c 100644 --- a/wxPython/contrib/gizmos/gizmos.i +++ b/wxPython/contrib/gizmos/gizmos.i @@ -21,7 +21,7 @@ %{ #include "wx/wxPython/wxPython.h" #include "wx/wxPython/pyclasses.h" - + #include #include #include @@ -30,8 +30,8 @@ #include #include #include - -#include "treelistctrl.h" + +#include "wx/treelistctrl.h" #include "wx/wxPython/pytree.h" %} @@ -421,6 +421,15 @@ enum { }; +enum { + // flags for FindItem + wxTL_SEARCH_VISIBLE, + wxTL_SEARCH_LEVEL, + wxTL_SEARCH_FULL, + wxTL_SEARCH_PARTIAL, + wxTL_SEARCH_NOCASE +}; + class wxTreeListColumnInfo: public wxObject { @@ -428,14 +437,18 @@ public: wxTreeListColumnInfo(const wxString& text = wxPyEmptyString, int image = -1, size_t width = 100, + bool shown = True, wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT); + bool GetShown() const; wxTreeListColumnAlign GetAlignment() const; wxString GetText() const; int GetImage() const; int GetSelectedImage() const; size_t GetWidth() const; + // TODO: These all actually return wxTreeListColumnInfo&, any problem with doing it for Python too? + void SetShown(bool shown); void SetAlignment(wxTreeListColumnAlign alignment); void SetText(const wxString& text); void SetImage(int image); @@ -511,7 +524,7 @@ public: void _setCallbackInfo(PyObject* self, PyObject* _class); - + // get the total number of items in the control size_t GetCount() const; @@ -521,10 +534,6 @@ public: unsigned int GetIndent() const; void SetIndent(unsigned int indent); - // spacing is the number of pixels between the start and the Text - unsigned int GetSpacing() const; - void SetSpacing(unsigned int spacing); - // line spacing is the space above and below the text on each line unsigned int GetLineSpacing() const; void SetLineSpacing(unsigned int spacing); @@ -558,6 +567,9 @@ public: // adds a column void AddColumn(const wxString& text); +// void AddColumn(const wxString& text, +// size_t width, +// wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT); %name(AddColumnInfo) void AddColumn(const wxTreeListColumnInfo& col); // inserts a column before the given one @@ -591,6 +603,8 @@ public: void SetColumnImage(size_t column, int image); int GetColumnImage(size_t column) const; + void ShowColumn(size_t column, bool shown); + bool IsColumnShown(size_t column) const; %extend { // retrieves item's label of the given column (main column by default) @@ -674,11 +688,11 @@ public: void SetItemBold(const wxTreeItemId& item, bool bold = True); // set the item's text colour - void SetItemTextColour(const wxTreeItemId& item, const wxColour& col); + void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour); // set the item's background colour void SetItemBackgroundColour(const wxTreeItemId& item, - const wxColour& col); + const wxColour& colour); // set the item's font (should be of the same height for all items) void SetItemFont(const wxTreeItemId& item, const wxFont& font); @@ -738,7 +752,7 @@ public: // get the parent of this item (may return NULL if root) - %name(GetItemParent)wxTreeItemId GetParent(const wxTreeItemId& item) const; + wxTreeItemId GetItemParent(const wxTreeItemId& item) const; // for this enumeration function you must pass in a "cookie" parameter // which is opaque for the application but is necessary for the library @@ -748,17 +762,19 @@ public: // the same! + // NOTE: These are a copy of the same methods in _treectrl.i, be sure to + // update both at the same time. (Or find a good way to refactor!) %extend { // Get the first child of this item. Returns a wxTreeItemId and an // opaque "cookie" value that should be passed to GetNextChild in // order to continue the search. PyObject* GetFirstChild(const wxTreeItemId& item) { - long cookie = 0; + void* cookie = 0; wxTreeItemId* ritem = new wxTreeItemId(self->GetFirstChild(item, cookie)); bool blocked = wxPyBeginBlockThreads(); PyObject* tup = PyTuple_New(2); - PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), true)); - PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(cookie)); + PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), True)); + PyTuple_SET_ITEM(tup, 1, wxPyMakeSwigPtr(cookie, wxT("void"))); wxPyEndBlockThreads(blocked); return tup; } @@ -768,15 +784,19 @@ public: // value returned from GetFirstChild or the previous GetNextChild. // Returns a wxTreeItemId and an opaque "cookie" value that should be // passed to GetNextChild in order to continue the search. - PyObject* GetNextChild(const wxTreeItemId& item, long cookie) { + PyObject* GetNextChild(const wxTreeItemId& item, void* cookie) { wxTreeItemId* ritem = new wxTreeItemId(self->GetNextChild(item, cookie)); bool blocked = wxPyBeginBlockThreads(); PyObject* tup = PyTuple_New(2); - PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), true)); - PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(cookie)); + PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), True)); + PyTuple_SET_ITEM(tup, 1, wxPyMakeSwigPtr(cookie, wxT("void"))); wxPyEndBlockThreads(blocked); return tup; - } + } + + + // TODO: GetPrevChild + } // get the last child of this item - this method doesn't use cookies @@ -868,6 +888,8 @@ public: void SelectItem(const wxTreeItemId& item, bool unselect_others=True, bool extended_select=False); + void SelectAll(bool extended_select=False); + // make sure this item is visible (expanding the parent item and/or // scrolling to this item if necessary) void EnsureVisible(const wxTreeItemId& item); @@ -905,12 +927,8 @@ public: // sort the children of this item using OnCompareItems void SortChildren(const wxTreeItemId& item); - // get the selected item image - int GetItemSelectedImage(const wxTreeItemId& item) const; - - // set the selected item image - void SetItemSelectedImage(const wxTreeItemId& item, int image); - + // searching + wxTreeItemId FindItem (const wxTreeItemId& item, const wxString& str, int flags = 0); wxWindow* GetHeaderWindow() const; wxWindow* GetMainWindow() const; @@ -935,8 +953,3 @@ public: //---------------------------------------------------------------------- //---------------------------------------------------------------------- - - - - - diff --git a/wxPython/contrib/gizmos/gtk/gizmos.py b/wxPython/contrib/gizmos/gtk/gizmos.py index e6d9599c42..107bedf7d4 100644 --- a/wxPython/contrib/gizmos/gtk/gizmos.py +++ b/wxPython/contrib/gizmos/gtk/gizmos.py @@ -353,18 +353,27 @@ TL_ALIGN_LEFT = _gizmos.TL_ALIGN_LEFT TL_ALIGN_RIGHT = _gizmos.TL_ALIGN_RIGHT TL_ALIGN_CENTER = _gizmos.TL_ALIGN_CENTER TREE_HITTEST_ONITEMCOLUMN = _gizmos.TREE_HITTEST_ONITEMCOLUMN +TL_SEARCH_VISIBLE = _gizmos.TL_SEARCH_VISIBLE +TL_SEARCH_LEVEL = _gizmos.TL_SEARCH_LEVEL +TL_SEARCH_FULL = _gizmos.TL_SEARCH_FULL +TL_SEARCH_PARTIAL = _gizmos.TL_SEARCH_PARTIAL +TL_SEARCH_NOCASE = _gizmos.TL_SEARCH_NOCASE class TreeListColumnInfo(_core.Object): def __repr__(self): return "<%s.%s; proxy of C++ wxTreeListColumnInfo instance at %s>" % (self.__class__.__module__, self.__class__.__name__, self.this,) def __init__(self, *args, **kwargs): """ __init__(self, String text=EmptyString, int image=-1, size_t width=100, - int alignment=TL_ALIGN_LEFT) -> TreeListColumnInfo + bool shown=True, int alignment=TL_ALIGN_LEFT) -> TreeListColumnInfo """ newobj = _gizmos.new_TreeListColumnInfo(*args, **kwargs) self.this = newobj.this self.thisown = 1 del newobj.thisown + def GetShown(*args, **kwargs): + """GetShown(self) -> bool""" + return _gizmos.TreeListColumnInfo_GetShown(*args, **kwargs) + def GetAlignment(*args, **kwargs): """GetAlignment(self) -> int""" return _gizmos.TreeListColumnInfo_GetAlignment(*args, **kwargs) @@ -385,6 +394,10 @@ class TreeListColumnInfo(_core.Object): """GetWidth(self) -> size_t""" return _gizmos.TreeListColumnInfo_GetWidth(*args, **kwargs) + def SetShown(*args, **kwargs): + """SetShown(self, bool shown)""" + return _gizmos.TreeListColumnInfo_SetShown(*args, **kwargs) + def SetAlignment(*args, **kwargs): """SetAlignment(self, int alignment)""" return _gizmos.TreeListColumnInfo_SetAlignment(*args, **kwargs) @@ -456,14 +469,6 @@ class TreeListCtrl(_core.Control): """SetIndent(self, unsigned int indent)""" return _gizmos.TreeListCtrl_SetIndent(*args, **kwargs) - def GetSpacing(*args, **kwargs): - """GetSpacing(self) -> unsigned int""" - return _gizmos.TreeListCtrl_GetSpacing(*args, **kwargs) - - def SetSpacing(*args, **kwargs): - """SetSpacing(self, unsigned int spacing)""" - return _gizmos.TreeListCtrl_SetSpacing(*args, **kwargs) - def GetLineSpacing(*args, **kwargs): """GetLineSpacing(self) -> unsigned int""" return _gizmos.TreeListCtrl_GetLineSpacing(*args, **kwargs) @@ -580,6 +585,14 @@ class TreeListCtrl(_core.Control): """GetColumnImage(self, size_t column) -> int""" return _gizmos.TreeListCtrl_GetColumnImage(*args, **kwargs) + def ShowColumn(*args, **kwargs): + """ShowColumn(self, size_t column, bool shown)""" + return _gizmos.TreeListCtrl_ShowColumn(*args, **kwargs) + + def IsColumnShown(*args, **kwargs): + """IsColumnShown(self, size_t column) -> bool""" + return _gizmos.TreeListCtrl_IsColumnShown(*args, **kwargs) + def GetItemText(*args, **kwargs): """GetItemText(self, TreeItemId item, int column=-1) -> String""" return _gizmos.TreeListCtrl_GetItemText(*args, **kwargs) @@ -623,11 +636,11 @@ class TreeListCtrl(_core.Control): return _gizmos.TreeListCtrl_SetItemBold(*args, **kwargs) def SetItemTextColour(*args, **kwargs): - """SetItemTextColour(self, TreeItemId item, Colour col)""" + """SetItemTextColour(self, TreeItemId item, Colour colour)""" return _gizmos.TreeListCtrl_SetItemTextColour(*args, **kwargs) def SetItemBackgroundColour(*args, **kwargs): - """SetItemBackgroundColour(self, TreeItemId item, Colour col)""" + """SetItemBackgroundColour(self, TreeItemId item, Colour colour)""" return _gizmos.TreeListCtrl_SetItemBackgroundColour(*args, **kwargs) def SetItemFont(*args, **kwargs): @@ -695,7 +708,7 @@ class TreeListCtrl(_core.Control): return _gizmos.TreeListCtrl_GetFirstChild(*args, **kwargs) def GetNextChild(*args, **kwargs): - """GetNextChild(self, TreeItemId item, long cookie) -> PyObject""" + """GetNextChild(self, TreeItemId item, void cookie) -> PyObject""" return _gizmos.TreeListCtrl_GetNextChild(*args, **kwargs) def GetLastChild(*args, **kwargs): @@ -802,6 +815,10 @@ class TreeListCtrl(_core.Control): """SelectItem(self, TreeItemId item, bool unselect_others=True, bool extended_select=False)""" return _gizmos.TreeListCtrl_SelectItem(*args, **kwargs) + def SelectAll(*args, **kwargs): + """SelectAll(self, bool extended_select=False)""" + return _gizmos.TreeListCtrl_SelectAll(*args, **kwargs) + def EnsureVisible(*args, **kwargs): """EnsureVisible(self, TreeItemId item)""" return _gizmos.TreeListCtrl_EnsureVisible(*args, **kwargs) @@ -830,13 +847,9 @@ class TreeListCtrl(_core.Control): """SortChildren(self, TreeItemId item)""" return _gizmos.TreeListCtrl_SortChildren(*args, **kwargs) - def GetItemSelectedImage(*args, **kwargs): - """GetItemSelectedImage(self, TreeItemId item) -> int""" - return _gizmos.TreeListCtrl_GetItemSelectedImage(*args, **kwargs) - - def SetItemSelectedImage(*args, **kwargs): - """SetItemSelectedImage(self, TreeItemId item, int image)""" - return _gizmos.TreeListCtrl_SetItemSelectedImage(*args, **kwargs) + def FindItem(*args, **kwargs): + """FindItem(self, TreeItemId item, String str, int flags=0) -> TreeItemId""" + return _gizmos.TreeListCtrl_FindItem(*args, **kwargs) def GetHeaderWindow(*args, **kwargs): """GetHeaderWindow(self) -> Window""" diff --git a/wxPython/contrib/gizmos/gtk/gizmos_wrap.cpp b/wxPython/contrib/gizmos/gtk/gizmos_wrap.cpp index f5022e0938..49f17cbb9d 100644 --- a/wxPython/contrib/gizmos/gtk/gizmos_wrap.cpp +++ b/wxPython/contrib/gizmos/gtk/gizmos_wrap.cpp @@ -294,7 +294,7 @@ static swig_type_info *swig_types[32]; #include "wx/wxPython/wxPython.h" #include "wx/wxPython/pyclasses.h" - + #include #include #include @@ -303,8 +303,8 @@ static swig_type_info *swig_types[32]; #include #include #include - -#include "treelistctrl.h" + +#include "wx/treelistctrl.h" #include "wx/wxPython/pytree.h" @@ -637,21 +637,21 @@ PyObject *wxPyTreeListCtrl_GetSelections(wxPyTreeListCtrl *self){ return rval; } PyObject *wxPyTreeListCtrl_GetFirstChild(wxPyTreeListCtrl *self,wxTreeItemId const &item){ - long cookie = 0; + void* cookie = 0; wxTreeItemId* ritem = new wxTreeItemId(self->GetFirstChild(item, cookie)); bool blocked = wxPyBeginBlockThreads(); PyObject* tup = PyTuple_New(2); - PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), true)); - PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(cookie)); + PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), True)); + PyTuple_SET_ITEM(tup, 1, wxPyMakeSwigPtr(cookie, wxT("void"))); wxPyEndBlockThreads(blocked); return tup; } -PyObject *wxPyTreeListCtrl_GetNextChild(wxPyTreeListCtrl *self,wxTreeItemId const &item,long cookie){ +PyObject *wxPyTreeListCtrl_GetNextChild(wxPyTreeListCtrl *self,wxTreeItemId const &item,void *cookie){ wxTreeItemId* ritem = new wxTreeItemId(self->GetNextChild(item, cookie)); bool blocked = wxPyBeginBlockThreads(); PyObject* tup = PyTuple_New(2); - PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), true)); - PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(cookie)); + PyTuple_SET_ITEM(tup, 0, wxPyConstructObject(ritem, wxT("wxTreeItemId"), True)); + PyTuple_SET_ITEM(tup, 1, wxPyMakeSwigPtr(cookie, wxT("void"))); wxPyEndBlockThreads(blocked); return tup; } @@ -2289,18 +2289,20 @@ static PyObject *_wrap_new_TreeListColumnInfo(PyObject *self, PyObject *args, Py wxString *arg1 = (wxString *) &arg1_defvalue ; int arg2 = (int) -1 ; size_t arg3 = (size_t) 100 ; - int arg4 = (int) wxTL_ALIGN_LEFT ; + bool arg4 = (bool) True ; + int arg5 = (int) wxTL_ALIGN_LEFT ; wxTreeListColumnInfo *result; bool temp1 = False ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; char *kwnames[] = { - (char *) "text",(char *) "image",(char *) "width",(char *) "alignment", NULL + (char *) "text",(char *) "image",(char *) "width",(char *) "shown",(char *) "alignment", NULL }; - if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|OOOO:new_TreeListColumnInfo",kwnames,&obj0,&obj1,&obj2,&obj3)) goto fail; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"|OOOOO:new_TreeListColumnInfo",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) goto fail; if (obj0) { { arg1 = wxString_in_helper(obj0); @@ -2317,12 +2319,16 @@ static PyObject *_wrap_new_TreeListColumnInfo(PyObject *self, PyObject *args, Py if (PyErr_Occurred()) SWIG_fail; } if (obj3) { - arg4 = (wxTreeListColumnAlign) SWIG_AsInt(obj3); + arg4 = (bool) SWIG_AsBool(obj3); + if (PyErr_Occurred()) SWIG_fail; + } + if (obj4) { + arg5 = (wxTreeListColumnAlign) SWIG_AsInt(obj4); if (PyErr_Occurred()) SWIG_fail; } { PyThreadState* __tstate = wxPyBeginAllowThreads(); - result = (wxTreeListColumnInfo *)new wxTreeListColumnInfo((wxString const &)*arg1,arg2,arg3,(wxTreeListColumnAlign )arg4); + result = (wxTreeListColumnInfo *)new wxTreeListColumnInfo((wxString const &)*arg1,arg2,arg3,arg4,(wxTreeListColumnAlign )arg5); wxPyEndAllowThreads(__tstate); if (PyErr_Occurred()) SWIG_fail; @@ -2342,6 +2348,34 @@ static PyObject *_wrap_new_TreeListColumnInfo(PyObject *self, PyObject *args, Py } +static PyObject *_wrap_TreeListColumnInfo_GetShown(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject *resultobj; + wxTreeListColumnInfo *arg1 = (wxTreeListColumnInfo *) 0 ; + bool result; + PyObject * obj0 = 0 ; + char *kwnames[] = { + (char *) "self", NULL + }; + + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:TreeListColumnInfo_GetShown",kwnames,&obj0)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxTreeListColumnInfo, + SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; + { + PyThreadState* __tstate = wxPyBeginAllowThreads(); + result = (bool)((wxTreeListColumnInfo const *)arg1)->GetShown(); + + wxPyEndAllowThreads(__tstate); + if (PyErr_Occurred()) SWIG_fail; + } + { + resultobj = result ? Py_True : Py_False; Py_INCREF(resultobj); + } + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_TreeListColumnInfo_GetAlignment(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *resultobj; wxTreeListColumnInfo *arg1 = (wxTreeListColumnInfo *) 0 ; @@ -2478,6 +2512,35 @@ static PyObject *_wrap_TreeListColumnInfo_GetWidth(PyObject *self, PyObject *arg } +static PyObject *_wrap_TreeListColumnInfo_SetShown(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject *resultobj; + wxTreeListColumnInfo *arg1 = (wxTreeListColumnInfo *) 0 ; + bool arg2 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + char *kwnames[] = { + (char *) "self",(char *) "shown", NULL + }; + + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:TreeListColumnInfo_SetShown",kwnames,&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxTreeListColumnInfo, + SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; + arg2 = (bool) SWIG_AsBool(obj1); + if (PyErr_Occurred()) SWIG_fail; + { + PyThreadState* __tstate = wxPyBeginAllowThreads(); + (arg1)->SetShown(arg2); + + wxPyEndAllowThreads(__tstate); + if (PyErr_Occurred()) SWIG_fail; + } + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_TreeListColumnInfo_SetAlignment(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *resultobj; wxTreeListColumnInfo *arg1 = (wxTreeListColumnInfo *) 0 ; @@ -2960,61 +3023,6 @@ static PyObject *_wrap_TreeListCtrl_SetIndent(PyObject *self, PyObject *args, Py } -static PyObject *_wrap_TreeListCtrl_GetSpacing(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *resultobj; - wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; - unsigned int result; - PyObject * obj0 = 0 ; - char *kwnames[] = { - (char *) "self", NULL - }; - - if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O:TreeListCtrl_GetSpacing",kwnames,&obj0)) goto fail; - if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, - SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; - { - PyThreadState* __tstate = wxPyBeginAllowThreads(); - result = (unsigned int)((wxPyTreeListCtrl const *)arg1)->GetSpacing(); - - wxPyEndAllowThreads(__tstate); - if (PyErr_Occurred()) SWIG_fail; - } - resultobj = SWIG_FromUnsignedInt((unsigned int)result); - return resultobj; - fail: - return NULL; -} - - -static PyObject *_wrap_TreeListCtrl_SetSpacing(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *resultobj; - wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; - unsigned int arg2 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - char *kwnames[] = { - (char *) "self",(char *) "spacing", NULL - }; - - if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:TreeListCtrl_SetSpacing",kwnames,&obj0,&obj1)) goto fail; - if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, - SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; - arg2 = (unsigned int) SWIG_AsUnsignedInt(obj1); - if (PyErr_Occurred()) SWIG_fail; - { - PyThreadState* __tstate = wxPyBeginAllowThreads(); - (arg1)->SetSpacing(arg2); - - wxPyEndAllowThreads(__tstate); - if (PyErr_Occurred()) SWIG_fail; - } - Py_INCREF(Py_None); resultobj = Py_None; - return resultobj; - fail: - return NULL; -} - - static PyObject *_wrap_TreeListCtrl_GetLineSpacing(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *resultobj; wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; @@ -3937,6 +3945,71 @@ static PyObject *_wrap_TreeListCtrl_GetColumnImage(PyObject *self, PyObject *arg } +static PyObject *_wrap_TreeListCtrl_ShowColumn(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject *resultobj; + wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; + size_t arg2 ; + bool arg3 ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + char *kwnames[] = { + (char *) "self",(char *) "column",(char *) "shown", NULL + }; + + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:TreeListCtrl_ShowColumn",kwnames,&obj0,&obj1,&obj2)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, + SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; + arg2 = (size_t) SWIG_AsUnsignedLong(obj1); + if (PyErr_Occurred()) SWIG_fail; + arg3 = (bool) SWIG_AsBool(obj2); + if (PyErr_Occurred()) SWIG_fail; + { + PyThreadState* __tstate = wxPyBeginAllowThreads(); + (arg1)->ShowColumn(arg2,arg3); + + wxPyEndAllowThreads(__tstate); + if (PyErr_Occurred()) SWIG_fail; + } + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + +static PyObject *_wrap_TreeListCtrl_IsColumnShown(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject *resultobj; + wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; + size_t arg2 ; + bool result; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + char *kwnames[] = { + (char *) "self",(char *) "column", NULL + }; + + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:TreeListCtrl_IsColumnShown",kwnames,&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, + SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; + arg2 = (size_t) SWIG_AsUnsignedLong(obj1); + if (PyErr_Occurred()) SWIG_fail; + { + PyThreadState* __tstate = wxPyBeginAllowThreads(); + result = (bool)((wxPyTreeListCtrl const *)arg1)->IsColumnShown(arg2); + + wxPyEndAllowThreads(__tstate); + if (PyErr_Occurred()) SWIG_fail; + } + { + resultobj = result ? Py_True : Py_False; Py_INCREF(resultobj); + } + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_TreeListCtrl_GetItemText(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *resultobj; wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; @@ -4372,7 +4445,7 @@ static PyObject *_wrap_TreeListCtrl_SetItemTextColour(PyObject *self, PyObject * PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char *kwnames[] = { - (char *) "self",(char *) "item",(char *) "col", NULL + (char *) "self",(char *) "item",(char *) "colour", NULL }; if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:TreeListCtrl_SetItemTextColour",kwnames,&obj0,&obj1,&obj2)) goto fail; @@ -4413,7 +4486,7 @@ static PyObject *_wrap_TreeListCtrl_SetItemBackgroundColour(PyObject *self, PyOb PyObject * obj1 = 0 ; PyObject * obj2 = 0 ; char *kwnames[] = { - (char *) "self",(char *) "item",(char *) "col", NULL + (char *) "self",(char *) "item",(char *) "colour", NULL }; if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:TreeListCtrl_SetItemBackgroundColour",kwnames,&obj0,&obj1,&obj2)) goto fail; @@ -4976,7 +5049,7 @@ static PyObject *_wrap_TreeListCtrl_GetItemParent(PyObject *self, PyObject *args } { PyThreadState* __tstate = wxPyBeginAllowThreads(); - result = ((wxPyTreeListCtrl const *)arg1)->GetParent((wxTreeItemId const &)*arg2); + result = ((wxPyTreeListCtrl const *)arg1)->GetItemParent((wxTreeItemId const &)*arg2); wxPyEndAllowThreads(__tstate); if (PyErr_Occurred()) SWIG_fail; @@ -5031,7 +5104,7 @@ static PyObject *_wrap_TreeListCtrl_GetNextChild(PyObject *self, PyObject *args, PyObject *resultobj; wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; wxTreeItemId *arg2 = 0 ; - long arg3 ; + void *arg3 = (void *) 0 ; PyObject *result; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; @@ -5050,8 +5123,7 @@ static PyObject *_wrap_TreeListCtrl_GetNextChild(PyObject *self, PyObject *args, PyErr_SetString(PyExc_TypeError,"null reference"); SWIG_fail; } - arg3 = (long) SWIG_AsLong(obj2); - if (PyErr_Occurred()) SWIG_fail; + if ((SWIG_ConvertPtr(obj2,&arg3,0,SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; { PyThreadState* __tstate = wxPyBeginAllowThreads(); result = (PyObject *)wxPyTreeListCtrl_GetNextChild(arg1,(wxTreeItemId const &)*arg2,arg3); @@ -6058,6 +6130,37 @@ static PyObject *_wrap_TreeListCtrl_SelectItem(PyObject *self, PyObject *args, P } +static PyObject *_wrap_TreeListCtrl_SelectAll(PyObject *self, PyObject *args, PyObject *kwargs) { + PyObject *resultobj; + wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; + bool arg2 = (bool) False ; + PyObject * obj0 = 0 ; + PyObject * obj1 = 0 ; + char *kwnames[] = { + (char *) "self",(char *) "extended_select", NULL + }; + + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"O|O:TreeListCtrl_SelectAll",kwnames,&obj0,&obj1)) goto fail; + if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, + SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; + if (obj1) { + arg2 = (bool) SWIG_AsBool(obj1); + if (PyErr_Occurred()) SWIG_fail; + } + { + PyThreadState* __tstate = wxPyBeginAllowThreads(); + (arg1)->SelectAll(arg2); + + wxPyEndAllowThreads(__tstate); + if (PyErr_Occurred()) SWIG_fail; + } + Py_INCREF(Py_None); resultobj = Py_None; + return resultobj; + fail: + return NULL; +} + + static PyObject *_wrap_TreeListCtrl_EnsureVisible(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *resultobj; wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; @@ -6320,18 +6423,23 @@ static PyObject *_wrap_TreeListCtrl_SortChildren(PyObject *self, PyObject *args, } -static PyObject *_wrap_TreeListCtrl_GetItemSelectedImage(PyObject *self, PyObject *args, PyObject *kwargs) { +static PyObject *_wrap_TreeListCtrl_FindItem(PyObject *self, PyObject *args, PyObject *kwargs) { PyObject *resultobj; wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; wxTreeItemId *arg2 = 0 ; - int result; + wxString *arg3 = 0 ; + int arg4 = (int) 0 ; + wxTreeItemId result; + bool temp3 = False ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; char *kwnames[] = { - (char *) "self",(char *) "item", NULL + (char *) "self",(char *) "item",(char *) "str",(char *) "flags", NULL }; - if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:TreeListCtrl_GetItemSelectedImage",kwnames,&obj0,&obj1)) goto fail; + if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO|O:TreeListCtrl_FindItem",kwnames,&obj0,&obj1,&obj2,&obj3)) goto fail; if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; if ((SWIG_ConvertPtr(obj1,(void **)(&arg2),SWIGTYPE_p_wxTreeItemId, @@ -6342,53 +6450,36 @@ static PyObject *_wrap_TreeListCtrl_GetItemSelectedImage(PyObject *self, PyObjec SWIG_fail; } { - PyThreadState* __tstate = wxPyBeginAllowThreads(); - result = (int)((wxPyTreeListCtrl const *)arg1)->GetItemSelectedImage((wxTreeItemId const &)*arg2); - - wxPyEndAllowThreads(__tstate); - if (PyErr_Occurred()) SWIG_fail; + arg3 = wxString_in_helper(obj2); + if (arg3 == NULL) SWIG_fail; + temp3 = True; } - resultobj = SWIG_FromInt((int)result); - return resultobj; - fail: - return NULL; -} - - -static PyObject *_wrap_TreeListCtrl_SetItemSelectedImage(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *resultobj; - wxPyTreeListCtrl *arg1 = (wxPyTreeListCtrl *) 0 ; - wxTreeItemId *arg2 = 0 ; - int arg3 ; - PyObject * obj0 = 0 ; - PyObject * obj1 = 0 ; - PyObject * obj2 = 0 ; - char *kwnames[] = { - (char *) "self",(char *) "item",(char *) "image", NULL - }; - - if(!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:TreeListCtrl_SetItemSelectedImage",kwnames,&obj0,&obj1,&obj2)) goto fail; - if ((SWIG_ConvertPtr(obj0,(void **)(&arg1),SWIGTYPE_p_wxPyTreeListCtrl, - SWIG_POINTER_EXCEPTION | 0)) == -1) SWIG_fail; - if ((SWIG_ConvertPtr(obj1,(void **)(&arg2),SWIGTYPE_p_wxTreeItemId, - SWIG_POINTER_EXCEPTION | 0)) == -1) - SWIG_fail; - if (arg2 == NULL) { - PyErr_SetString(PyExc_TypeError,"null reference"); - SWIG_fail; + if (obj3) { + arg4 = (int) SWIG_AsInt(obj3); + if (PyErr_Occurred()) SWIG_fail; } - arg3 = (int) SWIG_AsInt(obj2); - if (PyErr_Occurred()) SWIG_fail; { PyThreadState* __tstate = wxPyBeginAllowThreads(); - (arg1)->SetItemSelectedImage((wxTreeItemId const &)*arg2,arg3); + result = (arg1)->FindItem((wxTreeItemId const &)*arg2,(wxString const &)*arg3,arg4); wxPyEndAllowThreads(__tstate); if (PyErr_Occurred()) SWIG_fail; } - Py_INCREF(Py_None); resultobj = Py_None; + { + wxTreeItemId * resultptr; + resultptr = new wxTreeItemId((wxTreeItemId &) result); + resultobj = SWIG_NewPointerObj((void *)(resultptr), SWIGTYPE_p_wxTreeItemId, 1); + } + { + if (temp3) + delete arg3; + } return resultobj; fail: + { + if (temp3) + delete arg3; + } return NULL; } @@ -6505,11 +6596,13 @@ static PyMethodDef SwigMethods[] = { { (char *)"LEDNumberCtrl_SetValue", (PyCFunction) _wrap_LEDNumberCtrl_SetValue, METH_VARARGS | METH_KEYWORDS }, { (char *)"LEDNumberCtrl_swigregister", LEDNumberCtrl_swigregister, METH_VARARGS }, { (char *)"new_TreeListColumnInfo", (PyCFunction) _wrap_new_TreeListColumnInfo, METH_VARARGS | METH_KEYWORDS }, + { (char *)"TreeListColumnInfo_GetShown", (PyCFunction) _wrap_TreeListColumnInfo_GetShown, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_GetAlignment", (PyCFunction) _wrap_TreeListColumnInfo_GetAlignment, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_GetText", (PyCFunction) _wrap_TreeListColumnInfo_GetText, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_GetImage", (PyCFunction) _wrap_TreeListColumnInfo_GetImage, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_GetSelectedImage", (PyCFunction) _wrap_TreeListColumnInfo_GetSelectedImage, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_GetWidth", (PyCFunction) _wrap_TreeListColumnInfo_GetWidth, METH_VARARGS | METH_KEYWORDS }, + { (char *)"TreeListColumnInfo_SetShown", (PyCFunction) _wrap_TreeListColumnInfo_SetShown, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_SetAlignment", (PyCFunction) _wrap_TreeListColumnInfo_SetAlignment, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_SetText", (PyCFunction) _wrap_TreeListColumnInfo_SetText, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListColumnInfo_SetImage", (PyCFunction) _wrap_TreeListColumnInfo_SetImage, METH_VARARGS | METH_KEYWORDS }, @@ -6523,8 +6616,6 @@ static PyMethodDef SwigMethods[] = { { (char *)"TreeListCtrl_GetCount", (PyCFunction) _wrap_TreeListCtrl_GetCount, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetIndent", (PyCFunction) _wrap_TreeListCtrl_GetIndent, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_SetIndent", (PyCFunction) _wrap_TreeListCtrl_SetIndent, METH_VARARGS | METH_KEYWORDS }, - { (char *)"TreeListCtrl_GetSpacing", (PyCFunction) _wrap_TreeListCtrl_GetSpacing, METH_VARARGS | METH_KEYWORDS }, - { (char *)"TreeListCtrl_SetSpacing", (PyCFunction) _wrap_TreeListCtrl_SetSpacing, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetLineSpacing", (PyCFunction) _wrap_TreeListCtrl_GetLineSpacing, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_SetLineSpacing", (PyCFunction) _wrap_TreeListCtrl_SetLineSpacing, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetImageList", (PyCFunction) _wrap_TreeListCtrl_GetImageList, METH_VARARGS | METH_KEYWORDS }, @@ -6554,6 +6645,8 @@ static PyMethodDef SwigMethods[] = { { (char *)"TreeListCtrl_GetColumnAlignment", (PyCFunction) _wrap_TreeListCtrl_GetColumnAlignment, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_SetColumnImage", (PyCFunction) _wrap_TreeListCtrl_SetColumnImage, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetColumnImage", (PyCFunction) _wrap_TreeListCtrl_GetColumnImage, METH_VARARGS | METH_KEYWORDS }, + { (char *)"TreeListCtrl_ShowColumn", (PyCFunction) _wrap_TreeListCtrl_ShowColumn, METH_VARARGS | METH_KEYWORDS }, + { (char *)"TreeListCtrl_IsColumnShown", (PyCFunction) _wrap_TreeListCtrl_IsColumnShown, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetItemText", (PyCFunction) _wrap_TreeListCtrl_GetItemText, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetItemImage", (PyCFunction) _wrap_TreeListCtrl_GetItemImage, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_SetItemText", (PyCFunction) _wrap_TreeListCtrl_SetItemText, METH_VARARGS | METH_KEYWORDS }, @@ -6606,6 +6699,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"TreeListCtrl_Unselect", (PyCFunction) _wrap_TreeListCtrl_Unselect, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_UnselectAll", (PyCFunction) _wrap_TreeListCtrl_UnselectAll, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_SelectItem", (PyCFunction) _wrap_TreeListCtrl_SelectItem, METH_VARARGS | METH_KEYWORDS }, + { (char *)"TreeListCtrl_SelectAll", (PyCFunction) _wrap_TreeListCtrl_SelectAll, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_EnsureVisible", (PyCFunction) _wrap_TreeListCtrl_EnsureVisible, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_ScrollTo", (PyCFunction) _wrap_TreeListCtrl_ScrollTo, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_HitTest", (PyCFunction) _wrap_TreeListCtrl_HitTest, METH_VARARGS | METH_KEYWORDS }, @@ -6613,8 +6707,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"TreeListCtrl_EditLabel", (PyCFunction) _wrap_TreeListCtrl_EditLabel, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_Edit", (PyCFunction) _wrap_TreeListCtrl_Edit, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_SortChildren", (PyCFunction) _wrap_TreeListCtrl_SortChildren, METH_VARARGS | METH_KEYWORDS }, - { (char *)"TreeListCtrl_GetItemSelectedImage", (PyCFunction) _wrap_TreeListCtrl_GetItemSelectedImage, METH_VARARGS | METH_KEYWORDS }, - { (char *)"TreeListCtrl_SetItemSelectedImage", (PyCFunction) _wrap_TreeListCtrl_SetItemSelectedImage, METH_VARARGS | METH_KEYWORDS }, + { (char *)"TreeListCtrl_FindItem", (PyCFunction) _wrap_TreeListCtrl_FindItem, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetHeaderWindow", (PyCFunction) _wrap_TreeListCtrl_GetHeaderWindow, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_GetMainWindow", (PyCFunction) _wrap_TreeListCtrl_GetMainWindow, METH_VARARGS | METH_KEYWORDS }, { (char *)"TreeListCtrl_swigregister", TreeListCtrl_swigregister, METH_VARARGS }, @@ -8205,6 +8298,11 @@ SWIGEXPORT(void) SWIG_init(void) { PyDict_SetItemString(d,"TL_ALIGN_RIGHT", SWIG_FromInt((int)wxTL_ALIGN_RIGHT)); PyDict_SetItemString(d,"TL_ALIGN_CENTER", SWIG_FromInt((int)wxTL_ALIGN_CENTER)); PyDict_SetItemString(d,"TREE_HITTEST_ONITEMCOLUMN", SWIG_FromInt((int)wxTREE_HITTEST_ONITEMCOLUMN)); + PyDict_SetItemString(d,"TL_SEARCH_VISIBLE", SWIG_FromInt((int)wxTL_SEARCH_VISIBLE)); + PyDict_SetItemString(d,"TL_SEARCH_LEVEL", SWIG_FromInt((int)wxTL_SEARCH_LEVEL)); + PyDict_SetItemString(d,"TL_SEARCH_FULL", SWIG_FromInt((int)wxTL_SEARCH_FULL)); + PyDict_SetItemString(d,"TL_SEARCH_PARTIAL", SWIG_FromInt((int)wxTL_SEARCH_PARTIAL)); + PyDict_SetItemString(d,"TL_SEARCH_NOCASE", SWIG_FromInt((int)wxTL_SEARCH_NOCASE)); wxPyPtrTypeMap_Add("wxTreeCompanionWindow", "wxPyTreeCompanionWindow"); diff --git a/wxPython/contrib/gizmos/treelistctrl.cpp b/wxPython/contrib/gizmos/treelistctrl.cpp deleted file mode 100644 index 6bf7153707..0000000000 --- a/wxPython/contrib/gizmos/treelistctrl.cpp +++ /dev/null @@ -1,4834 +0,0 @@ -///////////////////////////////////////////////////////////////////////////// -// Name: treelistctrl.cpp (derived by treectlg.h) -// Purpose: multi column tree control implementation -// Author: Robert Roebling -// Created: 01/02/97 -// Modified: Alberto Griggio, 2002 -// 22/10/98 - almost total rewrite, simpler interface (VZ) -// Id: $Id$ -// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem -// Licence: wxWindows licence -///////////////////////////////////////////////////////////////////////////// - -// =========================================================================== -// declarations -// =========================================================================== - -// --------------------------------------------------------------------------- -// headers -// --------------------------------------------------------------------------- - -#if defined(__GNUG__) && !defined(__APPLE__) - #pragma implementation "treelistctrl.h" -#endif - -// For compilers that support precompilation, includes "wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ - #pragma hdrstop -#endif - - -#include -#include -#include -#include -#include -#include -#include -#include - -//#include "wx/gizmos/treelistctrl.h" -#include "treelistctrl.h" - - -#ifdef __WXGTK__ - #include - #include -#endif - -// --------------------------------------------------------------------------- -// array types -// --------------------------------------------------------------------------- - -class wxTreeListItem; - -WX_DEFINE_ARRAY(wxTreeListItem *, wxArrayTreeListItems); - -#include -WX_DECLARE_OBJARRAY(wxTreeListColumnInfo, wxArrayTreeListColumnInfo); -#include -WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo); - -#if !wxCHECK_VERSION(2, 3, 3) -WX_DEFINE_ARRAY(short, wxArrayShort); -#endif - - -// -------------------------------------------------------------------------- -// constants -// -------------------------------------------------------------------------- - -static const int NO_IMAGE = -1; - -#define PIXELS_PER_UNIT 10 - -const wxChar* wxTreeListCtrlNameStr = wxT("treelistctrl"); - -static wxTreeListColumnInfo wxInvalidTreeListColumnInfo; - - -// --------------------------------------------------------------------------- -// private classes -// --------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -// wxTreeListHeaderWindow (internal) -//----------------------------------------------------------------------------- - -class wxTreeListHeaderWindow : public wxWindow -{ -protected: - wxTreeListMainWindow *m_owner; - wxCursor *m_currentCursor; - wxCursor *m_resizeCursor; - bool m_isDragging; - - // column being resized - int m_column; - - // divider line position in logical (unscrolled) coords - int m_currentX; - - // minimal position beyond which the divider line can't be dragged in - // logical coords - int m_minX; - - wxArrayTreeListColumnInfo m_columns; - - // total width of the columns - int m_total_col_width; - - -public: - wxTreeListHeaderWindow(); - - wxTreeListHeaderWindow( wxWindow *win, - wxWindowID id, - wxTreeListMainWindow *owner, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - long style = 0, - const wxString &name = wxT("wxtreelistctrlcolumntitles") ); - - virtual ~wxTreeListHeaderWindow(); - - void DoDrawRect( wxDC *dc, int x, int y, int w, int h ); - void DrawCurrent(); - void AdjustDC(wxDC& dc); - - void OnPaint( wxPaintEvent &event ); - void OnMouse( wxMouseEvent &event ); - void OnSetFocus( wxFocusEvent &event ); - - - // columns manipulation - - size_t GetColumnCount() const { return m_columns.GetCount(); } - - void AddColumn(const wxTreeListColumnInfo& col); - - void InsertColumn(size_t before, const wxTreeListColumnInfo& col); - - void RemoveColumn(size_t column); - - void SetColumn(size_t column, const wxTreeListColumnInfo& info); - const wxTreeListColumnInfo& GetColumn(size_t column) const - { - wxCHECK_MSG(column < GetColumnCount(), wxInvalidTreeListColumnInfo, wxT("Invalid column")); - return m_columns[column]; - } - wxTreeListColumnInfo& GetColumn(size_t column) - { - wxCHECK_MSG(column < GetColumnCount(), wxInvalidTreeListColumnInfo, wxT("Invalid column")); - return m_columns[column]; - } - - void SetColumnWidth(size_t column, size_t width); - - void SetColumnText(size_t column, const wxString& text) - { - wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); - m_columns[column].SetText(text); - } - - wxString GetColumnText(size_t column) const - { - wxCHECK_MSG(column < GetColumnCount(), wxEmptyString, wxT("Invalid column")); - return m_columns[column].GetText(); - } - - int GetColumnWidth(size_t column) const - { - wxCHECK_MSG(column < GetColumnCount(), -1, wxT("Invalid column")); - return m_columns[column].GetWidth(); - } - - int GetWidth() const { return m_total_col_width; } - - // needs refresh - bool m_dirty; - -private: - // common part of all ctors - void Init(); - - void SendListEvent(wxEventType type, wxPoint pos); - - DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow) - DECLARE_EVENT_TABLE() -}; - - -// this is the "true" control -class wxTreeListMainWindow: public wxScrolledWindow -{ -public: - // creation - // -------- - wxTreeListMainWindow() { Init(); } - - wxTreeListMainWindow(wxTreeListCtrl *parent, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTR_DEFAULT_STYLE, - const wxValidator &validator = wxDefaultValidator, - const wxString& name = wxT("wxtreelistmainwindow")) - { - Init(); - Create(parent, id, pos, size, style, validator, name); - } - - virtual ~wxTreeListMainWindow(); - - bool Create(wxTreeListCtrl *parent, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTR_DEFAULT_STYLE, - const wxValidator &validator = wxDefaultValidator, - const wxString& name = wxT("wxtreelistctrl")); - - // accessors - // --------- - - // get the total number of items in the control - size_t GetCount() const; - - // indent is the number of pixels the children are indented relative to - // the parents position. SetIndent() also redraws the control - // immediately. - unsigned int GetIndent() const { return m_indent; } - void SetIndent(unsigned int indent); - - // spacing is the number of pixels between the start and the Text - unsigned int GetSpacing() const { return m_spacing; } - void SetSpacing(unsigned int spacing); - - // see wxTreeListCtrl for the meaning - unsigned int GetLineSpacing() const { return m_linespacing; } - void SetLineSpacing(unsigned int spacing); - - // image list: these functions allow to associate an image list with - // the control and retrieve it. Note that when assigned with - // SetImageList, the control does _not_ delete - // the associated image list when it's deleted in order to allow image - // lists to be shared between different controls. If you use - // AssignImageList, the control _does_ delete the image list. - // - // The normal image list is for the icons which correspond to the - // normal tree item state (whether it is selected or not). - // Additionally, the application might choose to show a state icon - // which corresponds to an app-defined item state (for example, - // checked/unchecked) which are taken from the state image list. - wxImageList *GetImageList() const; - wxImageList *GetStateImageList() const; - wxImageList *GetButtonsImageList() const; - - void SetImageList(wxImageList *imageList); - void SetStateImageList(wxImageList *imageList); - void SetButtonsImageList(wxImageList *imageList); - void AssignImageList(wxImageList *imageList); - void AssignStateImageList(wxImageList *imageList); - void AssignButtonsImageList(wxImageList *imageList); - - // Functions to work with tree ctrl items. - - // accessors - // --------- - - // retrieve item's label - wxString GetItemText(const wxTreeItemId& item) const - { return GetItemText(item, GetMainColumn()); } - // get one of the images associated with the item (normal by default) - int GetItemImage(const wxTreeItemId& item, - wxTreeItemIcon which = wxTreeItemIcon_Normal) const - { return GetItemImage(item, GetMainColumn(), which); } - - // get the data associated with the item - wxTreeItemData *GetItemData(const wxTreeItemId& item) const; - - bool GetItemBold(const wxTreeItemId& item) const; - wxColour GetItemTextColour(const wxTreeItemId& item) const; - wxColour GetItemBackgroundColour(const wxTreeItemId& item) const; - wxFont GetItemFont(const wxTreeItemId& item) const; - - // modifiers - // --------- - - // set item's label - void SetItemText(const wxTreeItemId& item, const wxString& text) - { SetItemText(item, GetMainColumn(), text); } - - // get one of the images associated with the item (normal by default) - void SetItemImage(const wxTreeItemId& item, int image, - wxTreeItemIcon which = wxTreeItemIcon_Normal) - { SetItemImage(item, GetMainColumn(), image, which); } - - // associate some data with the item - void SetItemData(const wxTreeItemId& item, wxTreeItemData *data); - - // force appearance of [+] button near the item. This is useful to - // allow the user to expand the items which don't have any children now - // - but instead add them only when needed, thus minimizing memory - // usage and loading time. - void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE); - - // the item will be shown in bold - void SetItemBold(const wxTreeItemId& item, bool bold = TRUE); - - // set the item's text colour - void SetItemTextColour(const wxTreeItemId& item, const wxColour& col); - - // set the item's background colour - void SetItemBackgroundColour(const wxTreeItemId& item, - const wxColour& col); - - // set the item's font (should be of the same height for all items) - void SetItemFont(const wxTreeItemId& item, const wxFont& font); - - // set the window font - virtual bool SetFont( const wxFont &font ); - - // set the styles. No need to specify a GetWindowStyle here since - // the base wxWindow member function will do it for us - void SetWindowStyle(const long styles); - - // item status inquiries - // --------------------- - - // is the item visible (it might be outside the view or not expanded)? - bool IsVisible(const wxTreeItemId& item) const; - // does the item has any children? - bool HasChildren(const wxTreeItemId& item) const - { return ItemHasChildren(item); } - bool ItemHasChildren(const wxTreeItemId& item) const; - // is the item expanded (only makes sense if HasChildren())? - bool IsExpanded(const wxTreeItemId& item) const; - // is this item currently selected (the same as has focus)? - bool IsSelected(const wxTreeItemId& item) const; - // is item text in bold font? - bool IsBold(const wxTreeItemId& item) const; - // does the layout include space for a button? - - // number of children - // ------------------ - - // if 'recursively' is FALSE, only immediate children count, otherwise - // the returned number is the number of all items in this branch - size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); - - // navigation - // ---------- - - // wxTreeItemId.IsOk() will return FALSE if there is no such item - - // get the root tree item - wxTreeItemId GetRootItem() const { return m_anchor; } - - // get the item currently selected (may return NULL if no selection) - wxTreeItemId GetSelection() const { return m_current; } - - // get the items currently selected, return the number of such item - size_t GetSelections(wxArrayTreeItemIds&) const; - - // get the parent of this item (may return NULL if root) - wxTreeItemId GetParent(const wxTreeItemId& item) const; - - // for this enumeration function you must pass in a "cookie" parameter - // which is opaque for the application but is necessary for the library - // to make these functions reentrant (i.e. allow more than one - // enumeration on one and the same object simultaneously). Of course, - // the "cookie" passed to GetFirstChild() and GetNextChild() should be - // the same! - - // get the first child of this item - wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const; - // get the next child - wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const; - // get the last child of this item - this method doesn't use cookies - wxTreeItemId GetLastChild(const wxTreeItemId& item) const; - - // get the next sibling of this item - wxTreeItemId GetNextSibling(const wxTreeItemId& item) const; - // get the previous sibling - wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const; - - // get first visible item - wxTreeItemId GetFirstVisibleItem() const; - // get the next visible item: item must be visible itself! - // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() - wxTreeItemId GetNextVisible(const wxTreeItemId& item) const; - // get the previous visible item: item must be visible itself! - wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const; - - // Only for internal use right now, but should probably be public - wxTreeItemId GetNext(const wxTreeItemId& item) const; - - // operations - // ---------- - - // add the root node to the tree - wxTreeItemId AddRoot(const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item in as the first child of the parent - wxTreeItemId PrependItem(const wxTreeItemId& parent, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item after a given one - wxTreeItemId InsertItem(const wxTreeItemId& parent, - const wxTreeItemId& idPrevious, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item before the one with the given index - wxTreeItemId InsertItem(const wxTreeItemId& parent, - size_t index, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item in as the last child of the parent - wxTreeItemId AppendItem(const wxTreeItemId& parent, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // delete this item and associated data if any - void Delete(const wxTreeItemId& item); - // delete all children (but don't delete the item itself) - // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events - void DeleteChildren(const wxTreeItemId& item); - // delete all items from the tree - // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events - void DeleteAllItems(); - - // expand this item - void Expand(const wxTreeItemId& item); - // expand this item and all subitems recursively - void ExpandAll(const wxTreeItemId& item); - // collapse the item without removing its children - void Collapse(const wxTreeItemId& item); - // collapse the item and remove all children - void CollapseAndReset(const wxTreeItemId& item); - // toggles the current state - void Toggle(const wxTreeItemId& item); - - // remove the selection from currently selected item (if any) - void Unselect(); - void UnselectAll(); - // select this item - void SelectItem(const wxTreeItemId& item, bool unselect_others=TRUE, - bool extended_select=FALSE); - // make sure this item is visible (expanding the parent item and/or - // scrolling to this item if necessary) - void EnsureVisible(const wxTreeItemId& item); - // scroll to this item (but don't expand its parent) - void ScrollTo(const wxTreeItemId& item); - void AdjustMyScrollbars(); - - // The first function is more portable (because easier to implement - // on other platforms), but the second one returns some extra info. - wxTreeItemId HitTest(const wxPoint& point) - { int dummy; return HitTest(point, dummy); } - wxTreeItemId HitTest(const wxPoint& point, int& flags) - { int col; return HitTest(point, flags, col); } - // ALB - wxTreeItemId HitTest(const wxPoint& point, int& flags, int& column); - - - // get the bounding rectangle of the item (or of its label only) - bool GetBoundingRect(const wxTreeItemId& item, - wxRect& rect, - bool textOnly = FALSE) const; - - // Start editing the item label: this (temporarily) replaces the item - // with a one line edit control. The item will be selected if it hadn't - // been before. - void EditLabel( const wxTreeItemId& item ) { Edit( item ); } - void Edit( const wxTreeItemId& item ); - - // sorting - // this function is called to compare 2 items and should return -1, 0 - // or +1 if the first item is less than, equal to or greater than the - // second one. The base class version performs alphabetic comparaison - // of item labels (GetText) - virtual int OnCompareItems(const wxTreeItemId& item1, - const wxTreeItemId& item2); - // sort the children of this item using OnCompareItems - // - // NB: this function is not reentrant and not MT-safe (FIXME)! - void SortChildren(const wxTreeItemId& item); - - // deprecated functions: use Set/GetItemImage directly - // get the selected item image - int GetItemSelectedImage(const wxTreeItemId& item) const - { return GetItemImage(item, wxTreeItemIcon_Selected); } - // set the selected item image - void SetItemSelectedImage(const wxTreeItemId& item, int image) - { SetItemImage(item, image, wxTreeItemIcon_Selected); } - - // implementation only from now on - - // overridden base class virtuals - virtual bool SetBackgroundColour(const wxColour& colour); - virtual bool SetForegroundColour(const wxColour& colour); - - // callbacks - void OnPaint( wxPaintEvent &event ); - void OnSetFocus( wxFocusEvent &event ); - void OnKillFocus( wxFocusEvent &event ); - void OnChar( wxKeyEvent &event ); - void OnMouse( wxMouseEvent &event ); - void OnIdle( wxIdleEvent &event ); - void OnSize(wxSizeEvent& event); // ALB - void OnScroll(wxScrollWinEvent& event); // ALB - - // implementation helpers - void SendDeleteEvent(wxTreeListItem *itemBeingDeleted); - - void DrawBorder(const wxTreeItemId& item); - void DrawLine(const wxTreeItemId& item, bool below); - - size_t GetColumnCount() const - { return m_owner->GetHeaderWindow()->GetColumnCount(); } - - void SetMainColumn(size_t column) - { - if(column < GetColumnCount()) - m_main_column = column; - } - size_t GetMainColumn() const { return m_main_column; } - - void SetItemText(const wxTreeItemId& item, size_t column, - const wxString& text); - wxString GetItemText(const wxTreeItemId& item, size_t column) const; - - void SetItemImage(const wxTreeItemId& item, size_t column, int image, - wxTreeItemIcon which = wxTreeItemIcon_Normal); - int GetItemImage(const wxTreeItemId& item, size_t column, - wxTreeItemIcon which = wxTreeItemIcon_Normal) const; -protected: - wxTreeListCtrl* m_owner; // ALB - - size_t m_main_column; // ALB - - friend class wxTreeListItem; - friend class wxTreeListRenameTimer; - friend class wxTreeListTextCtrl; - - wxFont m_normalFont; - wxFont m_boldFont; - - wxTreeListItem *m_anchor; - wxTreeListItem *m_current, *m_key_current, *m_currentEdit; - unsigned short m_indent; - unsigned short m_spacing; - int m_lineHeight; - unsigned short m_linespacing; - wxPen m_dottedPen; - wxBrush *m_hilightBrush, - *m_hilightUnfocusedBrush; - bool m_hasFocus; -public: - bool m_dirty; -protected: - bool m_ownsImageListNormal, - m_ownsImageListState, - m_ownsImageListButtons; - bool m_isDragging; // true between BEGIN/END drag events - bool m_renameAccept; - bool m_lastOnSame; // last click on the same item as prev - wxImageList *m_imageListNormal, - *m_imageListState, - *m_imageListButtons; - - int m_dragCount; - wxPoint m_dragStart; - wxTreeListItem *m_dropTarget; - wxCursor m_oldCursor; // cursor is changed while dragging - wxTreeListItem *m_oldSelection; - - wxTimer *m_renameTimer; - wxString m_renameRes; - - // the common part of all ctors - void Init(); - - // misc helpers - wxTreeItemId DoInsertItem(const wxTreeItemId& parent, - size_t previous, - const wxString& text, - int image, int selectedImage, - wxTreeItemData *data); - bool HasButtons(void) const - { return (m_imageListButtons != NULL) - || HasFlag(wxTR_TWIST_BUTTONS|wxTR_HAS_BUTTONS); } - -protected: - void CalculateLineHeight(); - int GetLineHeight(wxTreeListItem *item) const; - void PaintLevel( wxTreeListItem *item, wxDC& dc, int level, int &y, - int x_offset); - void PaintItem( wxTreeListItem *item, wxDC& dc); - - void CalculateLevel( wxTreeListItem *item, wxDC &dc, int level, int &y, - int x_offset); - void CalculatePositions(); - void CalculateSize( wxTreeListItem *item, wxDC &dc ); - - void RefreshSubtree( wxTreeListItem *item ); - void RefreshLine( wxTreeListItem *item ); - - // redraw all selected items - void RefreshSelected(); - - // RefreshSelected() recursive helper - void RefreshSelectedUnder(wxTreeListItem *item); - - void OnRenameTimer(); - void OnRenameAccept(); - - void FillArray(wxTreeListItem*, wxArrayTreeItemIds&) const; - void SelectItemRange( wxTreeListItem *item1, wxTreeListItem *item2 ); - bool TagAllChildrenUntilLast(wxTreeListItem *crt_item, - wxTreeListItem *last_item, bool select); - bool TagNextChildren(wxTreeListItem *crt_item, wxTreeListItem *last_item, - bool select); - void UnselectAllChildren( wxTreeListItem *item ); - - void DrawDropEffect(wxTreeListItem *item); - -private: - DECLARE_EVENT_TABLE() - DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow) -}; - - -// timer used for enabling in-place edit -class wxTreeListRenameTimer: public wxTimer -{ -public: - wxTreeListRenameTimer( wxTreeListMainWindow *owner ); - - void Notify(); - -private: - wxTreeListMainWindow *m_owner; -}; - -// control used for in-place edit -class wxTreeListTextCtrl: public wxTextCtrl -{ -public: - wxTreeListTextCtrl( wxWindow *parent, - const wxWindowID id, - bool *accept, - wxString *res, - wxTreeListMainWindow *owner, - const wxString &value = wxEmptyString, - const wxPoint &pos = wxDefaultPosition, - const wxSize &size = wxDefaultSize, - int style = wxSIMPLE_BORDER, - const wxValidator& validator = wxDefaultValidator, - const wxString &name = wxTextCtrlNameStr ); - - void OnChar( wxKeyEvent &event ); - void OnKeyUp( wxKeyEvent &event ); - void OnKillFocus( wxFocusEvent &event ); - -private: - bool *m_accept; - wxString *m_res; - wxTreeListMainWindow *m_owner; - wxString m_startValue; - bool m_finished; - - DECLARE_EVENT_TABLE() -}; - -// a tree item -class wxTreeListItem -{ -public: - // ctors & dtor - wxTreeListItem() { m_data = NULL; } - wxTreeListItem( wxTreeListMainWindow *owner, - wxTreeListItem *parent, - const wxArrayString& text, - int image, - int selImage, - wxTreeItemData *data ); - - ~wxTreeListItem(); - - // trivial accessors - wxArrayTreeListItems& GetChildren() { return m_children; } - - const wxString GetText() const - { - if(m_text.GetCount() > 0) return m_text[0]; - return wxEmptyString; - } - const wxString GetText(size_t col) const - { - if(m_text.GetCount() > col) return m_text[col]; - return wxEmptyString; - } - int GetImage(wxTreeItemIcon which = wxTreeItemIcon_Normal) const - { return m_images[which]; } - int GetImage(size_t col, wxTreeItemIcon which=wxTreeItemIcon_Normal) const - { - if(col == m_owner->GetMainColumn()) return m_images[which]; - if(col < m_col_images.GetCount()) return m_col_images[col]; - return NO_IMAGE; - } - wxTreeItemData *GetData() const { return m_data; } - - // returns the current image for the item (depending on its - // selected/expanded/whatever state) - int GetCurrentImage() const; - - void SetText( const wxString &text ); - void SetText(size_t col, const wxString& text) // ALB - { - if(col < m_text.GetCount()) - m_text[col] = text; - else if(col < m_owner->GetColumnCount()) { - int howmany = m_owner->GetColumnCount(); - for(int i = m_text.GetCount(); i < howmany; ++i) - m_text.Add(wxEmptyString); - m_text[col] = text; - } - } - void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; } - void SetImage(size_t col, int image, wxTreeItemIcon which) - { - if(col == m_owner->GetMainColumn()) m_images[which] = image; - else if(col < m_col_images.GetCount()) - m_col_images[col] = image; - else if(col < m_owner->GetColumnCount()) { - int howmany = m_owner->GetColumnCount(); - for(int i = m_col_images.GetCount(); i < howmany; ++i) - m_col_images.Add(NO_IMAGE); - m_col_images[col] = image; - } - } - - void SetData(wxTreeItemData *data) { m_data = data; } - - void SetHasPlus(bool has = TRUE) { m_hasPlus = has; } - - void SetBold(bool bold) { m_isBold = bold; } - - int GetX() const { return m_x; } - int GetY() const { return m_y; } - - void SetX(int x) { m_x = x; } - void SetY(int y) { m_y = y; } - - int GetHeight() const { return m_height; } - int GetWidth() const { return m_width; } - - void SetHeight(int h) { m_height = h; } - void SetWidth(int w) { m_width = w; } - - wxTreeListItem *GetParent() const { return m_parent; } - - // operations - // deletes all children notifying the treectrl about it if !NULL - // pointer given - void DeleteChildren(wxTreeListMainWindow *tree = NULL); - - // get count of all children (and grand children if 'recursively') - size_t GetChildrenCount(bool recursively = TRUE) const; - - void Insert(wxTreeListItem *child, size_t index) - { m_children.Insert(child, index); } - - void GetSize( int &x, int &y, const wxTreeListMainWindow* ); - - // return the item at given position (or NULL if no item), onButton is - // TRUE if the point belongs to the item's button, otherwise it lies - // on the button's label - wxTreeListItem *HitTest( const wxPoint& point, - const wxTreeListMainWindow *, - int &flags, - int level ); - wxTreeListItem *HitTest( const wxPoint& point, - const wxTreeListMainWindow *, - int &flags, int& column /*ALB*/, - int level ); - - void Expand() { m_isCollapsed = FALSE; } - void Collapse() { m_isCollapsed = TRUE; } - - void SetHilight( bool set = TRUE ) { m_hasHilight = set; } - - // status inquiries - bool HasChildren() const { return !m_children.IsEmpty(); } - bool IsSelected() const { return m_hasHilight != 0; } - bool IsExpanded() const { return !m_isCollapsed; } - bool HasPlus() const { return m_hasPlus || HasChildren(); } - bool IsBold() const { return m_isBold != 0; } - - // attributes - // get them - may be NULL - wxTreeItemAttr *GetAttributes() const { return m_attr; } - // get them ensuring that the pointer is not NULL - wxTreeItemAttr& Attr() - { - if ( !m_attr ) - { - m_attr = new wxTreeItemAttr; - m_ownsAttr = TRUE; - } - return *m_attr; - } - // set them - void SetAttributes(wxTreeItemAttr *attr) - { - if ( m_ownsAttr ) delete m_attr; - m_attr = attr; - m_ownsAttr = FALSE; - } - // set them and delete when done - void AssignAttributes(wxTreeItemAttr *attr) - { - SetAttributes(attr); - m_ownsAttr = TRUE; - } - -private: - wxTreeListMainWindow *m_owner; // control the item belongs to - - // since there can be very many of these, we save size by chosing - // the smallest representation for the elements and by ordering - // the members to avoid padding. - wxArrayString m_text; // labels to be rendered for item - - wxTreeItemData *m_data; // user-provided data - - wxArrayTreeListItems m_children; // list of children - wxTreeListItem *m_parent; // parent of this item - - wxTreeItemAttr *m_attr; // attributes??? - - // tree ctrl images for the normal, selected, expanded and - // expanded+selected states - short m_images[wxTreeItemIcon_Max]; - wxArrayShort m_col_images; // images for the various columns (!= main) - - wxCoord m_x; // (virtual) offset from top - wxCoord m_y; // (virtual) offset from left - short m_width; // width of this item - unsigned char m_height; // height of this item - - // use bitfields to save size - int m_isCollapsed :1; - int m_hasHilight :1; // same as focused - int m_hasPlus :1; // used for item which doesn't have - // children but has a [+] button - int m_isBold :1; // render the label in bold font - int m_ownsAttr :1; // delete attribute when done -}; - -// =========================================================================== -// implementation -// =========================================================================== - -// ---------------------------------------------------------------------------- -// private functions -// ---------------------------------------------------------------------------- - -// translate the key or mouse event flags to the type of selection we're -// dealing with -static void EventFlagsToSelType(long style, - bool shiftDown, - bool ctrlDown, - bool &is_multiple, - bool &extended_select, - bool &unselect_others) -{ - is_multiple = (style & wxTR_MULTIPLE) != 0; - extended_select = shiftDown && is_multiple; - unselect_others = !(extended_select || (ctrlDown && is_multiple)); -} - -// --------------------------------------------------------------------------- -// wxTreeListRenameTimer (internal) -// --------------------------------------------------------------------------- - -wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow *owner ) -{ - m_owner = owner; -} - -void wxTreeListRenameTimer::Notify() -{ - m_owner->OnRenameTimer(); -} - -//----------------------------------------------------------------------------- -// wxTreeListTextCtrl (internal) -//----------------------------------------------------------------------------- - -BEGIN_EVENT_TABLE(wxTreeListTextCtrl,wxTextCtrl) - EVT_CHAR (wxTreeListTextCtrl::OnChar) - EVT_KEY_UP (wxTreeListTextCtrl::OnKeyUp) - EVT_KILL_FOCUS (wxTreeListTextCtrl::OnKillFocus) -END_EVENT_TABLE() - -wxTreeListTextCtrl::wxTreeListTextCtrl( wxWindow *parent, - const wxWindowID id, - bool *accept, - wxString *res, - wxTreeListMainWindow *owner, - const wxString &value, - const wxPoint &pos, - const wxSize &size, - int style, - const wxValidator& validator, - const wxString &name ) - : wxTextCtrl( parent, id, value, pos, size, style, validator, name ) -{ - m_res = res; - m_accept = accept; - m_owner = owner; - (*m_accept) = FALSE; - (*m_res) = wxEmptyString; - m_startValue = value; - m_finished = FALSE; -} - -void wxTreeListTextCtrl::OnChar( wxKeyEvent &event ) -{ - if (event.m_keyCode == WXK_RETURN) - { - (*m_accept) = TRUE; - (*m_res) = GetValue(); - - if ((*m_res) != m_startValue) - m_owner->OnRenameAccept(); - - if (!wxPendingDelete.Member(this)) - wxPendingDelete.Append(this); - - m_finished = TRUE; - m_owner->SetFocus(); // This doesn't work. TODO. - - return; - } - if (event.m_keyCode == WXK_ESCAPE) - { - (*m_accept) = FALSE; - (*m_res) = wxEmptyString; - - if (!wxPendingDelete.Member(this)) - wxPendingDelete.Append(this); - - m_finished = TRUE; - m_owner->SetFocus(); // This doesn't work. TODO. - - return; - } - event.Skip(); -} - -void wxTreeListTextCtrl::OnKeyUp( wxKeyEvent &event ) -{ - if (m_finished) - { - event.Skip(); - return; - } - - // auto-grow the textctrl: - wxSize parentSize = m_owner->GetSize(); - wxPoint myPos = GetPosition(); - wxSize mySize = GetSize(); - int sx, sy; - GetTextExtent(GetValue() + _T("M"), &sx, &sy); - if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; - if (mySize.x > sx) sx = mySize.x; - SetSize(sx, -1); - - event.Skip(); -} - -void wxTreeListTextCtrl::OnKillFocus( wxFocusEvent &event ) -{ - if (m_finished) - { - event.Skip(); - return; - } - - if (!wxPendingDelete.Member(this)) - wxPendingDelete.Append(this); - - (*m_accept) = TRUE; - (*m_res) = GetValue(); - - if ((*m_res) != m_startValue) - m_owner->OnRenameAccept(); -} - -//----------------------------------------------------------------------------- -// wxTreeListHeaderWindow -//----------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow,wxWindow); - -BEGIN_EVENT_TABLE(wxTreeListHeaderWindow,wxWindow) - EVT_PAINT (wxTreeListHeaderWindow::OnPaint) - EVT_MOUSE_EVENTS (wxTreeListHeaderWindow::OnMouse) - EVT_SET_FOCUS (wxTreeListHeaderWindow::OnSetFocus) -END_EVENT_TABLE() - -void wxTreeListHeaderWindow::Init() -{ - m_currentCursor = (wxCursor *) NULL; - m_isDragging = FALSE; - m_dirty = FALSE; - m_total_col_width = 0; -} - -wxTreeListHeaderWindow::wxTreeListHeaderWindow() -{ - Init(); - - m_owner = (wxTreeListMainWindow *) NULL; - m_resizeCursor = (wxCursor *) NULL; -} - -wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow *win, - wxWindowID id, - wxTreeListMainWindow *owner, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString &name ) - : wxWindow( win, id, pos, size, style, name ) -{ - Init(); - - m_owner = owner; - m_resizeCursor = new wxCursor(wxCURSOR_SIZEWE); - - SetBackgroundColour(wxSystemSettings::GetSystemColour( - wxSYS_COLOUR_BTNFACE)); -} - -wxTreeListHeaderWindow::~wxTreeListHeaderWindow() -{ - delete m_resizeCursor; -} - -void wxTreeListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) -{ -#ifdef __WXGTK__ - GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL - : GTK_STATE_INSENSITIVE; - - x = dc->XLOG2DEV( x ); - - gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, - state, GTK_SHADOW_OUT, - (GdkRectangle*) NULL, m_wxwindow, "button", - x-1, y-1, w+2, h+2); -#elif defined( __WXMAC__ ) - const int m_corner = 1; - - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - - dc->SetPen( wxPen(wxSystemSettings::GetSystemColour( - wxSYS_COLOUR_BTNSHADOW), 1, wxSOLID)); - dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) - dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) - - wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID ); - - dc->SetPen( pen ); - dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) - dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) - - dc->SetPen( *wxWHITE_PEN ); - dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer) - dc->DrawRectangle( x, y, 1, h ); // left (outer) - dc->DrawLine( x, y+h-1, x+1, y+h-1 ); - dc->DrawLine( x+w-1, y, x+w-1, y+1 ); -#else // !GTK, !Mac - const int m_corner = 1; - - dc->SetBrush( *wxTRANSPARENT_BRUSH ); - - dc->SetPen( *wxBLACK_PEN ); - dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) - dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) - - wxPen pen(wxSystemSettings::GetSystemColour( - wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID); - - dc->SetPen( pen ); - dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) - dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) - - dc->SetPen( *wxWHITE_PEN ); - dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer) - dc->DrawRectangle( x, y, 1, h ); // left (outer) - dc->DrawLine( x, y+h-1, x+1, y+h-1 ); - dc->DrawLine( x+w-1, y, x+w-1, y+1 ); -#endif -} - -// shift the DC origin to match the position of the main window horz -// scrollbar: this allows us to always use logical coords -void wxTreeListHeaderWindow::AdjustDC(wxDC& dc) -{ - int xpix; - m_owner->GetScrollPixelsPerUnit( &xpix, NULL ); - - int x; - m_owner->GetViewStart( &x, NULL ); - - // account for the horz scrollbar offset - dc.SetDeviceOrigin( -x * xpix, 0 ); -} - -void wxTreeListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) -{ - static const int HEADER_OFFSET_X = 1, HEADER_OFFSET_Y = 1; -#ifdef __WXGTK__ - wxClientDC dc( this ); -#else - wxPaintDC dc( this ); -#endif - - PrepareDC( dc ); - AdjustDC( dc ); - - dc.BeginDrawing(); - - dc.SetFont( GetFont() ); - - // width and height of the entire header window - int w, h; - GetClientSize( &w, &h ); - m_owner->CalcUnscrolledPosition(w, 0, &w, NULL); - - dc.SetBackgroundMode(wxTRANSPARENT); - - // do *not* use the listctrl colour for headers - one day we will have a - // function to set it separately - //dc.SetTextForeground( *wxBLACK ); - dc.SetTextForeground(wxSystemSettings:: - GetSystemColour( wxSYS_COLOUR_WINDOWTEXT )); - - int x = HEADER_OFFSET_X; - - int numColumns = GetColumnCount(); - for ( int i = 0; i < numColumns && x < w; i++ ) - { - wxTreeListColumnInfo& column = GetColumn(i); - int wCol = column.GetWidth(); - - // the width of the rect to draw: make it smaller to fit entirely - // inside the column rect - int cw = wCol - 2; - - dc.SetPen( *wxWHITE_PEN ); - - DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 ); - - // if we have an image, draw it on the right of the label - int image = column.GetImage(); //item.m_image; - int ix = -2, iy = 0; - wxImageList* imageList = m_owner->GetImageList(); - if(image != -1) { - if(imageList) { - imageList->GetSize(image, ix, iy); - } - //else: ignore the column image - } - - // extra margins around the text label - static const int EXTRA_WIDTH = 3; - static const int EXTRA_HEIGHT = 4; - - int text_width = 0; - int text_x = x; - int image_offset = cw - ix - 1; - - switch(column.GetAlignment()) { - case wxTL_ALIGN_LEFT: - text_x += EXTRA_WIDTH; - cw -= ix + 2; - break; - case wxTL_ALIGN_RIGHT: - dc.GetTextExtent(column.GetText(), &text_width, NULL); - text_x += cw - text_width - EXTRA_WIDTH; - image_offset = 0; - break; - case wxTL_ALIGN_CENTER: - dc.GetTextExtent(column.GetText(), &text_width, NULL); - text_x += (cw - text_width)/2 + ix + 2; - image_offset = (cw - text_width - ix - 2)/2; - break; - } - - // draw the image - if(image != -1 && imageList) { - imageList->Draw(image, dc, x + image_offset/*cw - ix - 1*/, - HEADER_OFFSET_Y + (h - 4 - iy)/2, - wxIMAGELIST_DRAW_TRANSPARENT); - } - - // draw the text clipping it so that it doesn't overwrite the column - // boundary - wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 ); - - dc.DrawText( column.GetText(), - text_x, HEADER_OFFSET_Y + EXTRA_HEIGHT ); - - x += wCol; - } - - dc.EndDrawing(); -} - -void wxTreeListHeaderWindow::DrawCurrent() -{ - int x1 = m_currentX; - int y1 = 0; - ClientToScreen( &x1, &y1 ); - - int x2 = m_currentX-1; -#ifdef __WXMSW__ - ++x2; // but why ? -#endif - int y2 = 0; - m_owner->GetClientSize( NULL, &y2 ); - m_owner->ClientToScreen( &x2, &y2 ); - - wxScreenDC dc; - dc.SetLogicalFunction( wxINVERT ); - dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) ); - dc.SetBrush( *wxTRANSPARENT_BRUSH ); - - AdjustDC(dc); - - dc.DrawLine( x1, y1, x2, y2 ); - - dc.SetLogicalFunction( wxCOPY ); - - dc.SetPen( wxNullPen ); - dc.SetBrush( wxNullBrush ); -} - -void wxTreeListHeaderWindow::OnMouse( wxMouseEvent &event ) -{ - // we want to work with logical coords - int x; - m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL); - int y = event.GetY(); - - if (m_isDragging) - { - SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING, - event.GetPosition()); - - // we don't draw the line beyond our window, but we allow dragging it - // there - int w = 0; - GetClientSize( &w, NULL ); - m_owner->CalcUnscrolledPosition(w, 0, &w, NULL); - w -= 6; - - // erase the line if it was drawn - if ( m_currentX < w ) - DrawCurrent(); - - if (event.ButtonUp()) - { - ReleaseMouse(); - m_isDragging = FALSE; - m_dirty = TRUE; - SetColumnWidth( m_column, m_currentX - m_minX ); - Refresh(); - SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG, - event.GetPosition()); - } - else - { - if (x > m_minX + 7) - m_currentX = x; - else - m_currentX = m_minX + 7; - - // draw in the new location - if ( m_currentX < w ) - DrawCurrent(); - } - } - else // not dragging - { - m_minX = 0; - bool hit_border = FALSE; - - // end of the current column - int xpos = 0; - - // find the column where this event occured - int countCol = GetColumnCount(); - for (int col = 0; col < countCol; col++) - { - xpos += GetColumnWidth( col ); - m_column = col; - - if ( (abs(x-xpos) < 3) && (y < 22) ) - { - // near the column border - hit_border = TRUE; - break; - } - - if ( x < xpos ) - { - // inside the column - break; - } - - m_minX = xpos; - } - - if (event.LeftDown() || event.RightUp()) - { - if (hit_border && event.LeftDown()) - { - m_isDragging = TRUE; - m_currentX = x; - DrawCurrent(); - CaptureMouse(); - SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, - event.GetPosition()); - } - else // click on a column - { - SendListEvent( event.LeftDown() - ? wxEVT_COMMAND_LIST_COL_CLICK - : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, - event.GetPosition()); - } - } - else if (event.Moving()) - { - bool setCursor; - if (hit_border) - { - setCursor = m_currentCursor == wxSTANDARD_CURSOR; - m_currentCursor = m_resizeCursor; - } - else - { - setCursor = m_currentCursor != wxSTANDARD_CURSOR; - m_currentCursor = wxSTANDARD_CURSOR; - } - - if ( setCursor ) - SetCursor(*m_currentCursor); - } - } -} - -void wxTreeListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) -{ - m_owner->SetFocus(); -} - -void wxTreeListHeaderWindow::SendListEvent(wxEventType type, wxPoint pos) -{ - wxWindow *parent = GetParent(); - wxListEvent le( type, parent->GetId() ); - le.SetEventObject( parent ); - le.m_pointDrag = pos; - - // the position should be relative to the parent window, not - // this one for compatibility with MSW and common sense: the - // user code doesn't know anything at all about this header - // window, so why should it get positions relative to it? - le.m_pointDrag.y -= GetSize().y; - - le.m_col = m_column; - parent->GetEventHandler()->ProcessEvent( le ); -} - -inline -void wxTreeListHeaderWindow::AddColumn(const wxTreeListColumnInfo& col) -{ - m_columns.Add(col); - m_total_col_width += col.GetWidth(); - //m_owner->GetHeaderWindow()->Refresh(); - //m_dirty = TRUE; - m_owner->AdjustMyScrollbars(); - m_owner->m_dirty = TRUE; - Refresh(); -} - -inline -void wxTreeListHeaderWindow::SetColumnWidth(size_t column, size_t width) -{ - if(column < GetColumnCount()) { - m_total_col_width -= m_columns[column].GetWidth(); - m_columns[column].SetWidth(width); - m_total_col_width += width; - m_owner->AdjustMyScrollbars(); - m_owner->m_dirty = TRUE; - //m_dirty = TRUE; - Refresh(); - } -} - - -inline -void wxTreeListHeaderWindow::InsertColumn(size_t before, - const wxTreeListColumnInfo& col) -{ - wxCHECK_RET(before < GetColumnCount(), wxT("Invalid column index")); - m_columns.Insert(col, before); - m_total_col_width += col.GetWidth(); - //m_dirty = TRUE; - //m_owner->GetHeaderWindow()->Refresh(); - m_owner->AdjustMyScrollbars(); - m_owner->m_dirty = TRUE; - Refresh(); -} - -inline -void wxTreeListHeaderWindow::RemoveColumn(size_t column) -{ - wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); - m_total_col_width -= m_columns[column].GetWidth(); - m_columns.RemoveAt(column); - //m_dirty = TRUE; - m_owner->AdjustMyScrollbars(); - m_owner->m_dirty = TRUE; - Refresh(); -} - -inline -void wxTreeListHeaderWindow::SetColumn(size_t column, - const wxTreeListColumnInfo& info) -{ - wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); - size_t w = m_columns[column].GetWidth(); - m_columns[column] = info; - //m_owner->GetHeaderWindow()->Refresh(); - //m_dirty = TRUE; - if(w != info.GetWidth()) { - m_total_col_width += info.GetWidth() - w; - m_owner->AdjustMyScrollbars(); - m_owner->m_dirty = TRUE; - } - Refresh(); -} - -// --------------------------------------------------------------------------- -// wxTreeListItem -// --------------------------------------------------------------------------- - -wxTreeListItem::wxTreeListItem(wxTreeListMainWindow *owner, - wxTreeListItem *parent, - const wxArrayString& text, - int image, int selImage, - wxTreeItemData *data) - : m_text(text) -{ - m_images[wxTreeItemIcon_Normal] = image; - m_images[wxTreeItemIcon_Selected] = selImage; - m_images[wxTreeItemIcon_Expanded] = NO_IMAGE; - m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE; - - m_data = data; - m_x = m_y = 0; - - m_isCollapsed = TRUE; - m_hasHilight = FALSE; - m_hasPlus = FALSE; - m_isBold = FALSE; - - m_owner = owner; - - m_parent = parent; - - m_attr = (wxTreeItemAttr *)NULL; - m_ownsAttr = FALSE; - - // We don't know the height here yet. - m_width = 0; - m_height = 0; -} - -wxTreeListItem::~wxTreeListItem() -{ - delete m_data; - - if (m_ownsAttr) delete m_attr; - - wxASSERT_MSG( m_children.IsEmpty(), - wxT("please call DeleteChildren() before deleting the item") ); -} - -void wxTreeListItem::DeleteChildren(wxTreeListMainWindow *tree) -{ - size_t count = m_children.Count(); - for ( size_t n = 0; n < count; n++ ) - { - wxTreeListItem *child = m_children[n]; - if (tree) - tree->SendDeleteEvent(child); - - child->DeleteChildren(tree); - delete child; - } - - m_children.Empty(); -} - -void wxTreeListItem::SetText( const wxString &text ) -{ - if(m_text.GetCount() > 0) m_text[0] = text; - else { - m_text.Add(text); - } -} - -size_t wxTreeListItem::GetChildrenCount(bool recursively) const -{ - size_t count = m_children.Count(); - if ( !recursively ) - return count; - - size_t total = count; - for (size_t n = 0; n < count; ++n) - { - total += m_children[n]->GetChildrenCount(); - } - - return total; -} - -void wxTreeListItem::GetSize( int &x, int &y, - const wxTreeListMainWindow *theButton ) -{ - int bottomY=m_y+theButton->GetLineHeight(this); - if ( y < bottomY ) y = bottomY; - int width = m_x + m_width; - if ( x < width ) x = width; - - if (IsExpanded()) - { - size_t count = m_children.Count(); - for ( size_t n = 0; n < count; ++n ) - { - m_children[n]->GetSize( x, y, theButton ); - } - } -} - -wxTreeListItem *wxTreeListItem::HitTest(const wxPoint& point, - const wxTreeListMainWindow *theCtrl, - int &flags, - int level) -{ - // for a hidden root node, don't evaluate it, but do evaluate children - if ( !(level == 0 && theCtrl->HasFlag(wxTR_HIDE_ROOT)) ) - { - // evaluate the item - int h = theCtrl->GetLineHeight(this); - if ((point.y > m_y) && (point.y <= m_y + h)) - { - int y_mid = m_y + h/2; - if (point.y < y_mid ) - flags |= wxTREE_HITTEST_ONITEMUPPERPART; - else - flags |= wxTREE_HITTEST_ONITEMLOWERPART; - - // 5 is the size of the plus sign - int xCross = m_x - theCtrl->GetSpacing(); - if ((point.x > xCross-5) && (point.x < xCross+5) && - (point.y > y_mid-5) && (point.y < y_mid+5) && - HasPlus() && theCtrl->HasButtons() ) - { - flags |= wxTREE_HITTEST_ONITEMBUTTON; - return this; - } - - if ((point.x >= m_x) && (point.x <= m_x+m_width)) - { - int image_w = -1; - int image_h; - - //assuming every image (normal and selected) has the same size! - if ( (GetImage() != NO_IMAGE) && theCtrl->m_imageListNormal ) - theCtrl->m_imageListNormal->GetSize(GetImage(), - image_w, image_h); - - if ((image_w != -1) && (point.x <= m_x + image_w + 1)) - flags |= wxTREE_HITTEST_ONITEMICON; - else - flags |= wxTREE_HITTEST_ONITEMLABEL; - - return this; - } - - if (point.x < m_x) - flags |= wxTREE_HITTEST_ONITEMINDENT; - if (point.x > m_x+m_width) - flags |= wxTREE_HITTEST_ONITEMRIGHT; - - return this; - } - - // if children are expanded, fall through to evaluate them - if (m_isCollapsed) return (wxTreeListItem*) NULL; - } - - // evaluate children - size_t count = m_children.Count(); - for ( size_t n = 0; n < count; n++ ) - { - wxTreeListItem *res = m_children[n]->HitTest(point, theCtrl, - flags, level + 1); - if ( res != NULL ) - return res; - } - - return (wxTreeListItem*) NULL; -} - -// ALB -wxTreeListItem *wxTreeListItem::HitTest(const wxPoint& point, - const wxTreeListMainWindow *theCtrl, - int &flags, int& column, int level) -{ - column = theCtrl->GetMainColumn(); //-1; - wxTreeListItem* res = HitTest(point, theCtrl, flags, level); - - if (!res) { - column = -1; - return res; - } - - if (point.x >= theCtrl->m_owner->GetHeaderWindow()->GetWidth()) - column = -1; - else if (flags & wxTREE_HITTEST_ONITEMINDENT) { - int x = 0; - for (int i = 0; i < column; ++i) { - int w = theCtrl->m_owner->GetHeaderWindow()->GetColumnWidth(i); - if(point.x >= x && point.x < x+w) { - flags ^= wxTREE_HITTEST_ONITEMINDENT; - flags |= wxTREE_HITTEST_ONITEMCOLUMN; - column = i; - return res; - } - x += w; - } - } - else if (flags & wxTREE_HITTEST_ONITEMRIGHT) { - int x = 0; - int i; - for (i = 0; i < column+1; ++i) { - x += theCtrl->m_owner->GetHeaderWindow()->GetColumnWidth(i); - } - for (i = column+1; i < (int)theCtrl->GetColumnCount(); ++i) { - int w = theCtrl->m_owner->GetHeaderWindow()->GetColumnWidth(i); - if (point.x >= x && point.x < x+w) { - flags ^= wxTREE_HITTEST_ONITEMRIGHT; - flags |= wxTREE_HITTEST_ONITEMCOLUMN; - column = i; - return res; - } - x += w; - } - } - - return res; -} - - -int wxTreeListItem::GetCurrentImage() const -{ - int image = NO_IMAGE; - if ( IsExpanded() ) - { - if ( IsSelected() ) - { - image = GetImage(wxTreeItemIcon_SelectedExpanded); - } - - if ( image == NO_IMAGE ) - { - // we usually fall back to the normal item, but try just the - // expanded one (and not selected) first in this case - image = GetImage(wxTreeItemIcon_Expanded); - } - } - else // not expanded - { - if ( IsSelected() ) - image = GetImage(wxTreeItemIcon_Selected); - } - - // maybe it doesn't have the specific image we want, - // try the default one instead - if ( image == NO_IMAGE ) image = GetImage(); - - return image; -} - -// --------------------------------------------------------------------------- -// wxTreeListMainWindow implementation -// --------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow, wxScrolledWindow) - -BEGIN_EVENT_TABLE(wxTreeListMainWindow, wxScrolledWindow) - EVT_PAINT (wxTreeListMainWindow::OnPaint) - EVT_MOUSE_EVENTS (wxTreeListMainWindow::OnMouse) - EVT_CHAR (wxTreeListMainWindow::OnChar) - EVT_SET_FOCUS (wxTreeListMainWindow::OnSetFocus) - EVT_KILL_FOCUS (wxTreeListMainWindow::OnKillFocus) - EVT_IDLE (wxTreeListMainWindow::OnIdle) - //EVT_SIZE (wxTreeListMainWindow::OnSize) - EVT_SCROLLWIN (wxTreeListMainWindow::OnScroll) -END_EVENT_TABLE() - - -// --------------------------------------------------------------------------- -// construction/destruction -// --------------------------------------------------------------------------- - -void wxTreeListMainWindow::Init() -{ - m_current = m_key_current = m_anchor = (wxTreeListItem *) NULL; - m_hasFocus = FALSE; - m_dirty = FALSE; - - m_lineHeight = 10; - m_indent = 9; - m_spacing = 9; - m_linespacing = 4; - - m_hilightBrush = new wxBrush - ( - wxSystemSettings::GetSystemColour - ( - wxSYS_COLOUR_HIGHLIGHT - ), - wxSOLID - ); - - m_hilightUnfocusedBrush = new wxBrush - ( - wxSystemSettings::GetSystemColour - ( - wxSYS_COLOUR_BTNSHADOW - ), - wxSOLID - ); - - m_imageListNormal = m_imageListButtons = - m_imageListState = (wxImageList *) NULL; - m_ownsImageListNormal = m_ownsImageListButtons = - m_ownsImageListState = FALSE; - - m_dragCount = 0; - m_isDragging = FALSE; - m_dropTarget = m_oldSelection = (wxTreeListItem *)NULL; - - m_renameTimer = new wxTreeListRenameTimer( this ); - m_lastOnSame = FALSE; - - m_normalFont = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ); - m_boldFont = wxFont( m_normalFont.GetPointSize(), - m_normalFont.GetFamily(), - m_normalFont.GetStyle(), - wxBOLD, - m_normalFont.GetUnderlined()); -} - - -static const int HEADER_HEIGHT = 23; - -bool wxTreeListMainWindow::Create(wxTreeListCtrl *parent, - wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator &validator, - const wxString& name ) -{ -#ifdef __WXMAC__ - int major,minor; - wxGetOsVersion( &major, &minor ); - - if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS; - if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS; - style &= ~wxTR_LINES_AT_ROOT; - style |= wxTR_NO_LINES; - if (major < 10) - style |= wxTR_ROW_LINES; -#endif - - wxScrolledWindow::Create( parent, id, pos, size, - style|wxHSCROLL|wxVSCROLL, name ); - - // If the tree display has no buttons, but does have - // connecting lines, we can use a narrower layout. - // It may not be a good idea to force this... - if (!HasButtons() && !HasFlag(wxTR_NO_LINES)) - { - m_indent= 10; - m_spacing = 10; - } - -#if wxUSE_VALIDATORS - SetValidator( validator ); -#endif - - SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) ); - -// #ifdef __WXMSW__ -// m_dottedPen = wxPen( "black", 0, wxDOT ); // too slow under XFree86 -// #else - m_dottedPen = wxPen( wxT("grey"), 0, 0 ); -// #endif - - // ALB - m_owner = parent; - m_main_column = 0; - - return TRUE; -} - -wxTreeListMainWindow::~wxTreeListMainWindow() -{ - delete m_hilightBrush; - delete m_hilightUnfocusedBrush; - - DeleteAllItems(); - - delete m_renameTimer; - if (m_ownsImageListNormal) delete m_imageListNormal; - if (m_ownsImageListState) delete m_imageListState; - if (m_ownsImageListButtons) delete m_imageListButtons; -} - - - -//----------------------------------------------------------------------------- -// accessors -//----------------------------------------------------------------------------- - -inline -size_t wxTreeListMainWindow::GetCount() const -{ - return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount(); -} - -inline -void wxTreeListMainWindow::SetIndent(unsigned int indent) -{ - m_indent = indent; - m_dirty = TRUE; -} - -inline -void wxTreeListMainWindow::SetSpacing(unsigned int spacing) -{ - m_spacing = spacing; - m_dirty = TRUE; -} - -inline -void wxTreeListMainWindow::SetLineSpacing(unsigned int spacing) -{ - m_linespacing = spacing; - m_dirty = TRUE; - CalculateLineHeight(); -} - -inline -size_t wxTreeListMainWindow::GetChildrenCount(const wxTreeItemId& item, - bool recursively) -{ - wxCHECK_MSG( item.IsOk(), 0u, wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->GetChildrenCount(recursively); -} - -void wxTreeListMainWindow::SetWindowStyle(const long styles) -{ - // right now, just sets the styles. Eventually, we may - // want to update the inherited styles, but right now - // none of the parents has updatable styles - m_windowStyle = styles; - m_dirty = TRUE; -} - -//----------------------------------------------------------------------------- -// functions to work with tree items -//----------------------------------------------------------------------------- - -inline -int wxTreeListMainWindow::GetItemImage(const wxTreeItemId& item, size_t column, - wxTreeItemIcon which) const -{ - wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->GetImage(column, which); -} - -inline -wxTreeItemData *wxTreeListMainWindow::GetItemData(const wxTreeItemId& item) - const -{ - wxCHECK_MSG( item.IsOk(), NULL, wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->GetData(); -} - -inline -bool wxTreeListMainWindow::GetItemBold(const wxTreeItemId& item) const -{ - wxCHECK_MSG(item.IsOk(), FALSE, wxT("invalid tree item")); - return ((wxTreeListItem *)item.m_pItem)->IsBold(); -} - -inline -wxColour wxTreeListMainWindow::GetItemTextColour(const wxTreeItemId& item) - const -{ - wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - return pItem->Attr().GetTextColour(); -} - -inline -wxColour wxTreeListMainWindow::GetItemBackgroundColour( - const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - return pItem->Attr().GetBackgroundColour(); -} - -inline -wxFont wxTreeListMainWindow::GetItemFont(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxNullFont, wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - return pItem->Attr().GetFont(); -} - - - -inline -void wxTreeListMainWindow::SetItemImage(const wxTreeItemId& item, - size_t column, - int image, wxTreeItemIcon which) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - pItem->SetImage(column, image, which); - - wxClientDC dc(this); - CalculateSize(pItem, dc); - RefreshLine(pItem); -} - -inline -void wxTreeListMainWindow::SetItemData(const wxTreeItemId& item, - wxTreeItemData *data) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - ((wxTreeListItem*) item.m_pItem)->SetData(data); -} - -inline -void wxTreeListMainWindow::SetItemHasChildren(const wxTreeItemId& item, - bool has) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - pItem->SetHasPlus(has); - RefreshLine(pItem); -} - -inline -void wxTreeListMainWindow::SetItemBold(const wxTreeItemId& item, bool bold) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - // avoid redrawing the tree if no real change - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - if ( pItem->IsBold() != bold ) - { - pItem->SetBold(bold); - RefreshLine(pItem); - } -} - -inline -void wxTreeListMainWindow::SetItemTextColour(const wxTreeItemId& item, - const wxColour& col) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - pItem->Attr().SetTextColour(col); - RefreshLine(pItem); -} - -inline -void wxTreeListMainWindow::SetItemBackgroundColour(const wxTreeItemId& item, - const wxColour& col) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - pItem->Attr().SetBackgroundColour(col); - RefreshLine(pItem); -} - -inline -void wxTreeListMainWindow::SetItemFont(const wxTreeItemId& item, - const wxFont& font) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - pItem->Attr().SetFont(font); - RefreshLine(pItem); -} - -inline -bool wxTreeListMainWindow::SetFont( const wxFont &font ) -{ - wxScrolledWindow::SetFont(font); - - m_normalFont = font ; - m_boldFont = wxFont( m_normalFont.GetPointSize(), - m_normalFont.GetFamily(), - m_normalFont.GetStyle(), - wxBOLD, - m_normalFont.GetUnderlined()); - - return TRUE; -} - - -// ---------------------------------------------------------------------------- -// item status inquiries -// ---------------------------------------------------------------------------- - -inline -bool wxTreeListMainWindow::IsVisible(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); - - // An item is only visible if it's not a descendant of a collapsed item - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - wxTreeListItem* parent = pItem->GetParent(); - while (parent) - { - if (!parent->IsExpanded()) - return FALSE; - parent = parent->GetParent(); - } - - int startX, startY; - GetViewStart(& startX, & startY); - - wxSize clientSize = GetClientSize(); - - wxRect rect; - if (!GetBoundingRect(item, rect)) - return FALSE; - if (rect.GetWidth() == 0 || rect.GetHeight() == 0) - return FALSE; - if (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y) - return FALSE; - if (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x) - return FALSE; - - return TRUE; -} - -inline -bool wxTreeListMainWindow::ItemHasChildren(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); - - // consider that the item does have children if it has the "+" button: it - // might not have them (if it had never been expanded yet) but then it - // could have them as well and it's better to err on this side rather than - // disabling some operations which are restricted to the items with - // children for an item which does have them - return ((wxTreeListItem*) item.m_pItem)->HasPlus(); -} - -inline -bool wxTreeListMainWindow::IsExpanded(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->IsExpanded(); -} - -inline -bool wxTreeListMainWindow::IsSelected(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->IsSelected(); -} - -inline -bool wxTreeListMainWindow::IsBold(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->IsBold(); -} - -// ---------------------------------------------------------------------------- -// navigation -// ---------------------------------------------------------------------------- - -inline -wxTreeItemId wxTreeListMainWindow::GetParent(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->GetParent(); -} - -inline -wxTreeItemId wxTreeListMainWindow::GetFirstChild(const wxTreeItemId& item, - long& cookie) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - cookie = 0; - return GetNextChild(item, cookie); -} - -inline -wxTreeItemId wxTreeListMainWindow::GetNextChild(const wxTreeItemId& item, - long& cookie) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxArrayTreeListItems& children = ((wxTreeListItem*) - item.m_pItem)->GetChildren(); - if ( (size_t)cookie < children.Count() ) - { - return children.Item((size_t)cookie++); - } - else - { - // there are no more of them - return wxTreeItemId(); - } -} - -inline -wxTreeItemId wxTreeListMainWindow::GetLastChild(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren(); - return (children.IsEmpty() ? wxTreeItemId() : wxTreeItemId(children.Last())); -} - -inline -wxTreeItemId wxTreeListMainWindow::GetNextSibling(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; - wxTreeListItem *parent = i->GetParent(); - if ( parent == NULL ) - { - // root item doesn't have any siblings - return wxTreeItemId(); - } - - wxArrayTreeListItems& siblings = parent->GetChildren(); - int index = siblings.Index(i); - wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? - - size_t n = (size_t)(index + 1); - return n == siblings.Count() ? wxTreeItemId() : wxTreeItemId(siblings[n]); -} - -inline -wxTreeItemId wxTreeListMainWindow::GetPrevSibling(const wxTreeItemId& item) - const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; - wxTreeListItem *parent = i->GetParent(); - if ( parent == NULL ) - { - // root item doesn't have any siblings - return wxTreeItemId(); - } - - wxArrayTreeListItems& siblings = parent->GetChildren(); - int index = siblings.Index(i); - wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? - - return index == 0 ? wxTreeItemId() - : wxTreeItemId(siblings[(size_t)(index - 1)]); -} - -// Only for internal use right now, but should probably be public -wxTreeItemId wxTreeListMainWindow::GetNext(const wxTreeItemId& item) const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; - - // First see if there are any children. - wxArrayTreeListItems& children = i->GetChildren(); - if (children.GetCount() > 0) - { - return children.Item(0); - } - else - { - // Try a sibling of this or ancestor instead - wxTreeItemId p = item; - wxTreeItemId toFind; - do - { - toFind = GetNextSibling(p); - p = GetParent(p); - } while (p.IsOk() && !toFind.IsOk()); - return toFind; - } -} - -inline -wxTreeItemId wxTreeListMainWindow::GetFirstVisibleItem() const -{ - wxTreeItemId id = GetRootItem(); - if (!id.IsOk()) - return id; - - do - { - if (IsVisible(id)) - return id; - id = GetNext(id); - } while (id.IsOk()); - - return wxTreeItemId(); -} - -inline -wxTreeItemId wxTreeListMainWindow::GetNextVisible(const wxTreeItemId& item) - const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxTreeItemId id = item; - if (id.IsOk()) - { - while (id = GetNext(id), id.IsOk()) - { - if (IsVisible(id)) - return id; - } - } - return wxTreeItemId(); -} - -inline -wxTreeItemId wxTreeListMainWindow::GetPrevVisible(const wxTreeItemId& item) - const -{ - wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); - - wxFAIL_MSG(wxT("not implemented")); - - return wxTreeItemId(); -} - -// ---------------------------------------------------------------------------- -// operations -// ---------------------------------------------------------------------------- - -wxTreeItemId wxTreeListMainWindow::DoInsertItem(const wxTreeItemId& parentId, - size_t previous, - const wxString& text, - int image, int selImage, - wxTreeItemData *data) -{ - wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; - if ( !parent ) - { - // should we give a warning here? - return AddRoot(text, image, selImage, data); - } - - m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - - // ALB - wxArrayString arr; - arr.Alloc(GetColumnCount()); - for(size_t i = 0; i < GetColumnCount(); ++i) { - arr.Add(wxEmptyString); - } - arr[m_main_column] = text; - wxTreeListItem *item = - new wxTreeListItem( this, parent, arr, image, selImage, data ); - - if ( data != NULL ) - { - data->SetId((long)item); - } - - parent->Insert( item, previous ); - - return item; -} - -wxTreeItemId wxTreeListMainWindow::AddRoot(const wxString& text, - int image, int selImage, - wxTreeItemData *data) -{ - wxCHECK_MSG(!m_anchor, wxTreeItemId(), wxT("tree can have only one root")); - wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), wxT("Add column(s) before adding the root item")); - - m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - - // ALB - wxArrayString arr; - arr.Alloc(GetColumnCount()); - for(size_t i = 0; i < GetColumnCount(); ++i) { - arr.Add(wxEmptyString); - } - arr[m_main_column] = text; - m_anchor = new wxTreeListItem( this, (wxTreeListItem *)NULL, arr, - image, selImage, data); - if (HasFlag(wxTR_HIDE_ROOT)) - { - // if root is hidden, make sure we can navigate - // into children - m_anchor->SetHasPlus(); - Expand(m_anchor); - } - if ( data != NULL ) - { - data->SetId((long)m_anchor); - } - - if (!HasFlag(wxTR_MULTIPLE)) - { - m_current = m_key_current = m_anchor; - m_current->SetHilight( TRUE ); - } - - return m_anchor; -} - -inline -wxTreeItemId wxTreeListMainWindow::PrependItem(const wxTreeItemId& parent, - const wxString& text, - int image, int selImage, - wxTreeItemData *data) -{ - return DoInsertItem(parent, 0u, text, image, selImage, data); -} - -inline -wxTreeItemId wxTreeListMainWindow::InsertItem(const wxTreeItemId& parentId, - const wxTreeItemId& idPrevious, - const wxString& text, - int image, int selImage, - wxTreeItemData *data) -{ - wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; - if ( !parent ) - { - // should we give a warning here? - return AddRoot(text, image, selImage, data); - } - - int index = parent->GetChildren().Index((wxTreeListItem*) idPrevious.m_pItem); - wxASSERT_MSG( index != wxNOT_FOUND, - wxT("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") ); - - return DoInsertItem(parentId, (size_t)++index, text, image, selImage, data); -} - -inline -wxTreeItemId wxTreeListMainWindow::InsertItem(const wxTreeItemId& parentId, - size_t before, - const wxString& text, - int image, int selImage, - wxTreeItemData *data) -{ - wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; - if ( !parent ) - { - // should we give a warning here? - return AddRoot(text, image, selImage, data); - } - - return DoInsertItem(parentId, before, text, image, selImage, data); -} - -inline -wxTreeItemId wxTreeListMainWindow::AppendItem(const wxTreeItemId& parentId, - const wxString& text, - int image, int selImage, - wxTreeItemData *data) -{ - wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; - if ( !parent ) - { - // should we give a warning here? - return AddRoot(text, image, selImage, data); - } - - return DoInsertItem( parent, parent->GetChildren().Count(), text, - image, selImage, data); -} - -void wxTreeListMainWindow::SendDeleteEvent(wxTreeListItem *item) -{ - wxTreeEvent event( wxEVT_COMMAND_TREE_DELETE_ITEM, m_owner->GetId() ); - event.SetItem((long) item); - event.SetEventObject( /*this*/m_owner ); - m_owner->ProcessEvent( event ); -} - -// inline -// void wxTreeListMainWindow::DeleteChildren(const wxTreeItemId& itemId) -// { -// m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - -// wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; -// item->DeleteChildren(this); -// } - -// inline -// void wxTreeListMainWindow::Delete(const wxTreeItemId& itemId) -// { -// m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - -// wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - -// // don't stay with invalid m_key_current or we will crash in -// // the next call to OnChar() -// bool changeKeyCurrent = FALSE; -// wxTreeListItem *itemKey = m_key_current; -// while ( itemKey ) -// { -// if ( itemKey == item ) -// { -// // m_key_current is a descendant of the item being deleted -// changeKeyCurrent = TRUE; -// break; -// } -// itemKey = itemKey->GetParent(); -// } - -// wxTreeListItem *parent = item->GetParent(); -// if ( parent ) -// { -// parent->GetChildren().Remove( item ); // remove by value -// } - -// if ( changeKeyCurrent ) -// { -// // may be NULL or not -// m_key_current = parent; -// } - -// item->DeleteChildren(this); -// SendDeleteEvent(item); -// delete item; -// } - -// inline -// void wxTreeListMainWindow::DeleteAllItems() -// { -// if ( m_anchor ) -// { -// m_dirty = TRUE; - -// m_anchor->DeleteChildren(this); -// delete m_anchor; - -// m_anchor = NULL; -// } -// } - - -inline -void wxTreeListMainWindow::DeleteChildren(const wxTreeItemId& itemId) -{ - m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - // mst:16.10.03 - // moved from Delete() - // don't stay with invalid m_key_current or we will crash in - // the next call to OnChar() - wxTreeListItem *itemKey = m_key_current; - while ( itemKey ) - { - if ( itemKey == item ) - { - // m_key_current is a descendant of the item which childrens being deleted - m_key_current = item; - break; - } - itemKey = itemKey->GetParent(); - } - - item->DeleteChildren(this); -} - -inline -void wxTreeListMainWindow::Delete(const wxTreeItemId& itemId) -{ - m_dirty = TRUE; // do this first so stuff below doesn't cause flicker - - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - // mst:16.10.03 - item->DeleteChildren(this); - - wxTreeListItem *parent = item->GetParent(); - - if ( parent ) - parent->GetChildren().Remove( item ); // remove by value - - if (m_key_current == item) - m_key_current = parent; - - SendDeleteEvent(item); - - delete item; -} - -inline -void wxTreeListMainWindow::DeleteAllItems() -{ - if ( m_anchor ) - { - m_dirty = TRUE; - - m_key_current = NULL; // mst:16.10.03 - - m_anchor->DeleteChildren(this); - delete m_anchor; - - m_anchor = NULL; - } -} - - -void wxTreeListMainWindow::Expand(const wxTreeItemId& itemId) -{ - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - wxCHECK_RET( item, _T("invalid item in wxTreeListMainWindow::Expand") ); - - if ( !item->HasPlus() ) - return; - - if ( item->IsExpanded() ) - return; - - wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, m_owner->GetId() ); - event.SetItem( (long) item ); - event.SetEventObject( /*this*/m_owner ); - - if ( m_owner->ProcessEvent( event ) && !event.IsAllowed() ) - { - // cancelled by program - return; - } - - item->Expand(); - CalculatePositions(); - - RefreshSubtree(item); - - event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); - ProcessEvent( event ); -} - -void wxTreeListMainWindow::ExpandAll(const wxTreeItemId& item) -{ - Expand(item); - if ( IsExpanded(item) ) - { - long cookie; - wxTreeItemId child = GetFirstChild(item, cookie); - while ( child.IsOk() ) - { - ExpandAll(child); - - child = GetNextChild(item, cookie); - } - } -} - -void wxTreeListMainWindow::Collapse(const wxTreeItemId& itemId) -{ - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - if ( !item->IsExpanded() ) - return; - - wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, m_owner->GetId() ); - event.SetItem( (long) item ); - event.SetEventObject( /*this*/m_owner ); - if ( m_owner->ProcessEvent( event ) && !event.IsAllowed() ) - { - // cancelled by program - return; - } - - item->Collapse(); - -#if 0 // TODO why should items be collapsed recursively? - wxArrayTreeListItems& children = item->GetChildren(); - size_t count = children.Count(); - for ( size_t n = 0; n < count; n++ ) - { - Collapse(children[n]); - } -#endif - - CalculatePositions(); - - RefreshSubtree(item); - - event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED); - ProcessEvent( event ); -} - -void wxTreeListMainWindow::CollapseAndReset(const wxTreeItemId& item) -{ - Collapse(item); - DeleteChildren(item); -} - -void wxTreeListMainWindow::Toggle(const wxTreeItemId& itemId) -{ - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - if (item->IsExpanded()) - Collapse(itemId); - else - Expand(itemId); -} - -void wxTreeListMainWindow::Unselect() -{ - if (m_current) - { - m_current->SetHilight( FALSE ); - RefreshLine( m_current ); - } -} - -void wxTreeListMainWindow::UnselectAllChildren(wxTreeListItem *item) -{ - if (item->IsSelected()) - { - item->SetHilight(FALSE); - RefreshLine(item); - } - - if (item->HasChildren()) - { - wxArrayTreeListItems& children = item->GetChildren(); - size_t count = children.Count(); - for ( size_t n = 0; n < count; ++n ) - { - UnselectAllChildren(children[n]); - } - } -} - -void wxTreeListMainWindow::UnselectAll() -{ - UnselectAllChildren((wxTreeListItem*) GetRootItem().m_pItem); -} - -// Recursive function ! -// To stop we must have crt_itemGetParent(); - - if (parent == NULL) // This is root item - return TagAllChildrenUntilLast(crt_item, last_item, select); - - wxArrayTreeListItems& children = parent->GetChildren(); - int index = children.Index(crt_item); - wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? - - size_t count = children.Count(); - for (size_t n=(size_t)(index+1); nSetHilight(select); - RefreshLine(crt_item); - - if (crt_item==last_item) - return TRUE; - - if (crt_item->HasChildren()) - { - wxArrayTreeListItems& children = crt_item->GetChildren(); - size_t count = children.Count(); - for ( size_t n = 0; n < count; ++n ) - { - if (TagAllChildrenUntilLast(children[n], last_item, select)) - return TRUE; - } - } - - return FALSE; -} - -void wxTreeListMainWindow::SelectItemRange(wxTreeListItem *item1, wxTreeListItem *item2) -{ - // item2 is not necessary after item1 - wxTreeListItem *first=NULL, *last=NULL; - - // choice first' and 'last' between item1 and item2 - if (item1->GetY()GetY()) - { - first=item1; - last=item2; - } - else - { - first=item2; - last=item1; - } - - bool select = m_current->IsSelected(); - - if ( TagAllChildrenUntilLast(first,last,select) ) - return; - - TagNextChildren(first,last,select); -} - -void wxTreeListMainWindow::SelectItem(const wxTreeItemId& itemId, - bool unselect_others, - bool extended_select) -{ - wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") ); - - bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE); - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - //wxCHECK_RET( ( (!unselect_others) && is_single), - // wxT("this is a single selection tree") ); - - // to keep going anyhow !!! - if (is_single) - { - if (item->IsSelected()) - return; // nothing to do - unselect_others = TRUE; - extended_select = FALSE; - } - else if ( unselect_others && item->IsSelected() ) - { - // selection change if there is more than one item currently selected - wxArrayTreeItemIds selected_items; - if ( GetSelections(selected_items) == 1 ) - return; - } - - wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() ); - event.SetItem( (long) item ); - event.SetOldItem( (long) m_current ); - event.SetEventObject( /*this*/m_owner ); - // TODO : Here we don't send any selection mode yet ! - - if(m_owner->GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed()) - return; - - wxTreeItemId parent = GetParent( itemId ); - while (parent.IsOk()) - { - if (!IsExpanded(parent)) - Expand( parent ); - - parent = GetParent( parent ); - } - - EnsureVisible( itemId ); - - // ctrl press - if (unselect_others) - { - if (is_single) Unselect(); // to speed up thing - else UnselectAll(); - } - - // shift press - if (extended_select) - { - if ( !m_current ) - { - m_current = m_key_current = (wxTreeListItem*) GetRootItem().m_pItem; - } - - // don't change the mark (m_current) - SelectItemRange(m_current, item); - } - else - { - bool select=TRUE; // the default - - // Check if we need to toggle hilight (ctrl mode) - if (!unselect_others) - select=!item->IsSelected(); - - m_current = m_key_current = item; - m_current->SetHilight(select); - RefreshLine( m_current ); - } - - event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); - GetEventHandler()->ProcessEvent( event ); -} - -void wxTreeListMainWindow::FillArray(wxTreeListItem *item, - wxArrayTreeItemIds &array) const -{ - if ( item->IsSelected() ) - array.Add(wxTreeItemId(item)); - - if ( item->HasChildren() ) - { - wxArrayTreeListItems& children = item->GetChildren(); - size_t count = children.GetCount(); - for ( size_t n = 0; n < count; ++n ) - FillArray(children[n], array); - } -} - -size_t wxTreeListMainWindow::GetSelections(wxArrayTreeItemIds &array) const -{ - array.Empty(); - wxTreeItemId idRoot = GetRootItem(); - if ( idRoot.IsOk() ) - { - FillArray((wxTreeListItem*) idRoot.m_pItem, array); - } - //else: the tree is empty, so no selections - - return array.Count(); -} - -void wxTreeListMainWindow::EnsureVisible(const wxTreeItemId& item) -{ - if (!item.IsOk()) return; - - wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem; - - // first expand all parent branches - wxTreeListItem *parent = gitem->GetParent(); - while ( parent ) - { - Expand(parent); - parent = parent->GetParent(); - } - - //if (parent) CalculatePositions(); - - ScrollTo(item); -} - -void wxTreeListMainWindow::ScrollTo(const wxTreeItemId &item) -{ - if (!item.IsOk()) return; - - // We have to call this here because the label in - // question might just have been added and no screen - // update taken place. - if (m_dirty) wxYieldIfNeeded(); - - wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem; - - // now scroll to the item - int item_y = gitem->GetY(); - - int start_x = 0; - int start_y = 0; - GetViewStart( &start_x, &start_y ); - start_y *= PIXELS_PER_UNIT; - - int client_h = 0; - int client_w = 0; - GetClientSize( &client_w, &client_h ); - - if (item_y < start_y+3) - { - // going down - int x = 0; - int y = 0; - m_anchor->GetSize( x, y, this ); - x = m_owner->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB - y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels - //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels - int x_pos = GetScrollPos( wxHORIZONTAL ); - // Item should appear at top - SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, item_y/PIXELS_PER_UNIT ); - } - else if (item_y+GetLineHeight(gitem) > start_y+client_h) - { - // going up - int x = 0; - int y = 0; - m_anchor->GetSize( x, y, this ); - y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels - //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels - x = m_owner->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB - item_y += PIXELS_PER_UNIT+2; - int x_pos = GetScrollPos( wxHORIZONTAL ); - // Item should appear at bottom - SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, (item_y+GetLineHeight(gitem)-client_h)/PIXELS_PER_UNIT ); - } -} - -// FIXME: tree sorting functions are not reentrant and not MT-safe! -static wxTreeListMainWindow *s_treeBeingSorted = NULL; - -static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem **item1, - wxTreeListItem **item2) -{ - wxCHECK_MSG( s_treeBeingSorted, 0, wxT("bug in wxTreeListMainWindow::SortChildren()") ); - - return s_treeBeingSorted->OnCompareItems(*item1, *item2); -} - -int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId& item1, - const wxTreeItemId& item2) -{ - // ALB: delegate to m_owner, to let the user overrride the comparison - //return wxStrcmp(GetItemText(item1), GetItemText(item2)); - return m_owner->OnCompareItems(item1, item2); -} - -void wxTreeListMainWindow::SortChildren(const wxTreeItemId& itemId) -{ - wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") ); - - wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; - - wxCHECK_RET( !s_treeBeingSorted, - wxT("wxTreeListMainWindow::SortChildren is not reentrant") ); - - wxArrayTreeListItems& children = item->GetChildren(); - if ( children.Count() > 1 ) - { - m_dirty = TRUE; - - s_treeBeingSorted = this; - children.Sort(tree_ctrl_compare_func); - s_treeBeingSorted = NULL; - } - //else: don't make the tree dirty as nothing changed -} - -inline -wxImageList *wxTreeListMainWindow::GetImageList() const -{ - return m_imageListNormal; -} - -inline -wxImageList *wxTreeListMainWindow::GetButtonsImageList() const -{ - return m_imageListButtons; -} - -inline -wxImageList *wxTreeListMainWindow::GetStateImageList() const -{ - return m_imageListState; -} - -void wxTreeListMainWindow::CalculateLineHeight() -{ - wxClientDC dc(this); - m_lineHeight = (int)(dc.GetCharHeight() + m_linespacing*2); - - if ( m_imageListNormal ) - { - // Calculate a m_lineHeight value from the normal Image sizes. - // May be toggle off. Then wxTreeListMainWindow will spread when - // necessary (which might look ugly). - int n = m_imageListNormal->GetImageCount(); - for (int i = 0; i < n ; i++) - { - int width = 0, height = 0; - m_imageListNormal->GetSize(i, width, height); - if (height > m_lineHeight) m_lineHeight = height; - } - } - - if (m_imageListButtons) - { - // Calculate a m_lineHeight value from the Button image sizes. - // May be toggle off. Then wxTreeListMainWindow will spread when - // necessary (which might look ugly). - int n = m_imageListButtons->GetImageCount(); - for (int i = 0; i < n ; i++) - { - int width = 0, height = 0; - m_imageListButtons->GetSize(i, width, height); - if (height > m_lineHeight) m_lineHeight = height; - } - } - - if (m_lineHeight < 30) - m_lineHeight += 2; // at least 2 pixels - else - m_lineHeight += m_lineHeight/10; // otherwise 10% extra spacing -} - -inline -void wxTreeListMainWindow::SetImageList(wxImageList *imageList) -{ - if (m_ownsImageListNormal) delete m_imageListNormal; - m_imageListNormal = imageList; - m_ownsImageListNormal = FALSE; - m_dirty = TRUE; - CalculateLineHeight(); -} - -inline -void wxTreeListMainWindow::SetStateImageList(wxImageList *imageList) -{ - if (m_ownsImageListState) delete m_imageListState; - m_imageListState = imageList; - m_ownsImageListState = FALSE; -} - -inline -void wxTreeListMainWindow::SetButtonsImageList(wxImageList *imageList) -{ - if (m_ownsImageListButtons) delete m_imageListButtons; - m_imageListButtons = imageList; - m_ownsImageListButtons = FALSE; - m_dirty = TRUE; - CalculateLineHeight(); -} - -inline -void wxTreeListMainWindow::AssignImageList(wxImageList *imageList) -{ - SetImageList(imageList); - m_ownsImageListNormal = TRUE; -} - -inline -void wxTreeListMainWindow::AssignStateImageList(wxImageList *imageList) -{ - SetStateImageList(imageList); - m_ownsImageListState = TRUE; -} - -inline -void wxTreeListMainWindow::AssignButtonsImageList(wxImageList *imageList) -{ - SetButtonsImageList(imageList); - m_ownsImageListButtons = TRUE; -} - -// ---------------------------------------------------------------------------- -// helpers -// ---------------------------------------------------------------------------- - -void wxTreeListMainWindow::AdjustMyScrollbars() -{ - if (m_anchor) - { - int x = 0, y = 0; - m_anchor->GetSize( x, y, this ); - y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels - //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels - int x_pos = GetScrollPos( wxHORIZONTAL ); - int y_pos = GetScrollPos( wxVERTICAL ); - x = m_owner->GetHeaderWindow()->GetWidth() + 2; - if(x < GetClientSize().GetWidth()) x_pos = 0; - //m_total_col_width + 2; // ALB - SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, - y/PIXELS_PER_UNIT, x_pos, y_pos ); - } - else - { - SetScrollbars( 0, 0, 0, 0 ); - } -} - -int wxTreeListMainWindow::GetLineHeight(wxTreeListItem *item) const -{ - if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT) - return item->GetHeight(); - else - return m_lineHeight; -} - -void wxTreeListMainWindow::PaintItem(wxTreeListItem *item, wxDC& dc) -{ - // TODO implement "state" icon on items - - wxTreeItemAttr *attr = item->GetAttributes(); - if ( attr && attr->HasFont() ) - dc.SetFont(attr->GetFont()); - else if (item->IsBold()) - dc.SetFont(m_boldFont); - - long text_w = 0, text_h = 0; - - dc.GetTextExtent( item->GetText(GetMainColumn()), &text_w, &text_h ); - - int total_h = GetLineHeight(item); - - if ( item->IsSelected() ) - { - dc.SetBrush(*(m_hasFocus ? m_hilightBrush : m_hilightUnfocusedBrush)); - } - else - { - wxColour colBg; - if ( attr && attr->HasBackgroundColour() ) - colBg = attr->GetBackgroundColour(); - else - colBg = m_backgroundColour; - dc.SetBrush(wxBrush(colBg, wxSOLID)); - } - - int offset = HasFlag(wxTR_ROW_LINES) ? 1 : 0; - - dc.DrawRectangle(0, item->GetY()+offset, - m_owner->GetHeaderWindow()->GetWidth(), - total_h-offset); - - dc.SetBackgroundMode(wxTRANSPARENT); - int extraH = (total_h > text_h) ? (total_h - text_h)/2 : 0; - int extra_offset = 0; - for(size_t i = 0; i < GetColumnCount(); ++i) { - int coord_x = extra_offset, image_x = coord_x; - int clip_width = m_owner->GetHeaderWindow()->GetColumnWidth(i); - int image_h = 0, image_w = 0; //2; - int image = NO_IMAGE; - - if(i == GetMainColumn()) { - image = item->GetCurrentImage(); - coord_x = item->GetX(); - } - else { - image = item->GetImage(i); - } - - if(image != NO_IMAGE) { - if(m_imageListNormal) { - m_imageListNormal->GetSize( image, image_w, image_h ); - image_w += 4; - } - else { - image = NO_IMAGE; - } - } - - // honor text alignment - wxString text = item->GetText(i); - - switch(m_owner->GetHeaderWindow()->GetColumn(i).GetAlignment()) { - case wxTL_ALIGN_LEFT: - coord_x += image_w + 2; - image_x = coord_x - image_w; - break; - case wxTL_ALIGN_RIGHT: - dc.GetTextExtent(text, &text_w, NULL); - coord_x += clip_width - text_w - image_w - 2; - image_x = coord_x - image_w; - break; - case wxTL_ALIGN_CENTER: - dc.GetTextExtent(text, &text_w, NULL); - //coord_x += (clip_width - text_w)/2 + image_w; - image_x += (clip_width - text_w - image_w)/2 + 2; - coord_x = image_x + image_w; - } - - wxDCClipper clipper(dc, /*coord_x,*/ extra_offset, - item->GetY(), clip_width, - total_h); - - if(image != NO_IMAGE) { - m_imageListNormal->Draw( image, dc, image_x, - item->GetY() +((total_h > image_h)? - ((total_h-image_h)/2):0), - wxIMAGELIST_DRAW_TRANSPARENT ); - } - - dc.DrawText( text, - (wxCoord)(coord_x /*image_w + item->GetX()*/), - (wxCoord)(item->GetY() + extraH)); - extra_offset += m_owner->GetHeaderWindow()->GetColumnWidth(i); - } - - // restore normal font - dc.SetFont( m_normalFont ); -} - -// Now y stands for the top of the item, whereas it used to stand for middle ! -void wxTreeListMainWindow::PaintLevel( wxTreeListItem *item, wxDC &dc, - int level, int &y, int x_offset ) -{ - int x = level*m_indent + x_offset; - if (!HasFlag(wxTR_HIDE_ROOT)) - { - x += m_indent; - } - else if (level == 0) - { - // always expand hidden root - int origY = y; - wxArrayTreeListItems& children = item->GetChildren(); - int count = children.Count(); - if (count > 0) - { - int n = 0, oldY; - do { - oldY = y; - PaintLevel(children[n], dc, 1, y, x_offset); - } while (++n < count); - - if (!HasFlag(wxTR_NO_LINES) && HasFlag(wxTR_LINES_AT_ROOT) && - count > 0) - { - // draw line down to last child - origY += GetLineHeight(children[0])>>1; - oldY += GetLineHeight(children[n-1])>>1; - dc.DrawLine(3, origY, 3, oldY); - } - } - return; - } - - item->SetX(x+m_spacing); - item->SetY(y); - - int h = GetLineHeight(item); - int y_top = y; - int y_mid = y_top + (h>>1); - y += h; - - int exposed_x = dc.LogicalToDeviceX(0); - int exposed_y = dc.LogicalToDeviceY(y_top); - - if (IsExposed(exposed_x, exposed_y, 10000, h)) // 10000 = very much - { - wxPen *pen = -#ifndef __WXMAC__ - // don't draw rect outline if we already have the - // background color under Mac - (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN : -#endif // !__WXMAC__ - wxTRANSPARENT_PEN; - - wxColour colText; - if ( item->IsSelected() ) - { - colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); - } - else - { - wxTreeItemAttr *attr = item->GetAttributes(); - if (attr && attr->HasTextColour()) - colText = attr->GetTextColour(); - else - //colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT); - colText = GetForegroundColour(); - } - - // prepare to draw - dc.SetTextForeground(colText); - dc.SetPen(*pen); - - // draw - PaintItem(item, dc); - - if (HasFlag(wxTR_ROW_LINES)) - { - int total_width = m_owner->GetHeaderWindow()->GetWidth(); - // if the background colour is white, choose a - // contrasting color for the lines - dc.SetPen(*((GetBackgroundColour() == *wxWHITE) - ? wxMEDIUM_GREY_PEN : wxWHITE_PEN)); - dc.DrawLine(0, y_top, total_width, y_top); - dc.DrawLine(0, y, total_width, y); - } - - // restore DC objects - dc.SetBrush(*wxWHITE_BRUSH); - dc.SetPen(m_dottedPen); - dc.SetTextForeground(*wxBLACK); - - size_t clip_width = m_owner->GetHeaderWindow()->GetColumn( - m_main_column).GetWidth(); - //m_columns[m_main_column].GetWidth(); - if (item->HasPlus() && HasButtons()) // should the item show a button? - { - // clip to the column width - wxDCClipper clipper(dc, x_offset, y_top, clip_width, 10000); - - if (!HasFlag(wxTR_NO_LINES)) - { - if (x > (signed)m_indent) - dc.DrawLine(x - m_indent, y_mid, x - 5, y_mid); - else if (HasFlag(wxTR_LINES_AT_ROOT)) - dc.DrawLine(3, y_mid, x - 5, y_mid); - dc.DrawLine(x + 5, y_mid, x + m_spacing, y_mid); - } - - if (m_imageListButtons != NULL) - { - // draw the image button here - int image_h = 0, image_w = 0, image = wxTreeItemIcon_Normal; - if (item->IsExpanded()) image = wxTreeItemIcon_Expanded; - if (item->IsSelected()) - image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal; - m_imageListButtons->GetSize(image, image_w, image_h); - int xx = x - (image_w>>1); - int yy = y_mid - (image_h>>1); - dc.SetClippingRegion(xx, yy, image_w, image_h); - m_imageListButtons->Draw(image, dc, xx, yy, - wxIMAGELIST_DRAW_TRANSPARENT); - dc.DestroyClippingRegion(); - } - else if (HasFlag(wxTR_TWIST_BUTTONS)) - { - // draw the twisty button here - dc.SetPen(*wxBLACK_PEN); - dc.SetBrush(*m_hilightBrush); - - wxPoint button[3]; - - if (item->IsExpanded()) - { - button[0].x = x-5; - button[0].y = y_mid-2; - button[1].x = x+5; - button[1].y = y_mid-2; - button[2].x = x; - button[2].y = y_mid+3; - } - else - { - button[0].y = y_mid-5; - button[0].x = x-2; - button[1].y = y_mid+5; - button[1].x = x-2; - button[2].y = y_mid; - button[2].x = x+3; - } - dc.DrawPolygon(3, button); - - dc.SetPen(m_dottedPen); - } - else // if (HasFlag(wxTR_HAS_BUTTONS)) - { - // draw the plus sign here - dc.SetPen(*wxGREY_PEN); - dc.SetBrush(*wxWHITE_BRUSH); - dc.DrawRectangle(x-5, y_mid-4, 11, 9); - dc.SetPen(*wxBLACK_PEN); - dc.DrawLine(x-2, y_mid, x+3, y_mid); - if (!item->IsExpanded()) - dc.DrawLine(x, y_mid-2, x, y_mid+3); - dc.SetPen(m_dottedPen); - } - } - else if (!HasFlag(wxTR_NO_LINES)) // no button; maybe a line? - { - // clip to the column width - wxDCClipper clipper(dc, x_offset, y_top, clip_width, 10000); - // draw the horizontal line here - int x_start = x; - if (x > (signed)m_indent) - x_start -= m_indent; - else if (HasFlag(wxTR_LINES_AT_ROOT)) - x_start = 3; - dc.DrawLine(x_start, y_mid, x + m_spacing, y_mid); - } - } - - if (item->IsExpanded()) - { - wxArrayTreeListItems& children = item->GetChildren(); - int count = children.Count(); - if (count > 0) - { - int n = 0, oldY; - ++level; - do { - oldY = y; - PaintLevel(children[n], dc, level, y, x_offset); - } while (++n < count); - - if (!HasFlag(wxTR_NO_LINES) && count > 0) - { - size_t clip_width = m_owner->GetHeaderWindow()->GetColumn( - m_main_column).GetWidth(); - //m_columns[m_main_column].GetWidth(); - // clip to the column width - wxDCClipper clipper(dc, x_offset, y_top, clip_width, 10000); - // draw line down to last child - oldY += GetLineHeight(children[n-1])>>1; - if (HasButtons()) y_mid += 5; - dc.DrawLine(x, y_mid, x, oldY); - } - } - } -} - -void wxTreeListMainWindow::DrawDropEffect(wxTreeListItem *item) -{ - if ( item ) - { - if ( item->HasPlus() ) - { - // it's a folder, indicate it by a border - DrawBorder(item); - } - else - { - // draw a line under the drop target because the item will be - // dropped there - DrawLine(item, TRUE /* below */); - } - - SetCursor(wxCURSOR_BULLSEYE); - } - else - { - // can't drop here - SetCursor(wxCURSOR_NO_ENTRY); - } -} - -void wxTreeListMainWindow::DrawBorder(const wxTreeItemId &item) -{ - wxCHECK_RET( item.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); - - wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; - - wxClientDC dc(this); - PrepareDC( dc ); - dc.SetLogicalFunction(wxINVERT); - dc.SetBrush(*wxTRANSPARENT_BRUSH); - - int w = i->GetWidth() + 2; - int h = GetLineHeight(i) + 2; - - dc.DrawRectangle( i->GetX() - 1, i->GetY() - 1, w, h); -} - -void wxTreeListMainWindow::DrawLine(const wxTreeItemId &item, bool below) -{ - wxCHECK_RET( item.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); - - wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; - - wxClientDC dc(this); - PrepareDC( dc ); - dc.SetLogicalFunction(wxINVERT); - - int x = i->GetX(), - y = i->GetY(); - if ( below ) - { - y += GetLineHeight(i) - 1; - } - - dc.DrawLine( x, y, x + i->GetWidth(), y); -} - -// ---------------------------------------------------------------------------- -// wxWindows callbacks -// ---------------------------------------------------------------------------- - -void wxTreeListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) -{ - wxPaintDC dc(this); - - PrepareDC( dc ); - - if(!GetColumnCount()) return; // ALB - - if ( !m_anchor) - return; - - dc.SetFont( m_normalFont ); - dc.SetPen( m_dottedPen ); - - // this is now done dynamically - //if(GetImageList() == NULL) - // m_lineHeight = (int)(dc.GetCharHeight() + 4); - - int y = 0; //HEADER_HEIGHT; //2; - int x_offset = 0; - for(size_t i = 0; i < GetMainColumn(); ++i) { - x_offset += m_owner->GetHeaderWindow()->GetColumnWidth(i); - } - PaintLevel( m_anchor, dc, 0, y, x_offset ); -} - -void wxTreeListMainWindow::OnSetFocus( wxFocusEvent &event ) -{ - m_hasFocus = TRUE; - - RefreshSelected(); - - event.Skip(); -} - -void wxTreeListMainWindow::OnKillFocus( wxFocusEvent &event ) -{ - m_hasFocus = FALSE; - - RefreshSelected(); - - event.Skip(); -} - -void wxTreeListMainWindow::OnChar( wxKeyEvent &event ) -{ - wxTreeEvent te( wxEVT_COMMAND_TREE_KEY_DOWN, m_owner->GetId() ); - te.SetKeyEvent( event ); - te.SetEventObject( /*this*/m_owner ); - if ( m_owner->GetEventHandler()->ProcessEvent( te ) ) - { - // intercepted by the user code - return; - } - - if ( (m_current == 0) || (m_key_current == 0) ) - { - event.Skip(); - return; - } - - // how should the selection work for this event? - bool is_multiple, extended_select, unselect_others; - EventFlagsToSelType(GetWindowStyleFlag(), - event.ShiftDown(), - event.ControlDown(), - is_multiple, extended_select, unselect_others); - - // + : Expand (not on Win32) - // - : Collaspe (not on Win32) - // * : Expand all/Collapse all - // ' ' | return : activate - // up : go up (not last children!) - // down : go down - // left : go to parent (or collapse on Win32) - // right : open if parent and go next (or expand on Win32) - // home : go to root - // end : go to last item without opening parents - switch (event.GetKeyCode()) - { -#ifndef __WXMSW__ // mimic the standard win32 tree ctrl - case '+': - case WXK_ADD: - if (m_current->HasPlus() && !IsExpanded(m_current)) - { - Expand(m_current); - } - break; -#endif // __WXMSW__ - - case '*': - case WXK_MULTIPLY: - if ( !IsExpanded(m_current) ) - { - // expand all - ExpandAll(m_current); - break; - } - //else: fall through to Collapse() it - -#ifndef __WXMSW__ // mimic the standard wxTreeCtrl behaviour - case '-': - case WXK_SUBTRACT: - if (IsExpanded(m_current)) - { - Collapse(m_current); - } - break; -#endif // __WXMSW__ - - case ' ': - case WXK_RETURN: - { - wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, - m_owner->GetId() ); - event.SetItem( (long) m_current); - event.SetEventObject( /*this*/m_owner ); - m_owner->GetEventHandler()->ProcessEvent( event ); - } - break; - - // up goes to the previous sibling or to the last - // of its children if it's expanded - case WXK_UP: - { - wxTreeItemId prev = GetPrevSibling( m_key_current ); - if (!prev) - { - prev = GetParent( m_key_current ); - if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) - { - break; // don't go to root if it is hidden - } - if (prev) - { - long cookie = 0; - wxTreeItemId current = m_key_current; - // TODO: Huh? If we get here, we'd better be the first child of our parent. How else could it be? - if (current == GetFirstChild( prev, cookie )) - { - // otherwise we return to where we came from - SelectItem( prev, unselect_others, extended_select ); - m_key_current= (wxTreeListItem*) prev.m_pItem; - EnsureVisible( prev ); - break; - } - } - } - if (prev) - { - while ( IsExpanded(prev) && HasChildren(prev) ) - { - wxTreeItemId child = GetLastChild(prev); - if ( child ) - { - prev = child; - } - } - - SelectItem( prev, unselect_others, extended_select ); - m_key_current=(wxTreeListItem*) prev.m_pItem; - EnsureVisible( prev ); - } - } - break; - - // left arrow goes to the parent - case WXK_LEFT: -#if defined(__WXMSW__) // mimic the standard win32 tree ctrl - if (IsExpanded(m_current)) - { - Collapse(m_current); - } - else -#endif // __WXMSW__ - { - wxTreeItemId prev = GetParent( m_current ); - if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) - { - // don't go to root if it is hidden - prev = GetPrevSibling( m_current ); - } - if (prev) - { - EnsureVisible( prev ); - SelectItem( prev, unselect_others, extended_select ); - } - } - break; - - case WXK_RIGHT: -#if defined(__WXMSW__) // mimic the standard win32 tree ctrl - if (m_current->HasPlus() && !IsExpanded(m_current)) - { - Expand(m_current); - break; - } -#endif // __WXMSW__ - - // this works the same as the down arrow except that we - // also expand the item if it wasn't expanded yet - Expand(m_current); - // fall through - - case WXK_DOWN: - { - if (IsExpanded(m_key_current) && HasChildren(m_key_current)) - { - long cookie = 0; - wxTreeItemId child = GetFirstChild( m_key_current, cookie ); - SelectItem( child, unselect_others, extended_select ); - m_key_current=(wxTreeListItem*) child.m_pItem; - EnsureVisible( child ); - } - else - { - wxTreeItemId next = GetNextSibling( m_key_current ); - if (!next) - { - wxTreeItemId current = m_key_current; - while (current && !next) - { - current = GetParent( current ); - if (current) next = GetNextSibling( current ); - } - } - if (next) - { - SelectItem( next, unselect_others, extended_select ); - m_key_current=(wxTreeListItem*) next.m_pItem; - EnsureVisible( next ); - } - } - } - break; - - // selects the last visible tree item - case WXK_END: - { - wxTreeItemId last = GetRootItem(); - - while ( last.IsOk() && IsExpanded(last) ) - { - wxTreeItemId lastChild = GetLastChild(last); - - // it may happen if the item was expanded but then all of - // its children have been deleted - so IsExpanded() returned - // TRUE, but GetLastChild() returned invalid item - if ( !lastChild ) - break; - - last = lastChild; - } - - if ( last.IsOk() ) - { - EnsureVisible( last ); - SelectItem( last, unselect_others, extended_select ); - } - } - break; - - // selects the root item - case WXK_HOME: - { - wxTreeItemId prev = GetRootItem(); - if (!prev) break; - if (HasFlag(wxTR_HIDE_ROOT)) - { - long dummy; - prev = GetFirstChild(prev, dummy); - if (!prev) break; - } - EnsureVisible( prev ); - SelectItem( prev, unselect_others, extended_select ); - } - break; - - default: - event.Skip(); - } -} - -wxTreeItemId wxTreeListMainWindow::HitTest(const wxPoint& point, int& flags, - int& column) -{ - // JACS: removed wxYieldIfNeeded() because it can cause the window - // to be deleted from under us if a close window event is pending - - int w, h; - GetSize(&w, &h); - flags=0; - column = -1; - if (point.x<0) flags |= wxTREE_HITTEST_TOLEFT; - if (point.x>w) flags |= wxTREE_HITTEST_TORIGHT; - if (point.y<0) flags |= wxTREE_HITTEST_ABOVE; - if (point.y>h) flags |= wxTREE_HITTEST_BELOW; - if (flags) return wxTreeItemId(); - - if (m_anchor == NULL) - { - flags = wxTREE_HITTEST_NOWHERE; - return wxTreeItemId(); - } - - wxTreeListItem *hit = m_anchor->HitTest(CalcUnscrolledPosition(point), - this, flags, column, 0); - if (hit == NULL) - { - flags = wxTREE_HITTEST_NOWHERE; - return wxTreeItemId(); - } - return hit; -} - -// get the bounding rectangle of the item (or of its label only) -bool wxTreeListMainWindow::GetBoundingRect(const wxTreeItemId& item, - wxRect& rect, - bool WXUNUSED(textOnly)) const -{ - wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") ); - - wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; - - int startX, startY; - GetViewStart(& startX, & startY); - - rect.x = i->GetX() - startX*PIXELS_PER_UNIT; - rect.y = i->GetY() - startY*PIXELS_PER_UNIT; - rect.width = i->GetWidth(); - //rect.height = i->GetHeight(); - rect.height = GetLineHeight(i); - - return TRUE; -} - -/* **** */ - -void wxTreeListMainWindow::Edit( const wxTreeItemId& item ) -{ - if (!item.IsOk()) return; - - m_currentEdit = (wxTreeListItem*) item.m_pItem; - - wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, m_owner->GetId() ); - te.SetItem( (long) m_currentEdit); - te.SetEventObject( /*this*/m_owner ); - m_owner->GetEventHandler()->ProcessEvent( te ); - - if (!te.IsAllowed()) return; - - // We have to call this here because the label in - // question might just have been added and no screen - // update taken place. - if (m_dirty) wxYieldIfNeeded(); - - wxString s = m_currentEdit->GetText(/*ALB*/m_main_column); - int x = m_currentEdit->GetX(); - int y = m_currentEdit->GetY(); - int w = m_currentEdit->GetWidth(); - int h = m_currentEdit->GetHeight(); - - int image_h = 0; - int image_w = 0; - - int image = m_currentEdit->GetCurrentImage(); - if ( image != NO_IMAGE ) - { - if ( m_imageListNormal ) - { - m_imageListNormal->GetSize( image, image_w, image_h ); - image_w += 4; - } - else - { - wxFAIL_MSG(_T("you must create an image list to use images!")); - } - } - x += image_w; - w -= image_w + 4; // I don't know why +4 is needed - - wxClientDC dc(this); - PrepareDC( dc ); - x = dc.LogicalToDeviceX( x ); - y = dc.LogicalToDeviceY( y ); - - wxTreeListTextCtrl *text = new wxTreeListTextCtrl(this, -1, - &m_renameAccept, - &m_renameRes, - this, - s, - wxPoint(x-4,y-4), - wxSize(w+11,h+8)); - text->SetFocus(); -} - -void wxTreeListMainWindow::OnRenameTimer() -{ - Edit( m_current ); -} - -void wxTreeListMainWindow::OnRenameAccept() -{ - // TODO if the validator fails this causes a crash - wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, m_owner->GetId() ); - le.SetItem( (long) m_currentEdit ); - le.SetEventObject( /*this*/m_owner ); - le.SetLabel( m_renameRes ); - m_owner->GetEventHandler()->ProcessEvent( le ); - - if (!le.IsAllowed()) return; - - SetItemText( m_currentEdit, m_renameRes ); -} - -void wxTreeListMainWindow::OnMouse( wxMouseEvent &event ) -{ - if ( !m_anchor ) return; - - // we process left mouse up event (enables in-place edit), right down - // (pass to the user code), left dbl click (activate item) and - // dragging/moving events for items drag-and-drop - if ( !(event.LeftDown() || - event.LeftUp() || - event.RightDown() || - event.LeftDClick() || - event.Dragging() || - ((event.Moving() || event.RightUp()) && m_isDragging)) ) - { - event.Skip(); - - return; - } - - if ( event.LeftDown() ) - SetFocus(); - - wxClientDC dc(this); - PrepareDC(dc); - wxCoord x = dc.DeviceToLogicalX( event.GetX() ); - wxCoord y = dc.DeviceToLogicalY( event.GetY() ); - - int flags = 0; - wxTreeListItem *item = m_anchor->HitTest(wxPoint(x,y), this, flags, 0); - - if ( event.Dragging() && !m_isDragging ) - { - if (m_dragCount == 0) - m_dragStart = wxPoint(x,y); - - m_dragCount++; - - if (m_dragCount != 3) - { - // wait until user drags a bit further... - return; - } - - wxEventType command = event.RightIsDown() - ? wxEVT_COMMAND_TREE_BEGIN_RDRAG - : wxEVT_COMMAND_TREE_BEGIN_DRAG; - - wxTreeEvent nevent( command,/*ALB*/ m_owner->GetId() ); - nevent.SetItem( (long) m_current); - nevent.SetEventObject(/*this*/m_owner); // ALB - - // by default the dragging is not supported, the user code must - // explicitly allow the event for it to take place - nevent.Veto(); - - if ( m_owner->GetEventHandler()->ProcessEvent(nevent) && - nevent.IsAllowed() ) - { - // we're going to drag this item - m_isDragging = TRUE; - - // remember the old cursor because we will change it while - // dragging - m_oldCursor = m_cursor; - - // in a single selection control, hide the selection temporarily - if ( !(GetWindowStyleFlag() & wxTR_MULTIPLE) ) - { - m_oldSelection = (wxTreeListItem*) GetSelection().m_pItem; - - if ( m_oldSelection ) - { - m_oldSelection->SetHilight(FALSE); - RefreshLine(m_oldSelection); - } - } - - CaptureMouse(); - } - } - else if ( event.Moving() ) - { - if ( item != m_dropTarget ) - { - // unhighlight the previous drop target - DrawDropEffect(m_dropTarget); - - m_dropTarget = item; - - // highlight the current drop target if any - DrawDropEffect(m_dropTarget); - - wxYieldIfNeeded(); - } - } - else if ( (event.LeftUp() || event.RightUp()) && m_isDragging ) - { - // erase the highlighting - DrawDropEffect(m_dropTarget); - - if ( m_oldSelection ) - { - m_oldSelection->SetHilight(TRUE); - RefreshLine(m_oldSelection); - m_oldSelection = (wxTreeListItem *)NULL; - } - - // generate the drag end event - wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG,/*ALB*/m_owner->GetId()); - - event.SetItem( (long) item ); - event.SetPoint( wxPoint(x, y) ); - event.SetEventObject(/*this*/m_owner); - - (void)m_owner->GetEventHandler()->ProcessEvent(event); - - m_isDragging = FALSE; - m_dropTarget = (wxTreeListItem *)NULL; - - ReleaseMouse(); - - SetCursor(m_oldCursor); - - wxYieldIfNeeded(); - } - else - { - // here we process only the messages which happen on tree items - - m_dragCount = 0; - - if (item == NULL) return; /* we hit the blank area */ - - if ( event.RightDown() ) - { - SetFocus(); - wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, - m_owner->GetId()); - nevent.SetItem( (long) item ); - int nx, ny; - CalcScrolledPosition(x, y, &nx, &ny); - nevent.SetPoint( wxPoint(nx, ny)); - nevent.SetEventObject(/*this*/m_owner); - m_owner->GetEventHandler()->ProcessEvent(nevent); - } - else if ( event.LeftUp() ) - { - if ( m_lastOnSame ) - { - if ( (item == m_current) && - (flags & wxTREE_HITTEST_ONITEMLABEL) && - HasFlag(wxTR_EDIT_LABELS) ) - { - if ( m_renameTimer->IsRunning() ) - m_renameTimer->Stop(); - - m_renameTimer->Start( 100, TRUE ); - } - - m_lastOnSame = FALSE; - } - } - else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick() - { - if ( event.LeftDown() ) - { - SetFocus(); - m_lastOnSame = item == m_current; - } - - if ( flags & wxTREE_HITTEST_ONITEMBUTTON ) - { - // only toggle the item for a single click, double click on - // the button doesn't do anything (it toggles the item twice) - if ( event.LeftDown() ) - { - Toggle( item ); - } - - // don't select the item if the button was clicked - return; - } - - // how should the selection work for this event? - bool is_multiple, extended_select, unselect_others; - EventFlagsToSelType(GetWindowStyleFlag(), - event.ShiftDown(), - event.ControlDown(), - is_multiple, extended_select, unselect_others); - - SelectItem(item, unselect_others, extended_select); - - // For some reason, Windows isn't recognizing a left double-click, - // so we need to simulate it here. Allow 200 milliseconds for now. - if ( event.LeftDClick() ) - { - // double clicking should not start editing the item label - m_renameTimer->Stop(); - m_lastOnSame = FALSE; - - // send activate event first - wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, - m_owner->GetId() ); - nevent.SetItem( (long) item ); - int nx, ny; - CalcScrolledPosition(x, y, &nx, &ny); - nevent.SetPoint( wxPoint(nx, ny) ); - nevent.SetEventObject( /*this*/m_owner ); - if ( !m_owner->GetEventHandler()->ProcessEvent( nevent ) ) - { - // if the user code didn't process the activate event, - // handle it ourselves by toggling the item when it is - // double clicked - if ( item->HasPlus() ) - { - Toggle(item); - } - } - } - } - } -} - -void wxTreeListMainWindow::OnIdle( wxIdleEvent &WXUNUSED(event) ) -{ - /* after all changes have been done to the tree control, - * we actually redraw the tree when everything is over */ - - if (!m_dirty) return; - - m_dirty = FALSE; - - CalculatePositions(); - Refresh(); - AdjustMyScrollbars(); -} - -void wxTreeListMainWindow::OnSize(wxSizeEvent& WXUNUSED(event)) -{ -// int w, h; -// GetClientSize(&w, &h); -// m_header_win->SetSize(0, 0, w, HEADER_HEIGHT); -} - -void wxTreeListMainWindow::OnScroll(wxScrollWinEvent& event) -{ - // FIXME -#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) - wxScrolledWindow::OnScroll(event); -#else - HandleOnScroll( event ); -#endif - - if(event.GetOrientation() == wxHORIZONTAL) - { - m_owner->GetHeaderWindow()->Refresh(); - m_owner->GetHeaderWindow()->Update(); - } -} - - -void wxTreeListMainWindow::CalculateSize( wxTreeListItem *item, wxDC &dc ) -{ - wxCoord text_w = 0; - wxCoord text_h = 0; - - if (item->IsBold()) - dc.SetFont(m_boldFont); - - dc.GetTextExtent( item->GetText(/*ALB*/m_main_column), &text_w, &text_h ); - text_h+=2; - - // restore normal font - dc.SetFont( m_normalFont ); - - int image_h = 0; - int image_w = 0; - int image = item->GetCurrentImage(); - if ( image != NO_IMAGE ) - { - if ( m_imageListNormal ) - { - m_imageListNormal->GetSize( image, image_w, image_h ); - image_w += 4; - image_h += 2; - } - } - - int total_h = (image_h > text_h) ? image_h : text_h; - -// if (total_h < 30) -// total_h += 2; // at least 2 pixels -// else -// total_h += total_h/10; // otherwise 10% extra spacing - - item->SetHeight(total_h); - if (total_h>m_lineHeight) - m_lineHeight=total_h; - - item->SetWidth(image_w+text_w+2); -} - -// ----------------------------------------------------------------------------- -// for developper : y is now the top of the level -// not the middle of it ! -void wxTreeListMainWindow::CalculateLevel( wxTreeListItem *item, wxDC &dc, - int level, int &y, int x_offset ) -{ - int x = level*m_indent + x_offset; - if (!HasFlag(wxTR_HIDE_ROOT)) - { - x += m_indent; - } - else if (level == 0) - { - // a hidden root is not evaluated, but its - // children are always calculated - goto Recurse; - } - - CalculateSize( item, dc ); - - // set its position - item->SetX( x+m_spacing ); - item->SetY( y ); - y += GetLineHeight(item); - - if ( !item->IsExpanded() ) - { - // we don't need to calculate collapsed branches - return; - } - - Recurse: - wxArrayTreeListItems& children = item->GetChildren(); - size_t n, count = children.Count(); - ++level; - for (n = 0; n < count; ++n ) - CalculateLevel( children[n], dc, level, y, x_offset ); // recurse -} - -void wxTreeListMainWindow::CalculatePositions() -{ - if ( !m_anchor ) return; - - wxClientDC dc(this); - PrepareDC( dc ); - - dc.SetFont( m_normalFont ); - - dc.SetPen( m_dottedPen ); - //if(GetImageList() == NULL) - // m_lineHeight = (int)(dc.GetCharHeight() + 4); - - int y = 2; - int x_offset = 0; - for(size_t i = 0; i < GetMainColumn(); ++i) { - x_offset += m_owner->GetHeaderWindow()->GetColumnWidth(i); - } - CalculateLevel( m_anchor, dc, 0, y, x_offset ); // start recursion -} - -void wxTreeListMainWindow::RefreshSubtree(wxTreeListItem *item) -{ - if (m_dirty) return; - - wxClientDC dc(this); - PrepareDC(dc); - - int cw = 0; - int ch = 0; - //GetClientSize( &cw, &ch ); - GetVirtualSize(&cw, &ch); - - wxRect rect; - rect.x = dc.LogicalToDeviceX( 0 ); - rect.width = cw; - rect.y = dc.LogicalToDeviceY( item->GetY() - 2 ); - rect.height = ch; - - Refresh( TRUE, &rect ); - - AdjustMyScrollbars(); -} - -void wxTreeListMainWindow::RefreshLine( wxTreeListItem *item ) -{ - if (m_dirty) return; - - wxClientDC dc(this); - PrepareDC( dc ); - - int cw = 0; - int ch = 0; - //GetClientSize( &cw, &ch ); - GetVirtualSize(&cw, &ch); - - wxRect rect; - rect.x = dc.LogicalToDeviceX( 0 ); - rect.y = dc.LogicalToDeviceY( item->GetY() ); - rect.width = cw; - rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6; - - Refresh( TRUE, &rect ); -} - -void wxTreeListMainWindow::RefreshSelected() -{ - // TODO: this is awfully inefficient, we should keep the list of all - // selected items internally, should be much faster - if ( m_anchor ) - RefreshSelectedUnder(m_anchor); -} - -void wxTreeListMainWindow::RefreshSelectedUnder(wxTreeListItem *item) -{ - if ( item->IsSelected() ) - RefreshLine(item); - - const wxArrayTreeListItems& children = item->GetChildren(); - size_t count = children.GetCount(); - for ( size_t n = 0; n < count; n++ ) - { - RefreshSelectedUnder(children[n]); - } -} - -// ---------------------------------------------------------------------------- -// changing colours: we need to refresh the tree control -// ---------------------------------------------------------------------------- - -bool wxTreeListMainWindow::SetBackgroundColour(const wxColour& colour) -{ - if ( !wxWindow::SetBackgroundColour(colour) ) - return FALSE; - - Refresh(); - - return TRUE; -} - -bool wxTreeListMainWindow::SetForegroundColour(const wxColour& colour) -{ - if ( !wxWindow::SetForegroundColour(colour) ) - return FALSE; - - Refresh(); - - return TRUE; -} - -//----------- ALB ------------- -inline -void wxTreeListMainWindow::SetItemText(const wxTreeItemId& item, size_t column, - const wxString& text) -{ - wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); - - wxClientDC dc(this); - wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; - pItem->SetText(column, text); - CalculateSize(pItem, dc); - RefreshLine(pItem); -} - -inline -wxString wxTreeListMainWindow::GetItemText(const wxTreeItemId& item, - size_t column) const -{ - wxCHECK_MSG( item.IsOk(), wxT(""), wxT("invalid tree item") ); - - return ((wxTreeListItem*) item.m_pItem)->GetText(column); -} - -//----------------------------- - -//----------------------------------------------------------------------------- -// wxTreeListCtrl -//----------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl, wxControl); - -BEGIN_EVENT_TABLE(wxTreeListCtrl, wxControl) - EVT_SIZE(wxTreeListCtrl::OnSize) -END_EVENT_TABLE(); - -bool wxTreeListCtrl::Create(wxWindow *parent, wxWindowID id, - const wxPoint& pos, - const wxSize& size, - long style, const wxValidator &validator, - const wxString& name) -{ - long main_style = style & ~(wxRAISED_BORDER|wxSUNKEN_BORDER - |wxSIMPLE_BORDER|wxNO_BORDER|wxDOUBLE_BORDER - |wxSTATIC_BORDER); - if(!wxControl::Create(parent, id, pos, size, style, validator, name)) - return false; - - m_main_win = new wxTreeListMainWindow(this, -1, wxPoint(0, 0), size, - main_style, validator); - m_header_win = new wxTreeListHeaderWindow(this, -1, m_main_win, - wxPoint(0, 0), wxDefaultSize, - wxTAB_TRAVERSAL); - return TRUE; -} - -void wxTreeListCtrl::OnSize(wxSizeEvent& event) -{ - int w, h; - GetClientSize(&w, &h); - if(m_header_win) - m_header_win->SetSize(0, 0, w, HEADER_HEIGHT); - if(m_main_win) - m_main_win->SetSize(0, HEADER_HEIGHT + 1, w, h - HEADER_HEIGHT - 1); -} - -size_t wxTreeListCtrl::GetCount() const { return m_main_win->GetCount(); } - -unsigned int wxTreeListCtrl::GetIndent() const -{ return m_main_win->GetIndent(); } - -void wxTreeListCtrl::SetIndent(unsigned int indent) -{ m_main_win->SetIndent(indent); } - -unsigned int wxTreeListCtrl::GetSpacing() const -{ return m_main_win->GetSpacing(); } - -void wxTreeListCtrl::SetSpacing(unsigned int spacing) -{ m_main_win->SetSpacing(spacing); } - -unsigned int wxTreeListCtrl::GetLineSpacing() const -{ return m_main_win->GetLineSpacing(); } - -void wxTreeListCtrl::SetLineSpacing(unsigned int spacing) -{ m_main_win->SetLineSpacing(spacing); } - -wxImageList* wxTreeListCtrl::GetImageList() const -{ return m_main_win->GetImageList(); } - -wxImageList* wxTreeListCtrl::GetStateImageList() const -{ return m_main_win->GetStateImageList(); } - -wxImageList* wxTreeListCtrl::GetButtonsImageList() const -{ return m_main_win->GetButtonsImageList(); } - -void wxTreeListCtrl::SetImageList(wxImageList* imageList) -{ m_main_win->SetImageList(imageList); } - -void wxTreeListCtrl::SetStateImageList(wxImageList* imageList) -{ m_main_win->SetStateImageList(imageList); } - -void wxTreeListCtrl::SetButtonsImageList(wxImageList* imageList) -{ m_main_win->SetButtonsImageList(imageList); } - -void wxTreeListCtrl::AssignImageList(wxImageList* imageList) -{ m_main_win->AssignImageList(imageList); } - -void wxTreeListCtrl::AssignStateImageList(wxImageList* imageList) -{ m_main_win->AssignStateImageList(imageList); } - -void wxTreeListCtrl::AssignButtonsImageList(wxImageList* imageList) -{ m_main_win->AssignButtonsImageList(imageList); } - -wxString wxTreeListCtrl::GetItemText(const wxTreeItemId& item, size_t column) - const -{ return m_main_win->GetItemText(item, column); } - -int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, size_t column, - wxTreeItemIcon which) const -{ return m_main_win->GetItemImage(item, column, which); } - -wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item) const -{ return m_main_win->GetItemData(item); } - -bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item) const -{ return m_main_win->GetItemBold(item); } - -wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item) const -{ return m_main_win->GetItemTextColour(item); } - -wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item) - const -{ return m_main_win->GetItemBackgroundColour(item); } - -wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item) const -{ return m_main_win->GetItemFont(item); } - - -void wxTreeListCtrl::SetItemText(const wxTreeItemId& item, size_t column, - const wxString& text) -{ m_main_win->SetItemText(item, column, text); } - -void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item, - size_t column, - int image, - wxTreeItemIcon which) -{ m_main_win->SetItemImage(item, column, image, which); } - -void wxTreeListCtrl::SetItemData(const wxTreeItemId& item, - wxTreeItemData* data) -{ m_main_win->SetItemData(item, data); } - -void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) -{ m_main_win->SetItemHasChildren(item, has); } - -void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, bool bold) -{ m_main_win->SetItemBold(item, bold); } - -void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item, - const wxColour& col) -{ m_main_win->SetItemTextColour(item, col); } - -void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item, - const wxColour& col) -{ m_main_win->SetItemBackgroundColour(item, col); } - -void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item, - const wxFont& font) -{ m_main_win->SetItemFont(item, font); } - -bool wxTreeListCtrl::SetFont(const wxFont& font) -{ - if(m_header_win) m_header_win->SetFont(font); - if(m_main_win) - return m_main_win->SetFont(font); - else return FALSE; -} - -void wxTreeListCtrl::SetWindowStyle(const long style) -{ - if(m_main_win) - m_main_win->SetWindowStyle(style); - // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win -} - -long wxTreeListCtrl::GetWindowStyle() const -{ - long style = m_windowStyle; - if(m_main_win) - style |= m_main_win->GetWindowStyle(); - return style; -} - -bool wxTreeListCtrl::IsVisible(const wxTreeItemId& item) const -{ return m_main_win->IsVisible(item); } - -bool wxTreeListCtrl::ItemHasChildren(const wxTreeItemId& item) const -{ return m_main_win->ItemHasChildren(item); } - -bool wxTreeListCtrl::IsExpanded(const wxTreeItemId& item) const -{ return m_main_win->IsExpanded(item); } - -bool wxTreeListCtrl::IsSelected(const wxTreeItemId& item) const -{ return m_main_win->IsSelected(item); } - -bool wxTreeListCtrl::IsBold(const wxTreeItemId& item) const -{ return m_main_win->IsBold(item); } - -size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId& item, bool rec) -{ return m_main_win->GetChildrenCount(item, rec); } - -wxTreeItemId wxTreeListCtrl::GetRootItem() const -{ return m_main_win->GetRootItem(); } - -wxTreeItemId wxTreeListCtrl::GetSelection() const -{ return m_main_win->GetSelection(); } - -size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds& arr) const -{ return m_main_win->GetSelections(arr); } - -wxTreeItemId wxTreeListCtrl::GetParent(const wxTreeItemId& item) const -{ return m_main_win->GetParent(item); } - -wxTreeItemId wxTreeListCtrl::GetFirstChild(const wxTreeItemId& item, - long& cookie) const -{ return m_main_win->GetFirstChild(item, cookie); } - -wxTreeItemId wxTreeListCtrl::GetNextChild(const wxTreeItemId& item, - long& cookie) const -{ return m_main_win->GetNextChild(item, cookie); } - -wxTreeItemId wxTreeListCtrl::GetLastChild(const wxTreeItemId& item) const -{ return m_main_win->GetLastChild(item); } - -wxTreeItemId wxTreeListCtrl::GetNextSibling(const wxTreeItemId& item) const -{ return m_main_win->GetNextSibling(item); } - -wxTreeItemId wxTreeListCtrl::GetPrevSibling(const wxTreeItemId& item) const -{ return m_main_win->GetPrevSibling(item); } - -wxTreeItemId wxTreeListCtrl::GetFirstVisibleItem() const -{ return m_main_win->GetFirstVisibleItem(); } - -wxTreeItemId wxTreeListCtrl::GetNextVisible(const wxTreeItemId& item) const -{ return m_main_win->GetNextVisible(item); } - -wxTreeItemId wxTreeListCtrl::GetPrevVisible(const wxTreeItemId& item) const -{ return m_main_win->GetPrevVisible(item); } - -wxTreeItemId wxTreeListCtrl::GetNext(const wxTreeItemId& item) const -{ return m_main_win->GetNext(item); } - -wxTreeItemId wxTreeListCtrl::AddRoot(const wxString& text, int image, - int selectedImage, wxTreeItemData* data) -{ return m_main_win->AddRoot(text, image, selectedImage, data); } - -wxTreeItemId wxTreeListCtrl::PrependItem(const wxTreeItemId& parent, - const wxString& text, int image, - int selectedImage, - wxTreeItemData* data) -{ return m_main_win->PrependItem(parent, text, image, selectedImage, data); } - -wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent, - const wxTreeItemId& previous, - const wxString& text, int image, - int selectedImage, - wxTreeItemData* data) -{ - return m_main_win->InsertItem(parent, previous, text, image, - selectedImage, data); -} - -wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent, - size_t index, - const wxString& text, int image, - int selectedImage, - wxTreeItemData* data) -{ - return m_main_win->InsertItem(parent, index, text, image, - selectedImage, data); -} - -wxTreeItemId wxTreeListCtrl::AppendItem(const wxTreeItemId& parent, - const wxString& text, int image, - int selectedImage, - wxTreeItemData* data) -{ return m_main_win->AppendItem(parent, text, image, selectedImage, data); } - -void wxTreeListCtrl::Delete(const wxTreeItemId& item) -{ m_main_win->Delete(item); } - -void wxTreeListCtrl::DeleteChildren(const wxTreeItemId& item) -{ m_main_win->DeleteChildren(item); } - -void wxTreeListCtrl::DeleteAllItems() -{ m_main_win->DeleteAllItems(); } - -void wxTreeListCtrl::Expand(const wxTreeItemId& item) -{ m_main_win->Expand(item); } - -void wxTreeListCtrl::ExpandAll(const wxTreeItemId& item) -{ m_main_win->ExpandAll(item); } - -void wxTreeListCtrl::Collapse(const wxTreeItemId& item) -{ m_main_win->Collapse(item); } - -void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId& item) -{ m_main_win->CollapseAndReset(item); } - -void wxTreeListCtrl::Toggle(const wxTreeItemId& item) -{ m_main_win->Toggle(item); } - -void wxTreeListCtrl::Unselect() -{ m_main_win->Unselect(); } - -void wxTreeListCtrl::UnselectAll() -{ m_main_win->UnselectAll(); } - -void wxTreeListCtrl::SelectItem(const wxTreeItemId& item, bool unselect_others, - bool extended_select) -{ m_main_win->SelectItem(item, unselect_others, extended_select); } - -void wxTreeListCtrl::EnsureVisible(const wxTreeItemId& item) -{ m_main_win->EnsureVisible(item); } - -void wxTreeListCtrl::ScrollTo(const wxTreeItemId& item) -{ m_main_win->ScrollTo(item); } - -wxTreeItemId wxTreeListCtrl::HitTest(const wxPoint& pos, int& flags, - int& column) -{ - return m_main_win->HitTest(pos, flags, column); -} - -bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId& item, wxRect& rect, - bool textOnly) const -{ return m_main_win->GetBoundingRect(item, rect, textOnly); } - -void wxTreeListCtrl::Edit(const wxTreeItemId& item) -{ m_main_win->Edit(item); } - -int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1, - const wxTreeItemId& item2) -{ - // ALB: do the comparison here, and not delegate to m_main_win, in order - // to let the user override it - //return m_main_win->OnCompareItems(item1, item2); - return wxStrcmp(GetItemText(item1), GetItemText(item2)); -} - -void wxTreeListCtrl::SortChildren(const wxTreeItemId& item) -{ m_main_win->SortChildren(item); } - -bool wxTreeListCtrl::SetBackgroundColour(const wxColour& colour) -{ return m_main_win->SetBackgroundColour(colour); } - -bool wxTreeListCtrl::SetForegroundColour(const wxColour& colour) -{ return m_main_win->SetForegroundColour(colour); } - -size_t wxTreeListCtrl::GetColumnCount() const -{ return m_main_win->GetColumnCount(); } - -void wxTreeListCtrl::SetColumnWidth(size_t column, size_t width) -{ m_header_win->SetColumnWidth(column, width); } - -int wxTreeListCtrl::GetColumnWidth(size_t column) const -{ return m_header_win->GetColumnWidth(column); } - -void wxTreeListCtrl::SetMainColumn(size_t column) -{ m_main_win->SetMainColumn(column); } - -size_t wxTreeListCtrl::GetMainColumn() const -{ return m_main_win->GetMainColumn(); } - -void wxTreeListCtrl::SetColumnText(size_t column, const wxString& text) -{ - m_header_win->SetColumnText(column, text); - m_header_win->Refresh(); -} - -wxString wxTreeListCtrl::GetColumnText(size_t column) const -{ return m_header_win->GetColumnText(column); } - -void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo& col) -{ m_header_win->AddColumn(col); } - -void wxTreeListCtrl::InsertColumn(size_t before, - const wxTreeListColumnInfo& col) -{ m_header_win->InsertColumn(before, col); } - -void wxTreeListCtrl::RemoveColumn(size_t column) -{ m_header_win->RemoveColumn(column); } - -void wxTreeListCtrl::SetColumn(size_t column, const wxTreeListColumnInfo& col) -{ m_header_win->SetColumn(column, col); } - -const wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(size_t column) const -{ return m_header_win->GetColumn(column); } - -wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(size_t column) -{ return m_header_win->GetColumn(column); } - -void wxTreeListCtrl::SetColumnImage(size_t column, int image) -{ - m_header_win->SetColumn(column, GetColumn(column).SetImage(image)); -} - -int wxTreeListCtrl::GetColumnImage(size_t column) const -{ - return m_header_win->GetColumn(column).GetImage(); -} - -void wxTreeListCtrl::SetColumnAlignment(size_t column, - wxTreeListColumnAlign align) -{ - m_header_win->SetColumn(column, GetColumn(column).SetAlignment(align)); -} - -wxTreeListColumnAlign wxTreeListCtrl::GetColumnAlignment(size_t column) const -{ - return m_header_win->GetColumn(column).GetAlignment(); -} - -void wxTreeListCtrl::Refresh(bool erase, const wxRect* rect) -{ - m_main_win->Refresh(erase, rect); - m_header_win->Refresh(erase, rect); -} - -void wxTreeListCtrl::SetFocus() -{ m_main_win->SetFocus(); } diff --git a/wxPython/contrib/gizmos/treelistctrl.h b/wxPython/contrib/gizmos/treelistctrl.h deleted file mode 100644 index a1e75e9ade..0000000000 --- a/wxPython/contrib/gizmos/treelistctrl.h +++ /dev/null @@ -1,509 +0,0 @@ -// -*- C++ -*- ////////////////////////////////////////////////////////////// -// Name: treelistctrl.h (derived by wx/treectrlg.h) -// Purpose: wxTreeListCtrl class -// Author: Robert Roebling -// Modified by: Alberto Griggio, 2002 -// Created: 01/02/97 -// RCS-ID: $Id$ -// Copyright: (c) 1997,1998 Robert Roebling -// Licence: wxWindows license -///////////////////////////////////////////////////////////////////////////// - - -#ifndef TREELISTCTRL_H -#define TREELISTCTRL_H - -#if defined(__GNUG__) && !defined(__APPLE__) - #pragma interface "treelistctrl.h" -#endif - -#include -#include -#include -#include // for wxListEvent - -#ifdef GIZMOISDLL -#define GIZMODLLEXPORT WXDLLEXPORT -#else -#define GIZMODLLEXPORT -#endif - - -class GIZMODLLEXPORT wxTreeListItem; -class GIZMODLLEXPORT wxTreeListHeaderWindow; -class GIZMODLLEXPORT wxTreeListMainWindow; - -//----------------------------------------------------------------------------- -// wxTreeListColumnAttrs -//----------------------------------------------------------------------------- - -enum wxTreeListColumnAlign { - wxTL_ALIGN_LEFT, - wxTL_ALIGN_RIGHT, - wxTL_ALIGN_CENTER -}; - - -class GIZMODLLEXPORT wxTreeListColumnInfo: public wxObject { -public: - enum { DEFAULT_COL_WIDTH = 100 }; - - wxTreeListColumnInfo(const wxChar* text = wxT(""), - int image = -1, - size_t width = DEFAULT_COL_WIDTH, - wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT) - { - m_image = image; - m_selected_image = -1; - m_text = text; - m_width = width; - m_alignment = alignment; - } - - wxTreeListColumnInfo(const wxTreeListColumnInfo& other) - { - m_image = other.m_image; - m_selected_image = other.m_selected_image; - m_text = other.m_text; - m_width = other.m_width; - m_alignment = other.m_alignment; - } - - ~wxTreeListColumnInfo() {} - - // getters - wxTreeListColumnAlign GetAlignment() const { return m_alignment; } - wxString GetText() const { return m_text; } - int GetImage() const { return m_image; } - int GetSelectedImage() const { return m_selected_image; } - size_t GetWidth() const { return m_width; } - - // setters - wxTreeListColumnInfo& SetAlignment(wxTreeListColumnAlign alignment) - { m_alignment = alignment; return *this; } - - wxTreeListColumnInfo& SetText(const wxString& text) - { m_text = text; return *this; } - - wxTreeListColumnInfo& SetImage(int image) - { m_image = image; return *this; } - - wxTreeListColumnInfo& SetSelectedImage(int image) - { m_selected_image = image; return *this; } - - wxTreeListColumnInfo& SetWidth(size_t with) - { m_width = with; return *this; } - -private: - wxTreeListColumnAlign m_alignment; - wxString m_text; - int m_image; - int m_selected_image; - size_t m_width; -}; - -//---------------------------------------------------------------------------- -// wxTreeListCtrl - the multicolumn tree control -//---------------------------------------------------------------------------- - -// additional flag for HitTest -const int wxTREE_HITTEST_ONITEMCOLUMN = 0x2000; -extern GIZMODLLEXPORT const wxChar* wxTreeListCtrlNameStr; - - -class GIZMODLLEXPORT wxTreeListCtrl : public wxControl -{ -public: - // creation - // -------- - wxTreeListCtrl() {} - - wxTreeListCtrl(wxWindow *parent, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTR_DEFAULT_STYLE, - const wxValidator &validator = wxDefaultValidator, - const wxString& name = wxTreeListCtrlNameStr ) - : m_header_win(0), m_main_win(0) - { - Create(parent, id, pos, size, style, validator, name); - } - - virtual ~wxTreeListCtrl() {} - - bool Create(wxWindow *parent, wxWindowID id = -1, - const wxPoint& pos = wxDefaultPosition, - const wxSize& size = wxDefaultSize, - long style = wxTR_DEFAULT_STYLE, - const wxValidator &validator = wxDefaultValidator, - const wxString& name = wxTreeListCtrlNameStr ); - - void Refresh(bool erase=TRUE, const wxRect* rect=NULL); - void SetFocus(); - // accessors - // --------- - - // get the total number of items in the control - size_t GetCount() const; - - // indent is the number of pixels the children are indented relative to - // the parents position. SetIndent() also redraws the control - // immediately. - unsigned int GetIndent() const; - void SetIndent(unsigned int indent); - - // spacing is the number of pixels between the start and the Text - unsigned int GetSpacing() const; - void SetSpacing(unsigned int spacing); - - // line spacing is the space above and below the text on each line - unsigned int GetLineSpacing() const; - void SetLineSpacing(unsigned int spacing); - - // image list: these functions allow to associate an image list with - // the control and retrieve it. Note that when assigned with - // SetImageList, the control does _not_ delete - // the associated image list when it's deleted in order to allow image - // lists to be shared between different controls. If you use - // AssignImageList, the control _does_ delete the image list. - // - // The normal image list is for the icons which correspond to the - // normal tree item state (whether it is selected or not). - // Additionally, the application might choose to show a state icon - // which corresponds to an app-defined item state (for example, - // checked/unchecked) which are taken from the state image list. - wxImageList *GetImageList() const; - wxImageList *GetStateImageList() const; - wxImageList *GetButtonsImageList() const; - - void SetImageList(wxImageList *imageList); - void SetStateImageList(wxImageList *imageList); - void SetButtonsImageList(wxImageList *imageList); - void AssignImageList(wxImageList *imageList); - void AssignStateImageList(wxImageList *imageList); - void AssignButtonsImageList(wxImageList *imageList); - - - // Functions to work with tree list ctrl columns - - // adds a column - void AddColumn(const wxString& text) - { AddColumn(wxTreeListColumnInfo().SetText(text)); } - void AddColumn(const wxTreeListColumnInfo& col); - - // inserts a column before the given one - void InsertColumn(size_t before, const wxString& text) - { InsertColumn(before, wxTreeListColumnInfo().SetText(text)); } - void InsertColumn(size_t before, const wxTreeListColumnInfo& col); - - // deletes the given column - does not delete the corresponding column - // of each item - void RemoveColumn(size_t column); - - // returns the number of columns in the ctrl - size_t GetColumnCount() const; - - void SetColumnWidth(size_t column, size_t width); - int GetColumnWidth(size_t column) const; - - // tells which column is the "main" one, i.e. the "threaded" one - void SetMainColumn(size_t column); - size_t GetMainColumn() const; - - void SetColumnText(size_t column, const wxString& text); - wxString GetColumnText(size_t column) const; - - void SetColumn(size_t column, const wxTreeListColumnInfo& info); - wxTreeListColumnInfo& GetColumn(size_t column); - const wxTreeListColumnInfo& GetColumn(size_t column) const; - - // other column-related methods - void SetColumnAlignment(size_t column, wxTreeListColumnAlign align); - wxTreeListColumnAlign GetColumnAlignment(size_t column) const; - - void SetColumnImage(size_t column, int image); - int GetColumnImage(size_t column) const; - - // Functions to work with tree list ctrl items. - - // accessors - // --------- - - // retrieve item's label (of the main column) - wxString GetItemText(const wxTreeItemId& item) const - { return GetItemText(item, GetMainColumn()); } - // retrieves item's label of the given column - wxString GetItemText(const wxTreeItemId& item, size_t column) const; - - // get one of the images associated with the item (normal by default) - int GetItemImage(const wxTreeItemId& item, - wxTreeItemIcon which = wxTreeItemIcon_Normal) const - { return GetItemImage(item, GetMainColumn(), which); } - int GetItemImage(const wxTreeItemId& item, size_t column, - wxTreeItemIcon which = wxTreeItemIcon_Normal) const; - - // get the data associated with the item - wxTreeItemData *GetItemData(const wxTreeItemId& item) const; - - bool GetItemBold(const wxTreeItemId& item) const; - wxColour GetItemTextColour(const wxTreeItemId& item) const; - wxColour GetItemBackgroundColour(const wxTreeItemId& item) const; - wxFont GetItemFont(const wxTreeItemId& item) const; - - // modifiers - // --------- - - // set item's label - void SetItemText(const wxTreeItemId& item, const wxString& text) - { SetItemText(item, GetMainColumn(), text); } - void SetItemText(const wxTreeItemId& item, size_t column, - const wxString& text); - - // get one of the images associated with the item (normal by default) - void SetItemImage(const wxTreeItemId& item, int image, - wxTreeItemIcon which = wxTreeItemIcon_Normal) - { SetItemImage(item, GetMainColumn(), image, which); } - // the which parameter is ignored for all columns but the main one - void SetItemImage(const wxTreeItemId& item, size_t column, int image, - wxTreeItemIcon which = wxTreeItemIcon_Normal); - - // associate some data with the item - void SetItemData(const wxTreeItemId& item, wxTreeItemData *data); - - // force appearance of [+] button near the item. This is useful to - // allow the user to expand the items which don't have any children now - // - but instead add them only when needed, thus minimizing memory - // usage and loading time. - void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE); - - // the item will be shown in bold - void SetItemBold(const wxTreeItemId& item, bool bold = TRUE); - - // set the item's text colour - void SetItemTextColour(const wxTreeItemId& item, const wxColour& col); - - // set the item's background colour - void SetItemBackgroundColour(const wxTreeItemId& item, - const wxColour& col); - - // set the item's font (should be of the same height for all items) - void SetItemFont(const wxTreeItemId& item, const wxFont& font); - - // set the window font - virtual bool SetFont( const wxFont &font ); - - // set the styles. - void SetWindowStyle(const long styles); - long GetWindowStyle() const; - long GetWindowStyleFlag() const { return GetWindowStyle(); } - - // item status inquiries - // --------------------- - - // is the item visible (it might be outside the view or not expanded)? - bool IsVisible(const wxTreeItemId& item) const; - // does the item has any children? - bool HasChildren(const wxTreeItemId& item) const - { return ItemHasChildren(item); } - bool ItemHasChildren(const wxTreeItemId& item) const; - // is the item expanded (only makes sense if HasChildren())? - bool IsExpanded(const wxTreeItemId& item) const; - // is this item currently selected (the same as has focus)? - bool IsSelected(const wxTreeItemId& item) const; - // is item text in bold font? - bool IsBold(const wxTreeItemId& item) const; - // does the layout include space for a button? - - // number of children - // ------------------ - - // if 'recursively' is FALSE, only immediate children count, otherwise - // the returned number is the number of all items in this branch - size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); - - // navigation - // ---------- - - // wxTreeItemId.IsOk() will return FALSE if there is no such item - - // get the root tree item - wxTreeItemId GetRootItem() const; - - // get the item currently selected (may return NULL if no selection) - wxTreeItemId GetSelection() const; - - // get the items currently selected, return the number of such item - size_t GetSelections(wxArrayTreeItemIds&) const; - - // get the parent of this item (may return NULL if root) - wxTreeItemId GetParent(const wxTreeItemId& item) const; - - // for this enumeration function you must pass in a "cookie" parameter - // which is opaque for the application but is necessary for the library - // to make these functions reentrant (i.e. allow more than one - // enumeration on one and the same object simultaneously). Of course, - // the "cookie" passed to GetFirstChild() and GetNextChild() should be - // the same! - - // get the first child of this item - wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const; - // get the next child - wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const; - // get the last child of this item - this method doesn't use cookies - wxTreeItemId GetLastChild(const wxTreeItemId& item) const; - - // get the next sibling of this item - wxTreeItemId GetNextSibling(const wxTreeItemId& item) const; - // get the previous sibling - wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const; - - // get first visible item - wxTreeItemId GetFirstVisibleItem() const; - // get the next visible item: item must be visible itself! - // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() - wxTreeItemId GetNextVisible(const wxTreeItemId& item) const; - // get the previous visible item: item must be visible itself! - wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const; - - // Only for internal use right now, but should probably be public - wxTreeItemId GetNext(const wxTreeItemId& item) const; - - // operations - // ---------- - - // add the root node to the tree - wxTreeItemId AddRoot(const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item in as the first child of the parent - wxTreeItemId PrependItem(const wxTreeItemId& parent, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item after a given one - wxTreeItemId InsertItem(const wxTreeItemId& parent, - const wxTreeItemId& idPrevious, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item before the one with the given index - wxTreeItemId InsertItem(const wxTreeItemId& parent, - size_t index, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // insert a new item in as the last child of the parent - wxTreeItemId AppendItem(const wxTreeItemId& parent, - const wxString& text, - int image = -1, int selectedImage = -1, - wxTreeItemData *data = NULL); - - // delete this item and associated data if any - void Delete(const wxTreeItemId& item); - // delete all children (but don't delete the item itself) - // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events - void DeleteChildren(const wxTreeItemId& item); - // delete all items from the tree - // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events - void DeleteAllItems(); - - // expand this item - void Expand(const wxTreeItemId& item); - // expand this item and all subitems recursively - void ExpandAll(const wxTreeItemId& item); - // collapse the item without removing its children - void Collapse(const wxTreeItemId& item); - // collapse the item and remove all children - void CollapseAndReset(const wxTreeItemId& item); - // toggles the current state - void Toggle(const wxTreeItemId& item); - - // remove the selection from currently selected item (if any) - void Unselect(); - void UnselectAll(); - // select this item - void SelectItem(const wxTreeItemId& item, bool unselect_others=TRUE, - bool extended_select=FALSE); - // make sure this item is visible (expanding the parent item and/or - // scrolling to this item if necessary) - void EnsureVisible(const wxTreeItemId& item); - // scroll to this item (but don't expand its parent) - void ScrollTo(const wxTreeItemId& item); - //void AdjustMyScrollbars(); - - // The first function is more portable (because easier to implement - // on other platforms), but the second one returns some extra info. - wxTreeItemId HitTest(const wxPoint& point) - { int dummy; return HitTest(point, dummy); } - wxTreeItemId HitTest(const wxPoint& point, int& flags) - { int col; return HitTest(point, flags, col); } - wxTreeItemId HitTest(const wxPoint& point, int& flags, int& column); - - // get the bounding rectangle of the item (or of its label only) - bool GetBoundingRect(const wxTreeItemId& item, - wxRect& rect, - bool textOnly = FALSE) const; - - // Start editing the item label: this (temporarily) replaces the item - // with a one line edit control. The item will be selected if it hadn't - // been before. - void EditLabel( const wxTreeItemId& item ) { Edit( item ); } - void Edit( const wxTreeItemId& item ); - - // sorting - // this function is called to compare 2 items and should return -1, 0 - // or +1 if the first item is less than, equal to or greater than the - // second one. The base class version performs alphabetic comparaison - // of item labels (GetText) - virtual int OnCompareItems(const wxTreeItemId& item1, - const wxTreeItemId& item2); - // sort the children of this item using OnCompareItems - // - // NB: this function is not reentrant and not MT-safe (FIXME)! - void SortChildren(const wxTreeItemId& item); - - // deprecated functions: use Set/GetItemImage directly - // get the selected item image - int GetItemSelectedImage(const wxTreeItemId& item) const - { return GetItemImage(item, wxTreeItemIcon_Selected); } - // set the selected item image - void SetItemSelectedImage(const wxTreeItemId& item, int image) - { SetItemImage(item, image, wxTreeItemIcon_Selected); } - - // implementation only from now on - - // overridden base class virtuals - virtual bool SetBackgroundColour(const wxColour& colour); - virtual bool SetForegroundColour(const wxColour& colour); - - - wxTreeListHeaderWindow* GetHeaderWindow() const - { return m_header_win; } - - wxTreeListMainWindow* GetMainWindow() const - { return m_main_win; } - - -protected: - // header window, responsible for column visualization and manipulation - wxTreeListHeaderWindow* m_header_win; - // main window, the "true" tree ctrl - wxTreeListMainWindow* m_main_win; - - // the common part of all ctors - void Init(); - - void OnSize(wxSizeEvent& event); - - -private: - DECLARE_EVENT_TABLE() - DECLARE_DYNAMIC_CLASS(wxTreeListCtrl) -}; - -#endif // TREELISTCTRL_H - diff --git a/wxPython/contrib/gizmos/wxCode/include/wx/treelistctrl.h b/wxPython/contrib/gizmos/wxCode/include/wx/treelistctrl.h new file mode 100644 index 0000000000..0600984616 --- /dev/null +++ b/wxPython/contrib/gizmos/wxCode/include/wx/treelistctrl.h @@ -0,0 +1,550 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: treelistctrl.h +// Purpose: wxTreeListCtrl class +// Author: Robert Roebling +// Modified by: Alberto Griggio, 2002 +// Created: 01/02/97 +// RCS-ID: $Id$ +// Copyright: (c) Robert Roebling, Julian Smart, Alberto Griggio, +// Vadim Zeitlin, Otto Wyss +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + + +#ifndef TREELISTCTRL_H +#define TREELISTCTRL_H + +#if defined(__GNUG__) && !defined(__APPLE__) + #pragma interface "treelistctrl.h" +#endif + +#include +#include +#include +#include // for wxListEvent + +#ifdef GIZMOISDLL +#define GIZMODLLEXPORT WXDLLEXPORT +#else +#define GIZMODLLEXPORT +#endif + + +class GIZMODLLEXPORT wxTreeListItem; +class GIZMODLLEXPORT wxTreeListHeaderWindow; +class GIZMODLLEXPORT wxTreeListMainWindow; + + +// Using this typedef removes an ambiguity when calling Remove() +#ifdef __WXMSW__ +#if !wxCHECK_VERSION(2, 5, 0) +typedef long wxTreeItemIdValue; +#else +typedef void *wxTreeItemIdValue; +#endif +#endif + +//----------------------------------------------------------------------------- +// wxTreeListColumnAttrs +//----------------------------------------------------------------------------- + +enum wxTreeListColumnAlign { + wxTL_ALIGN_LEFT, + wxTL_ALIGN_RIGHT, + wxTL_ALIGN_CENTER +}; + + +class GIZMODLLEXPORT wxTreeListColumnInfo: public wxObject { +public: + enum { DEFAULT_COL_WIDTH = 100 }; + + wxTreeListColumnInfo(const wxString &text = wxT(""), + int image = -1, + size_t width = DEFAULT_COL_WIDTH, + bool shown = true, + wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT) + { + m_image = image; + m_selected_image = -1; + m_text = text; + m_width = width; + m_shown = shown; + m_alignment = alignment; + } + + wxTreeListColumnInfo(const wxTreeListColumnInfo& other) + { + m_image = other.m_image; + m_selected_image = other.m_selected_image; + m_text = other.m_text; + m_width = other.m_width; + m_shown = other.m_shown; + m_alignment = other.m_alignment; + } + + ~wxTreeListColumnInfo() {} + + // getters + bool GetShown() const { return m_shown; } + wxTreeListColumnAlign GetAlignment() const { return m_alignment; } + wxString GetText() const { return m_text; } + int GetImage() const { return m_image; } + int GetSelectedImage() const { return m_selected_image; } + size_t GetWidth() const { return m_width; } + + // setters + wxTreeListColumnInfo& SetShown(bool shown) + { m_shown = shown; return *this; } + + wxTreeListColumnInfo& SetAlignment(wxTreeListColumnAlign alignment) + { m_alignment = alignment; return *this; } + + wxTreeListColumnInfo& SetText(const wxString& text) + { m_text = text; return *this; } + + wxTreeListColumnInfo& SetImage(int image) + { m_image = image; return *this; } + + wxTreeListColumnInfo& SetSelectedImage(int image) + { m_selected_image = image; return *this; } + + wxTreeListColumnInfo& SetWidth(size_t with) + { m_width = with; return *this; } + +private: + bool m_shown; + wxTreeListColumnAlign m_alignment; + wxString m_text; + int m_image; + int m_selected_image; + size_t m_width; +}; + +//---------------------------------------------------------------------------- +// wxTreeListCtrl - the multicolumn tree control +//---------------------------------------------------------------------------- + +// flags for FindItem +const int wxTL_SEARCH_VISIBLE = 0x0000; +const int wxTL_SEARCH_LEVEL = 0x0001; +const int wxTL_SEARCH_FULL = 0x0002; +const int wxTL_SEARCH_PARTIAL = 0x0010; +const int wxTL_SEARCH_NOCASE = 0x0020; + +// additional flag for HitTest +const int wxTREE_HITTEST_ONITEMCOLUMN = 0x2000; +extern GIZMODLLEXPORT const wxChar* wxTreeListCtrlNameStr; + + +class GIZMODLLEXPORT wxTreeListCtrl : public wxControl +{ +public: + // creation + // -------- + wxTreeListCtrl() {} + + wxTreeListCtrl(wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTR_DEFAULT_STYLE, + const wxValidator &validator = wxDefaultValidator, + const wxString& name = wxTreeListCtrlNameStr ) + : m_header_win(0), m_main_win(0) + { + Create(parent, id, pos, size, style, validator, name); + } + + virtual ~wxTreeListCtrl() {} + + bool Create(wxWindow *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTR_DEFAULT_STYLE, + const wxValidator &validator = wxDefaultValidator, + const wxString& name = wxTreeListCtrlNameStr ); + + void Refresh(bool erase=TRUE, const wxRect* rect=NULL); + void SetFocus(); + // accessors + // --------- + + // get the total number of items in the control + size_t GetCount() const; + + // indent is the number of pixels the children are indented relative to + // the parents position. SetIndent() also redraws the control + // immediately. + unsigned int GetIndent() const; + void SetIndent(unsigned int indent); + + // line spacing is the space above and below the text on each line + unsigned int GetLineSpacing() const; + void SetLineSpacing(unsigned int spacing); + + // image list: these functions allow to associate an image list with + // the control and retrieve it. Note that when assigned with + // SetImageList, the control does _not_ delete + // the associated image list when it's deleted in order to allow image + // lists to be shared between different controls. If you use + // AssignImageList, the control _does_ delete the image list. + // + // The normal image list is for the icons which correspond to the + // normal tree item state (whether it is selected or not). + // Additionally, the application might choose to show a state icon + // which corresponds to an app-defined item state (for example, + // checked/unchecked) which are taken from the state image list. + wxImageList *GetImageList() const; + wxImageList *GetStateImageList() const; + wxImageList *GetButtonsImageList() const; + + void SetImageList(wxImageList *imageList); + void SetStateImageList(wxImageList *imageList); + void SetButtonsImageList(wxImageList *imageList); + void AssignImageList(wxImageList *imageList); + void AssignStateImageList(wxImageList *imageList); + void AssignButtonsImageList(wxImageList *imageList); + + + // Functions to work with tree list ctrl columns + + // adds a column + void AddColumn(const wxString& text) + { AddColumn(wxTreeListColumnInfo(text)); } + void AddColumn(const wxString& text, + size_t width, + wxTreeListColumnAlign alignment = wxTL_ALIGN_LEFT) + { AddColumn(wxTreeListColumnInfo(text, + -1, + width, + true, + alignment)); } + void AddColumn(const wxTreeListColumnInfo& col); + + // inserts a column before the given one + void InsertColumn(size_t before, const wxString& text) + { InsertColumn(before, wxTreeListColumnInfo(text)); } + void InsertColumn(size_t before, const wxTreeListColumnInfo& col); + + // deletes the given column - does not delete the corresponding column + // of each item + void RemoveColumn(size_t column); + + // returns the number of columns in the ctrl + size_t GetColumnCount() const; + + void SetColumnWidth(size_t column, size_t width); + int GetColumnWidth(size_t column) const; + + // tells which column is the "main" one, i.e. the "threaded" one + void SetMainColumn(size_t column); + size_t GetMainColumn() const; + + void SetColumnText(size_t column, const wxString& text); + wxString GetColumnText(size_t column) const; + + void SetColumn(size_t column, const wxTreeListColumnInfo& info); + wxTreeListColumnInfo& GetColumn(size_t column); + const wxTreeListColumnInfo& GetColumn(size_t column) const; + + // other column-related methods + void SetColumnAlignment(size_t column, wxTreeListColumnAlign align); + wxTreeListColumnAlign GetColumnAlignment(size_t column) const; + + void SetColumnImage(size_t column, int image); + int GetColumnImage(size_t column) const; + + void ShowColumn(size_t column, bool shown); + bool IsColumnShown(size_t column) const; + + // Functions to work with tree list ctrl items. + + // accessors + // --------- + + // retrieve item's label (of the main column) + wxString GetItemText(const wxTreeItemId& item) const + { return GetItemText(item, GetMainColumn()); } + // retrieves item's label of the given column + wxString GetItemText(const wxTreeItemId& item, size_t column) const; + + // get one of the images associated with the item (normal by default) + int GetItemImage(const wxTreeItemId& item, + wxTreeItemIcon which = wxTreeItemIcon_Normal) const + { return GetItemImage(item, GetMainColumn(), which); } + int GetItemImage(const wxTreeItemId& item, size_t column, + wxTreeItemIcon which = wxTreeItemIcon_Normal) const; + + // get the data associated with the item + wxTreeItemData *GetItemData(const wxTreeItemId& item) const; + + bool GetItemBold(const wxTreeItemId& item) const; + wxColour GetItemTextColour(const wxTreeItemId& item) const; + wxColour GetItemBackgroundColour(const wxTreeItemId& item) const; + wxFont GetItemFont(const wxTreeItemId& item) const; + + // modifiers + // --------- + + // set item's label + void SetItemText(const wxTreeItemId& item, const wxString& text) + { SetItemText(item, GetMainColumn(), text); } + void SetItemText(const wxTreeItemId& item, size_t column, + const wxString& text); + + // get one of the images associated with the item (normal by default) + void SetItemImage(const wxTreeItemId& item, int image, + wxTreeItemIcon which = wxTreeItemIcon_Normal) + { SetItemImage(item, GetMainColumn(), image, which); } + // the which parameter is ignored for all columns but the main one + void SetItemImage(const wxTreeItemId& item, size_t column, int image, + wxTreeItemIcon which = wxTreeItemIcon_Normal); + + // associate some data with the item + void SetItemData(const wxTreeItemId& item, wxTreeItemData *data); + + // force appearance of [+] button near the item. This is useful to + // allow the user to expand the items which don't have any children now + // - but instead add them only when needed, thus minimizing memory + // usage and loading time. + void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE); + + // the item will be shown in bold + void SetItemBold(const wxTreeItemId& item, bool bold = TRUE); + + // set the item's text colour + void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour); + + // set the item's background colour + void SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour); + + // set the item's font (should be of the same height for all items) + void SetItemFont(const wxTreeItemId& item, const wxFont& font); + + // set the window font + virtual bool SetFont( const wxFont &font ); + + // set the styles. + void SetWindowStyle(const long styles); + long GetWindowStyle() const; + long GetWindowStyleFlag() const { return GetWindowStyle(); } + + // item status inquiries + // --------------------- + + // is the item visible (it might be outside the view or not expanded)? + bool IsVisible(const wxTreeItemId& item) const; + // does the item has any children? + bool HasChildren(const wxTreeItemId& item) const + { return ItemHasChildren(item); } + bool ItemHasChildren(const wxTreeItemId& item) const; + // is the item expanded (only makes sense if HasChildren())? + bool IsExpanded(const wxTreeItemId& item) const; + // is this item currently selected (the same as has focus)? + bool IsSelected(const wxTreeItemId& item) const; + // is item text in bold font? + bool IsBold(const wxTreeItemId& item) const; + // does the layout include space for a button? + + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); + + // navigation + // ---------- + + // wxTreeItemId.IsOk() will return FALSE if there is no such item + + // get the root tree item + wxTreeItemId GetRootItem() const; + + // get the item currently selected (may return NULL if no selection) + wxTreeItemId GetSelection() const; + + // get the items currently selected, return the number of such item + size_t GetSelections(wxArrayTreeItemIds&) const; + + // get the parent of this item (may return NULL if root) + wxTreeItemId GetItemParent(const wxTreeItemId& item) const; + + // for this enumeration function you must pass in a "cookie" parameter + // which is opaque for the application but is necessary for the library + // to make these functions reentrant (i.e. allow more than one + // enumeration on one and the same object simultaneously). Of course, + // the "cookie" passed to GetFirstChild() and GetNextChild() should be + // the same! + + // get the first child of this item +#if !wxCHECK_VERSION(2, 5, 0) + wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const; +#else + wxTreeItemId GetFirstChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const; +#endif + // get the next child +#if !wxCHECK_VERSION(2, 5, 0) + wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const; +#else + wxTreeItemId GetNextChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const; +#endif + // get the prev child +#if !wxCHECK_VERSION(2, 5, 0) + wxTreeItemId GetPrevChild(const wxTreeItemId& item, long& cookie) const; +#else + wxTreeItemId GetPrevChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const; +#endif + // get the last child of this item - this method doesn't use cookies + wxTreeItemId GetLastChild(const wxTreeItemId& item) const; + + // get the next sibling of this item + wxTreeItemId GetNextSibling(const wxTreeItemId& item) const; + // get the previous sibling + wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const; + + // get first visible item + wxTreeItemId GetFirstVisibleItem() const; + // get the next visible item: item must be visible itself! + // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() + wxTreeItemId GetNextVisible(const wxTreeItemId& item) const; + // get the previous visible item: item must be visible itself! + wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const; + + // Only for internal use right now, but should probably be public + wxTreeItemId GetNext(const wxTreeItemId& item) const; + + // operations + // ---------- + + // add the root node to the tree + wxTreeItemId AddRoot(const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item in as the first child of the parent + wxTreeItemId PrependItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item after a given one + wxTreeItemId InsertItem(const wxTreeItemId& parent, + const wxTreeItemId& idPrevious, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item before the one with the given index + wxTreeItemId InsertItem(const wxTreeItemId& parent, + size_t index, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item in as the last child of the parent + wxTreeItemId AppendItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // delete this item and associated data if any + void Delete(const wxTreeItemId& item); + // delete all children (but don't delete the item itself) + // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events + void DeleteChildren(const wxTreeItemId& item); + // delete all items from the tree + // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events + void DeleteAllItems(); + + // expand this item + void Expand(const wxTreeItemId& item); + // expand this item and all subitems recursively + void ExpandAll(const wxTreeItemId& item); + // collapse the item without removing its children + void Collapse(const wxTreeItemId& item); + // collapse the item and remove all children + void CollapseAndReset(const wxTreeItemId& item); + // toggles the current state + void Toggle(const wxTreeItemId& item); + + // remove the selection from currently selected item (if any) + void Unselect(); + void UnselectAll(); + // select this item + void SelectItem(const wxTreeItemId& item, bool unselect_others=TRUE, + bool extended_select=FALSE); + void SelectAll(bool extended_select=FALSE); + // make sure this item is visible (expanding the parent item and/or + // scrolling to this item if necessary) + void EnsureVisible(const wxTreeItemId& item); + // scroll to this item (but don't expand its parent) + void ScrollTo(const wxTreeItemId& item); + //void AdjustMyScrollbars(); + + // The first function is more portable (because easier to implement + // on other platforms), but the second one returns some extra info. + wxTreeItemId HitTest(const wxPoint& point) + { int dummy; return HitTest(point, dummy); } + wxTreeItemId HitTest(const wxPoint& point, int& flags) + { int col; return HitTest(point, flags, col); } + wxTreeItemId HitTest(const wxPoint& point, int& flags, int& column); + + // get the bounding rectangle of the item (or of its label only) + bool GetBoundingRect(const wxTreeItemId& item, + wxRect& rect, + bool textOnly = FALSE) const; + + // Start editing the item label: this (temporarily) replaces the item + // with a one line edit control. The item will be selected if it hadn't + // been before. + void EditLabel( const wxTreeItemId& item ) { Edit( item ); } + void Edit( const wxTreeItemId& item ); + + // sorting + // this function is called to compare 2 items and should return -1, 0 + // or +1 if the first item is less than, equal to or greater than the + // second one. The base class version performs alphabetic comparaison + // of item labels (GetText) + virtual int OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2); + // sort the children of this item using OnCompareItems + // + // NB: this function is not reentrant and not MT-safe (FIXME)! + void SortChildren(const wxTreeItemId& item); + + // searching + wxTreeItemId FindItem (const wxTreeItemId& item, const wxString& str, int flags = 0); + + // overridden base class virtuals + virtual bool SetBackgroundColour(const wxColour& colour); + virtual bool SetForegroundColour(const wxColour& colour); + + + wxTreeListHeaderWindow* GetHeaderWindow() const + { return m_header_win; } + + wxTreeListMainWindow* GetMainWindow() const + { return m_main_win; } + +protected: + // header window, responsible for column visualization and manipulation + wxTreeListHeaderWindow* m_header_win; + // main window, the "true" tree ctrl + wxTreeListMainWindow* m_main_win; + +// // the common part of all ctors +// void Init(); + + void OnSize(wxSizeEvent& event); + + +private: + size_t fill_column; + + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxTreeListCtrl) +}; + +#endif // TREELISTCTRL_H + diff --git a/wxPython/contrib/gizmos/wxCode/src/treelistctrl.cpp b/wxPython/contrib/gizmos/wxCode/src/treelistctrl.cpp new file mode 100644 index 0000000000..288ea108b6 --- /dev/null +++ b/wxPython/contrib/gizmos/wxCode/src/treelistctrl.cpp @@ -0,0 +1,5015 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: treelistctrl.cpp +// Purpose: multi column tree control implementation +// Author: Robert Roebling +// Created: 01/02/97 +// Modified: Alberto Griggio, 2002 +// 22/10/98 - almost total rewrite, simpler interface (VZ) +// Id: $Id$ +// Copyright: (c) Robert Roebling, Julian Smart, Alberto Griggio, +// Vadim Zeitlin, Otto Wyss +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// =========================================================================== +// declarations +// =========================================================================== + +// --------------------------------------------------------------------------- +// headers +// --------------------------------------------------------------------------- + +#if defined(__GNUG__) && !defined(__APPLE__) + #pragma implementation "treelistctrl.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wx/treelistctrl.h" + +#ifdef __WXGTK__ + #include + #include +#endif + +// --------------------------------------------------------------------------- +// array types +// --------------------------------------------------------------------------- + +class wxTreeListItem; + +#if !wxCHECK_VERSION(2, 5, 0) +WX_DEFINE_ARRAY(wxTreeListItem *, wxArrayTreeListItems); +#else +WX_DEFINE_ARRAY_PTR(wxTreeListItem *, wxArrayTreeListItems); +#endif + +#include +WX_DECLARE_OBJARRAY(wxTreeListColumnInfo, wxArrayTreeListColumnInfo); +#include +WX_DEFINE_OBJARRAY(wxArrayTreeListColumnInfo); + +#if !wxCHECK_VERSION(2, 3, 3) +WX_DEFINE_ARRAY(short, wxArrayShort); +#endif + + +// -------------------------------------------------------------------------- +// constants +// -------------------------------------------------------------------------- + +static const int NO_IMAGE = -1; + +const int LINEHEIGHT = 10; +const int PIXELS_PER_UNIT = 10; +const int LINEATROOT = 5; +const int MARGIN = 2; +const int MININDENT = 10; +const int BTNWIDTH = 11; +const int BTNHEIGHT = 11; + +const wxChar* wxTreeListCtrlNameStr = wxT("treelistctrl"); + +static wxTreeListColumnInfo wxInvalidTreeListColumnInfo; + + +// --------------------------------------------------------------------------- +// private classes +// --------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// wxTreeListHeaderWindow (internal) +//----------------------------------------------------------------------------- + +class wxTreeListHeaderWindow : public wxWindow +{ +protected: + wxTreeListMainWindow *m_owner; + wxCursor *m_currentCursor; + wxCursor *m_resizeCursor; + bool m_isDragging; + + // column being resized + int m_column; + + // divider line position in logical (unscrolled) coords + int m_currentX; + + // minimal position beyond which the divider line can't be dragged in + // logical coords + int m_minX; + + wxArrayTreeListColumnInfo m_columns; + + // total width of the columns + int m_total_col_width; + + +public: + wxTreeListHeaderWindow(); + + wxTreeListHeaderWindow( wxWindow *win, + wxWindowID id, + wxTreeListMainWindow *owner, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + long style = 0, + const wxString &name = wxT("wxtreelistctrlcolumntitles") ); + + virtual ~wxTreeListHeaderWindow(); + + void DoDrawRect( wxDC *dc, int x, int y, int w, int h ); + void DrawCurrent(); + void AdjustDC(wxDC& dc); + + void OnPaint( wxPaintEvent &event ); + void OnMouse( wxMouseEvent &event ); + void OnSetFocus( wxFocusEvent &event ); + + + // columns manipulation + + size_t GetColumnCount() const { return m_columns.GetCount(); } + + void AddColumn(const wxTreeListColumnInfo& col); + + void InsertColumn(size_t before, const wxTreeListColumnInfo& col); + + void RemoveColumn(size_t column); + + void SetColumn(size_t column, const wxTreeListColumnInfo& info); + const wxTreeListColumnInfo& GetColumn(size_t column) const + { + wxCHECK_MSG(column < GetColumnCount(), wxInvalidTreeListColumnInfo, wxT("Invalid column")); + return m_columns[column]; + } + wxTreeListColumnInfo& GetColumn(size_t column) + { + wxCHECK_MSG(column < GetColumnCount(), wxInvalidTreeListColumnInfo, wxT("Invalid column")); + return m_columns[column]; + } + + void SetColumnWidth(size_t column, size_t width); + + void SetColumnText(size_t column, const wxString& text) + { + wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); + m_columns[column].SetText(text); + } + + void SetColumnShown(size_t column, bool shown) + { + wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); + m_columns[column].SetShown(shown); + } + + wxString GetColumnText(size_t column) const + { + wxCHECK_MSG(column < GetColumnCount(), wxEmptyString, wxT("Invalid column")); + return m_columns[column].GetText(); + } + + int GetColumnWidth(size_t column) const + { + wxCHECK_MSG(column < GetColumnCount(), -1, wxT("Invalid column")); + return m_columns[column].GetWidth(); + } + + int GetWidth() const { return m_total_col_width; } + + int GetColumnShown(size_t column) const + { + wxCHECK_MSG(column < GetColumnCount(), -1, wxT("Invalid column")); + return m_columns[column].GetShown(); + } + + // needs refresh + bool m_dirty; + +private: + // common part of all ctors + void Init(); + + void SendListEvent(wxEventType type, wxPoint pos); + + DECLARE_DYNAMIC_CLASS(wxTreeListHeaderWindow) + DECLARE_EVENT_TABLE() +}; + + +// this is the "true" control +class wxTreeListMainWindow: public wxScrolledWindow +{ +public: + // creation + // -------- + wxTreeListMainWindow() { Init(); } + + wxTreeListMainWindow(wxTreeListCtrl *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTR_DEFAULT_STYLE, + const wxValidator &validator = wxDefaultValidator, + const wxString& name = wxT("wxtreelistmainwindow")) + { + Init(); + Create(parent, id, pos, size, style, validator, name); + } + + virtual ~wxTreeListMainWindow(); + + bool Create(wxTreeListCtrl *parent, wxWindowID id = -1, + const wxPoint& pos = wxDefaultPosition, + const wxSize& size = wxDefaultSize, + long style = wxTR_DEFAULT_STYLE, + const wxValidator &validator = wxDefaultValidator, + const wxString& name = wxT("wxtreelistctrl")); + + // accessors + // --------- + + // get the total number of items in the control + size_t GetCount() const; + + // indent is the number of pixels the children are indented relative to + // the parents position. SetIndent() also redraws the control + // immediately. + unsigned int GetIndent() const { return m_indent; } + void SetIndent(unsigned int indent); + + // see wxTreeListCtrl for the meaning + unsigned int GetLineSpacing() const { return m_linespacing; } + void SetLineSpacing(unsigned int spacing); + + // image list: these functions allow to associate an image list with + // the control and retrieve it. Note that when assigned with + // SetImageList, the control does _not_ delete + // the associated image list when it's deleted in order to allow image + // lists to be shared between different controls. If you use + // AssignImageList, the control _does_ delete the image list. + + // The normal image list is for the icons which correspond to the + // normal tree item state (whether it is selected or not). + // Additionally, the application might choose to show a state icon + // which corresponds to an app-defined item state (for example, + // checked/unchecked) which are taken from the state image list. + wxImageList *GetImageList() const; + wxImageList *GetStateImageList() const; + wxImageList *GetButtonsImageList() const; + + void SetImageList(wxImageList *imageList); + void SetStateImageList(wxImageList *imageList); + void SetButtonsImageList(wxImageList *imageList); + void AssignImageList(wxImageList *imageList); + void AssignStateImageList(wxImageList *imageList); + void AssignButtonsImageList(wxImageList *imageList); + + // Functions to work with tree ctrl items. + + // accessors + // --------- + + // retrieve item's label + wxString GetItemText(const wxTreeItemId& item) const + { return GetItemText(item, GetMainColumn()); } + // get one of the images associated with the item (normal by default) + int GetItemImage(const wxTreeItemId& item, + wxTreeItemIcon which = wxTreeItemIcon_Normal) const + { return GetItemImage(item, GetMainColumn(), which); } + + // get the data associated with the item + wxTreeItemData *GetItemData(const wxTreeItemId& item) const; + + bool GetItemBold(const wxTreeItemId& item) const; + wxColour GetItemTextColour(const wxTreeItemId& item) const; + wxColour GetItemBackgroundColour(const wxTreeItemId& item) const; + wxFont GetItemFont(const wxTreeItemId& item) const; + + // modifiers + // --------- + + // set item's label + void SetItemText(const wxTreeItemId& item, const wxString& text) + { SetItemText(item, GetMainColumn(), text); } + + // get one of the images associated with the item (normal by default) + void SetItemImage(const wxTreeItemId& item, int image, + wxTreeItemIcon which = wxTreeItemIcon_Normal) + { SetItemImage(item, GetMainColumn(), image, which); } + + // associate some data with the item + void SetItemData(const wxTreeItemId& item, wxTreeItemData *data); + + // force appearance of [+] button near the item. This is useful to + // allow the user to expand the items which don't have any children now + // - but instead add them only when needed, thus minimizing memory + // usage and loading time. + void SetItemHasChildren(const wxTreeItemId& item, bool has = TRUE); + + // the item will be shown in bold + void SetItemBold(const wxTreeItemId& item, bool bold = TRUE); + + // set the item's text colour + void SetItemTextColour(const wxTreeItemId& item, const wxColour& colour); + + // set the item's background colour + void SetItemBackgroundColour(const wxTreeItemId& item, const wxColour& colour); + + // set the item's font (should be of the same height for all items) + void SetItemFont(const wxTreeItemId& item, const wxFont& font); + + // set the window font + virtual bool SetFont( const wxFont &font ); + + // set the styles. No need to specify a GetWindowStyle here since + // the base wxWindow member function will do it for us + void SetWindowStyle(const long styles); + + // item status inquiries + // --------------------- + + // is the item visible (it might be outside the view or not expanded)? + bool IsVisible(const wxTreeItemId& item) const; + // does the item has any children? + bool HasChildren(const wxTreeItemId& item) const + { return ItemHasChildren(item); } + bool ItemHasChildren(const wxTreeItemId& item) const; + // is the item expanded (only makes sense if HasChildren())? + bool IsExpanded(const wxTreeItemId& item) const; + // is this item currently selected (the same as has focus)? + bool IsSelected(const wxTreeItemId& item) const; + // is item text in bold font? + bool IsBold(const wxTreeItemId& item) const; + // does the layout include space for a button? + + // number of children + // ------------------ + + // if 'recursively' is FALSE, only immediate children count, otherwise + // the returned number is the number of all items in this branch + size_t GetChildrenCount(const wxTreeItemId& item, bool recursively = TRUE); + + // navigation + // ---------- + + // wxTreeItemId.IsOk() will return FALSE if there is no such item + + // get the root tree item + wxTreeItemId GetRootItem() const { return m_anchor; } + + // get the item currently selected (may return NULL if no selection) + wxTreeItemId GetSelection() const { return m_current; } + + // get the items currently selected, return the number of such item + size_t GetSelections(wxArrayTreeItemIds&) const; + + // get the parent of this item (may return NULL if root) + wxTreeItemId GetItemParent(const wxTreeItemId& item) const; + + // for this enumeration function you must pass in a "cookie" parameter + // which is opaque for the application but is necessary for the library + // to make these functions reentrant (i.e. allow more than one + // enumeration on one and the same object simultaneously). Of course, + // the "cookie" passed to GetFirstChild() and GetNextChild() should be + // the same! + + // get the first child of this item +#if !wxCHECK_VERSION(2, 5, 0) + wxTreeItemId GetFirstChild(const wxTreeItemId& item, long& cookie) const; +#else + wxTreeItemId GetFirstChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const; +#endif + // get the next child +#if !wxCHECK_VERSION(2, 5, 0) + wxTreeItemId GetNextChild(const wxTreeItemId& item, long& cookie) const; +#else + wxTreeItemId GetNextChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const; +#endif + // get the prev child +#if !wxCHECK_VERSION(2, 5, 0) + wxTreeItemId GetPrevChild(const wxTreeItemId& item, long& cookie) const; +#else + wxTreeItemId GetPrevChild(const wxTreeItemId& item, wxTreeItemIdValue& cookie) const; +#endif + // get the last child of this item - this method doesn't use cookies + wxTreeItemId GetLastChild(const wxTreeItemId& item) const; + + // get the next sibling of this item + wxTreeItemId GetNextSibling(const wxTreeItemId& item) const; + // get the previous sibling + wxTreeItemId GetPrevSibling(const wxTreeItemId& item) const; + + // get first visible item + wxTreeItemId GetFirstVisibleItem() const; + // get the next visible item: item must be visible itself! + // see IsVisible() and wxTreeCtrl::GetFirstVisibleItem() + wxTreeItemId GetNextVisible(const wxTreeItemId& item) const; + // get the previous visible item: item must be visible itself! + wxTreeItemId GetPrevVisible(const wxTreeItemId& item) const; + + // Only for internal use right now, but should probably be public + wxTreeItemId GetNext(const wxTreeItemId& item) const; + + // operations + // ---------- + + // add the root node to the tree + wxTreeItemId AddRoot(const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item in as the first child of the parent + wxTreeItemId PrependItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item after a given one + wxTreeItemId InsertItem(const wxTreeItemId& parent, + const wxTreeItemId& idPrevious, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item before the one with the given index + wxTreeItemId InsertItem(const wxTreeItemId& parent, + size_t index, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // insert a new item in as the last child of the parent + wxTreeItemId AppendItem(const wxTreeItemId& parent, + const wxString& text, + int image = -1, int selectedImage = -1, + wxTreeItemData *data = NULL); + + // delete this item and associated data if any + void Delete(const wxTreeItemId& item); + // delete all children (but don't delete the item itself) + // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events + void DeleteChildren(const wxTreeItemId& item); + // delete all items from the tree + // NB: this won't send wxEVT_COMMAND_TREE_ITEM_DELETED events + void DeleteAllItems(); + + // expand this item + void Expand(const wxTreeItemId& item); + // expand this item and all subitems recursively + void ExpandAll(const wxTreeItemId& item); + // collapse the item without removing its children + void Collapse(const wxTreeItemId& item); + // collapse the item and remove all children + void CollapseAndReset(const wxTreeItemId& item); + // toggles the current state + void Toggle(const wxTreeItemId& item); + + // remove the selection from currently selected item (if any) + void Unselect(); + void UnselectAll(); + // select this item + void SelectItem(const wxTreeItemId& item, bool unselect_others=TRUE, + bool extended_select=FALSE); + void SelectAll(bool extended_select=FALSE); + // make sure this item is visible (expanding the parent item and/or + // scrolling to this item if necessary) + void EnsureVisible(const wxTreeItemId& item); + // scroll to this item (but don't expand its parent) + void ScrollTo(const wxTreeItemId& item); + void AdjustMyScrollbars(); + + // The first function is more portable (because easier to implement + // on other platforms), but the second one returns some extra info. + wxTreeItemId HitTest(const wxPoint& point) + { int dummy; return HitTest(point, dummy); } + wxTreeItemId HitTest(const wxPoint& point, int& flags) + { int col; return HitTest(point, flags, col); } + // ALB + wxTreeItemId HitTest(const wxPoint& point, int& flags, int& column); + + + // get the bounding rectangle of the item (or of its label only) + bool GetBoundingRect(const wxTreeItemId& item, + wxRect& rect, + bool textOnly = FALSE) const; + + // Start editing the item label: this (temporarily) replaces the item + // with a one line edit control. The item will be selected if it hadn't + // been before. + void EditLabel( const wxTreeItemId& item ) { Edit( item ); } + void Edit( const wxTreeItemId& item ); + + // sorting + // this function is called to compare 2 items and should return -1, 0 + // or +1 if the first item is less than, equal to or greater than the + // second one. The base class version performs alphabetic comparaison + // of item labels (GetText) + virtual int OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2); + // sort the children of this item using OnCompareItems + // + // NB: this function is not reentrant and not MT-safe (FIXME)! + void SortChildren(const wxTreeItemId& item); + + // searching + wxTreeItemId FindItem (const wxTreeItemId& item, const wxString& str, int flags = 0); + + // deprecated functions: use Set/GetItemImage directly + // get the selected item image + int GetItemSelectedImage(const wxTreeItemId& item) const + { return GetItemImage(item, wxTreeItemIcon_Selected); } + // set the selected item image + void SetItemSelectedImage(const wxTreeItemId& item, int image) + { SetItemImage(item, image, wxTreeItemIcon_Selected); } + + // implementation only from now on + + // overridden base class virtuals + virtual bool SetBackgroundColour(const wxColour& colour); + virtual bool SetForegroundColour(const wxColour& colour); + + // callbacks + void OnPaint( wxPaintEvent &event ); + void OnSetFocus( wxFocusEvent &event ); + void OnKillFocus( wxFocusEvent &event ); + void OnChar( wxKeyEvent &event ); + void OnMouse( wxMouseEvent &event ); + void OnIdle( wxIdleEvent &event ); + void OnSize(wxSizeEvent& event); // ALB + void OnScroll(wxScrollWinEvent& event); // ALB + + // implementation helpers + void SendDeleteEvent(wxTreeListItem *itemBeingDeleted); + + void DrawBorder(const wxTreeItemId& item); + void DrawLine(const wxTreeItemId& item, bool below); + + size_t GetColumnCount() const + { return m_owner->GetHeaderWindow()->GetColumnCount(); } + + void SetMainColumn(size_t column) + { + if(column < GetColumnCount()) + m_main_column = column; + } + size_t GetMainColumn() const { return m_main_column; } + + void SetItemText(const wxTreeItemId& item, size_t column, + const wxString& text); + wxString GetItemText(const wxTreeItemId& item, size_t column) const; + + void SetItemImage(const wxTreeItemId& item, size_t column, int image, + wxTreeItemIcon which = wxTreeItemIcon_Normal); + int GetItemImage(const wxTreeItemId& item, size_t column, + wxTreeItemIcon which = wxTreeItemIcon_Normal) const; + + void SetFocus(); + +protected: + wxTreeListCtrl* m_owner; // ALB + + size_t m_main_column; // ALB + + friend class wxTreeListItem; + friend class wxTreeListRenameTimer; + friend class wxTreeListTextCtrl; + + wxFont m_normalFont; + wxFont m_boldFont; + + wxTreeListItem *m_anchor; + wxTreeListItem *m_current, *m_key_current, *m_currentEdit; + int m_btnWidth, m_btnWidth2; + int m_btnHeight, m_btnHeight2; + int m_imgWidth, m_imgWidth2; + int m_imgHeight, m_imgHeight2; + unsigned short m_indent; + int m_lineHeight; + unsigned short m_linespacing; + wxPen m_dottedPen; + wxBrush *m_hilightBrush, + *m_hilightUnfocusedBrush; + bool m_hasFocus; +public: + bool m_dirty; +protected: + bool m_ownsImageListNormal, + m_ownsImageListState, + m_ownsImageListButtons; + bool m_isDragging; // true between BEGIN/END drag events + bool m_renameAccept; + bool m_lastOnSame; // last click on the same item as prev + wxImageList *m_imageListNormal, + *m_imageListState, + *m_imageListButtons; + + int m_dragCount; + wxPoint m_dragStart; + wxTreeListItem *m_dropTarget; + wxCursor m_oldCursor; // cursor is changed while dragging + wxTreeListItem *m_oldSelection; + + wxTimer *m_renameTimer; + wxString m_renameRes; + + // char navigation + wxTimer *m_findTimer; + wxString m_findStr; + + // the common part of all ctors + void Init(); + + // misc helpers + wxTreeItemId DoInsertItem(const wxTreeItemId& parent, + size_t previous, + const wxString& text, + int image, int selectedImage, + wxTreeItemData *data); + bool HasButtons(void) const + { return (m_imageListButtons != NULL) || + HasFlag (wxTR_TWIST_BUTTONS|wxTR_HAS_BUTTONS); } + +protected: + void CalculateLineHeight(); + int GetLineHeight(wxTreeListItem *item) const; + void PaintLevel( wxTreeListItem *item, wxDC& dc, int level, int &y, + int x_colstart); + void PaintItem( wxTreeListItem *item, wxDC& dc); + + void CalculateLevel( wxTreeListItem *item, wxDC &dc, int level, int &y, + int x_colstart); + void CalculatePositions(); + void CalculateSize( wxTreeListItem *item, wxDC &dc ); + + void RefreshSubtree( wxTreeListItem *item ); + void RefreshLine( wxTreeListItem *item ); + + // redraw all selected items + void RefreshSelected(); + + // RefreshSelected() recursive helper + void RefreshSelectedUnder(wxTreeListItem *item); + + void OnRenameTimer(); + void OnRenameAccept(); + + void FillArray(wxTreeListItem*, wxArrayTreeItemIds&) const; + void SelectItemRange( wxTreeListItem *item1, wxTreeListItem *item2 ); + bool TagAllChildrenUntilLast(wxTreeListItem *crt_item, + wxTreeListItem *last_item, bool select); + bool TagNextChildren(wxTreeListItem *crt_item, wxTreeListItem *last_item, + bool select); + void UnselectAllChildren( wxTreeListItem *item ); + + void DrawDropEffect(wxTreeListItem *item); + +private: + DECLARE_EVENT_TABLE() + DECLARE_DYNAMIC_CLASS(wxTreeListMainWindow) +}; + + +// timer used for enabling in-place edit +class wxTreeListRenameTimer: public wxTimer +{ +public: + wxTreeListRenameTimer( wxTreeListMainWindow *owner ); + + void Notify(); + +private: + wxTreeListMainWindow *m_owner; +}; + +// control used for in-place edit +class wxTreeListTextCtrl: public wxTextCtrl +{ +public: + wxTreeListTextCtrl( wxWindow *parent, + const wxWindowID id, + bool *accept, + wxString *res, + wxTreeListMainWindow *owner, + const wxString &value = wxEmptyString, + const wxPoint &pos = wxDefaultPosition, + const wxSize &size = wxDefaultSize, + int style = wxSIMPLE_BORDER, + const wxValidator& validator = wxDefaultValidator, + const wxString &name = wxTextCtrlNameStr ); + + void OnChar( wxKeyEvent &event ); + void OnKeyUp( wxKeyEvent &event ); + void OnKillFocus( wxFocusEvent &event ); + +private: + bool *m_accept; + wxString *m_res; + wxTreeListMainWindow *m_owner; + wxString m_startValue; + bool m_finished; + + DECLARE_EVENT_TABLE() +}; + +// a tree item +class wxTreeListItem +{ +public: + // ctors & dtor + wxTreeListItem() { m_data = NULL; } + wxTreeListItem( wxTreeListMainWindow *owner, + wxTreeListItem *parent, + const wxArrayString& text, + int image, + int selImage, + wxTreeItemData *data ); + + ~wxTreeListItem(); + + // trivial accessors + wxArrayTreeListItems& GetChildren() { return m_children; } + + const wxString GetText() const + { + if(m_text.GetCount() > 0) return m_text[0]; + return wxEmptyString; + } + const wxString GetText(size_t col) const + { + if(m_text.GetCount() > col) return m_text[col]; + return wxEmptyString; + } + int GetImage(wxTreeItemIcon which = wxTreeItemIcon_Normal) const + { return m_images[which]; } + int GetImage(size_t col, wxTreeItemIcon which=wxTreeItemIcon_Normal) const + { + if(col == m_owner->GetMainColumn()) return m_images[which]; + if(col < m_col_images.GetCount()) return m_col_images[col]; + return NO_IMAGE; + } + wxTreeItemData *GetData() const { return m_data; } + + // returns the current image for the item (depending on its + // selected/expanded/whatever state) + int GetCurrentImage() const; + + void SetText( const wxString &text ); + void SetText(size_t col, const wxString& text) // ALB + { + if(col < m_text.GetCount()) + m_text[col] = text; + else if(col < m_owner->GetColumnCount()) { + int howmany = m_owner->GetColumnCount(); + for(int i = m_text.GetCount(); i < howmany; ++i) + m_text.Add(wxEmptyString); + m_text[col] = text; + } + } + void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; } + void SetImage(size_t col, int image, wxTreeItemIcon which) + { + if(col == m_owner->GetMainColumn()) m_images[which] = image; + else if(col < m_col_images.GetCount()) + m_col_images[col] = image; + else if(col < m_owner->GetColumnCount()) { + int howmany = m_owner->GetColumnCount(); + for(int i = m_col_images.GetCount(); i < howmany; ++i) + m_col_images.Add(NO_IMAGE); + m_col_images[col] = image; + } + } + + void SetData(wxTreeItemData *data) { m_data = data; } + + void SetHasPlus(bool has = TRUE) { m_hasPlus = has; } + + void SetBold(bool bold) { m_isBold = bold; } + + int GetX() const { return m_x; } + int GetY() const { return m_y; } + + void SetX(int x) { m_x = x; } + void SetY(int y) { m_y = y; } + + int GetHeight() const { return m_height; } + int GetWidth() const { return m_width; } + + void SetHeight(int h) { m_height = h; } + void SetWidth(int w) { m_width = w; } + + wxTreeListItem *GetItemParent() const { return m_parent; } + + // operations + // deletes all children notifying the treectrl about it if !NULL + // pointer given + void DeleteChildren(wxTreeListMainWindow *tree = NULL); + + // get count of all children (and grand children if 'recursively') + size_t GetChildrenCount(bool recursively = TRUE) const; + + void Insert(wxTreeListItem *child, size_t index) + { m_children.Insert(child, index); } + + void GetSize( int &x, int &y, const wxTreeListMainWindow* ); + + // return the item at given position (or NULL if no item), onButton is + // TRUE if the point belongs to the item's button, otherwise it lies + // on the button's label + wxTreeListItem *HitTest( const wxPoint& point, + const wxTreeListMainWindow *, + int &flags, + int level ); + wxTreeListItem *HitTest( const wxPoint& point, + const wxTreeListMainWindow *, + int &flags, int& column /*ALB*/, + int level ); + + void Expand() { m_isCollapsed = FALSE; } + void Collapse() { m_isCollapsed = TRUE; } + + void SetHilight( bool set = TRUE ) { m_hasHilight = set; } + + // status inquiries + bool HasChildren() const { return !m_children.IsEmpty(); } + bool IsSelected() const { return m_hasHilight != 0; } + bool IsExpanded() const { return !m_isCollapsed; } + bool HasPlus() const { return m_hasPlus || HasChildren(); } + bool IsBold() const { return m_isBold != 0; } + + // attributes + // get them - may be NULL + wxTreeItemAttr *GetAttributes() const { return m_attr; } + // get them ensuring that the pointer is not NULL + wxTreeItemAttr& Attr() + { + if ( !m_attr ) + { + m_attr = new wxTreeItemAttr; + m_ownsAttr = TRUE; + } + return *m_attr; + } + // set them + void SetAttributes(wxTreeItemAttr *attr) + { + if ( m_ownsAttr ) delete m_attr; + m_attr = attr; + m_ownsAttr = FALSE; + } + // set them and delete when done + void AssignAttributes(wxTreeItemAttr *attr) + { + SetAttributes(attr); + m_ownsAttr = TRUE; + } + +private: + wxTreeListMainWindow *m_owner; // control the item belongs to + + // since there can be very many of these, we save size by chosing + // the smallest representation for the elements and by ordering + // the members to avoid padding. + wxArrayString m_text; // labels to be rendered for item + + wxTreeItemData *m_data; // user-provided data + + wxArrayTreeListItems m_children; // list of children + wxTreeListItem *m_parent; // parent of this item + + wxTreeItemAttr *m_attr; // attributes??? + + // tree ctrl images for the normal, selected, expanded and + // expanded+selected states + short m_images[wxTreeItemIcon_Max]; + wxArrayShort m_col_images; // images for the various columns (!= main) + + wxCoord m_x; // (virtual) offset from top + wxCoord m_y; // (virtual) offset from left + short m_width; // width of this item + unsigned char m_height; // height of this item + + // use bitfields to save size + int m_isCollapsed :1; + int m_hasHilight :1; // same as focused + int m_hasPlus :1; // used for item which doesn't have + // children but has a [+] button + int m_isBold :1; // render the label in bold font + int m_ownsAttr :1; // delete attribute when done +}; + +// =========================================================================== +// implementation +// =========================================================================== + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +// translate the key or mouse event flags to the type of selection we're +// dealing with +static void EventFlagsToSelType(long style, + bool shiftDown, + bool ctrlDown, + bool &is_multiple, + bool &extended_select, + bool &unselect_others) +{ + is_multiple = (style & wxTR_MULTIPLE) != 0; + extended_select = shiftDown && is_multiple; + unselect_others = !(extended_select || (ctrlDown && is_multiple)); +} + +// --------------------------------------------------------------------------- +// wxTreeListRenameTimer (internal) +// --------------------------------------------------------------------------- + +wxTreeListRenameTimer::wxTreeListRenameTimer( wxTreeListMainWindow *owner ) +{ + m_owner = owner; +} + +void wxTreeListRenameTimer::Notify() +{ + m_owner->OnRenameTimer(); +} + +//----------------------------------------------------------------------------- +// wxTreeListTextCtrl (internal) +//----------------------------------------------------------------------------- + +BEGIN_EVENT_TABLE(wxTreeListTextCtrl,wxTextCtrl) + EVT_CHAR (wxTreeListTextCtrl::OnChar) + EVT_KEY_UP (wxTreeListTextCtrl::OnKeyUp) + EVT_KILL_FOCUS (wxTreeListTextCtrl::OnKillFocus) +END_EVENT_TABLE() + +wxTreeListTextCtrl::wxTreeListTextCtrl( wxWindow *parent, + const wxWindowID id, + bool *accept, + wxString *res, + wxTreeListMainWindow *owner, + const wxString &value, + const wxPoint &pos, + const wxSize &size, + int style, + const wxValidator& validator, + const wxString &name ) + : wxTextCtrl( parent, id, value, pos, size, style, validator, name ) +{ + m_res = res; + m_accept = accept; + m_owner = owner; + (*m_accept) = FALSE; + (*m_res) = wxEmptyString; + m_startValue = value; + m_finished = FALSE; +} + +void wxTreeListTextCtrl::OnChar( wxKeyEvent &event ) +{ + if (event.m_keyCode == WXK_RETURN) + { + (*m_accept) = TRUE; + (*m_res) = GetValue(); + + if ((*m_res) != m_startValue) + m_owner->OnRenameAccept(); + + if (!wxPendingDelete.Member(this)) + wxPendingDelete.Append(this); + + m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. + + return; + } + if (event.m_keyCode == WXK_ESCAPE) + { + (*m_accept) = FALSE; + (*m_res) = wxEmptyString; + + if (!wxPendingDelete.Member(this)) + wxPendingDelete.Append(this); + + m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. + + return; + } + event.Skip(); +} + +void wxTreeListTextCtrl::OnKeyUp( wxKeyEvent &event ) +{ + if (m_finished) + { + event.Skip(); + return; + } + + // auto-grow the textctrl: + wxSize parentSize = m_owner->GetSize(); + wxPoint myPos = GetPosition(); + wxSize mySize = GetSize(); + int sx, sy; + GetTextExtent(GetValue() + _T("M"), &sx, &sy); + if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; + if (mySize.x > sx) sx = mySize.x; + SetSize(sx, -1); + + event.Skip(); +} + +void wxTreeListTextCtrl::OnKillFocus( wxFocusEvent &event ) +{ + if (m_finished) + { + event.Skip(); + return; + } + + if (!wxPendingDelete.Member(this)) + wxPendingDelete.Append(this); + + (*m_accept) = TRUE; + (*m_res) = GetValue(); + + if ((*m_res) != m_startValue) + m_owner->OnRenameAccept(); +} + +//----------------------------------------------------------------------------- +// wxTreeListHeaderWindow +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow,wxWindow); + +BEGIN_EVENT_TABLE(wxTreeListHeaderWindow,wxWindow) + EVT_PAINT (wxTreeListHeaderWindow::OnPaint) + EVT_MOUSE_EVENTS (wxTreeListHeaderWindow::OnMouse) + EVT_SET_FOCUS (wxTreeListHeaderWindow::OnSetFocus) +END_EVENT_TABLE() + +void wxTreeListHeaderWindow::Init() +{ + m_currentCursor = (wxCursor *) NULL; + m_isDragging = FALSE; + m_dirty = FALSE; + m_total_col_width = 0; +} + +wxTreeListHeaderWindow::wxTreeListHeaderWindow() +{ + Init(); + + m_owner = (wxTreeListMainWindow *) NULL; + m_resizeCursor = (wxCursor *) NULL; +} + +wxTreeListHeaderWindow::wxTreeListHeaderWindow( wxWindow *win, + wxWindowID id, + wxTreeListMainWindow *owner, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString &name ) + : wxWindow( win, id, pos, size, style, name ) +{ + Init(); + + m_owner = owner; + m_resizeCursor = new wxCursor(wxCURSOR_SIZEWE); + + SetBackgroundColour(wxSystemSettings::GetSystemColour( + wxSYS_COLOUR_BTNFACE)); +} + +wxTreeListHeaderWindow::~wxTreeListHeaderWindow() +{ + delete m_resizeCursor; +} + +void wxTreeListHeaderWindow::DoDrawRect( wxDC *dc, int x, int y, int w, int h ) +{ +#ifdef __WXGTK__ + GtkStateType state = m_parent->IsEnabled() ? GTK_STATE_NORMAL + : GTK_STATE_INSENSITIVE; + + x = dc->XLOG2DEV( x ); + + gtk_paint_box (m_wxwindow->style, GTK_PIZZA(m_wxwindow)->bin_window, + state, GTK_SHADOW_OUT, + (GdkRectangle*) NULL, m_wxwindow, "button", + x-1, y-1, w+2, h+2); +#elif defined( __WXMAC__ ) + const int m_corner = 1; + + dc->SetBrush( *wxTRANSPARENT_BRUSH ); + + dc->SetPen( wxPen(wxSystemSettings::GetSystemColour( + wxSYS_COLOUR_BTNSHADOW), 1, wxSOLID)); + dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) + dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) + + wxPen pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID ); + + dc->SetPen( pen ); + dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) + dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) + + dc->SetPen( *wxWHITE_PEN ); + dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer) + dc->DrawRectangle( x, y, 1, h ); // left (outer) + dc->DrawLine( x, y+h-1, x+1, y+h-1 ); + dc->DrawLine( x+w-1, y, x+w-1, y+1 ); +#else // !GTK, !Mac + const int m_corner = 1; + + dc->SetBrush( *wxTRANSPARENT_BRUSH ); + + dc->SetPen( *wxBLACK_PEN ); + dc->DrawLine( x+w-m_corner+1, y, x+w, y+h ); // right (outer) + dc->DrawRectangle( x, y+h, w+1, 1 ); // bottom (outer) + + wxPen pen(wxSystemSettings::GetSystemColour( + wxSYS_COLOUR_BTNSHADOW ), 1, wxSOLID); + + dc->SetPen( pen ); + dc->DrawLine( x+w-m_corner, y, x+w-1, y+h ); // right (inner) + dc->DrawRectangle( x+1, y+h-1, w-2, 1 ); // bottom (inner) + + dc->SetPen( *wxWHITE_PEN ); + dc->DrawRectangle( x, y, w-m_corner+1, 1 ); // top (outer) + dc->DrawRectangle( x, y, 1, h ); // left (outer) + dc->DrawLine( x, y+h-1, x+1, y+h-1 ); + dc->DrawLine( x+w-1, y, x+w-1, y+1 ); +#endif +} + +// shift the DC origin to match the position of the main window horz +// scrollbar: this allows us to always use logical coords +void wxTreeListHeaderWindow::AdjustDC(wxDC& dc) +{ + int xpix; + m_owner->GetScrollPixelsPerUnit( &xpix, NULL ); + + int x; + m_owner->GetViewStart( &x, NULL ); + + // account for the horz scrollbar offset + dc.SetDeviceOrigin( -x * xpix, 0 ); +} + +void wxTreeListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) +{ + static const int HEADER_OFFSET_X = 1, HEADER_OFFSET_Y = 1; +#ifdef __WXGTK__ + wxClientDC dc( this ); +#else + wxPaintDC dc( this ); +#endif + + PrepareDC( dc ); + AdjustDC( dc ); + + dc.BeginDrawing(); + + dc.SetFont( GetFont() ); + + // width and height of the entire header window + int w, h; + GetClientSize( &w, &h ); + m_owner->CalcUnscrolledPosition(w, 0, &w, NULL); + + dc.SetBackgroundMode(wxTRANSPARENT); + + // do *not* use the listctrl colour for headers - one day we will have a + // function to set it separately + //dc.SetTextForeground( *wxBLACK ); + dc.SetTextForeground(wxSystemSettings:: + GetSystemColour( wxSYS_COLOUR_WINDOWTEXT )); + + int x = HEADER_OFFSET_X; + + int numColumns = GetColumnCount(); + for ( int i = 0; i < numColumns && x < w; i++ ) + { + if (!GetColumnShown (i)) continue; + + wxTreeListColumnInfo& column = GetColumn(i); + int wCol = column.GetWidth(); + + // the width of the rect to draw: make it smaller to fit entirely + // inside the column rect + int cw = wCol - 2; + + dc.SetPen( *wxWHITE_PEN ); + + DoDrawRect( &dc, x, HEADER_OFFSET_Y, cw, h-2 ); + + // if we have an image, draw it on the right of the label + int image = column.GetImage(); //item.m_image; + int ix = -2, iy = 0; + wxImageList* imageList = m_owner->GetImageList(); + if(image != -1) { + if(imageList) { + imageList->GetSize(image, ix, iy); + } + //else: ignore the column image + } + + // extra margins around the text label + static const int EXTRA_WIDTH = 3; + static const int EXTRA_HEIGHT = 4; + + int text_width = 0; + int text_x = x; + int image_offset = cw - ix - 1; + + switch(column.GetAlignment()) { + case wxTL_ALIGN_LEFT: + text_x += EXTRA_WIDTH; + cw -= ix + 2; + break; + case wxTL_ALIGN_RIGHT: + dc.GetTextExtent(column.GetText(), &text_width, NULL); + text_x += cw - text_width - EXTRA_WIDTH; + image_offset = 0; + break; + case wxTL_ALIGN_CENTER: + dc.GetTextExtent(column.GetText(), &text_width, NULL); + text_x += (cw - text_width)/2 + ix + 2; + image_offset = (cw - text_width - ix - 2)/2; + break; + } + + // draw the image + if(image != -1 && imageList) { + imageList->Draw(image, dc, x + image_offset/*cw - ix - 1*/, + HEADER_OFFSET_Y + (h - 4 - iy)/2, + wxIMAGELIST_DRAW_TRANSPARENT); + } + + // draw the text clipping it so that it doesn't overwrite the column + // boundary + wxDCClipper clipper(dc, x, HEADER_OFFSET_Y, cw, h - 4 ); + + dc.DrawText( column.GetText(), + text_x, HEADER_OFFSET_Y + EXTRA_HEIGHT ); + + x += wCol; + } + + int more_w = m_owner->GetSize().x - x; + if (more_w > 0) + { + DoDrawRect( &dc, x, HEADER_OFFSET_Y, more_w, h-2 ); + } + + + dc.EndDrawing(); +} + +void wxTreeListHeaderWindow::DrawCurrent() +{ + int x1 = m_currentX; + int y1 = 0; + ClientToScreen( &x1, &y1 ); + + int x2 = m_currentX-1; +#ifdef __WXMSW__ + ++x2; // but why ? +#endif + int y2 = 0; + m_owner->GetClientSize( NULL, &y2 ); + m_owner->ClientToScreen( &x2, &y2 ); + + wxScreenDC dc; + dc.SetLogicalFunction( wxINVERT ); + dc.SetPen( wxPen( *wxBLACK, 2, wxSOLID ) ); + dc.SetBrush( *wxTRANSPARENT_BRUSH ); + + AdjustDC(dc); + + dc.DrawLine( x1, y1, x2, y2 ); + + dc.SetLogicalFunction( wxCOPY ); + + dc.SetPen( wxNullPen ); + dc.SetBrush( wxNullBrush ); +} + +void wxTreeListHeaderWindow::OnMouse( wxMouseEvent &event ) +{ + // we want to work with logical coords + int x; + m_owner->CalcUnscrolledPosition(event.GetX(), 0, &x, NULL); + int y = event.GetY(); + + if (m_isDragging) + { + SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING, + event.GetPosition()); + + // we don't draw the line beyond our window, but we allow dragging it + // there + int w = 0; + GetClientSize( &w, NULL ); + m_owner->CalcUnscrolledPosition(w, 0, &w, NULL); + w -= 6; + + // erase the line if it was drawn + if ( m_currentX < w ) + DrawCurrent(); + + if (event.ButtonUp()) + { + ReleaseMouse(); + m_isDragging = FALSE; + m_dirty = TRUE; + SetColumnWidth( m_column, m_currentX - m_minX ); + Refresh(); + SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG, + event.GetPosition()); + } + else + { + if (x > m_minX + 7) + m_currentX = x; + else + m_currentX = m_minX + 7; + + // draw in the new location + if ( m_currentX < w ) + DrawCurrent(); + } + } + else // not dragging + { + m_minX = 0; + bool hit_border = FALSE; + + // end of the current column + int xpos = 0; + + // find the column where this event occured + int countCol = GetColumnCount(); + for (int col = 0; col < countCol; col++) + { + if (!GetColumnShown (col)) continue; + xpos += GetColumnWidth (col); + m_column = col; + + if ( (abs(x-xpos) < 3) && (y < 22) ) + { + // near the column border + hit_border = TRUE; + break; + } + + if ( x < xpos ) + { + // inside the column + break; + } + + m_minX = xpos; + } + + if (event.LeftDown() || event.RightUp()) + { + if (hit_border && event.LeftDown()) + { + m_isDragging = TRUE; + m_currentX = x; + DrawCurrent(); + CaptureMouse(); + SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, + event.GetPosition()); + } + else // click on a column + { + SendListEvent( event.LeftDown() + ? wxEVT_COMMAND_LIST_COL_CLICK + : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, + event.GetPosition()); + } + } + else if (event.Moving()) + { + bool setCursor; + if (hit_border) + { + setCursor = m_currentCursor == wxSTANDARD_CURSOR; + m_currentCursor = m_resizeCursor; + } + else + { + setCursor = m_currentCursor != wxSTANDARD_CURSOR; + m_currentCursor = wxSTANDARD_CURSOR; + } + + if ( setCursor ) + SetCursor(*m_currentCursor); + } + } +} + +void wxTreeListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) +{ + m_owner->SetFocus(); +} + +void wxTreeListHeaderWindow::SendListEvent(wxEventType type, wxPoint pos) +{ + wxWindow *parent = GetParent(); + wxListEvent le( type, parent->GetId() ); + le.SetEventObject( parent ); + le.m_pointDrag = pos; + + // the position should be relative to the parent window, not + // this one for compatibility with MSW and common sense: the + // user code doesn't know anything at all about this header + // window, so why should it get positions relative to it? + le.m_pointDrag.y -= GetSize().y; + + le.m_col = m_column; + parent->GetEventHandler()->ProcessEvent( le ); +} + +void wxTreeListHeaderWindow::AddColumn(const wxTreeListColumnInfo& col) +{ + m_columns.Add(col); + m_total_col_width += col.GetWidth(); + //m_owner->GetHeaderWindow()->Refresh(); + //m_dirty = TRUE; + m_owner->AdjustMyScrollbars(); + m_owner->m_dirty = TRUE; + Refresh(); +} + +void wxTreeListHeaderWindow::SetColumnWidth(size_t column, size_t width) +{ + if(column < GetColumnCount()) { + m_total_col_width -= m_columns[column].GetWidth(); + m_columns[column].SetWidth(width); + m_total_col_width += width; + m_owner->AdjustMyScrollbars(); + m_owner->m_dirty = TRUE; + //m_dirty = TRUE; + Refresh(); + } +} + + +void wxTreeListHeaderWindow::InsertColumn(size_t before, + const wxTreeListColumnInfo& col) +{ + wxCHECK_RET(before < GetColumnCount(), wxT("Invalid column index")); + m_columns.Insert(col, before); + m_total_col_width += col.GetWidth(); + //m_dirty = TRUE; + //m_owner->GetHeaderWindow()->Refresh(); + m_owner->AdjustMyScrollbars(); + m_owner->m_dirty = TRUE; + Refresh(); +} + +void wxTreeListHeaderWindow::RemoveColumn(size_t column) +{ + wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); + m_total_col_width -= m_columns[column].GetWidth(); + m_columns.RemoveAt(column); + //m_dirty = TRUE; + m_owner->AdjustMyScrollbars(); + m_owner->m_dirty = TRUE; + Refresh(); +} + +void wxTreeListHeaderWindow::SetColumn(size_t column, + const wxTreeListColumnInfo& info) +{ + wxCHECK_RET(column < GetColumnCount(), wxT("Invalid column")); + size_t w = m_columns[column].GetWidth(); + m_columns[column] = info; + //m_owner->GetHeaderWindow()->Refresh(); + //m_dirty = TRUE; + if(w != info.GetWidth()) { + m_total_col_width += info.GetWidth() - w; + m_owner->AdjustMyScrollbars(); + m_owner->m_dirty = TRUE; + } + Refresh(); +} + +// --------------------------------------------------------------------------- +// wxTreeListItem +// --------------------------------------------------------------------------- + +wxTreeListItem::wxTreeListItem(wxTreeListMainWindow *owner, + wxTreeListItem *parent, + const wxArrayString& text, + int image, int selImage, + wxTreeItemData *data) + : m_text(text) +{ + m_images[wxTreeItemIcon_Normal] = image; + m_images[wxTreeItemIcon_Selected] = selImage; + m_images[wxTreeItemIcon_Expanded] = NO_IMAGE; + m_images[wxTreeItemIcon_SelectedExpanded] = NO_IMAGE; + + m_data = data; + m_x = m_y = 0; + + m_isCollapsed = TRUE; + m_hasHilight = FALSE; + m_hasPlus = FALSE; + m_isBold = FALSE; + + m_owner = owner; + + m_parent = parent; + + m_attr = (wxTreeItemAttr *)NULL; + m_ownsAttr = FALSE; + + // We don't know the height here yet. + m_width = 0; + m_height = 0; +} + +wxTreeListItem::~wxTreeListItem() +{ + delete m_data; + + if (m_ownsAttr) delete m_attr; + + wxASSERT_MSG( m_children.IsEmpty(), + wxT("please call DeleteChildren() before deleting the item") ); +} + +void wxTreeListItem::DeleteChildren(wxTreeListMainWindow *tree) +{ + size_t count = m_children.Count(); + for ( size_t n = 0; n < count; n++ ) + { + wxTreeListItem *child = m_children[n]; + if (tree) + tree->SendDeleteEvent(child); + + child->DeleteChildren(tree); + delete child; + } + + m_children.Empty(); +} + +void wxTreeListItem::SetText( const wxString &text ) +{ + if(m_text.GetCount() > 0) m_text[0] = text; + else { + m_text.Add(text); + } +} + +size_t wxTreeListItem::GetChildrenCount(bool recursively) const +{ + size_t count = m_children.Count(); + if ( !recursively ) + return count; + + size_t total = count; + for (size_t n = 0; n < count; ++n) + { + total += m_children[n]->GetChildrenCount(); + } + + return total; +} + +void wxTreeListItem::GetSize( int &x, int &y, + const wxTreeListMainWindow *theButton ) +{ + int bottomY=m_y+theButton->GetLineHeight(this); + if ( y < bottomY ) y = bottomY; + int width = m_x + m_width; + if ( x < width ) x = width; + + if (IsExpanded()) + { + size_t count = m_children.Count(); + for ( size_t n = 0; n < count; ++n ) + { + m_children[n]->GetSize( x, y, theButton ); + } + } +} + +wxTreeListItem *wxTreeListItem::HitTest(const wxPoint& point, + const wxTreeListMainWindow *theCtrl, + int &flags, + int level) +{ + // for a hidden root node, don't evaluate it, but do evaluate children + if (!(theCtrl->HasFlag(wxTR_HIDE_ROOT) && (level == 0))) + { + // evaluate the item + int h = theCtrl->GetLineHeight(this); + if ((point.y > m_y) && (point.y < m_y + h)) + { + // check for above/below middle + int y_mid = m_y + h/2; + if (point.y < y_mid ) + flags |= wxTREE_HITTEST_ONITEMUPPERPART; + else + flags |= wxTREE_HITTEST_ONITEMLOWERPART; + + // check for button hit + if (HasPlus() && theCtrl->HasButtons()) { + int bntX = m_x - theCtrl->m_btnWidth2; + int bntY = y_mid - theCtrl->m_btnHeight2; + if ((point.x > bntX) && (point.x < (bntX + theCtrl->m_btnWidth)) && + (point.y > bntY) && (point.y < (bntY + theCtrl->m_btnHeight))) { + flags |= wxTREE_HITTEST_ONITEMBUTTON; + return this; + } + } + + // check for image hit + if (theCtrl->m_imgWidth > 0) { + int imgX = m_x - theCtrl->m_imgWidth2; + int imgY = y_mid - theCtrl->m_imgHeight2; + if ((point.x >= imgX) && (point.x <= (imgX + theCtrl->m_imgWidth)) && + (point.y >= imgY) && (point.y <= (imgY + theCtrl->m_imgHeight))) { + flags |= wxTREE_HITTEST_ONITEMICON; + return this; + } + } + + // check for label hit + int lblX = m_x - theCtrl->m_imgWidth2 + theCtrl->m_imgWidth + MARGIN; + if ((point.x >= lblX) && (point.x <= (m_x + m_width)) && + (point.y >= m_y) && (point.y <= (m_y + h))) { + flags |= wxTREE_HITTEST_ONITEMLABEL; + return this; + } + + // else check for indent + if (point.x < m_x) { + flags |= wxTREE_HITTEST_ONITEMINDENT; + return this; + } + + // else check for item right??? + if (point.x > m_x + m_width) { + flags |= wxTREE_HITTEST_ONITEMRIGHT; + return this; + } + + } + + // if children are expanded, fall through to evaluate them + if (m_isCollapsed) return (wxTreeListItem*) NULL; + } + + // evaluate children + size_t count = m_children.Count(); + for ( size_t n = 0; n < count; n++ ) + { + wxTreeListItem *res = m_children[n]->HitTest(point, theCtrl, + flags, level + 1); + if ( res != NULL ) + return res; + } + + return (wxTreeListItem*) NULL; +} + +// ALB +wxTreeListItem *wxTreeListItem::HitTest(const wxPoint& point, + const wxTreeListMainWindow *theCtrl, + int &flags, int& column, int level) +{ + column = theCtrl->GetMainColumn(); //-1; + + wxTreeListItem* res = HitTest(point, theCtrl, flags, level); + if(!res) { + column = -1; + return res; + } + + wxTreeListHeaderWindow* header_win = theCtrl->m_owner->GetHeaderWindow(); + if (point.x >= header_win->GetWidth()) + column = -1; + else if(flags & wxTREE_HITTEST_ONITEMINDENT) { + int x = 0; + for(size_t i = 0; i < theCtrl->GetMainColumn(); ++i) { + if (!header_win->GetColumnShown(i)) continue; + int w = header_win->GetColumnWidth(i); + if(point.x >= x && point.x < x+w) { + flags ^= wxTREE_HITTEST_ONITEMINDENT; + flags |= wxTREE_HITTEST_ONITEMCOLUMN; + column = i; + return res; + } + } + } + else if(flags & wxTREE_HITTEST_ONITEMRIGHT) { + int x = 0; + size_t i; + for(i = 0; i < theCtrl->GetMainColumn()+1; ++i) { + if (!header_win->GetColumnShown(i)) continue; + x += header_win->GetColumnWidth(i); + } + for(i = theCtrl->GetMainColumn()+1; i < theCtrl->GetColumnCount(); ++i) { + if (!header_win->GetColumnShown(i)) continue; + int w = header_win->GetColumnWidth(i); + if(point.x >= x && point.x < x+w) { + flags ^= wxTREE_HITTEST_ONITEMRIGHT; + flags |= wxTREE_HITTEST_ONITEMCOLUMN; + column = i; + return res; + } + } + } + + return res; +} + + +int wxTreeListItem::GetCurrentImage() const +{ + int image = NO_IMAGE; + if ( IsExpanded() ) + { + if ( IsSelected() ) + { + image = GetImage(wxTreeItemIcon_SelectedExpanded); + } + + if ( image == NO_IMAGE ) + { + // we usually fall back to the normal item, but try just the + // expanded one (and not selected) first in this case + image = GetImage(wxTreeItemIcon_Expanded); + } + } + else // not expanded + { + if ( IsSelected() ) + image = GetImage(wxTreeItemIcon_Selected); + } + + // maybe it doesn't have the specific image we want, + // try the default one instead + if ( image == NO_IMAGE ) image = GetImage(); + + return image; +} + +// --------------------------------------------------------------------------- +// wxTreeListMainWindow implementation +// --------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxTreeListMainWindow, wxScrolledWindow) + +BEGIN_EVENT_TABLE(wxTreeListMainWindow, wxScrolledWindow) + EVT_PAINT (wxTreeListMainWindow::OnPaint) + EVT_MOUSE_EVENTS (wxTreeListMainWindow::OnMouse) + EVT_CHAR (wxTreeListMainWindow::OnChar) + EVT_SET_FOCUS (wxTreeListMainWindow::OnSetFocus) + EVT_KILL_FOCUS (wxTreeListMainWindow::OnKillFocus) + EVT_IDLE (wxTreeListMainWindow::OnIdle) +//? EVT_SIZE (wxTreeListMainWindow::OnSize) + EVT_SCROLLWIN (wxTreeListMainWindow::OnScroll) +END_EVENT_TABLE() + + +// --------------------------------------------------------------------------- +// construction/destruction +// --------------------------------------------------------------------------- + +void wxTreeListMainWindow::Init() +{ + m_current = m_key_current = m_anchor = (wxTreeListItem *) NULL; + m_hasFocus = FALSE; + m_dirty = FALSE; + + m_lineHeight = LINEHEIGHT; + m_indent = MININDENT; // min. indent + m_linespacing = 4; + + m_hilightBrush = new wxBrush + ( + wxSystemSettings::GetSystemColour + ( + wxSYS_COLOUR_HIGHLIGHT + ), + wxSOLID + ); + + m_hilightUnfocusedBrush = new wxBrush + ( + wxSystemSettings::GetSystemColour + ( + wxSYS_COLOUR_BTNSHADOW + ), + wxSOLID + ); + + m_imageListNormal = m_imageListButtons = + m_imageListState = (wxImageList *) NULL; + m_ownsImageListNormal = m_ownsImageListButtons = + m_ownsImageListState = FALSE; + + m_dragCount = 0; + m_isDragging = FALSE; + m_dropTarget = m_oldSelection = (wxTreeListItem *)NULL; + + m_renameTimer = new wxTreeListRenameTimer( this ); + m_lastOnSame = FALSE; + + m_findTimer = new wxTimer (this, -1); + + m_normalFont = wxSystemSettings::GetSystemFont( wxSYS_DEFAULT_GUI_FONT ); + m_boldFont = wxFont( m_normalFont.GetPointSize(), + m_normalFont.GetFamily(), + m_normalFont.GetStyle(), + wxBOLD, + m_normalFont.GetUnderlined()); +} + + +static const int HEADER_HEIGHT = 23; + +bool wxTreeListMainWindow::Create(wxTreeListCtrl *parent, + wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator &validator, + const wxString& name ) +{ +#ifdef __WXMAC__ + int major,minor; + wxGetOsVersion( &major, &minor ); + + if (style & wxTR_HAS_BUTTONS) style |= wxTR_MAC_BUTTONS; + if (style & wxTR_HAS_BUTTONS) style &= ~wxTR_HAS_BUTTONS; + style &= ~wxTR_LINES_AT_ROOT; + style |= wxTR_NO_LINES; + if (major < 10) + style |= wxTR_ROW_LINES; +#endif + + wxScrolledWindow::Create( parent, id, pos, size, + style|wxHSCROLL|wxVSCROLL, name ); + +#if wxUSE_VALIDATORS + SetValidator( validator ); +#endif + + SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX ) ); + +#ifdef __WXMSW__ + { + int i, j; + wxBitmap bmp(8, 8); + wxMemoryDC bdc; + bdc.SelectObject(bmp); + bdc.SetPen(*wxGREY_PEN); + bdc.DrawRectangle(-1, -1, 10, 10); + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + if (!((i + j) & 1)) { + bdc.DrawPoint(i, j); + } + } + } + + m_dottedPen = wxPen(bmp, 1); + } +#else + //m_dottedPen = wxPen( *wxGREY_PEN, 1, wxDOT ); // too slow under XFree86 + m_dottedPen = wxPen( wxT("grey"), 0, 0 ); // Bitmap based pen is not supported by GTK! +#endif + + // ALB + m_owner = parent; + m_main_column = 0; + + return TRUE; +} + +wxTreeListMainWindow::~wxTreeListMainWindow() +{ + delete m_hilightBrush; + delete m_hilightUnfocusedBrush; + + DeleteAllItems(); + + delete m_renameTimer; + delete m_findTimer; + if (m_ownsImageListNormal) delete m_imageListNormal; + if (m_ownsImageListState) delete m_imageListState; + if (m_ownsImageListButtons) delete m_imageListButtons; +} + + + +//----------------------------------------------------------------------------- +// accessors +//----------------------------------------------------------------------------- + +size_t wxTreeListMainWindow::GetCount() const +{ + return m_anchor == NULL ? 0u : m_anchor->GetChildrenCount(); +} + +void wxTreeListMainWindow::SetIndent(unsigned int indent) +{ + m_indent = indent; + m_dirty = TRUE; +} + +void wxTreeListMainWindow::SetLineSpacing(unsigned int spacing) +{ + m_linespacing = spacing; + m_dirty = TRUE; + CalculateLineHeight(); +} + +size_t wxTreeListMainWindow::GetChildrenCount(const wxTreeItemId& item, + bool recursively) +{ + wxCHECK_MSG( item.IsOk(), 0u, wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->GetChildrenCount(recursively); +} + +void wxTreeListMainWindow::SetWindowStyle(const long styles) +{ + // right now, just sets the styles. Eventually, we may + // want to update the inherited styles, but right now + // none of the parents has updatable styles + m_windowStyle = styles; + m_dirty = TRUE; +} + +//----------------------------------------------------------------------------- +// functions to work with tree items +//----------------------------------------------------------------------------- + +int wxTreeListMainWindow::GetItemImage(const wxTreeItemId& item, size_t column, + wxTreeItemIcon which) const +{ + wxCHECK_MSG( item.IsOk(), -1, wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->GetImage(column, which); +} + +wxTreeItemData *wxTreeListMainWindow::GetItemData(const wxTreeItemId& item) + const +{ + wxCHECK_MSG( item.IsOk(), NULL, wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->GetData(); +} + +bool wxTreeListMainWindow::GetItemBold(const wxTreeItemId& item) const +{ + wxCHECK_MSG(item.IsOk(), FALSE, wxT("invalid tree item")); + return ((wxTreeListItem *)item.m_pItem)->IsBold(); +} + +wxColour wxTreeListMainWindow::GetItemTextColour(const wxTreeItemId& item) + const +{ + wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + return pItem->Attr().GetTextColour(); +} + +wxColour wxTreeListMainWindow::GetItemBackgroundColour( + const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxNullColour, wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + return pItem->Attr().GetBackgroundColour(); +} + +wxFont wxTreeListMainWindow::GetItemFont(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxNullFont, wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + return pItem->Attr().GetFont(); +} + + + +void wxTreeListMainWindow::SetItemImage(const wxTreeItemId& item, + size_t column, + int image, wxTreeItemIcon which) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + pItem->SetImage(column, image, which); + + wxClientDC dc(this); + CalculateSize(pItem, dc); + RefreshLine(pItem); +} + +void wxTreeListMainWindow::SetItemData(const wxTreeItemId& item, + wxTreeItemData *data) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + ((wxTreeListItem*) item.m_pItem)->SetData(data); +} + +void wxTreeListMainWindow::SetItemHasChildren(const wxTreeItemId& item, + bool has) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + pItem->SetHasPlus(has); + RefreshLine(pItem); +} + +void wxTreeListMainWindow::SetItemBold(const wxTreeItemId& item, bool bold) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + // avoid redrawing the tree if no real change + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + if ( pItem->IsBold() != bold ) + { + pItem->SetBold(bold); + RefreshLine(pItem); + } +} + +void wxTreeListMainWindow::SetItemTextColour(const wxTreeItemId& item, + const wxColour& col) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + pItem->Attr().SetTextColour(col); + RefreshLine(pItem); +} + +void wxTreeListMainWindow::SetItemBackgroundColour(const wxTreeItemId& item, + const wxColour& col) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + pItem->Attr().SetBackgroundColour(col); + RefreshLine(pItem); +} + +void wxTreeListMainWindow::SetItemFont(const wxTreeItemId& item, + const wxFont& font) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + pItem->Attr().SetFont(font); + RefreshLine(pItem); +} + +bool wxTreeListMainWindow::SetFont( const wxFont &font ) +{ + wxScrolledWindow::SetFont(font); + + m_normalFont = font ; + m_boldFont = wxFont( m_normalFont.GetPointSize(), + m_normalFont.GetFamily(), + m_normalFont.GetStyle(), + wxBOLD, + m_normalFont.GetUnderlined()); + + return TRUE; +} + + +// ---------------------------------------------------------------------------- +// item status inquiries +// ---------------------------------------------------------------------------- + +bool wxTreeListMainWindow::IsVisible(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); + + // An item is only visible if it's not a descendant of a collapsed item + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + wxTreeListItem* parent = pItem->GetItemParent(); + while (parent) + { + if (!parent->IsExpanded()) + return FALSE; + parent = parent->GetItemParent(); + } + + int startX, startY; + GetViewStart(& startX, & startY); + + wxSize clientSize = GetClientSize(); + + wxRect rect; + if (!GetBoundingRect(item, rect)) + return FALSE; + if (rect.GetWidth() == 0 || rect.GetHeight() == 0) + return FALSE; + if (rect.GetBottom() < 0 || rect.GetTop() > clientSize.y) + return FALSE; + if (rect.GetRight() < 0 || rect.GetLeft() > clientSize.x) + return FALSE; + + return TRUE; +} + +bool wxTreeListMainWindow::ItemHasChildren(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); + + // consider that the item does have children if it has the "+" button: it + // might not have them (if it had never been expanded yet) but then it + // could have them as well and it's better to err on this side rather than + // disabling some operations which are restricted to the items with + // children for an item which does have them + return ((wxTreeListItem*) item.m_pItem)->HasPlus(); +} + +bool wxTreeListMainWindow::IsExpanded(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->IsExpanded(); +} + +bool wxTreeListMainWindow::IsSelected(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->IsSelected(); +} + +bool wxTreeListMainWindow::IsBold(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), FALSE, wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->IsBold(); +} + +// ---------------------------------------------------------------------------- +// navigation +// ---------------------------------------------------------------------------- + +wxTreeItemId wxTreeListMainWindow::GetItemParent(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->GetItemParent(); +} + +#if !wxCHECK_VERSION(2, 5, 0) +wxTreeItemId wxTreeListMainWindow::GetFirstChild(const wxTreeItemId& item, + long& cookie) const +#else +wxTreeItemId wxTreeListMainWindow::GetFirstChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +#endif +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + cookie = 0; + return GetNextChild(item, cookie); +} + +#if !wxCHECK_VERSION(2, 5, 0) +wxTreeItemId wxTreeListMainWindow::GetNextChild(const wxTreeItemId& item, + long& cookie) const +#else +wxTreeItemId wxTreeListMainWindow::GetNextChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +#endif +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren(); + + // it's ok to cast cookie to size_t, we never have indices big enough to + // overflow "void *" + size_t *pIndex = (size_t *)&cookie; + if ( *pIndex < children.Count() ) + { + return children.Item((*pIndex)++); + } + else + { + // there are no more of them + return wxTreeItemId(); + } +} + +#if !wxCHECK_VERSION(2, 5, 0) +wxTreeItemId wxTreeListMainWindow::GetPrevChild(const wxTreeItemId& item, + long& cookie) const +#else +wxTreeItemId wxTreeListMainWindow::GetPrevChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +#endif +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren(); + + // it's ok to cast cookie to size_t, we never have indices big enough to + // overflow "void *" + size_t *pIndex = (size_t *)&cookie; + if ( *pIndex > 0 ) + { + return children.Item(--(*pIndex)); + } + else + { + // there are no more of them + return wxTreeItemId(); + } +} + +wxTreeItemId wxTreeListMainWindow::GetLastChild(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxArrayTreeListItems& children = ((wxTreeListItem*) item.m_pItem)->GetChildren(); + return (children.IsEmpty() ? wxTreeItemId() : wxTreeItemId(children.Last())); +} + +wxTreeItemId wxTreeListMainWindow::GetNextSibling(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; + wxTreeListItem *parent = i->GetItemParent(); + if ( parent == NULL ) + { + // root item doesn't have any siblings + return wxTreeItemId(); + } + + wxArrayTreeListItems& siblings = parent->GetChildren(); + int index = siblings.Index(i); + wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? + + size_t n = (size_t)(index + 1); + return n == siblings.Count() ? wxTreeItemId() : wxTreeItemId(siblings[n]); +} + +wxTreeItemId wxTreeListMainWindow::GetPrevSibling(const wxTreeItemId& item) + const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; + wxTreeListItem *parent = i->GetItemParent(); + if ( parent == NULL ) + { + // root item doesn't have any siblings + return wxTreeItemId(); + } + + wxArrayTreeListItems& siblings = parent->GetChildren(); + int index = siblings.Index(i); + wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? + + return index == 0 ? wxTreeItemId() + : wxTreeItemId(siblings[(size_t)(index - 1)]); +} + +// Only for internal use right now, but should probably be public +wxTreeItemId wxTreeListMainWindow::GetNext(const wxTreeItemId& item) const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; + + // First see if there are any children. + wxArrayTreeListItems& children = i->GetChildren(); + if (children.GetCount() > 0) + { + return children.Item(0); + } + else + { + // Try a sibling of this or ancestor instead + wxTreeItemId p = item; + wxTreeItemId toFind; + do + { + toFind = GetNextSibling(p); + p = GetItemParent(p); + } while (p.IsOk() && !toFind.IsOk()); + return toFind; + } +} + +wxTreeItemId wxTreeListMainWindow::GetFirstVisibleItem() const +{ + wxTreeItemId id = GetRootItem(); + if (!id.IsOk()) + return id; + + do + { + if (IsVisible(id)) + return id; + id = GetNext(id); + } while (id.IsOk()); + + return wxTreeItemId(); +} + +wxTreeItemId wxTreeListMainWindow::GetNextVisible(const wxTreeItemId& item) + const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxTreeItemId id = item; + if (id.IsOk()) + { + while (id = GetNext(id), id.IsOk()) + { + if (IsVisible(id)) + return id; + } + } + return wxTreeItemId(); +} + +wxTreeItemId wxTreeListMainWindow::GetPrevVisible(const wxTreeItemId& item) + const +{ + wxCHECK_MSG( item.IsOk(), wxTreeItemId(), wxT("invalid tree item") ); + + wxFAIL_MSG(wxT("not implemented")); + + return wxTreeItemId(); +} + +// ---------------------------------------------------------------------------- +// operations +// ---------------------------------------------------------------------------- + +wxTreeItemId wxTreeListMainWindow::DoInsertItem(const wxTreeItemId& parentId, + size_t previous, + const wxString& text, + int image, int selImage, + wxTreeItemData *data) +{ + wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; + if ( !parent ) + { + // should we give a warning here? + return AddRoot(text, image, selImage, data); + } + + m_dirty = TRUE; // do this first so stuff below doesn't cause flicker + + // ALB + wxArrayString arr; + arr.Alloc(GetColumnCount()); + for(size_t i = 0; i < GetColumnCount(); ++i) { + arr.Add(wxEmptyString); + } + arr[m_main_column] = text; + wxTreeListItem *item = + new wxTreeListItem( this, parent, arr, image, selImage, data ); + + if ( data != NULL ) + { + data->SetId((long)item); + } + + parent->Insert( item, previous ); + + return item; +} + +wxTreeItemId wxTreeListMainWindow::AddRoot(const wxString& text, + int image, int selImage, + wxTreeItemData *data) +{ + wxCHECK_MSG(!m_anchor, wxTreeItemId(), wxT("tree can have only one root")); + wxCHECK_MSG(GetColumnCount(), wxTreeItemId(), wxT("Add column(s) before adding the root item")); + + m_dirty = TRUE; // do this first so stuff below doesn't cause flicker + + // ALB + wxArrayString arr; + arr.Alloc(GetColumnCount()); + for(size_t i = 0; i < GetColumnCount(); ++i) { + arr.Add(wxEmptyString); + } + arr[m_main_column] = text; + m_anchor = new wxTreeListItem( this, (wxTreeListItem *)NULL, arr, + image, selImage, data); +#if 0 + if (HasFlag(wxTR_HIDE_ROOT)) + { + // if root is hidden, make sure we can navigate + // into children + m_anchor->SetHasPlus(); + Expand(m_anchor); + } +#endif + if ( data != NULL ) + { + data->SetId((long)m_anchor); + } + + if (!HasFlag(wxTR_MULTIPLE)) + { + m_current = m_key_current = m_anchor; + m_current->SetHilight( TRUE ); + } + + return m_anchor; +} + +wxTreeItemId wxTreeListMainWindow::PrependItem(const wxTreeItemId& parent, + const wxString& text, + int image, int selImage, + wxTreeItemData *data) +{ + return DoInsertItem(parent, 0u, text, image, selImage, data); +} + +wxTreeItemId wxTreeListMainWindow::InsertItem(const wxTreeItemId& parentId, + const wxTreeItemId& idPrevious, + const wxString& text, + int image, int selImage, + wxTreeItemData *data) +{ + wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; + if ( !parent ) + { + // should we give a warning here? + return AddRoot(text, image, selImage, data); + } + + int index = parent->GetChildren().Index((wxTreeListItem*) idPrevious.m_pItem); + wxASSERT_MSG( index != wxNOT_FOUND, + wxT("previous item in wxTreeListMainWindow::InsertItem() is not a sibling") ); + + return DoInsertItem(parentId, (size_t)++index, text, image, selImage, data); +} + +wxTreeItemId wxTreeListMainWindow::InsertItem(const wxTreeItemId& parentId, + size_t before, + const wxString& text, + int image, int selImage, + wxTreeItemData *data) +{ + wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; + if ( !parent ) + { + // should we give a warning here? + return AddRoot(text, image, selImage, data); + } + + return DoInsertItem(parentId, before, text, image, selImage, data); +} + +wxTreeItemId wxTreeListMainWindow::AppendItem(const wxTreeItemId& parentId, + const wxString& text, + int image, int selImage, + wxTreeItemData *data) +{ + wxTreeListItem *parent = (wxTreeListItem*) parentId.m_pItem; + if ( !parent ) + { + // should we give a warning here? + return AddRoot(text, image, selImage, data); + } + + return DoInsertItem( parent, parent->GetChildren().Count(), text, + image, selImage, data); +} + +void wxTreeListMainWindow::SendDeleteEvent(wxTreeListItem *item) +{ + wxTreeEvent event( wxEVT_COMMAND_TREE_DELETE_ITEM, m_owner->GetId() ); + event.SetItem((long) item); + event.SetEventObject( /*this*/m_owner ); + m_owner->ProcessEvent( event ); +} + +void wxTreeListMainWindow::DeleteChildren(const wxTreeItemId& itemId) +{ + m_dirty = TRUE; // do this first so stuff below doesn't cause flicker + + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + item->DeleteChildren(this); +} + +void wxTreeListMainWindow::Delete(const wxTreeItemId& itemId) +{ + m_dirty = TRUE; // do this first so stuff below doesn't cause flicker + + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + + // don't stay with invalid m_key_current or we will crash in + // the next call to OnChar() + bool changeKeyCurrent = FALSE; + wxTreeListItem *itemKey = m_key_current; + while ( itemKey ) + { + if ( itemKey == item ) + { + // m_key_current is a descendant of the item being deleted + changeKeyCurrent = TRUE; + break; + } + itemKey = itemKey->GetItemParent(); + } + + wxTreeListItem *parent = item->GetItemParent(); + if ( parent ) + { + parent->GetChildren().Remove( item ); // remove by value + } + + if ( changeKeyCurrent ) + { + // may be NULL or not + m_key_current = parent; + } + + item->DeleteChildren(this); + SendDeleteEvent(item); + delete item; +} + +void wxTreeListMainWindow::DeleteAllItems() +{ + if ( m_anchor ) + { + m_dirty = TRUE; + + m_anchor->DeleteChildren(this); + delete m_anchor; + + m_anchor = NULL; + } +} + +void wxTreeListMainWindow::Expand(const wxTreeItemId& itemId) +{ + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + + wxCHECK_RET( item, _T("invalid item in wxTreeListMainWindow::Expand") ); + + if ( !item->HasPlus() ) + return; + + if ( item->IsExpanded() ) + return; + + wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_EXPANDING, m_owner->GetId() ); + event.SetItem( (long) item ); + event.SetEventObject( /*this*/m_owner ); + + if ( m_owner->ProcessEvent( event ) && !event.IsAllowed() ) + { + // cancelled by program + return; + } + + item->Expand(); + CalculatePositions(); + + RefreshSubtree(item); + + event.SetEventType(wxEVT_COMMAND_TREE_ITEM_EXPANDED); + ProcessEvent( event ); +} + +void wxTreeListMainWindow::ExpandAll(const wxTreeItemId& item) +{ + Expand(item); + if ( IsExpanded(item) ) + { +#if !wxCHECK_VERSION(2, 5, 0) + long cookie; +#else + wxTreeItemIdValue cookie; +#endif + wxTreeItemId child = GetFirstChild(item, cookie); + while ( child.IsOk() ) + { + ExpandAll(child); + + child = GetNextChild(item, cookie); + } + } +} + +void wxTreeListMainWindow::Collapse(const wxTreeItemId& itemId) +{ + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + + if ( !item->IsExpanded() ) + return; + + wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_COLLAPSING, m_owner->GetId() ); + event.SetItem( (long) item ); + event.SetEventObject( /*this*/m_owner ); + if ( m_owner->ProcessEvent( event ) && !event.IsAllowed() ) + { + // cancelled by program + return; + } + + item->Collapse(); + +#if 0 // TODO why should items be collapsed recursively? + wxArrayTreeListItems& children = item->GetChildren(); + size_t count = children.Count(); + for ( size_t n = 0; n < count; n++ ) + { + Collapse(children[n]); + } +#endif + + CalculatePositions(); + + RefreshSubtree(item); + + event.SetEventType(wxEVT_COMMAND_TREE_ITEM_COLLAPSED); + ProcessEvent( event ); +} + +void wxTreeListMainWindow::CollapseAndReset(const wxTreeItemId& item) +{ + Collapse(item); + DeleteChildren(item); +} + +void wxTreeListMainWindow::Toggle(const wxTreeItemId& itemId) +{ + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + + if (item->IsExpanded()) + Collapse(itemId); + else + Expand(itemId); +} + +void wxTreeListMainWindow::Unselect() +{ + if (m_current) + { + m_current->SetHilight( FALSE ); + RefreshLine( m_current ); + } +} + +void wxTreeListMainWindow::UnselectAllChildren(wxTreeListItem *item) +{ + if (item->IsSelected()) + { + item->SetHilight(FALSE); + RefreshLine(item); + } + + if (item->HasChildren()) + { + wxArrayTreeListItems& children = item->GetChildren(); + size_t count = children.Count(); + for ( size_t n = 0; n < count; ++n ) + { + UnselectAllChildren(children[n]); + } + } +} + +void wxTreeListMainWindow::UnselectAll() +{ + UnselectAllChildren((wxTreeListItem*)GetRootItem().m_pItem); +} + +// Recursive function ! +// To stop we must have crt_itemGetItemParent(); + + if (parent == NULL) // This is root item + return TagAllChildrenUntilLast(crt_item, last_item, select); + + wxArrayTreeListItems& children = parent->GetChildren(); + int index = children.Index(crt_item); + wxASSERT( index != wxNOT_FOUND ); // I'm not a child of my parent? + + size_t count = children.Count(); + for (size_t n=(size_t)(index+1); nSetHilight(select); + RefreshLine(crt_item); + + if (crt_item==last_item) + return TRUE; + + if (crt_item->HasChildren()) + { + wxArrayTreeListItems& children = crt_item->GetChildren(); + size_t count = children.Count(); + for ( size_t n = 0; n < count; ++n ) + { + if (TagAllChildrenUntilLast(children[n], last_item, select)) + return TRUE; + } + } + + return FALSE; +} + +void wxTreeListMainWindow::SelectItemRange(wxTreeListItem *item1, wxTreeListItem *item2) +{ + // item2 is not necessary after item1 + wxTreeListItem *first=NULL, *last=NULL; + + // choice first' and 'last' between item1 and item2 + if (item1->GetY()GetY()) + { + first=item1; + last=item2; + } + else + { + first=item2; + last=item1; + } + + bool select = m_current->IsSelected(); + + if ( TagAllChildrenUntilLast(first,last,select) ) + return; + + TagNextChildren(first,last,select); +} + +void wxTreeListMainWindow::SelectItem(const wxTreeItemId& itemId, + bool unselect_others, + bool extended_select) +{ + wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") ); + + bool is_single=!(GetWindowStyleFlag() & wxTR_MULTIPLE); + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + + //wxCHECK_RET( ( (!unselect_others) && is_single), + // wxT("this is a single selection tree") ); + + // to keep going anyhow !!! + if (is_single) + { + if (item->IsSelected()) + return; // nothing to do + unselect_others = TRUE; + extended_select = FALSE; + } + else if ( unselect_others && item->IsSelected() ) + { + // selection change if there is more than one item currently selected + wxArrayTreeItemIds selected_items; + if ( GetSelections(selected_items) == 1 ) + return; + } + + wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() ); + event.SetItem( (long) item ); + event.SetOldItem( (long) m_current ); + event.SetEventObject( /*this*/m_owner ); + // TODO : Here we don't send any selection mode yet ! + + if(m_owner->GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed()) + return; + + wxTreeItemId parent = GetItemParent( itemId ); + while (parent.IsOk()) + { + if (!IsExpanded(parent)) + Expand( parent ); + + parent = GetItemParent( parent ); + } + + EnsureVisible( itemId ); + + // ctrl press + if (unselect_others) + { + if (is_single) Unselect(); // to speed up thing + else UnselectAll(); + } + + // shift press + if (extended_select) + { + if ( !m_current ) + { + m_current = m_key_current = (wxTreeListItem*)GetRootItem().m_pItem; + } + + // don't change the mark (m_current) + SelectItemRange(m_current, item); + } + else + { + bool select=TRUE; // the default + + // Check if we need to toggle hilight (ctrl mode) + if (!unselect_others) + select=!item->IsSelected(); + + m_current = m_key_current = item; + m_current->SetHilight(select); + RefreshLine( m_current ); + } + + event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); + GetEventHandler()->ProcessEvent( event ); +} + +void wxTreeListMainWindow::SelectAll(bool extended_select) +{ + wxCHECK_RET( GetWindowStyleFlag() & wxTR_MULTIPLE, wxT("invalid tree style") ); + + wxTreeEvent event( wxEVT_COMMAND_TREE_SEL_CHANGING, m_owner->GetId() ); + event.SetItem( GetRootItem() ); + event.SetOldItem( (long) m_current ); + event.SetEventObject( /*this*/m_owner ); + // TODO : Here we don't send any selection mode yet ! + + if(m_owner->GetEventHandler()->ProcessEvent( event ) && !event.IsAllowed()) + return; + + // shift press + if (!extended_select) + { + + } + else + { + + } +#if !wxCHECK_VERSION(2, 5, 0) + long cookie = 0; +#else + wxTreeItemIdValue cookie = 0; +#endif + wxTreeItemId root = GetRootItem(); + wxTreeListItem *first = (wxTreeListItem *)GetFirstChild (root, cookie).m_pItem; + wxTreeListItem *last = (wxTreeListItem *)GetLastChild (GetRootItem()).m_pItem; + if (TagAllChildrenUntilLast (first, last, true)) return; + TagNextChildren (first, last, true); + + event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED); + GetEventHandler()->ProcessEvent( event ); +} + +void wxTreeListMainWindow::FillArray(wxTreeListItem *item, + wxArrayTreeItemIds &array) const +{ + if ( item->IsSelected() ) + array.Add(wxTreeItemId(item)); + + if ( item->HasChildren() ) + { + wxArrayTreeListItems& children = item->GetChildren(); + size_t count = children.GetCount(); + for ( size_t n = 0; n < count; ++n ) + FillArray(children[n], array); + } +} + +size_t wxTreeListMainWindow::GetSelections(wxArrayTreeItemIds &array) const +{ + array.Empty(); + wxTreeItemId idRoot = GetRootItem(); + if ( idRoot.IsOk() ) + { + FillArray((wxTreeListItem*) idRoot.m_pItem, array); + } + //else: the tree is empty, so no selections + + return array.Count(); +} + +void wxTreeListMainWindow::EnsureVisible(const wxTreeItemId& item) +{ + if (!item.IsOk()) return; + + wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem; + + // first expand all parent branches + wxTreeListItem *parent = gitem->GetItemParent(); + while ( parent ) + { + Expand(parent); + parent = parent->GetItemParent(); + } + + //if (parent) CalculatePositions(); + + ScrollTo(item); +} + +void wxTreeListMainWindow::ScrollTo(const wxTreeItemId &item) +{ + if (!item.IsOk()) return; + + // We have to call this here because the label in + // question might just have been added and no screen + // update taken place. + if (m_dirty) wxYieldIfNeeded(); + + wxTreeListItem *gitem = (wxTreeListItem*) item.m_pItem; + + // now scroll to the item + int item_y = gitem->GetY(); + + int start_x = 0; + int start_y = 0; + GetViewStart( &start_x, &start_y ); + start_y *= PIXELS_PER_UNIT; + + int client_h = 0; + int client_w = 0; + GetClientSize( &client_w, &client_h ); + + if (item_y < start_y+3) + { + // going down + int x = 0; + int y = 0; + m_anchor->GetSize( x, y, this ); + x = m_owner->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB + y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels + //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels + int x_pos = GetScrollPos( wxHORIZONTAL ); + // Item should appear at top + SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, item_y/PIXELS_PER_UNIT ); + } + else if (item_y+GetLineHeight(gitem) > start_y+client_h) + { + // going up + int x = 0; + int y = 0; + m_anchor->GetSize( x, y, this ); + y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels + //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels + x = m_owner->GetHeaderWindow()->GetWidth(); //m_total_col_width; // ALB + item_y += PIXELS_PER_UNIT+2; + int x_pos = GetScrollPos( wxHORIZONTAL ); + // Item should appear at bottom + SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, y/PIXELS_PER_UNIT, x_pos, (item_y+GetLineHeight(gitem)-client_h)/PIXELS_PER_UNIT ); + } +} + +// FIXME: tree sorting functions are not reentrant and not MT-safe! +static wxTreeListMainWindow *s_treeBeingSorted = NULL; + +static int LINKAGEMODE tree_ctrl_compare_func(wxTreeListItem **item1, + wxTreeListItem **item2) +{ + wxCHECK_MSG( s_treeBeingSorted, 0, wxT("bug in wxTreeListMainWindow::SortChildren()") ); + + return s_treeBeingSorted->OnCompareItems(*item1, *item2); +} + +int wxTreeListMainWindow::OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2) +{ + // ALB: delegate to m_owner, to let the user overrride the comparison + //return wxStrcmp(GetItemText(item1), GetItemText(item2)); + return m_owner->OnCompareItems(item1, item2); +} + +void wxTreeListMainWindow::SortChildren(const wxTreeItemId& itemId) +{ + wxCHECK_RET( itemId.IsOk(), wxT("invalid tree item") ); + + wxTreeListItem *item = (wxTreeListItem*) itemId.m_pItem; + + wxCHECK_RET( !s_treeBeingSorted, + wxT("wxTreeListMainWindow::SortChildren is not reentrant") ); + + wxArrayTreeListItems& children = item->GetChildren(); + if ( children.Count() > 1 ) + { + m_dirty = TRUE; + + s_treeBeingSorted = this; + children.Sort(tree_ctrl_compare_func); + s_treeBeingSorted = NULL; + } + //else: don't make the tree dirty as nothing changed +} + +wxTreeItemId wxTreeListMainWindow::FindItem (const wxTreeItemId& item, const wxString& str, int flags) { +#if !wxCHECK_VERSION(2, 5, 0) + long cookie = 0; +#else + wxTreeItemIdValue cookie = 0; +#endif + wxTreeItemId next = item; + if (!next.IsOk()) next = GetSelection(); + if (!next.IsOk()) { + if (HasFlag(wxTR_HIDE_ROOT)) { + next = (wxTreeListItem*)GetFirstChild (GetRootItem().m_pItem, cookie).m_pItem; + } else { + next = (wxTreeListItem*)GetRootItem().m_pItem; + } + } + if (!next.IsOk()) return item; + + // start checking the next items + wxString itemText; + while (next.IsOk()) { + itemText = GetItemText (next); + if (flags & wxTL_SEARCH_LEVEL) { + next = GetNextSibling (next); + }else if (flags & wxTL_SEARCH_FULL) { + wxTreeItemId n = GetFirstChild (next, cookie); + if (!n.IsOk()) + n = GetNextSibling (next); + if (!n.IsOk()) + n = GetNextSibling (GetItemParent (next)); + next = n; + }else{ // wxTL_SEARCH_VISIBLE + next = GetNextVisible (next); + } + if (!next.IsOk()) break; // done + if (flags & wxTL_SEARCH_PARTIAL) { + itemText = GetItemText (next).Mid (0, str.Length()); + }else{ + itemText = GetItemText (next); + } + if (flags & wxTL_SEARCH_NOCASE) { + if (itemText.CmpNoCase (str) == 0) return next; + }else{ + if (itemText.Cmp (str) == 0) return next; + } + } + return item; +} + +wxImageList *wxTreeListMainWindow::GetImageList() const +{ + return m_imageListNormal; +} + +wxImageList *wxTreeListMainWindow::GetButtonsImageList() const +{ + return m_imageListButtons; +} + +wxImageList *wxTreeListMainWindow::GetStateImageList() const +{ + return m_imageListState; +} + +void wxTreeListMainWindow::CalculateLineHeight() +{ + wxClientDC dc(this); + dc.SetFont( m_normalFont ); + m_lineHeight = (int)(dc.GetCharHeight() + m_linespacing); + + if ( m_imageListNormal ) + { + // Calculate a m_lineHeight value from the normal Image sizes. + // May be toggle off. Then wxTreeListMainWindow will spread when + // necessary (which might look ugly). + int n = m_imageListNormal->GetImageCount(); + for (int i = 0; i < n ; i++) + { + int width = 0, height = 0; + m_imageListNormal->GetSize(i, width, height); + if (height > m_lineHeight) m_lineHeight = height + m_linespacing; + } + } + + if (m_imageListButtons) + { + // Calculate a m_lineHeight value from the Button image sizes. + // May be toggle off. Then wxTreeListMainWindow will spread when + // necessary (which might look ugly). + int n = m_imageListButtons->GetImageCount(); + for (int i = 0; i < n ; i++) + { + int width = 0, height = 0; + m_imageListButtons->GetSize(i, width, height); + if (height > m_lineHeight) m_lineHeight = height + m_linespacing; + } + } + +/*? FIXME: Don't get what this code is for... Adding a line space is already done!!! + if (m_lineHeight < 30) + m_lineHeight += 2; // at least 2 pixels + else + m_lineHeight += m_lineHeight/10; // otherwise 10% extra spacing +?*/ +} + +void wxTreeListMainWindow::SetImageList(wxImageList *imageList) +{ + if (m_ownsImageListNormal) delete m_imageListNormal; + m_imageListNormal = imageList; + m_ownsImageListNormal = FALSE; + m_dirty = TRUE; + CalculateLineHeight(); +} + +void wxTreeListMainWindow::SetStateImageList(wxImageList *imageList) +{ + if (m_ownsImageListState) delete m_imageListState; + m_imageListState = imageList; + m_ownsImageListState = FALSE; +} + +void wxTreeListMainWindow::SetButtonsImageList(wxImageList *imageList) +{ + if (m_ownsImageListButtons) delete m_imageListButtons; + m_imageListButtons = imageList; + m_ownsImageListButtons = FALSE; + m_dirty = TRUE; + CalculateLineHeight(); +} + +void wxTreeListMainWindow::AssignImageList(wxImageList *imageList) +{ + SetImageList(imageList); + m_ownsImageListNormal = TRUE; +} + +void wxTreeListMainWindow::AssignStateImageList(wxImageList *imageList) +{ + SetStateImageList(imageList); + m_ownsImageListState = TRUE; +} + +void wxTreeListMainWindow::AssignButtonsImageList(wxImageList *imageList) +{ + SetButtonsImageList(imageList); + m_ownsImageListButtons = TRUE; +} + +// ---------------------------------------------------------------------------- +// helpers +// ---------------------------------------------------------------------------- + +void wxTreeListMainWindow::AdjustMyScrollbars() +{ + if (m_anchor) + { + int x = 0, y = 0; + m_anchor->GetSize( x, y, this ); + y += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels + //x += PIXELS_PER_UNIT+2; // one more scrollbar unit + 2 pixels + int x_pos = GetScrollPos( wxHORIZONTAL ); + int y_pos = GetScrollPos( wxVERTICAL ); + x = m_owner->GetHeaderWindow()->GetWidth() + 2; + if(x < GetClientSize().GetWidth()) x_pos = 0; + //m_total_col_width + 2; // ALB + SetScrollbars( PIXELS_PER_UNIT, PIXELS_PER_UNIT, x/PIXELS_PER_UNIT, + y/PIXELS_PER_UNIT, x_pos, y_pos ); + } + else + { + SetScrollbars( 0, 0, 0, 0 ); + } +} + +int wxTreeListMainWindow::GetLineHeight(wxTreeListItem *item) const +{ + if (GetWindowStyleFlag() & wxTR_HAS_VARIABLE_ROW_HEIGHT) + return item->GetHeight(); + else + return m_lineHeight; +} + +void wxTreeListMainWindow::PaintItem(wxTreeListItem *item, wxDC& dc) +{ + wxTreeItemAttr *attr = item->GetAttributes(); + if (attr && attr->HasFont()) { + dc.SetFont(attr->GetFont()); + }else if (item->IsBold()) { + dc.SetFont(m_boldFont); + } + wxColour colText; + if (attr && attr->HasTextColour()) { + colText = attr->GetTextColour(); + }else{ + colText = GetForegroundColour(); + } + + wxPen *pen = +#ifndef __WXMAC__ + // don't draw rect outline if we already have the + // background color under Mac + (item->IsSelected() && m_hasFocus) ? wxBLACK_PEN : +#endif // !__WXMAC__ + wxTRANSPARENT_PEN; + + long text_w = 0, text_h = 0; + + dc.GetTextExtent( item->GetText(GetMainColumn()), &text_w, &text_h ); + + int total_h = GetLineHeight(item); + + if (item->IsSelected() && HasFlag (wxTR_FULL_ROW_HIGHLIGHT)) { + dc.SetBrush(*(m_hasFocus ? m_hilightBrush : m_hilightUnfocusedBrush)); + int offset = HasFlag(wxTR_ROW_LINES) ? 1 : 0; + dc.DrawRectangle (0, item->GetY() + offset, + m_owner->GetHeaderWindow()->GetWidth(), total_h-offset); + colText = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + }else{ + wxColour colBg; + if (attr && attr->HasBackgroundColour()) { + colBg = attr->GetBackgroundColour(); + }else{ + colBg = m_backgroundColour; + } + dc.SetBrush(wxBrush(colBg, wxTRANSPARENT)); + } + + dc.SetBackgroundMode(wxTRANSPARENT); + int text_extraH = (total_h > text_h) ? (total_h - text_h)/2 : 0; + int img_extraH = (total_h > m_imgHeight)? (total_h-m_imgHeight)/2: 0; + int x_colstart = 0; + for ( size_t i = 0; i < GetColumnCount(); ++i ) { + if (!m_owner->GetHeaderWindow()->GetColumnShown(i)) continue; + int colwidth = m_owner->GetHeaderWindow()->GetColumnWidth(i); + int image; + int image_x = 0; + int image_w = 0; + if(i == GetMainColumn()) { + image = item->GetCurrentImage(); + if (HasButtons()) { + image_x = item->GetX() + (m_btnWidth-m_btnWidth2) + LINEATROOT; + }else{ + image_x = item->GetX() - m_imgWidth2; + } + } + else + { + image = item->GetImage(i); + image_x = x_colstart + MARGIN; + } + if (image != NO_IMAGE) image_w = m_imgWidth + MARGIN; + + // honor text alignment + wxString text = item->GetText(i); + switch ( m_owner->GetHeaderWindow()->GetColumn(i).GetAlignment() ) { + case wxTL_ALIGN_LEFT: + // already left aligned + break; + case wxTL_ALIGN_RIGHT: + dc.GetTextExtent(text, &text_w, NULL); + image_x = x_colstart + colwidth - (image_w + text_w + MARGIN); + break; + case wxTL_ALIGN_CENTER: + dc.GetTextExtent(text, &text_w, NULL); + int w = colwidth - image_w - text_w; + image_x = x_colstart + (w > 0)? w: 0; + break; + } + int text_x = image_x + image_w; + + if (item->IsSelected() && (i==GetMainColumn()) && !HasFlag (wxTR_FULL_ROW_HIGHLIGHT)) + { + dc.SetBrush(*(m_hasFocus ? m_hilightBrush : m_hilightUnfocusedBrush)); + int offset = HasFlag (wxTR_ROW_LINES) ? 1 : 0; + dc.DrawRectangle (text_x, item->GetY() + offset, text_w, total_h-offset); + dc.SetBackgroundMode(wxTRANSPARENT); + dc.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT)); + }else{ + dc.SetTextForeground(colText); + } + + dc.SetPen(*pen); + + wxDCClipper clipper (dc, x_colstart, item->GetY(), colwidth, total_h); + if (image != NO_IMAGE) + { + int image_y = item->GetY() + img_extraH; + m_imageListNormal->Draw ( image, dc, image_x, image_y, + wxIMAGELIST_DRAW_TRANSPARENT ); + } + int text_y = item->GetY() + text_extraH; + dc.DrawText ( text, (wxCoord)text_x, (wxCoord)text_y ); + + x_colstart += colwidth; + } + + // restore normal font + dc.SetFont( m_normalFont ); +} + +// Now y stands for the top of the item, whereas it used to stand for middle ! +void wxTreeListMainWindow::PaintLevel (wxTreeListItem *item, wxDC &dc, + int level, int &y, int x_colstart ) +{ + // Handle hide root (only level 0) + if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) { + // always expand hidden root + wxArrayTreeListItems& children = item->GetChildren(); + int n; + for (n = 0; n < (int)children.Count(); n++) { + PaintLevel (children[n], dc, 1, y, x_colstart); + } + // end after expanding root + return; + } + + // calculate position of vertical lines + int x = x_colstart + MARGIN; // start of column + if (HasFlag (wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root + if (HasButtons()) { + x += m_btnWidth2; // middle of button + }else{ + if (m_imgWidth > 0) x += m_imgWidth2; // middle of image + } + if (!HasFlag (wxTR_HIDE_ROOT)) { + x += m_indent * level; // indent according to level + }else{ + if (level > 0) x += m_indent * (level-1); // but not level 1 + } + + // handle column text + item->SetX (x); + item->SetY (y); + + int h = GetLineHeight(item); + int y_top = y; + int y_mid = y_top + (h/2); + y += h; + + int exposed_x = dc.LogicalToDeviceX(0); + int exposed_y = dc.LogicalToDeviceY(y_top); + + if (IsExposed(exposed_x, exposed_y, 10000, h)) // 10000 = very much + { + if (HasFlag(wxTR_ROW_LINES)) + { + //dc.DestroyClippingRegion(); + int total_width = m_owner->GetHeaderWindow()->GetWidth(); + // if the background colour is white, choose a + // contrasting color for the lines + dc.SetPen (*((GetBackgroundColour() == *wxWHITE)? + wxMEDIUM_GREY_PEN : wxWHITE_PEN)); + dc.DrawLine(0, y_top, total_width, y_top); + dc.DrawLine(0, y, total_width, y); + } + + // restore DC objects + dc.SetBrush(*wxWHITE_BRUSH); + dc.SetPen(m_dottedPen); + + if (((level == 0) || ((level == 1) && HasFlag(wxTR_HIDE_ROOT))) && + HasFlag(wxTR_LINES_AT_ROOT) && !HasFlag(wxTR_NO_LINES)) { + int rootPos = x_colstart + MARGIN; + dc.DrawLine (rootPos, y_mid, rootPos+LINEATROOT, y_mid); + } + + size_t clip_width = m_owner->GetHeaderWindow()-> + GetColumn(m_main_column).GetWidth(); + + if (item->HasPlus() && HasButtons()) // should the item show a button? + { + // clip to the column width + wxDCClipper clipper(dc, x_colstart, y_top, clip_width, 10000); + + if (m_imageListButtons != NULL) + { + // draw the image button here + int image = wxTreeItemIcon_Normal; + if (item->IsExpanded()) image = wxTreeItemIcon_Expanded; + if (item->IsSelected()) + image += wxTreeItemIcon_Selected - wxTreeItemIcon_Normal; + int xx = x + m_btnWidth2; + int yy = y_mid - m_btnHeight2; + dc.SetClippingRegion(xx, yy, m_btnWidth, m_btnHeight); + m_imageListButtons->Draw(image, dc, xx, yy, + wxIMAGELIST_DRAW_TRANSPARENT); + dc.DestroyClippingRegion(); + } + else if (HasFlag(wxTR_TWIST_BUTTONS)) + { + // draw the twisty button here + dc.SetPen(*wxBLACK_PEN); + dc.SetBrush(*m_hilightBrush); + + wxPoint button[3]; + + if (item->IsExpanded()) + { + button[0].x = x - (m_btnWidth2+1); + button[0].y = y_mid - (m_btnHeight/3); + button[1].x = x + (m_btnWidth2+1); + button[1].y = button[0].y; + button[2].x = x; + button[2].y = button[0].y + (m_btnHeight2+1); + } + else + { + button[0].x = x - (m_btnWidth/3); + button[0].y = y_mid - (m_btnHeight2+1); + button[1].x = button[0].x; + button[1].y = y_mid + (m_btnHeight2+1); + button[2].x = button[0].x + (m_btnWidth2+1); + button[2].y = y_mid; + } + dc.DrawPolygon(3, button); + + dc.SetPen(m_dottedPen); + } + else // if (HasFlag(wxTR_HAS_BUTTONS)) + { + // draw the plus sign here + dc.SetPen(*wxGREY_PEN); + dc.SetBrush(*wxWHITE_BRUSH); + dc.DrawRectangle (x-m_btnWidth2, y_mid-m_btnHeight2, + m_btnWidth, m_btnHeight); + dc.SetPen(*wxBLACK_PEN); + dc.DrawLine (x-(m_btnWidth2-3), y_mid, + x+(m_btnWidth2-2), y_mid); + if (!item->IsExpanded()) + dc.DrawLine (x, y_mid-(m_btnHeight2-2), + x, y_mid+(m_btnHeight2-1)); + dc.SetPen(m_dottedPen); + } + + if (!HasFlag(wxTR_NO_LINES)) { + if (!(level == 0) && !((level == 1) && HasFlag(wxTR_HIDE_ROOT))) { + if (m_imgWidth > 0) { + dc.DrawLine(x+m_btnWidth2, y_mid, x+m_indent-m_imgWidth2, y_mid); + }else{ + dc.DrawLine(x+m_btnWidth2, y_mid, x+m_btnWidth2+LINEATROOT-MARGIN, y_mid); + } + } + } + } + else if (!HasFlag(wxTR_NO_LINES)) // no button; maybe a line? + { + // clip to the column width + wxDCClipper clipper(dc, x_colstart, y_top, clip_width, 10000); + + // draw the horizontal line here + if (!(level == 0) && !((level == 1) && HasFlag(wxTR_HIDE_ROOT))) { + int x2 = x; + if (!HasButtons()) x2 = x - m_indent; + if (m_imgWidth > 0) { + dc.DrawLine(x2, y_mid, x2+m_indent-m_imgWidth2, y_mid); + }else{ + dc.DrawLine(x2, y_mid, x2+m_btnWidth2+LINEATROOT-MARGIN, y_mid); + } + } + } + + // draw item + PaintItem(item, dc); + } + + // restore DC objects + dc.SetBrush(*wxWHITE_BRUSH); + dc.SetPen(m_dottedPen); + dc.SetTextForeground(*wxBLACK); + + if (item->IsExpanded()) + { + wxArrayTreeListItems& children = item->GetChildren(); + + // clip to the column width + size_t clip_width = m_owner->GetHeaderWindow()-> + GetColumn(m_main_column).GetWidth(); + wxDCClipper clipper(dc, x_colstart, y_top, clip_width, 10000); + + // process lower levels + int oldY; + if (m_imgWidth > 0) { + oldY = y_mid + m_imgHeight2; + }else{ + oldY = y_mid + h/2; + } + int y2; + int n; + for (n = 0; n < (int)children.Count(); ++n) { + + if (!HasFlag(wxTR_NO_LINES)) + { + // draw line down to last child + if (children[n]->HasPlus() && HasButtons()) { + y2 = y + h/2 - m_btnHeight2; + if (HasButtons()) { + dc.DrawLine(x+m_indent, oldY, x+m_indent, y2); + }else{ + dc.DrawLine(x, oldY, x, y2); + } + oldY = y2 + m_btnHeight; + }else{ + y2 = y + h/2; + if (HasButtons()) { + dc.DrawLine(x+m_indent, oldY, x+m_indent, y2); + }else{ + dc.DrawLine(x, oldY, x, y2); + } + oldY = y2; + } + } + + PaintLevel (children[n], dc, level+1, y, x_colstart); + } + } +} + +void wxTreeListMainWindow::DrawDropEffect(wxTreeListItem *item) +{ + if ( item ) + { + if ( item->HasPlus() ) + { + // it's a folder, indicate it by a border + DrawBorder(item); + } + else + { + // draw a line under the drop target because the item will be + // dropped there + DrawLine(item, TRUE /* below */); + } + + SetCursor(wxCURSOR_BULLSEYE); + } + else + { + // can't drop here + SetCursor(wxCURSOR_NO_ENTRY); + } +} + +void wxTreeListMainWindow::DrawBorder(const wxTreeItemId &item) +{ + wxCHECK_RET( item.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); + + wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; + + wxClientDC dc(this); + PrepareDC( dc ); + dc.SetLogicalFunction(wxINVERT); + dc.SetBrush(*wxTRANSPARENT_BRUSH); + + int w = i->GetWidth() + 2; + int h = GetLineHeight(i) + 2; + + dc.DrawRectangle( i->GetX() - 1, i->GetY() - 1, w, h); +} + +void wxTreeListMainWindow::DrawLine(const wxTreeItemId &item, bool below) +{ + wxCHECK_RET( item.IsOk(), _T("invalid item in wxTreeListMainWindow::DrawLine") ); + + wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; + + wxClientDC dc(this); + PrepareDC( dc ); + dc.SetLogicalFunction(wxINVERT); + + int x = i->GetX(), + y = i->GetY(); + if ( below ) + { + y += GetLineHeight(i) - 1; + } + + dc.DrawLine( x, y, x + i->GetWidth(), y); +} + +// ---------------------------------------------------------------------------- +// wxWindows callbacks +// ---------------------------------------------------------------------------- + +void wxTreeListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) +{ + wxPaintDC dc(this); + + PrepareDC( dc ); + + if(!GetColumnCount()) return; // ALB + + if ( !m_anchor) + return; + + // calculate button size + m_btnWidth = 0, m_btnWidth2 = 0; + m_btnHeight = 0, m_btnHeight2 = 0; + if (m_imageListButtons) { + m_imageListButtons->GetSize (0, m_btnWidth, m_btnHeight); + }else if (HasButtons()) { + m_btnWidth = BTNWIDTH; + m_btnHeight = BTNHEIGHT; + } + m_btnWidth2 = m_btnWidth/2; + m_btnHeight2 = m_btnHeight/2; + + // calculate image size + m_imgWidth = 0, m_imgWidth2 = 0; + m_imgHeight = 0, m_imgHeight2 = 0; + if (m_imageListNormal) { + m_imageListNormal->GetSize (0, m_imgWidth, m_imgHeight); + m_imgWidth += 4; //? ToDo: Why + 4? + } + m_imgWidth2 = m_imgWidth/2; + m_imgHeight2 = m_imgHeight/2; + + // calculate indent size + int btnIndent = HasButtons()? m_btnWidth + LINEATROOT: 0; + m_indent = wxMax (MININDENT, wxMax (m_imgWidth, btnIndent)) + MARGIN; + + // set default values + dc.SetFont( m_normalFont ); + dc.SetPen( m_dottedPen ); + + // this is now done dynamically + //if(GetImageList() == NULL) + // m_lineHeight = (int)(dc.GetCharHeight() + 4); + + // calculate column start and paint + int x_colstart = 0; + int i = 0; + for (i = 0; i < (int)GetMainColumn(); ++i) { + if (!m_owner->GetHeaderWindow()->GetColumnShown(i)) continue; + x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth (i); + } + int y = 0; + PaintLevel ( m_anchor, dc, 0, y, x_colstart ); +} + +void wxTreeListMainWindow::OnSetFocus( wxFocusEvent &event ) +{ + m_hasFocus = TRUE; + + RefreshSelected(); + + event.Skip(); +} + +void wxTreeListMainWindow::OnKillFocus( wxFocusEvent &event ) +{ + m_hasFocus = FALSE; + + RefreshSelected(); + + event.Skip(); +} + +void wxTreeListMainWindow::OnChar( wxKeyEvent &event ) +{ + wxTreeEvent te( wxEVT_COMMAND_TREE_KEY_DOWN, m_owner->GetId() ); + te.SetKeyEvent( event ); + te.SetEventObject( /*this*/m_owner ); + if ( m_owner->GetEventHandler()->ProcessEvent( te ) ) + { + // intercepted by the user code + return; + } + + if ( !m_current ) + { + if (HasFlag(wxTR_HIDE_ROOT)) { +#if !wxCHECK_VERSION(2, 5, 0) + long cookie = 0; +#else + wxTreeItemIdValue cookie = 0; +#endif + m_current = m_key_current = (wxTreeListItem*)GetFirstChild (GetRootItem().m_pItem, cookie).m_pItem; + } + else + { + m_current = m_key_current = (wxTreeListItem*)GetRootItem().m_pItem; + } + } + + // how should the selection work for this event? + bool is_multiple, extended_select, unselect_others; + EventFlagsToSelType(GetWindowStyleFlag(), + event.ShiftDown(), + event.ControlDown(), + is_multiple, extended_select, unselect_others); + + // + : Expand (not on Win32) + // - : Collaspe (not on Win32) + // * : Expand all/Collapse all + // ' ' | return : activate + // up : go up (not last children!) + // down : go down + // left : go to parent (or collapse on Win32) + // right : open if parent and go next (or expand on Win32) + // home : go to root + // end : go to last item without opening parents + switch (event.GetKeyCode()) + { +#ifndef __WXMSW__ // mimic the standard win32 tree ctrl + case '+': + case WXK_ADD: + if (m_current->HasPlus() && !IsExpanded(m_current)) + { + Expand (m_current); + } + break; +#endif // __WXMSW__ + + case '*': + case WXK_MULTIPLY: + if ( !IsExpanded(m_current) ) + { + // expand all + ExpandAll (m_current); + break; + } + //else: fall through to Collapse() it + +#ifndef __WXMSW__ // mimic the standard wxTreeCtrl behaviour + case '-': + case WXK_SUBTRACT: + if (IsExpanded(m_current)) + { + Collapse (m_current); + } + break; +#endif // __WXMSW__ + + case ' ': + case WXK_RETURN: + { + wxTreeEvent event( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, + m_owner->GetId() ); + event.SetItem( (long) m_current); + event.SetEventObject( /*this*/m_owner ); + m_owner->GetEventHandler()->ProcessEvent( event ); + } + break; + + // backspace goes to the parent, sends "root" activation + case WXK_BACK: + { + wxTreeItemId prev = GetItemParent( m_current ); + if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) + { + // don't go to root if it is hidden + prev = GetPrevSibling( m_current ); + } + if (prev) + { + SelectItem( prev, unselect_others, extended_select ); + EnsureVisible( prev ); + } + } + break; + + // up goes to the previous sibling or to the last + // of its children if it's expanded + case WXK_UP: + { + wxTreeItemId prev = GetPrevSibling( m_key_current ); + if (!prev) + { + prev = GetItemParent( m_key_current ); + if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) + { + break; // don't go to root if it is hidden + } + if (prev) + { +#if !wxCHECK_VERSION(2, 5, 0) + long cookie = 0; +#else + wxTreeItemIdValue cookie = 0; +#endif + wxTreeItemId current = m_key_current; + // TODO: Huh? If we get here, we'd better be the first child of our parent. How else could it be? + if (current == GetFirstChild( prev, cookie )) + { + // otherwise we return to where we came from + SelectItem( prev, unselect_others, extended_select ); + m_key_current= (wxTreeListItem*) prev.m_pItem; + EnsureVisible( prev ); + break; + } + } + } + if (prev) + { + while ( IsExpanded(prev) && HasChildren(prev) ) + { + wxTreeItemId child = GetLastChild(prev); + if ( !child ) + { + break; + } + prev = child; + } + + SelectItem( prev, unselect_others, extended_select ); + m_key_current=(wxTreeListItem*) prev.m_pItem; + EnsureVisible( prev ); + } + } + break; + + // left arrow goes to the parent + case WXK_LEFT: + if (IsExpanded(m_current)) + { + Collapse(m_current); + } + else + { + wxTreeItemId prev = GetItemParent( m_current ); + if ((prev == GetRootItem()) && HasFlag(wxTR_HIDE_ROOT)) + { + // don't go to root if it is hidden + prev = GetPrevSibling( m_current ); + } + if (prev) + { + SelectItem( prev, unselect_others, extended_select ); + EnsureVisible( prev ); + } + } + break; + + case WXK_RIGHT: +#if defined(__WXMSW__) // mimic the standard win32 tree ctrl + if (m_current->HasPlus() && !IsExpanded(m_current)) + { + Expand(m_current); + break; + } +#endif // __WXMSW__ + + // this works the same as the down arrow except that we + // also expand the item if it wasn't expanded yet + Expand(m_current); + // fall through + + case WXK_DOWN: + { + if (IsExpanded(m_key_current) && HasChildren(m_key_current)) + { +#if !wxCHECK_VERSION(2, 5, 0) + long cookie = 0; +#else + wxTreeItemIdValue cookie = 0; +#endif + wxTreeItemId child = GetFirstChild( m_key_current, cookie ); + if (child) { + SelectItem( child, unselect_others, extended_select ); + m_key_current=(wxTreeListItem*) child.m_pItem; + EnsureVisible( child ); + break; + } + } + wxTreeItemId next = GetNextSibling( m_key_current ); + if (!next) + { + wxTreeItemId current = m_key_current; + while (current && !next) + { + current = GetItemParent( current ); + if (current) next = GetNextSibling( current ); + } + } + if (next) + { + SelectItem( next, unselect_others, extended_select ); + m_key_current=(wxTreeListItem*) next.m_pItem; + EnsureVisible( next ); + } + } + break; + + // selects the last visible tree item + case WXK_END: + { + wxTreeItemId last = GetRootItem(); + + while ( last.IsOk() && IsExpanded(last) ) + { + wxTreeItemId lastChild = GetLastChild(last); + + // it may happen if the item was expanded but then all of + // its children have been deleted - so IsExpanded() returned + // TRUE, but GetLastChild() returned invalid item + if ( !lastChild ) + break; + + last = lastChild; + } + + if ( last.IsOk() ) + { + SelectItem( last, unselect_others, extended_select ); + EnsureVisible( last ); + } + } + break; + + // selects the root item + case WXK_HOME: + { + wxTreeItemId prev = GetRootItem(); + if (!prev) break; + if (HasFlag(wxTR_HIDE_ROOT)) + { +#if !wxCHECK_VERSION(2, 5, 0) + long cookie = 0; +#else + wxTreeItemIdValue cookie = 0; +#endif + prev = GetFirstChild(prev, cookie); + if (!prev) break; + } + SelectItem( prev, unselect_others, extended_select ); + EnsureVisible( prev ); + } + break; + + default: + if (event.m_keyCode >= (int)' ') { + if (!m_findTimer->IsRunning()) m_findStr.Clear(); + m_findStr.Append (event.m_keyCode); + m_findTimer->Start (500, wxTIMER_ONE_SHOT); + wxTreeItemId dummy = (wxTreeItemId*)NULL; + wxTreeItemId item = FindItem (dummy, m_findStr, wxTL_SEARCH_VISIBLE | + wxTL_SEARCH_PARTIAL | + wxTL_SEARCH_NOCASE); + if (item.IsOk()) { + EnsureVisible (item); + SelectItem (item); + } + } + event.Skip(); + } +} + +wxTreeItemId wxTreeListMainWindow::HitTest(const wxPoint& point, int& flags, + int& column) +{ + // JACS: removed wxYieldIfNeeded() because it can cause the window + // to be deleted from under us if a close window event is pending + + int w, h; + GetSize(&w, &h); + flags=0; + column = -1; + if (point.x<0) flags |= wxTREE_HITTEST_TOLEFT; + if (point.x>w) flags |= wxTREE_HITTEST_TORIGHT; + if (point.y<0) flags |= wxTREE_HITTEST_ABOVE; + if (point.y>h) flags |= wxTREE_HITTEST_BELOW; + if (flags) return wxTreeItemId(); + + if (m_anchor == NULL) + { + flags = wxTREE_HITTEST_NOWHERE; + return wxTreeItemId(); + } + + wxClientDC dc(this); + PrepareDC(dc); + wxCoord x = dc.DeviceToLogicalX( point.x ); + wxCoord y = dc.DeviceToLogicalY( point.y ); + wxTreeListItem *hit = m_anchor->HitTest(wxPoint(x, y), this, flags, + column, 0); + if (hit == NULL) + { + flags = wxTREE_HITTEST_NOWHERE; + return wxTreeItemId(); + } + return hit; +} + +// get the bounding rectangle of the item (or of its label only) +bool wxTreeListMainWindow::GetBoundingRect(const wxTreeItemId& item, + wxRect& rect, + bool WXUNUSED(textOnly)) const +{ + wxCHECK_MSG( item.IsOk(), FALSE, _T("invalid item in wxTreeListMainWindow::GetBoundingRect") ); + + wxTreeListItem *i = (wxTreeListItem*) item.m_pItem; + + int startX, startY; + GetViewStart(& startX, & startY); + + rect.x = i->GetX() - startX*PIXELS_PER_UNIT; + rect.y = i->GetY() - startY*PIXELS_PER_UNIT; + rect.width = i->GetWidth(); + //rect.height = i->GetHeight(); + rect.height = GetLineHeight(i); + + return TRUE; +} + +/* **** */ + +void wxTreeListMainWindow::Edit( const wxTreeItemId& item ) +{ + if (!item.IsOk()) return; + + m_currentEdit = (wxTreeListItem*) item.m_pItem; + + wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, m_owner->GetId() ); + te.SetItem( (long) m_currentEdit); + te.SetEventObject( /*this*/m_owner ); + m_owner->GetEventHandler()->ProcessEvent( te ); + + if (!te.IsAllowed()) return; + + // We have to call this here because the label in + // question might just have been added and no screen + // update taken place. + if (m_dirty) wxYieldIfNeeded(); + + wxString s = m_currentEdit->GetText(/*ALB*/m_main_column); + int x = m_currentEdit->GetX() + m_imgWidth2; + int y = m_currentEdit->GetY(); + int w = wxMin (m_currentEdit->GetWidth(), + m_owner->GetHeaderWindow()->GetWidth()) - m_imgWidth2; + int h = m_currentEdit->GetHeight() + 2; + wxClientDC dc(this); + PrepareDC( dc ); + x = dc.LogicalToDeviceX( x ); + y = dc.LogicalToDeviceY( y ); + + wxTreeListTextCtrl *text = new wxTreeListTextCtrl(this, -1, + &m_renameAccept, + &m_renameRes, + this, + s, + wxPoint (x,y), + wxSize (w,h)); + text->SetFocus(); +} + +void wxTreeListMainWindow::OnRenameTimer() +{ + Edit( m_current ); +} + +void wxTreeListMainWindow::OnRenameAccept() +{ + // TODO if the validator fails this causes a crash + wxTreeEvent le( wxEVT_COMMAND_TREE_END_LABEL_EDIT, m_owner->GetId() ); + le.SetItem( (long) m_currentEdit ); + le.SetEventObject( /*this*/m_owner ); + le.SetLabel( m_renameRes ); + m_owner->GetEventHandler()->ProcessEvent( le ); + + if (!le.IsAllowed()) return; + + SetItemText( m_currentEdit, m_renameRes ); +} + +void wxTreeListMainWindow::OnMouse( wxMouseEvent &event ) +{ + if ( !m_anchor ) return; + + // we process left mouse up event (enables in-place edit), right down + // (pass to the user code), left dbl click (activate item) and + // dragging/moving events for items drag-and-drop + if ( !(event.LeftDown() || + event.LeftUp() || + event.RightDown() || + event.LeftDClick() || + event.Dragging() || + ((event.Moving() || event.RightUp()) && m_isDragging)) ) + { + event.Skip(); + return; + } + + if ( event.LeftDown() ) + SetFocus(); + + wxClientDC dc(this); + PrepareDC(dc); + wxCoord x = dc.DeviceToLogicalX( event.GetX() ); + wxCoord y = dc.DeviceToLogicalY( event.GetY() ); + + int flags = 0; + wxTreeListItem *item = m_anchor->HitTest(wxPoint(x,y), this, flags, 0); + + if ( event.Dragging() && !m_isDragging ) + { + if (m_dragCount == 0) + m_dragStart = wxPoint(x,y); + + m_dragCount++; + + if (m_dragCount != 3) + { + // wait until user drags a bit further... + return; + } + + wxEventType command = event.RightIsDown() + ? wxEVT_COMMAND_TREE_BEGIN_RDRAG + : wxEVT_COMMAND_TREE_BEGIN_DRAG; + + wxTreeEvent nevent( command,/*ALB*/ m_owner->GetId() ); + nevent.SetItem( (long) m_current); + nevent.SetEventObject(/*this*/m_owner); // ALB + + // by default the dragging is not supported, the user code must + // explicitly allow the event for it to take place + nevent.Veto(); + + if ( m_owner->GetEventHandler()->ProcessEvent(nevent) && + nevent.IsAllowed() ) + { + // we're going to drag this item + m_isDragging = TRUE; + + // remember the old cursor because we will change it while + // dragging + m_oldCursor = m_cursor; + + // in a single selection control, hide the selection temporarily + if ( !(GetWindowStyleFlag() & wxTR_MULTIPLE) ) + { + m_oldSelection = (wxTreeListItem*) GetSelection().m_pItem; + + if ( m_oldSelection ) + { + m_oldSelection->SetHilight(FALSE); + RefreshLine(m_oldSelection); + } + } + + CaptureMouse(); + } + } + else if ( event.Moving() ) + { + if ( item != m_dropTarget ) + { + // unhighlight the previous drop target + DrawDropEffect(m_dropTarget); + + m_dropTarget = item; + + // highlight the current drop target if any + DrawDropEffect(m_dropTarget); + + wxYieldIfNeeded(); + } + } + else if ( (event.LeftUp() || event.RightUp()) && m_isDragging ) + { + // erase the highlighting + DrawDropEffect(m_dropTarget); + + if ( m_oldSelection ) + { + m_oldSelection->SetHilight(TRUE); + RefreshLine(m_oldSelection); + m_oldSelection = (wxTreeListItem *)NULL; + } + + // generate the drag end event + wxTreeEvent event(wxEVT_COMMAND_TREE_END_DRAG,/*ALB*/m_owner->GetId()); + + event.SetItem( (long) item ); + event.SetPoint( wxPoint(x, y) ); + event.SetEventObject(/*this*/m_owner); + + (void)m_owner->GetEventHandler()->ProcessEvent(event); + + m_isDragging = FALSE; + m_dropTarget = (wxTreeListItem *)NULL; + + ReleaseMouse(); + + SetCursor(m_oldCursor); + + wxYieldIfNeeded(); + } + else + { + // here we process only the messages which happen on tree items + + m_dragCount = 0; + + if ( item == NULL ) return; /* we hit the blank area */ + + if ( event.RightDown() ) + { + SetFocus(); + wxTreeEvent nevent(wxEVT_COMMAND_TREE_ITEM_RIGHT_CLICK, + m_owner->GetId()); + nevent.SetItem( (long) item ); + int nx, ny; + CalcScrolledPosition(x, y, &nx, &ny); + nevent.SetPoint( wxPoint(nx, ny)); + nevent.SetEventObject(/*this*/m_owner); + m_owner->GetEventHandler()->ProcessEvent(nevent); + } + else if ( event.LeftUp() ) + { + if ( m_lastOnSame ) + { + if ( ( item == m_current ) && + ( flags & wxTREE_HITTEST_ONITEMLABEL ) && + HasFlag(wxTR_EDIT_LABELS ) ) + { + if ( m_renameTimer->IsRunning() ) + m_renameTimer->Stop(); + + m_renameTimer->Start( 100, TRUE ); + } + + m_lastOnSame = FALSE; + } + } + else // !RightDown() && !LeftUp() ==> LeftDown() || LeftDClick() + { + if ( event.LeftDown() ) + { + SetFocus(); + m_lastOnSame = item == m_current; + } + + if ((flags & wxTREE_HITTEST_ONITEMBUTTON) || + ((flags & wxTREE_HITTEST_ONITEMICON)) && + !HasButtons() && item->HasPlus()) + { + // only toggle the item for a single click, double click on + // the button doesn't do anything (it toggles the item twice) + if ( event.LeftDown() ) + { + Toggle( item ); + } + + // don't select the item if the button was clicked + return; + } + + // how should the selection work for this event? + bool is_multiple, extended_select, unselect_others; + EventFlagsToSelType(GetWindowStyleFlag(), + event.ShiftDown(), + event.ControlDown(), + is_multiple, extended_select, unselect_others); + + SelectItem (item, unselect_others, extended_select); + + // For some reason, Windows isn't recognizing a left double-click, + // so we need to simulate it here. Allow 200 milliseconds for now. + if ( event.LeftDClick() ) + { + // double clicking should not start editing the item label + m_renameTimer->Stop(); + m_lastOnSame = FALSE; + + // send activate event first + wxTreeEvent nevent( wxEVT_COMMAND_TREE_ITEM_ACTIVATED, + m_owner->GetId() ); + nevent.SetItem( (long) item ); + int nx, ny; + CalcScrolledPosition(x, y, &nx, &ny); + nevent.SetPoint( wxPoint(nx, ny) ); + nevent.SetEventObject( /*this*/m_owner ); + if ( !m_owner->GetEventHandler()->ProcessEvent( nevent ) ) + { + // if the user code didn't process the activate event, + // handle it ourselves by toggling the item when it is + // double clicked + if ( item->HasPlus() ) + { + Toggle(item); + } + } + } + } + } +} + +void wxTreeListMainWindow::OnIdle( wxIdleEvent &WXUNUSED(event) ) +{ + /* after all changes have been done to the tree control, + * we actually redraw the tree when everything is over */ + + if (!m_dirty) return; + + m_dirty = FALSE; + + CalculatePositions(); + Refresh(); + AdjustMyScrollbars(); +} + +void wxTreeListMainWindow::OnSize(wxSizeEvent& WXUNUSED(event)) +{ +// int w, h; +// GetClientSize(&w, &h); +// m_header_win->SetSize(0, 0, w, HEADER_HEIGHT); +} + +void wxTreeListMainWindow::OnScroll(wxScrollWinEvent& event) +{ + // FIXME +#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) + wxScrolledWindow::OnScroll(event); +#else + HandleOnScroll( event ); +#endif + + if(event.GetOrientation() == wxHORIZONTAL) + { + m_owner->GetHeaderWindow()->Refresh(); + m_owner->GetHeaderWindow()->Update(); + } +} + + +void wxTreeListMainWindow::CalculateSize( wxTreeListItem *item, wxDC &dc ) +{ + wxCoord text_w = 0; + wxCoord text_h = 0; + + if (item->IsBold()) + dc.SetFont(m_boldFont); + + dc.GetTextExtent( item->GetText(/*ALB*/m_main_column), &text_w, &text_h ); + text_h+=2; + + // restore normal font + dc.SetFont( m_normalFont ); + + int total_h = (m_imgHeight > text_h) ? m_imgHeight : text_h; + + item->SetHeight(total_h); + if (total_h>m_lineHeight) + m_lineHeight=total_h; + + item->SetWidth(m_imgWidth + text_w+2); +} + +// ----------------------------------------------------------------------------- +// for developper : y is now the top of the level +// not the middle of it ! +void wxTreeListMainWindow::CalculateLevel( wxTreeListItem *item, wxDC &dc, + int level, int &y, int x_colstart ) +{ + // calculate position of vertical lines + int x = x_colstart + MARGIN; // start of column + if (HasFlag(wxTR_LINES_AT_ROOT)) x += LINEATROOT; // space for lines at root + if (HasButtons()) x += m_btnWidth2; // space for buttons etc. + if (!HasFlag(wxTR_HIDE_ROOT)) x += m_indent; // indent root as well + x += m_indent * level; // indent according to level + + // a hidden root is not evaluated, but its children are always + if (HasFlag(wxTR_HIDE_ROOT) && (level == 0)) goto Recurse; + + CalculateSize( item, dc ); + + // set its position + item->SetX (x); + item->SetY (y); + y += GetLineHeight(item); + + // we don't need to calculate collapsed branches + if ( !item->IsExpanded() ) return; + +Recurse: + wxArrayTreeListItems& children = item->GetChildren(); + size_t n, count = children.Count(); + ++level; + for (n = 0; n < count; ++n ) + CalculateLevel( children[n], dc, level, y, x_colstart ); // recurse +} + +void wxTreeListMainWindow::CalculatePositions() +{ + if ( !m_anchor ) return; + + wxClientDC dc(this); + PrepareDC( dc ); + + dc.SetFont( m_normalFont ); + + dc.SetPen( m_dottedPen ); + //if(GetImageList() == NULL) + // m_lineHeight = (int)(dc.GetCharHeight() + 4); + + int y = 2; + int x_colstart = 0; + for(size_t i = 0; i < GetMainColumn(); ++i) { + if (!m_owner->GetHeaderWindow()->GetColumnShown(i)) continue; + x_colstart += m_owner->GetHeaderWindow()->GetColumnWidth(i); + } + CalculateLevel( m_anchor, dc, 0, y, x_colstart ); // start recursion +} + +void wxTreeListMainWindow::RefreshSubtree(wxTreeListItem *item) +{ + if (m_dirty) return; + + wxClientDC dc(this); + PrepareDC(dc); + + int cw = 0; + int ch = 0; + GetClientSize( &cw, &ch ); // GetVirtualSize??? + + wxRect rect; + rect.x = dc.LogicalToDeviceX( 0 ); + rect.width = cw; + rect.y = dc.LogicalToDeviceY( item->GetY() - 2 ); + rect.height = ch; + + Refresh( TRUE, &rect ); + + AdjustMyScrollbars(); +} + +void wxTreeListMainWindow::RefreshLine( wxTreeListItem *item ) +{ + if (m_dirty) return; + + wxClientDC dc(this); + PrepareDC( dc ); + + int cw = 0; + int ch = 0; + GetClientSize( &cw, &ch ); // GetVirtualSize ?? + + wxRect rect; + rect.x = dc.LogicalToDeviceX( 0 ); + rect.y = dc.LogicalToDeviceY( item->GetY() ); + rect.width = cw; + rect.height = GetLineHeight(item); //dc.GetCharHeight() + 6; + + Refresh( TRUE, &rect ); +} + +void wxTreeListMainWindow::RefreshSelected() +{ + // TODO: this is awfully inefficient, we should keep the list of all + // selected items internally, should be much faster + if ( m_anchor ) + RefreshSelectedUnder(m_anchor); +} + +void wxTreeListMainWindow::RefreshSelectedUnder(wxTreeListItem *item) +{ + if ( item->IsSelected() ) + RefreshLine(item); + + const wxArrayTreeListItems& children = item->GetChildren(); + size_t count = children.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + RefreshSelectedUnder(children[n]); + } +} + +// ---------------------------------------------------------------------------- +// changing colours: we need to refresh the tree control +// ---------------------------------------------------------------------------- + +bool wxTreeListMainWindow::SetBackgroundColour(const wxColour& colour) +{ + if ( !wxWindow::SetBackgroundColour(colour) ) + return FALSE; + + Refresh(); + + return TRUE; +} + +bool wxTreeListMainWindow::SetForegroundColour(const wxColour& colour) +{ + if ( !wxWindow::SetForegroundColour(colour) ) + return FALSE; + + Refresh(); + + return TRUE; +} + +//----------- ALB ------------- +void wxTreeListMainWindow::SetItemText(const wxTreeItemId& item, size_t column, + const wxString& text) +{ + wxCHECK_RET( item.IsOk(), wxT("invalid tree item") ); + + wxClientDC dc(this); + wxTreeListItem *pItem = (wxTreeListItem*) item.m_pItem; + pItem->SetText(column, text); + CalculateSize(pItem, dc); + RefreshLine(pItem); +} + +wxString wxTreeListMainWindow::GetItemText(const wxTreeItemId& item, + size_t column) const +{ + wxCHECK_MSG( item.IsOk(), wxT(""), wxT("invalid tree item") ); + + return ((wxTreeListItem*) item.m_pItem)->GetText(column); +} + +void wxTreeListMainWindow::SetFocus() +{ + wxWindow::SetFocus(); +} + + +//----------------------------------------------------------------------------- +// wxTreeListCtrl +//----------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxTreeListCtrl, wxControl); + +BEGIN_EVENT_TABLE(wxTreeListCtrl, wxControl) + EVT_SIZE(wxTreeListCtrl::OnSize) +END_EVENT_TABLE(); + +bool wxTreeListCtrl::Create(wxWindow *parent, wxWindowID id, + const wxPoint& pos, + const wxSize& size, + long style, const wxValidator &validator, + const wxString& name) +{ + long main_style = style & ~(wxRAISED_BORDER|wxSUNKEN_BORDER + |wxSIMPLE_BORDER|wxNO_BORDER|wxDOUBLE_BORDER + |wxSTATIC_BORDER); + long ctrl_style = style & ~(wxVSCROLL|wxHSCROLL); + + if (!wxControl::Create(parent, id, pos, size, ctrl_style, validator, name)) { + return false; + } + m_main_win = new wxTreeListMainWindow(this, -1, wxPoint(0, 0), size, + main_style, validator); + m_header_win = new wxTreeListHeaderWindow(this, -1, m_main_win, + wxPoint(0, 0), wxDefaultSize, + wxTAB_TRAVERSAL); + return TRUE; +} + +void wxTreeListCtrl::OnSize(wxSizeEvent& WXUNUSED(event)) +{ + int w, h; + GetClientSize(&w, &h); + if(m_header_win) + m_header_win->SetSize(0, 0, w, HEADER_HEIGHT); + if(m_main_win) + m_main_win->SetSize(0, HEADER_HEIGHT + 1, w, h - HEADER_HEIGHT - 1); +} + + +size_t wxTreeListCtrl::GetCount() const { return m_main_win->GetCount(); } + +unsigned int wxTreeListCtrl::GetIndent() const +{ return m_main_win->GetIndent(); } + +void wxTreeListCtrl::SetIndent(unsigned int indent) +{ m_main_win->SetIndent(indent); } + +unsigned int wxTreeListCtrl::GetLineSpacing() const +{ return m_main_win->GetLineSpacing(); } + +void wxTreeListCtrl::SetLineSpacing(unsigned int spacing) +{ m_main_win->SetLineSpacing(spacing); } + +wxImageList* wxTreeListCtrl::GetImageList() const +{ return m_main_win->GetImageList(); } + +wxImageList* wxTreeListCtrl::GetStateImageList() const +{ return m_main_win->GetStateImageList(); } + +wxImageList* wxTreeListCtrl::GetButtonsImageList() const +{ return m_main_win->GetButtonsImageList(); } + +void wxTreeListCtrl::SetImageList(wxImageList* imageList) +{ m_main_win->SetImageList(imageList); } + +void wxTreeListCtrl::SetStateImageList(wxImageList* imageList) +{ m_main_win->SetStateImageList(imageList); } + +void wxTreeListCtrl::SetButtonsImageList(wxImageList* imageList) +{ m_main_win->SetButtonsImageList(imageList); } + +void wxTreeListCtrl::AssignImageList(wxImageList* imageList) +{ m_main_win->AssignImageList(imageList); } + +void wxTreeListCtrl::AssignStateImageList(wxImageList* imageList) +{ m_main_win->AssignStateImageList(imageList); } + +void wxTreeListCtrl::AssignButtonsImageList(wxImageList* imageList) +{ m_main_win->AssignButtonsImageList(imageList); } + +wxString wxTreeListCtrl::GetItemText(const wxTreeItemId& item, size_t column) + const +{ return m_main_win->GetItemText(item, column); } + +int wxTreeListCtrl::GetItemImage(const wxTreeItemId& item, size_t column, + wxTreeItemIcon which) const +{ return m_main_win->GetItemImage(item, column, which); } + +wxTreeItemData* wxTreeListCtrl::GetItemData(const wxTreeItemId& item) const +{ return m_main_win->GetItemData(item); } + +bool wxTreeListCtrl::GetItemBold(const wxTreeItemId& item) const +{ return m_main_win->GetItemBold(item); } + +wxColour wxTreeListCtrl::GetItemTextColour(const wxTreeItemId& item) const +{ return m_main_win->GetItemTextColour(item); } + +wxColour wxTreeListCtrl::GetItemBackgroundColour(const wxTreeItemId& item) + const +{ return m_main_win->GetItemBackgroundColour(item); } + +wxFont wxTreeListCtrl::GetItemFont(const wxTreeItemId& item) const +{ return m_main_win->GetItemFont(item); } + + +void wxTreeListCtrl::SetItemText(const wxTreeItemId& item, size_t column, + const wxString& text) +{ m_main_win->SetItemText(item, column, text); } + +void wxTreeListCtrl::SetItemImage(const wxTreeItemId& item, + size_t column, + int image, + wxTreeItemIcon which) +{ m_main_win->SetItemImage(item, column, image, which); } + +void wxTreeListCtrl::SetItemData(const wxTreeItemId& item, + wxTreeItemData* data) +{ m_main_win->SetItemData(item, data); } + +void wxTreeListCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) +{ m_main_win->SetItemHasChildren(item, has); } + +void wxTreeListCtrl::SetItemBold(const wxTreeItemId& item, bool bold) +{ m_main_win->SetItemBold(item, bold); } + +void wxTreeListCtrl::SetItemTextColour(const wxTreeItemId& item, + const wxColour& col) +{ m_main_win->SetItemTextColour(item, col); } + +void wxTreeListCtrl::SetItemBackgroundColour(const wxTreeItemId& item, + const wxColour& col) +{ m_main_win->SetItemBackgroundColour(item, col); } + +void wxTreeListCtrl::SetItemFont(const wxTreeItemId& item, + const wxFont& font) +{ m_main_win->SetItemFont(item, font); } + +bool wxTreeListCtrl::SetFont(const wxFont& font) +{ + if(m_header_win) m_header_win->SetFont(font); + if(m_main_win) + return m_main_win->SetFont(font); + else return FALSE; +} + +void wxTreeListCtrl::SetWindowStyle(const long style) +{ + if(m_main_win) + m_main_win->SetWindowStyle(style); + // TODO: provide something like wxTL_NO_HEADERS to hide m_header_win +} + +long wxTreeListCtrl::GetWindowStyle() const +{ + long style = m_windowStyle; + if(m_main_win) + style |= m_main_win->GetWindowStyle(); + return style; +} + +bool wxTreeListCtrl::IsVisible(const wxTreeItemId& item) const +{ return m_main_win->IsVisible(item); } + +bool wxTreeListCtrl::ItemHasChildren(const wxTreeItemId& item) const +{ return m_main_win->ItemHasChildren(item); } + +bool wxTreeListCtrl::IsExpanded(const wxTreeItemId& item) const +{ return m_main_win->IsExpanded(item); } + +bool wxTreeListCtrl::IsSelected(const wxTreeItemId& item) const +{ return m_main_win->IsSelected(item); } + +bool wxTreeListCtrl::IsBold(const wxTreeItemId& item) const +{ return m_main_win->IsBold(item); } + +size_t wxTreeListCtrl::GetChildrenCount(const wxTreeItemId& item, bool rec) +{ return m_main_win->GetChildrenCount(item, rec); } + +wxTreeItemId wxTreeListCtrl::GetRootItem() const +{ return m_main_win->GetRootItem(); } + +wxTreeItemId wxTreeListCtrl::GetSelection() const +{ return m_main_win->GetSelection(); } + +size_t wxTreeListCtrl::GetSelections(wxArrayTreeItemIds& arr) const +{ return m_main_win->GetSelections(arr); } + +wxTreeItemId wxTreeListCtrl::GetItemParent(const wxTreeItemId& item) const +{ return m_main_win->GetItemParent(item); } + +#if !wxCHECK_VERSION(2, 5, 0) +wxTreeItemId wxTreeListCtrl::GetFirstChild(const wxTreeItemId& item, + long& cookie) const +#else +wxTreeItemId wxTreeListCtrl::GetFirstChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +#endif +{ return m_main_win->GetFirstChild(item, cookie); } + +#if !wxCHECK_VERSION(2, 5, 0) +wxTreeItemId wxTreeListCtrl::GetNextChild(const wxTreeItemId& item, + long& cookie) const +#else +wxTreeItemId wxTreeListCtrl::GetNextChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +#endif +{ return m_main_win->GetNextChild(item, cookie); } + +#if !wxCHECK_VERSION(2, 5, 0) +wxTreeItemId wxTreeListCtrl::GetPrevChild(const wxTreeItemId& item, + long& cookie) const +#else +wxTreeItemId wxTreeListCtrl::GetPrevChild(const wxTreeItemId& item, + wxTreeItemIdValue& cookie) const +#endif +{ return m_main_win->GetPrevChild(item, cookie); } + +wxTreeItemId wxTreeListCtrl::GetLastChild(const wxTreeItemId& item) const +{ return m_main_win->GetLastChild(item); } + +wxTreeItemId wxTreeListCtrl::GetNextSibling(const wxTreeItemId& item) const +{ return m_main_win->GetNextSibling(item); } + +wxTreeItemId wxTreeListCtrl::GetPrevSibling(const wxTreeItemId& item) const +{ return m_main_win->GetPrevSibling(item); } + +wxTreeItemId wxTreeListCtrl::GetFirstVisibleItem() const +{ return m_main_win->GetFirstVisibleItem(); } + +wxTreeItemId wxTreeListCtrl::GetNextVisible(const wxTreeItemId& item) const +{ return m_main_win->GetNextVisible(item); } + +wxTreeItemId wxTreeListCtrl::GetPrevVisible(const wxTreeItemId& item) const +{ return m_main_win->GetPrevVisible(item); } + +wxTreeItemId wxTreeListCtrl::GetNext(const wxTreeItemId& item) const +{ return m_main_win->GetNext(item); } + +wxTreeItemId wxTreeListCtrl::AddRoot(const wxString& text, int image, + int selectedImage, wxTreeItemData* data) +{ return m_main_win->AddRoot(text, image, selectedImage, data); } + +wxTreeItemId wxTreeListCtrl::PrependItem(const wxTreeItemId& parent, + const wxString& text, int image, + int selectedImage, + wxTreeItemData* data) +{ return m_main_win->PrependItem(parent, text, image, selectedImage, data); } + +wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent, + const wxTreeItemId& previous, + const wxString& text, int image, + int selectedImage, + wxTreeItemData* data) +{ + return m_main_win->InsertItem(parent, previous, text, image, + selectedImage, data); +} + +wxTreeItemId wxTreeListCtrl::InsertItem(const wxTreeItemId& parent, + size_t index, + const wxString& text, int image, + int selectedImage, + wxTreeItemData* data) +{ + return m_main_win->InsertItem(parent, index, text, image, + selectedImage, data); +} + +wxTreeItemId wxTreeListCtrl::AppendItem(const wxTreeItemId& parent, + const wxString& text, int image, + int selectedImage, + wxTreeItemData* data) +{ return m_main_win->AppendItem(parent, text, image, selectedImage, data); } + +void wxTreeListCtrl::Delete(const wxTreeItemId& item) +{ m_main_win->Delete(item); } + +void wxTreeListCtrl::DeleteChildren(const wxTreeItemId& item) +{ m_main_win->DeleteChildren(item); } + +void wxTreeListCtrl::DeleteAllItems() +{ m_main_win->DeleteAllItems(); } + +void wxTreeListCtrl::Expand(const wxTreeItemId& item) +{ m_main_win->Expand(item); } + +void wxTreeListCtrl::ExpandAll(const wxTreeItemId& item) +{ m_main_win->ExpandAll(item); } + +void wxTreeListCtrl::Collapse(const wxTreeItemId& item) +{ m_main_win->Collapse(item); } + +void wxTreeListCtrl::CollapseAndReset(const wxTreeItemId& item) +{ m_main_win->CollapseAndReset(item); } + +void wxTreeListCtrl::Toggle(const wxTreeItemId& item) +{ m_main_win->Toggle(item); } + +void wxTreeListCtrl::Unselect() +{ m_main_win->Unselect(); } + +void wxTreeListCtrl::UnselectAll() +{ m_main_win->UnselectAll(); } + +void wxTreeListCtrl::SelectItem(const wxTreeItemId& item, bool unselect_others, + bool extended_select) +{ m_main_win->SelectItem(item, unselect_others, extended_select); } + +void wxTreeListCtrl::SelectAll(bool extended_select) +{ m_main_win->SelectAll(extended_select); } + +void wxTreeListCtrl::EnsureVisible(const wxTreeItemId& item) +{ m_main_win->EnsureVisible(item); } + +void wxTreeListCtrl::ScrollTo(const wxTreeItemId& item) +{ m_main_win->ScrollTo(item); } + +wxTreeItemId wxTreeListCtrl::HitTest(const wxPoint& pos, int& flags, + int& column) +{ + return m_main_win->HitTest(m_main_win->ScreenToClient(ClientToScreen(pos)), + flags, column); +} + +bool wxTreeListCtrl::GetBoundingRect(const wxTreeItemId& item, wxRect& rect, + bool textOnly) const +{ return m_main_win->GetBoundingRect(item, rect, textOnly); } + +void wxTreeListCtrl::Edit(const wxTreeItemId& item) +{ m_main_win->Edit(item); } + +int wxTreeListCtrl::OnCompareItems(const wxTreeItemId& item1, + const wxTreeItemId& item2) +{ + // ALB: do the comparison here, and not delegate to m_main_win, in order + // to let the user override it + //return m_main_win->OnCompareItems(item1, item2); + return wxStrcmp(GetItemText(item1), GetItemText(item2)); +} + +void wxTreeListCtrl::SortChildren(const wxTreeItemId& item) +{ m_main_win->SortChildren(item); } + +wxTreeItemId wxTreeListCtrl::FindItem (const wxTreeItemId& item, const wxString& str, int flags) +{ return m_main_win->FindItem (item, str, flags); } + +bool wxTreeListCtrl::SetBackgroundColour(const wxColour& colour) +{ return m_main_win->SetBackgroundColour(colour); } + +bool wxTreeListCtrl::SetForegroundColour(const wxColour& colour) +{ return m_main_win->SetForegroundColour(colour); } + +size_t wxTreeListCtrl::GetColumnCount() const +{ return m_main_win->GetColumnCount(); } + +void wxTreeListCtrl::SetColumnWidth(size_t column, size_t width) +{ m_header_win->SetColumnWidth(column, width); } + +int wxTreeListCtrl::GetColumnWidth(size_t column) const +{ return m_header_win->GetColumnWidth(column); } + +void wxTreeListCtrl::SetMainColumn(size_t column) +{ m_main_win->SetMainColumn(column); } + +size_t wxTreeListCtrl::GetMainColumn() const +{ return m_main_win->GetMainColumn(); } + +void wxTreeListCtrl::SetColumnText(size_t column, const wxString& text) +{ + m_header_win->SetColumnText(column, text); + m_header_win->Refresh(); +} + +wxString wxTreeListCtrl::GetColumnText(size_t column) const +{ return m_header_win->GetColumnText(column); } + +void wxTreeListCtrl::AddColumn(const wxTreeListColumnInfo& col) +{ m_header_win->AddColumn(col); } + +void wxTreeListCtrl::InsertColumn(size_t before, + const wxTreeListColumnInfo& col) +{ m_header_win->InsertColumn(before, col); } + +void wxTreeListCtrl::RemoveColumn(size_t column) +{ m_header_win->RemoveColumn(column); } + +void wxTreeListCtrl::SetColumn(size_t column, const wxTreeListColumnInfo& col) +{ m_header_win->SetColumn(column, col); } + +const wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(size_t column) const +{ return m_header_win->GetColumn(column); } + +wxTreeListColumnInfo& wxTreeListCtrl::GetColumn(size_t column) +{ return m_header_win->GetColumn(column); } + +void wxTreeListCtrl::SetColumnImage(size_t column, int image) +{ + m_header_win->SetColumn(column, GetColumn(column).SetImage(image)); +} + +int wxTreeListCtrl::GetColumnImage(size_t column) const +{ + return m_header_win->GetColumn(column).GetImage(); +} + +void wxTreeListCtrl::ShowColumn(size_t column, bool shown) +{ + wxASSERT_MSG( column != GetMainColumn(), + wxT("The main column may not be hidden") ); + m_header_win->SetColumn(column, GetColumn(column).SetShown(GetMainColumn()? true: shown)); +} + +bool wxTreeListCtrl::IsColumnShown(size_t column) const +{ + return m_header_win->GetColumn(column).GetShown(); +} + +void wxTreeListCtrl::SetColumnAlignment(size_t column, + wxTreeListColumnAlign align) +{ + m_header_win->SetColumn(column, GetColumn(column).SetAlignment(align)); +} + +wxTreeListColumnAlign wxTreeListCtrl::GetColumnAlignment(size_t column) const +{ + return m_header_win->GetColumn(column).GetAlignment(); +} + +void wxTreeListCtrl::Refresh(bool erase, const wxRect* rect) +{ + m_main_win->Refresh(erase, rect); + m_header_win->Refresh(erase, rect); +} + +void wxTreeListCtrl::SetFocus() +{ m_main_win->SetFocus(); } + diff --git a/wxPython/docs/CHANGES.txt b/wxPython/docs/CHANGES.txt index 350aa5dbe5..f4bef2e3bc 100644 --- a/wxPython/docs/CHANGES.txt +++ b/wxPython/docs/CHANGES.txt @@ -1,7 +1,7 @@ Recent Changes for wxPython ===================================================================== -2.5.1.6 +2.5.2.0 ------- wx.ADJUST_MINSIZE is now the default behaviour for window items in @@ -64,6 +64,11 @@ running on wxGTK to work around the fact that GTK requires the locale to be set to the system settings but Python depends on LC_NUMERIC remaining compatible with "C". +Switched gizmos.TreeListCtrl to the newer version of the code from the +wxCode project. + + + 2.5.1.5 diff --git a/wxPython/setup.py b/wxPython/setup.py index 346f552fad..7822c28dcc 100755 --- a/wxPython/setup.py +++ b/wxPython/setup.py @@ -586,9 +586,9 @@ if BUILD_GIZMOS: USE_SWIG, swig_force, swig_args, swig_deps) ext = Extension('_gizmos', - [ '%s/treelistctrl.cpp' % location ] + swig_sources, + [ '%s/treelistctrl.cpp' % opj(location, 'wxCode/src') ] + swig_sources, - include_dirs = includes + [ location ] + CONTRIBS_INC, + include_dirs = includes + [ location, opj(location, 'wxCode/include') ] + CONTRIBS_INC, define_macros = defines, library_dirs = libdirs, diff --git a/wxPython/wxPython/gizmos.py b/wxPython/wxPython/gizmos.py index a715b71580..b6fde3ea48 100644 --- a/wxPython/wxPython/gizmos.py +++ b/wxPython/wxPython/gizmos.py @@ -58,6 +58,11 @@ wxTL_ALIGN_LEFT = wx.gizmos.TL_ALIGN_LEFT wxTL_ALIGN_RIGHT = wx.gizmos.TL_ALIGN_RIGHT wxTL_ALIGN_CENTER = wx.gizmos.TL_ALIGN_CENTER wxTREE_HITTEST_ONITEMCOLUMN = wx.gizmos.TREE_HITTEST_ONITEMCOLUMN +wxTL_SEARCH_VISIBLE = wx.gizmos.TL_SEARCH_VISIBLE +wxTL_SEARCH_LEVEL = wx.gizmos.TL_SEARCH_LEVEL +wxTL_SEARCH_FULL = wx.gizmos.TL_SEARCH_FULL +wxTL_SEARCH_PARTIAL = wx.gizmos.TL_SEARCH_PARTIAL +wxTL_SEARCH_NOCASE = wx.gizmos.TL_SEARCH_NOCASE wxTreeListColumnInfo = wx.gizmos.TreeListColumnInfo wxTreeListColumnInfoPtr = wx.gizmos.TreeListColumnInfoPtr wxTreeListCtrl = wx.gizmos.TreeListCtrl