From: Vadim Zeitlin Date: Sat, 24 Oct 1998 23:53:20 +0000 (+0000) Subject: some new functions: X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/3a5a2f56f25522d5e6662022fb05cf4539a70e91?ds=inline some new functions: 1. wxTreeItemData::SetId() added 2. wxTreeCtrl::SetItemHasChildren() added git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@908 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/msw/treectrl.h b/include/wx/msw/treectrl.h index bb44c4e08b..ce4523f1e2 100644 --- a/include/wx/msw/treectrl.h +++ b/include/wx/msw/treectrl.h @@ -131,27 +131,19 @@ protected: // Because the objects of this class are deleted by the tree, they should // always be allocated on the heap! // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxTreeItemData +class WXDLLEXPORT wxTreeItemData : private wxTreeItemId { -friend class wxTreeCtrl; public: - // creation/destruction - // -------------------- - // default ctor - wxTreeItemData() { } + // default ctor/copy ctor/assignment operator are ok - // default copy ctor/assignment operator are ok - - // dtor is virtual and all the items are deleted by the tree control - // when it's deleted, so you normally don't have to care about freeing - // memory allocated in your wxTreeItemData-derived class + // dtor is virtual and all the items are deleted by the tree control when + // it's deleted, so you normally don't have to care about freeing memory + // allocated in your wxTreeItemData-derived class virtual ~wxTreeItemData() { } - // accessor: get the item associated with us - const wxTreeItemId& GetItemId() const { return m_itemId; } - -protected: - wxTreeItemId m_itemId; + // accessors: set/get the item associated with this node + void SetId(const wxTreeItemId& id) { m_itemId = id; } + const wxTreeItemId& GetId() const { return m_itemId; } }; // ---------------------------------------------------------------------------- @@ -240,6 +232,12 @@ public: // 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); + // item status inquiries // --------------------- diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index 94a72b0d55..9417971398 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -6,53 +6,59 @@ // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// #ifdef __GNUG__ -#pragma implementation -#pragma interface + #pragma implementation + #pragma interface #endif // For compilers that support precompilation, includes "wx/wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #ifndef WX_PRECOMP -#include "wx/wx.h" + #include "wx/wx.h" #endif +// under Windows the icons are in the .rc file #ifndef __WXMSW__ #include "icon1.xpm" #include "icon2.xpm" #include "mondrian.xpm" #endif +#include "wx/log.h" + +#include "wx/imaglist.h" #include "wx/treectrl.h" #include "treetest.h" BEGIN_EVENT_TABLE(MyFrame, wxFrame) - EVT_MENU(TREE_QUIT, MyFrame::OnQuit) - EVT_MENU(TREE_ABOUT, MyFrame::OnAbout) + EVT_MENU(TreeTest_Quit, MyFrame::OnQuit) + EVT_MENU(TreeTest_About, MyFrame::OnAbout) END_EVENT_TABLE() BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl) - EVT_TREE_BEGIN_DRAG(TREE_CTRL, MyTreeCtrl::OnBeginDrag) - EVT_TREE_BEGIN_RDRAG(TREE_CTRL, MyTreeCtrl::OnBeginRDrag) - EVT_TREE_BEGIN_LABEL_EDIT(TREE_CTRL, MyTreeCtrl::OnBeginLabelEdit) - EVT_TREE_END_LABEL_EDIT(TREE_CTRL, MyTreeCtrl::OnEndLabelEdit) - EVT_TREE_DELETE_ITEM(TREE_CTRL, MyTreeCtrl::OnDeleteItem) - EVT_TREE_GET_INFO(TREE_CTRL, MyTreeCtrl::OnGetInfo) - EVT_TREE_SET_INFO(TREE_CTRL, MyTreeCtrl::OnSetInfo) - EVT_TREE_ITEM_EXPANDED(TREE_CTRL, MyTreeCtrl::OnItemExpanded) - EVT_TREE_ITEM_EXPANDING(TREE_CTRL, MyTreeCtrl::OnItemExpanding) - EVT_TREE_SEL_CHANGED(TREE_CTRL, MyTreeCtrl::OnSelChanged) - EVT_TREE_SEL_CHANGING(TREE_CTRL, MyTreeCtrl::OnSelChanging) - EVT_TREE_KEY_DOWN(TREE_CTRL, MyTreeCtrl::OnKeyDown) + EVT_TREE_BEGIN_DRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginDrag) + EVT_TREE_BEGIN_RDRAG(TreeTest_Ctrl, MyTreeCtrl::OnBeginRDrag) + EVT_TREE_BEGIN_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnBeginLabelEdit) + EVT_TREE_END_LABEL_EDIT(TreeTest_Ctrl, MyTreeCtrl::OnEndLabelEdit) + EVT_TREE_DELETE_ITEM(TreeTest_Ctrl, MyTreeCtrl::OnDeleteItem) + EVT_TREE_GET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnGetInfo) + EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo) + EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded) + EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding) + EVT_TREE_ITEM_COLLAPSED(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsed) + EVT_TREE_ITEM_COLLAPSING(TreeTest_Ctrl, MyTreeCtrl::OnItemCollapsing) + EVT_TREE_SEL_CHANGED(TreeTest_Ctrl, MyTreeCtrl::OnSelChanged) + EVT_TREE_SEL_CHANGING(TreeTest_Ctrl, MyTreeCtrl::OnSelChanging) + EVT_TREE_KEY_DOWN(TreeTest_Ctrl, MyTreeCtrl::OnKeyDown) END_EVENT_TABLE() IMPLEMENT_APP(MyApp) @@ -61,320 +67,198 @@ IMPLEMENT_APP(MyApp) bool MyApp::OnInit() { // Create the main frame window - MyFrame *frame = new MyFrame((wxFrame *) NULL, (char *) "wxTreeCtrl Test", 50, 50, 450, 340); + MyFrame *frame = new MyFrame("wxTreeCtrl Test", 50, 50, 450, 340); - // This reduces flicker effects - even better would be to define OnEraseBackground - // to do nothing. When the tree control's scrollbars are show or hidden, the - // frame is sent a background erase event. - frame->SetBackgroundColour(wxColour(255, 255, 255)); + // Show the frame + frame->Show(TRUE); + SetTopWindow(frame); - // Give it an icon - frame->SetIcon(wxICON(mondrian)); + return TRUE; +} - // Make an image list containing small icons - m_imageListNormal = new wxImageList(16, 16, TRUE); - m_imageListNormal->Add(wxICON(icon1)); - m_imageListNormal->Add(wxICON(icon2)); +// My frame constructor +MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h) + : wxFrame((wxFrame *)NULL, -1, title, wxPoint(x, y), wxSize(w, h)) +{ + // This reduces flicker effects - even better would be to define + // OnEraseBackground to do nothing. When the tree control's scrollbars are + // show or hidden, the frame is sent a background erase event. + SetBackgroundColour(wxColour(255, 255, 255)); + + // Give it an icon + SetIcon(wxICON(mondrian)); // Make a menubar wxMenu *file_menu = new wxMenu; - file_menu->Append(TREE_ABOUT, "&About"); - file_menu->Append(TREE_QUIT, "E&xit"); + file_menu->Append(TreeTest_About, "&About..."); + file_menu->Append(TreeTest_Quit, "E&xit"); wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); - frame->SetMenuBar(menu_bar); + SetMenuBar(menu_bar); // Make a panel with a message - frame->m_treeCtrl = new MyTreeCtrl(frame, TREE_CTRL, wxPoint(0, 0), wxSize(400, 200), - wxTR_HAS_BUTTONS|wxSUNKEN_BORDER); - frame->m_logWindow = new wxTextCtrl(frame, -1, "", wxPoint(0, 0), wxSize(400, 200), - wxTE_MULTILINE|wxSUNKEN_BORDER); + m_treeCtrl = new MyTreeCtrl(this, TreeTest_Ctrl, + wxDefaultPosition, wxDefaultSize, + wxTR_HAS_BUTTONS | wxSUNKEN_BORDER); + wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, "", + wxDefaultPosition, wxDefaultSize, + wxTE_MULTILINE | wxSUNKEN_BORDER); wxLayoutConstraints *c = new wxLayoutConstraints; - c->top.SameAs (frame, wxTop); - c->left.SameAs (frame, wxLeft); - c->right.SameAs (frame, wxRight); - c->height.PercentOf (frame, wxHeight, 66); - frame->m_treeCtrl->SetConstraints(c); + c->top.SameAs(this, wxTop); + c->left.SameAs(this, wxLeft); + c->right.SameAs(this, wxRight); + c->height.PercentOf(this, wxHeight, 66); + m_treeCtrl->SetConstraints(c); c = new wxLayoutConstraints; - c->top.Below (frame->m_treeCtrl); - c->left.SameAs (frame, wxLeft); - c->right.SameAs (frame, wxRight); - c->bottom.SameAs (frame, wxBottom); - frame->m_logWindow->SetConstraints(c); - frame->SetAutoLayout(TRUE); - - frame->m_treeCtrl->SetImageList(wxGetApp().m_imageListNormal, wxIMAGE_LIST_NORMAL); - - wxTreeItemId rootId = frame->m_treeCtrl->AddRoot("Root", 0); - - char buf[20]; - int i; - wxString str; - - for ( i = 0; i < 10; i++) - { - sprintf(buf, "Folder child %d", i); - str = buf; - wxTreeItemId id = frame->m_treeCtrl->AppendItem(rootId, str, 0); - int j; - for ( j = 0; j < 5; j++) - { - sprintf(buf, "File child %d", j); - str = buf; - frame->m_treeCtrl->AppendItem(id, str, 1); - } - } - for ( i = 0; i < 10; i++) - { - sprintf(buf, "File child %d", i); - str = buf; - frame->m_treeCtrl->AppendItem(rootId, str, 1); - } - - frame->CreateStatusBar(3); - frame->SetStatusText("", 0); - - // Show the frame - frame->Show(TRUE); - - SetTopWindow(frame); - - return TRUE; -} - -// My frame constructor -MyFrame::MyFrame(wxFrame *frame, char *title, int x, int y, int w, int h): - wxFrame(frame, -1, title, wxPoint(x, y), wxSize(w, h)) -{ - m_treeCtrl = (MyTreeCtrl *) NULL; - m_logWindow = (wxTextCtrl *) NULL; + c->top.Below(m_treeCtrl); + c->left.SameAs(this, wxLeft); + c->right.SameAs(this, wxRight); + c->bottom.SameAs(this, wxBottom); + textCtrl->SetConstraints(c); + SetAutoLayout(TRUE); + + // create a status bar with 3 panes + CreateStatusBar(3); + SetStatusText("", 0); + + // set our text control as the log target + wxLogTextCtrl *logWindow = new wxLogTextCtrl(textCtrl); + delete wxLog::SetActiveTarget(logWindow); } MyFrame::~MyFrame() { - delete wxGetApp().m_imageListNormal; + delete wxLog::SetActiveTarget(NULL); } -void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) +void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) { Close(TRUE); } -void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) ) +void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) { wxMessageDialog dialog(this, "Tree test sample\nJulian Smart (c) 1997", - "About tree test", wxOK|wxCANCEL); + "About tree test", wxOK); dialog.ShowModal(); } -// MyTreeCtrl - -void MyTreeCtrl::OnBeginDrag(wxTreeEvent& WXUNUSED(event) ) -{ - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnBeginDrag\n"; - str.flush(); -#endif -} - -void MyTreeCtrl::OnBeginRDrag(wxTreeEvent& WXUNUSED(event) ) +// MyTreeCtrl implementation +MyTreeCtrl::MyTreeCtrl(wxWindow *parent, const wxWindowID id, + const wxPoint& pos, const wxSize& size, + long style) + : wxTreeCtrl(parent, id, pos, size, style) { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnBeginRDrag\n"; - str.flush(); -#endif -} - -void MyTreeCtrl::OnBeginLabelEdit(wxTreeEvent& WXUNUSED(event) ) -{ - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnBeginLabelEdit\n"; - str.flush(); -#endif -} - -void MyTreeCtrl::OnEndLabelEdit(wxTreeEvent& WXUNUSED(event) ) -{ - if ( !wxGetApp().GetTopWindow() ) - return; + // Make an image list containing small icons + m_imageListNormal = new wxImageList(16, 16, TRUE); - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; + // should correspond to TreeCtrlIcon_xxx enum + m_imageListNormal->Add(wxICON(icon1)); + m_imageListNormal->Add(wxICON(icon2)); -#ifndef __GNUWIN32__ - ostream str(text); + SetImageList(m_imageListNormal); - str << "OnEndLabelEdit\n"; - str.flush(); -#endif + // Add some items to the tree + AddTestItemsToTree(4, 3); } -void MyTreeCtrl::OnDeleteItem(wxTreeEvent& WXUNUSED(event) ) +MyTreeCtrl::~MyTreeCtrl() { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnDeleteItem\n"; - str.flush(); -#endif + delete m_imageListNormal; } -void MyTreeCtrl::OnGetInfo(wxTreeEvent& WXUNUSED(event) ) +void MyTreeCtrl::AddItemsRecursively(const wxTreeItemId& idParent, + size_t numChildren, + size_t depth) { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnGetInfo\n"; - str.flush(); -#endif + if ( depth > 0 ) + { + wxString str; + for ( size_t n = 0; n < numChildren; n++ ) + { + // at depth 1 elements won't have any more children + str.Printf("%s child %d", depth == 1 ? "File" : "Folder", n); + int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder; + wxTreeItemId id = AppendItem(idParent, str, image, image, + new MyTreeItemData(str)); + AddItemsRecursively(id, numChildren, depth - 1); + } + } + //else: done! } -void MyTreeCtrl::OnSetInfo(wxTreeEvent& WXUNUSED(event) ) +void MyTreeCtrl::AddTestItemsToTree(size_t numChildren, + size_t depth) { - if ( !wxGetApp().GetTopWindow() ) - return; + long rootId = AddRoot("Root", + TreeCtrlIcon_Folder, TreeCtrlIcon_Folder, + new MyTreeItemData("Root item")); - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnSetInfo\n"; - str.flush(); -#endif + AddItemsRecursively(rootId, numChildren, depth); } -void MyTreeCtrl::OnItemExpanded(wxTreeEvent& WXUNUSED(event) ) -{ - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnItemExpanded\n"; - str.flush(); -#endif -} +// avoid repetition +#define TREE_EVENT_HANDLER(name) \ + void MyTreeCtrl::name(wxTreeEvent& WXUNUSED(event)) \ + { \ + wxLogMessage(#name); \ + } -void MyTreeCtrl::OnItemExpanding(wxTreeEvent& WXUNUSED(event) ) +TREE_EVENT_HANDLER(OnBeginDrag) +TREE_EVENT_HANDLER(OnBeginRDrag) +TREE_EVENT_HANDLER(OnBeginLabelEdit) +TREE_EVENT_HANDLER(OnEndLabelEdit) +TREE_EVENT_HANDLER(OnDeleteItem) +TREE_EVENT_HANDLER(OnGetInfo) +TREE_EVENT_HANDLER(OnSetInfo) +TREE_EVENT_HANDLER(OnItemExpanded) +TREE_EVENT_HANDLER(OnItemExpanding) +TREE_EVENT_HANDLER(OnItemCollapsed) +TREE_EVENT_HANDLER(OnSelChanged) +TREE_EVENT_HANDLER(OnSelChanging) + +#undef TREE_EVENT_HANDLER + +void MyTreeCtrl::OnItemCollapsing(wxTreeEvent& event) { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); + // for testing, prevent the user from collapsing the root item + wxTreeItemId itemId = event.GetItem(); + if ( !GetParent(itemId).IsOk() ) + { + wxMessageBox("Root item shouldn't collapse"); - str << "OnItemExpanding\n"; - str.flush(); -#endif + event.Veto(); + } } -void MyTreeCtrl::OnSelChanged(wxTreeEvent& WXUNUSED(event) ) +void MyTreeCtrl::OnKeyDown(wxTreeEvent& event) { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; + // show some info about this item + wxTreeItemId itemId = GetSelection(); + MyTreeItemData *item = (MyTreeItemData *)GetItemData(itemId); -#ifndef __GNUWIN32__ - ostream str(text); + if ( item != NULL ) + { + item->ShowInfo(this); + } - str << "OnSelChanged\n"; - str.flush(); -#endif + wxLogMessage("OnKeyDown"); } -void MyTreeCtrl::OnSelChanging(wxTreeEvent& WXUNUSED(event) ) +static inline const char *Bool2String(bool b) { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnSelChanging\n"; - str.flush(); -#endif + return b ? "" : "not "; } -void MyTreeCtrl::OnKeyDown(wxTreeEvent& WXUNUSED(event) ) +void MyTreeItemData::ShowInfo(wxTreeCtrl *tree) { - if ( !wxGetApp().GetTopWindow() ) - return; - - wxTextCtrl *text = ((MyFrame *)wxGetApp().GetTopWindow())->m_logWindow; - if ( !text ) - return; - -#ifndef __GNUWIN32__ - ostream str(text); - - str << "OnKeyDown\n"; - str.flush(); -#endif + wxLogMessage("Item '%s': %sselected, %sexpanded.", + m_desc.c_str(), + Bool2String(tree->IsExpanded(m_itemId)), + Bool2String(tree->IsSelected(m_itemId))); } - diff --git a/src/msw/treectrl.cpp b/src/msw/treectrl.cpp index 2a0c43ffc8..b129018649 100644 --- a/src/msw/treectrl.cpp +++ b/src/msw/treectrl.cpp @@ -319,14 +319,7 @@ wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const return NULL; } - wxTreeItemData *data = (wxTreeItemData *)tvItem.lParam; - if ( data != NULL ) - { - // the data object should know about its id - data->m_itemId = item; - } - - return data; + return (wxTreeItemData *)tvItem.lParam; } void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) @@ -336,6 +329,13 @@ void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data) DoSetItem(&tvItem); } +void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has) +{ + wxTreeViewItem tvItem(item, TVIF_CHILDREN); + tvItem.cChildren = (int)has; + DoSetItem(&tvItem); +} + // ---------------------------------------------------------------------------- // Item status // ---------------------------------------------------------------------------- @@ -466,6 +466,12 @@ wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parent, { mask |= TVIF_IMAGE; tvIns.item.iImage = image; + + if ( selectedImage = -1 ) + { + // take the same image for selected icon if not specified + selectedImage = image; + } } if ( selectedImage != -1 )