left of parent items.}
\twocolitem{\windowstyle{wxTR\_EDIT\_LABELS}}{Use this style if you wish the user to be
able to edit labels in the tree control.}
+\twocolitem{\windowstyle{wxTR\_MULTIPLE}}{Use this style to allow the user to
+select more than one item in the control - by default, only one item may be
+selected.}
\end{twocollist}
See also \helpref{window styles overview}{windowstyles}.
\constfunc{wxTreeItemId}{GetSelection}{\void}
Returns the selection, or an invalid item if there is no selection.
+This function only works with the controls without wxTR\_MULTIPLE style, use
+\helpref{GetSelections}{wxtreectrlgetselections} for the controls which do have
+this style.
+
+\membersection{wxTreeCtrl::GetSelections}\label{wxtreectrlgetselections}
+
+\constfunc{size\_t}{GetSelections}{\param{wxArrayTreeItemIds\& }{selection}}
+
+Fills the array of tree items passed in with the currently selected items. This
+function can be called only if the control has the wxTR\_MULTIPLE style.
+
+Returns the number of selected items.
\membersection{wxTreeCtrl::HitTest}\label{wxtreectrlhittest}
Removes the selection from the currently selected item (if any).
+\membersection{wxTreeCtrl::UnselectAll}\label{wxtreectrlunselectall}
+
+\func{void}{UnselectAll}{\void}
+
+This function either behaves the same as \helpref{Unselect}{wxtreectrlunselect}
+if the control doesn't have wxTR\_MULTIPLE style, or removes the selection from
+all items if it does have this style.
+
\section{\class{wxTreeItemData}}\label{wxtreeitemdata}
wxTreeItemData is some (arbitrary) user class associated with some item. The
#include "wx/dynarray.h"
#include "wx/timer.h"
-//those defines should only be done in generic/treectrl.h,
+//those defines should only be done in generic/treectrl.h,
//because wxMSW doesn't allow mutiple selection
#ifndef wxTR_SINGLE
public:
wxTreeTextCtrl(void) {};
- wxTreeTextCtrl( wxWindow *parent, const wxWindowID id,
+ wxTreeTextCtrl( wxWindow *parent, const wxWindowID id,
bool *accept, wxString *res, wxTreeCtrl *owner,
const wxString &value = "",
const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize,
const wxString &name = "wxTreeTextCtrlText" );
void OnChar( wxKeyEvent &event );
void OnKillFocus( wxFocusEvent &event );
-
+
DECLARE_EVENT_TABLE()
};
unsigned int GetIndent() const { return m_indent; }
void SetIndent(unsigned int indent);
- // spacing is the number of pixels between the start and the Text
+ // spacing is the number of pixels between the start and the Text
unsigned int GetSpacing() const { return m_spacing; }
void SetSpacing(unsigned int spacing);
-
+
// image list: these functions allow to associate an image list with
// the control and retrieve it. Note that the control does _not_ delete
// the associated image list when it's deleted in order to allow image
// 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
// Draw Special Information
void DrawBorder(wxTreeItemId& item);
void DrawLine(wxTreeItemId& item, bool below);
-
+
protected:
friend class wxGenericTreeItem;
friend class wxTreeRenameTimer;
void RefreshSubtree( wxGenericTreeItem *item );
void RefreshLine( wxGenericTreeItem *item );
-
+
void OnRenameTimer();
void OnRenameAccept();
long m_itemId;
};
+WX_DEFINE_ARRAY(wxTreeItemId, wxArrayTreeItemIds);
+
// ----------------------------------------------------------------------------
// wxTreeItemData is some (arbitrary) user class associated with some item. The
// main advantage of having this class (compared to old untyped interface) is
// 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);
+ size_t GetChildrenCount(const wxTreeItemId& item,
+ bool recursively = TRUE) const;
// navigation
// ----------
// 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
+ //
+ // NB: this operation is expensive and can take a long time for a
+ // control with a lot of items (~ O(number of items)).
+ size_t GetSelections(wxArrayTreeItemIds& selections) const;
+
// get the parent of this item (may return NULL if root)
wxTreeItemId GetParent(const wxTreeItemId& item) const;
// remove the selection from currently selected item (if any)
void Unselect();
+ // unselect all items (only makes sense for multiple selection control)
+ void UnselectAll();
// select this item
void SelectItem(const wxTreeItemId& item);
// make sure this item is visible (expanding the parent item and/or
virtual bool MSWCommand(WXUINT param, WXWORD id);
virtual bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result);
+ // get/set the check state for the item (only for wxTR_MULTIPLE)
+ bool IsItemChecked(const wxTreeItemId& item) const;
+ void SetItemCheck(const wxTreeItemId& item, bool check = TRUE);
+
protected:
// SetImageList helper
void SetAnyImageList(wxImageList *imageList, int which);
int image, int selectedImage,
wxTreeItemData *data);
+ void DoSetItemImages(const wxTreeItemId& item, int image, int imageSel);
+
void DeleteTextCtrl();
DECLARE_DYNAMIC_CLASS(wxTreeCtrl)
#include "math.h"
-#include "treetest.h"
-
#ifdef __WXMSW__
- #define NO_ADVANCED_FEATURES
+ //#define NO_MULTIPLE_SELECTION
+ #define NO_VARIABLE_HEIGHT
#endif
+#include "treetest.h"
+
// under Windows the icons are in the .rc file
#ifndef __WXMSW__
#include "icon1.xpm"
EVT_MENU(TreeTest_Quit, MyFrame::OnQuit)
EVT_MENU(TreeTest_About, MyFrame::OnAbout)
EVT_MENU(TreeTest_Dump, MyFrame::OnDump)
- EVT_MENU(TreeTest_Dump_Selected, MyFrame::OnDumpSelected)
+#ifndef NO_MULTIPLE_SELECTION
+ EVT_MENU(TreeTest_DumpSelected, MyFrame::OnDumpSelected)
+ EVT_MENU(TreeTest_Select, MyFrame::OnSelect)
+ EVT_MENU(TreeTest_Unselect, MyFrame::OnUnselect)
+#endif // NO_MULTIPLE_SELECTION
EVT_MENU(TreeTest_Rename, MyFrame::OnRename)
EVT_MENU(TreeTest_Sort, MyFrame::OnSort)
EVT_MENU(TreeTest_SortRev, MyFrame::OnSortRev)
EVT_MENU(TreeTest_DecIndent, MyFrame::OnDecIndent)
EVT_MENU(TreeTest_IncSpacing, MyFrame::OnIncSpacing)
EVT_MENU(TreeTest_DecSpacing, MyFrame::OnDecSpacing)
+ EVT_MENU(TreeTest_ToggleIcon, MyFrame::OnToggleIcon)
END_EVENT_TABLE()
BEGIN_EVENT_TABLE(MyTreeCtrl, wxTreeCtrl)
tree_menu->Append(TreeTest_DecSpacing, "Reduce spacing by 5 points\tCtrl-R");
item_menu->Append(TreeTest_Dump, "&Dump item children");
-#ifndef NO_ADVANCED_FEATURES
- item_menu->Append(TreeTest_Dump_Selected, "Dump selected items\tAlt-S");
-#endif
item_menu->Append(TreeTest_Rename, "&Rename item...");
item_menu->AppendSeparator();
item_menu->Append(TreeTest_Bold, "Make item &bold");
item_menu->Append(TreeTest_UnBold, "Make item ¬ bold");
+ item_menu->AppendSeparator();
+ item_menu->Append(TreeTest_ToggleIcon, "Toggle the items &icon");
+
+#ifndef NO_MULTIPLE_SELECTION
+ item_menu->AppendSeparator();
+ item_menu->Append(TreeTest_DumpSelected, "Dump selected items\tAlt-D");
+ item_menu->Append(TreeTest_Select, "Select current item\tAlt-S");
+ item_menu->Append(TreeTest_Unselect, "Unselect everything\tAlt-U");
+#endif
wxMenuBar *menu_bar = new wxMenuBar;
menu_bar->Append(file_menu, "&File");
wxDefaultPosition, wxDefaultSize,
wxTR_HAS_BUTTONS |
wxTR_EDIT_LABELS |
-#ifndef NO_ADVANCED_FEATURES
wxTR_MULTIPLE |
wxTR_HAS_VARIABLE_ROW_HEIGHT |
-#endif
wxSUNKEN_BORDER);
wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, "",
wxDefaultPosition, wxDefaultSize,
m_treeCtrl->GetItemsRecursively(root, -1);
}
+#ifndef NO_MULTIPLE_SELECTION
+
void MyFrame::OnDumpSelected(wxCommandEvent& WXUNUSED(event))
{
-#ifndef NO_ADVANCED_FEATURES
- wxArrayTreeItemIds array;
+ wxArrayTreeItemIds array;
- m_treeCtrl->GetSelections(array);
- size_t nos=array.Count();
- wxLogMessage(wxString("items selected : ")<< (int)nos);
+ size_t count = m_treeCtrl->GetSelections(array);
+ wxLogMessage(_T("%u items selected"), count);
- for (size_t n=0; n<nos; ++n)
- wxLogMessage(m_treeCtrl->GetItemText(array.Item(n)));
-#endif
+ for ( size_t n = 0; n < count; n++ )
+ {
+ wxLogMessage("\t%s", m_treeCtrl->GetItemText(array.Item(n)).c_str());
+ }
+}
+
+void MyFrame::OnSelect(wxCommandEvent& event)
+{
+ m_treeCtrl->SelectItem(m_treeCtrl->GetSelection());
+}
+
+void MyFrame::OnUnselect(wxCommandEvent& event)
+{
+ m_treeCtrl->UnselectAll();
}
+#endif // NO_MULTIPLE_SELECTION
+
void MyFrame::DoSetBold(bool bold)
{
wxTreeItemId item = m_treeCtrl->GetSelection();
m_treeCtrl->SetSpacing( indent-5 );
}
+void MyFrame::OnToggleIcon(wxCommandEvent& WXUNUSED(event))
+{
+ wxTreeItemId item = m_treeCtrl->GetSelection();
+
+ CHECK_ITEM( item );
+
+ m_treeCtrl->DoToggleIcon(item);
+}
+
// MyTreeCtrl implementation
IMPLEMENT_DYNAMIC_CLASS(MyTreeCtrl, wxTreeCtrl)
: wxTreeCtrl(parent, id, pos, size, style)
{
#if (USE_TR_HAS_VARIABLE_ROW_HIGHT && wxUSE_LIBJPEG)
- wxImage::AddHandler(new wxJPEGHandler);
+ wxImage::AddHandler(new wxJPEGHandler);
wxImage image;
image.LoadFile(wxString("horse.jpg"), wxBITMAP_TYPE_JPEG );
else
str.Printf("%s child %d", "Folder", n + 1);
-// int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
- int image = depth == 1 ? -1 : TreeCtrlIcon_Folder;
+ int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
wxTreeItemId id = AppendItem(idParent, str, image, image,
new MyTreeItemData(str));
if(id <= 0)
return;
- wxString text=GetItemText(id);
+ wxString text = GetItemText(id);
wxLogMessage(text);
if (ItemHasChildren(id))
GetItemsRecursively(idParent, cookie);
}
+void MyTreeCtrl::DoToggleIcon(const wxTreeItemId& item)
+{
+ int image = GetItemImage(item) == TreeCtrlIcon_Folder ? TreeCtrlIcon_File
+ : TreeCtrlIcon_Folder;
+
+ SetItemImage(item, image);
+}
+
// avoid repetition
#define TREE_EVENT_HANDLER(name) \
void AddTestItemsToTree(size_t numChildren, size_t depth);
void DoSortChildren(const wxTreeItemId& item, bool reverse = FALSE)
- { m_reverseSort = reverse; wxTreeCtrl::SortChildren(item); }
+ { m_reverseSort = reverse; wxTreeCtrl::SortChildren(item); }
void DoEnsureVisible() { EnsureVisible(m_lastItem); }
+ void DoToggleIcon(const wxTreeItemId& item);
+
protected:
virtual int OnCompareItems(const wxTreeItemId& i1, const wxTreeItemId& i2);
void OnAbout(wxCommandEvent& event);
void OnDump(wxCommandEvent& event);
+#ifndef NO_MULTIPLE_SELECTION
void OnDumpSelected(wxCommandEvent& event);
+ void OnSelect(wxCommandEvent& event);
+ void OnUnselect(wxCommandEvent& event);
+#endif // NO_MULTIPLE_SELECTION
void OnDelete(wxCommandEvent& event);
void OnDeleteChildren(wxCommandEvent& event);
void OnDeleteAll(wxCommandEvent& event);
void OnSortRev(wxCommandEvent& event) { DoSort(TRUE); }
void OnAddItem(wxCommandEvent& event);
-
+
void OnIncIndent(wxCommandEvent& event);
void OnDecIndent(wxCommandEvent& event);
void OnIncSpacing(wxCommandEvent& event);
void OnDecSpacing(wxCommandEvent& event);
+ void OnToggleIcon(wxCommandEvent& event);
+
private:
void DoSort(bool reverse = FALSE);
TreeTest_Quit,
TreeTest_About,
TreeTest_Dump,
- TreeTest_Dump_Selected,
+ TreeTest_DumpSelected,
TreeTest_Sort,
TreeTest_SortRev,
TreeTest_Bold,
TreeTest_DecIndent,
TreeTest_IncSpacing,
TreeTest_DecSpacing,
- TreeTest_Ctrl = 100
+ TreeTest_ToggleIcon,
+ TreeTest_Select,
+ TreeTest_Unselect,
+ TreeTest_Ctrl = 1000
};
{
(*m_accept) = TRUE;
(*m_res) = GetValue();
- m_owner->SetFocus();
+ m_owner->SetFocus();
return;
}
if (event.m_keyCode == WXK_ESCAPE)
{
(*m_accept) = FALSE;
(*m_res) = "";
- m_owner->SetFocus();
+ m_owner->SetFocus();
return;
}
event.Skip();
if (wxPendingDelete.Member(this)) return;
wxPendingDelete.Append(this);
-
+
if ((*m_accept) && ((*m_res) != m_startValue))
m_owner->OnRenameAccept();
}
// -----------------------------------------------------------------------------
IMPLEMENT_DYNAMIC_CLASS(wxTreeEvent, wxNotifyEvent)
-
+
wxTreeEvent::wxTreeEvent( wxEventType commandType, int id )
: wxNotifyEvent( commandType, id )
{
m_imageListState = (wxImageList *) NULL;
m_dragCount = 0;
-
+
m_renameTimer = new wxTreeRenameTimer( this );
}
wxDELETE( m_hilightBrush );
DeleteAllItems();
-
+
delete m_renameTimer;
}
GetEventHandler()->ProcessEvent( event );
}
-void wxTreeCtrl::FillArray(wxGenericTreeItem *item, wxArrayTreeItemIds &array) const
+void wxTreeCtrl::FillArray(wxGenericTreeItem *item,
+ wxArrayTreeItemIds &array) const
{
- if (item->HasHilight()) array.Add(wxTreeItemId(item));
+ if ( item->HasHilight() )
+ array.Add(wxTreeItemId(item));
- if (item->HasChildren())
+ if ( item->HasChildren() )
{
- wxArrayGenericTreeItems& children = item->GetChildren();
- size_t count = children.Count();
- for ( size_t n = 0; n < count; ++n )
- FillArray(children[n],array);
+ wxArrayGenericTreeItems& children = item->GetChildren();
+ size_t count = children.GetCount();
+ for ( size_t n = 0; n < count; ++n )
+ FillArray(children[n],array);
}
}
dc.SetPen( *wxGREY_PEN );
dc.SetBrush( *wxWHITE_BRUSH );
dc.DrawRectangle( horizX+(m_indent-5), y-4, 11, 9 );
-
+
dc.SetPen( *wxBLACK_PEN );
dc.DrawLine( horizX+(m_indent-2), y, horizX+(m_indent+3), y );
if (!item->IsExpanded())
dc.DrawLine( horizX+m_indent, y-2, horizX+m_indent, y+3 );
-
+
dc.SetPen( m_dottedPen );
}
if (!item.IsOk()) return;
m_currentEdit = item.m_pItem;
-
+
wxTreeEvent te( wxEVT_COMMAND_TREE_BEGIN_LABEL_EDIT, GetId() );
te.m_item = m_currentEdit;
te.SetEventObject( this );
GetEventHandler()->ProcessEvent( te );
if (!te.IsAllowed()) return;
-
+
wxString s = m_currentEdit->GetText();
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;
if ((m_currentEdit->IsExpanded()) && (m_currentEdit->GetSelectedImage() != -1))
le.SetEventObject( this );
le.m_label = m_renameRes;
GetEventHandler()->ProcessEvent( le );
-
+
if (!le.IsAllowed()) return;
-
+
SetItemText( m_currentEdit, m_renameRes );
}
-
+
void wxTreeCtrl::OnMouse( wxMouseEvent &event )
{
if (!event.LeftIsDown()) m_dragCount = 0;
return;
}
- if (event.LeftUp() && (item == m_current) &&
- (flags & wxTREE_HITTEST_ONITEMLABEL) &&
- HasFlag(wxTR_EDIT_LABELS) )
+ if (event.LeftUp() && (item == m_current) &&
+ (flags & wxTREE_HITTEST_ONITEMLABEL) &&
+ HasFlag(wxTR_EDIT_LABELS) )
{
m_renameTimer->Start( 100, TRUE );
return;
}
-
+
bool is_multiple=(GetWindowStyleFlag() & wxTR_MULTIPLE);
bool extended_select=(event.ShiftDown() && is_multiple);
bool unselect_others=!(extended_select || (event.ControlDown() && is_multiple));
{
long text_w = 0;
long text_h = 0;
-
+
wxFont fontOld;
wxFont fontNew;
if (item->IsBold())
wxFAIL_MSG(_T("wxDC::GetFont() failed!"));
}
}
-
+
dc.GetTextExtent( item->GetText(), &text_w, &text_h );
text_h+=2;
// restore normal font for bold items
if (fontOld.Ok())
dc.SetFont( fontOld);
-
+
int image_h = 0;
int image_w = 0;
if ((item->IsExpanded()) && (item->GetSelectedImage() != -1))
#include "wx/window.h"
#include "wx/msw/private.h"
-#ifndef WX_PRECOMP
- #include "wx/settings.h"
-#endif
-
// Mingw32 is a bit mental even though this is done in winundef
#ifdef GetFirstChild
#undef GetFirstChild
// a convenient wrapper around TV_ITEM struct which adds a ctor
struct wxTreeViewItem : public TV_ITEM
{
- wxTreeViewItem(const wxTreeItemId& item,
- UINT mask_, UINT stateMask_ = 0)
+ wxTreeViewItem(const wxTreeItemId& item, // the item handle
+ UINT mask_, // fields which are valid
+ UINT stateMask_ = 0) // for TVIF_STATE only
{
- mask = mask_;
+ // hItem member is always valid
+ mask = mask_ | TVIF_HANDLE;
stateMask = stateMask_;
hItem = (HTREEITEM) (WXHTREEITEM) item;
}
};
+// a class which encapsulates the tree traversal logic: it vists all (unless
+// OnVisit() returns FALSE) items under the given one
+class wxTreeTraversal
+{
+public:
+ wxTreeTraversal(const wxTreeCtrl *tree)
+ {
+ m_tree = tree;
+ }
+
+ // do traverse the tree: visit all items (recursively by default) under the
+ // given one; return TRUE if all items were traversed or FALSE if the
+ // traversal was aborted because OnVisit returned FALSE
+ bool DoTraverse(const wxTreeItemId& root, bool recursively = TRUE);
+
+ // override this function to do whatever is needed for each item, return
+ // FALSE to stop traversing
+ virtual bool OnVisit(const wxTreeItemId& item) = 0;
+
+protected:
+ const wxTreeCtrl *GetTree() const { return m_tree; }
+
+private:
+ bool Traverse(const wxTreeItemId& root, bool recursively);
+
+ const wxTreeCtrl *m_tree;
+};
+
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
// implementation
// ============================================================================
+// ----------------------------------------------------------------------------
+// tree traversal
+// ----------------------------------------------------------------------------
+
+bool wxTreeTraversal::DoTraverse(const wxTreeItemId& root, bool recursively)
+{
+ if ( !OnVisit(root) )
+ return FALSE;
+
+ return Traverse(root, recursively);
+}
+
+bool wxTreeTraversal::Traverse(const wxTreeItemId& root, bool recursively)
+{
+ long cookie;
+ wxTreeItemId child = m_tree->GetFirstChild(root, cookie);
+ while ( child.IsOk() )
+ {
+ // depth first traversal
+ if ( recursively && !Traverse(child, TRUE) )
+ return FALSE;
+
+ if ( !OnVisit(child) )
+ return FALSE;
+
+ child = m_tree->GetNextChild(root, cookie);
+ }
+
+ return TRUE;
+}
+
// ----------------------------------------------------------------------------
// construction and destruction
// ----------------------------------------------------------------------------
m_textCtrl = NULL;
}
-bool wxTreeCtrl::Create(wxWindow *parent, wxWindowID id,
- const wxPoint& pos, const wxSize& size,
- long style, const wxValidator& validator,
+bool wxTreeCtrl::Create(wxWindow *parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
const wxString& name)
{
Init();
- wxSystemSettings settings;
-
- SetName(name);
- SetValidator(validator);
-
- m_windowStyle = style;
-
- SetParent(parent);
-
- m_windowId = (id == -1) ? NewControlId() : id;
+ if ( !CreateControl(parent, id, pos, size, style, validator, name) )
+ return FALSE;
DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP |
TVS_HASLINES | TVS_SHOWSELALWAYS;
- bool want3D;
- WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
-
- // Even with extended styles, need to combine with WS_BORDER
- // for them to look right.
- if ( want3D || wxStyleHasBorder(m_windowStyle) )
- {
- wstyle |= WS_BORDER;
- }
-
if ( m_windowStyle & wxTR_HAS_BUTTONS )
wstyle |= TVS_HASBUTTONS;
if ( m_windowStyle & wxTR_LINES_AT_ROOT )
wstyle |= TVS_LINESATROOT;
+ // we emulate the multiple selection tree controls by using checkboxes: set
+ // up the image list we need for this if we do have multiple selections
+ if ( m_windowStyle & wxTR_MULTIPLE )
+ wstyle |= TVS_CHECKBOXES;
+
// Create the tree control.
- m_hWnd = (WXHWND)::CreateWindowEx
- (
- exStyle,
- WC_TREEVIEW,
- _T(""),
- wstyle,
- pos.x, pos.y, size.x, size.y,
- (HWND)parent->GetHWND(),
- (HMENU)m_windowId,
- wxGetInstance(),
- NULL
- );
-
- wxCHECK_MSG( m_hWnd, FALSE, _T("Failed to create tree ctrl") );
-
- if ( parent )
- parent->AddChild(this);
-
- SubclassWin(m_hWnd);
+ if ( !MSWCreateControl(WC_TREEVIEW, wstyle) )
+ return FALSE;
+
+ // VZ: this is some experimental code which may be used to get the
+ // TVS_CHECKBOXES style functionality for comctl32.dll < 4.71.
+ // AFAIK, the standard DLL does about the same thing anyhow.
+#if 0
+ if ( m_windowStyle & wxTR_MULTIPLE )
+ {
+ wxBitmap bmp;
+
+ // create the DC compatible with the current screen
+ HDC hdcMem = CreateCompatibleDC(NULL);
+
+ // create a mono bitmap of the standard size
+ int x = GetSystemMetrics(SM_CXMENUCHECK);
+ int y = GetSystemMetrics(SM_CYMENUCHECK);
+ wxImageList imagelistCheckboxes(x, y, FALSE, 2);
+ HBITMAP hbmpCheck = CreateBitmap(x, y, // bitmap size
+ 1, // # of color planes
+ 1, // # bits needed for one pixel
+ 0); // array containing colour data
+ SelectObject(hdcMem, hbmpCheck);
+
+ // then draw a check mark into it
+ RECT rect = { 0, 0, x, y };
+ if ( !::DrawFrameControl(hdcMem, &rect,
+ DFC_BUTTON,
+ DFCS_BUTTONCHECK | DFCS_CHECKED) )
+ {
+ wxLogLastError(_T("DrawFrameControl(check)"));
+ }
+
+ bmp.SetHBITMAP((WXHBITMAP)hbmpCheck);
+ imagelistCheckboxes.Add(bmp);
+
+ if ( !::DrawFrameControl(hdcMem, &rect,
+ DFC_BUTTON,
+ DFCS_BUTTONCHECK) )
+ {
+ wxLogLastError(_T("DrawFrameControl(uncheck)"));
+ }
+
+ bmp.SetHBITMAP((WXHBITMAP)hbmpCheck);
+ imagelistCheckboxes.Add(bmp);
+
+ // clean up
+ ::DeleteDC(hdcMem);
+
+ // set the imagelist
+ SetStateImageList(&imagelistCheckboxes);
+ }
+#endif // 0
+
+ SetSize(pos.x, pos.y, size.x, size.y);
return TRUE;
}
SetAnyImageList(m_imageListState = imageList, TVSIL_STATE);
}
-size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item, bool recursively)
+size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
+ bool recursively) const
{
- long cookie;
+ class TraverseCounter : public wxTreeTraversal
+ {
+ public:
+ TraverseCounter(const wxTreeCtrl *tree,
+ const wxTreeItemId& root,
+ bool recursively)
+ : wxTreeTraversal(tree)
+ {
+ m_count = 0;
- size_t result = 0;
+ DoTraverse(root, recursively);
+ }
- wxArrayLong children;
- wxTreeItemId child = GetFirstChild(item, cookie);
- while ( child.IsOk() )
- {
- if ( recursively )
+ virtual bool OnVisit(const wxTreeItemId& item)
{
- // recursive call
- result += GetChildrenCount(child, TRUE);
+ m_count++;
+
+ return TRUE;
}
- // add the child to the result in any case
- result++;
+ size_t GetCount() const { return m_count; }
- child = GetNextChild(item, cookie);
- }
+ private:
+ size_t m_count;
+ } counter(this, item, recursively);
- return result;
+ return counter.GetCount();
}
// ----------------------------------------------------------------------------
DoSetItem(&tvItem);
}
+void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item,
+ int image,
+ int imageSel)
+{
+ wxTreeViewItem tvItem(item, TVIF_IMAGE | TVIF_SELECTEDIMAGE);
+ tvItem.iSelectedImage = imageSel;
+ tvItem.iImage = image;
+ DoSetItem(&tvItem);
+}
+
int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const
{
wxTreeViewItem tvItem(item, TVIF_IMAGE);
void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image)
{
- wxTreeViewItem tvItem(item, TVIF_IMAGE);
- tvItem.iImage = image;
- DoSetItem(&tvItem);
+ // NB: at least in version 5.00.0518.9 of comctl32.dll we need to always
+ // change both normal and selected image - otherwise the change simply
+ // doesn't take place!
+ DoSetItemImages(item, image, GetItemSelectedImage(item));
}
int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const
void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image)
{
- wxTreeViewItem tvItem(item, TVIF_SELECTEDIMAGE);
- tvItem.iSelectedImage = image;
- DoSetItem(&tvItem);
+ // NB: at least in version 5.00.0518.9 of comctl32.dll we need to always
+ // change both normal and selected image - otherwise the change simply
+ // doesn't take place!
+ DoSetItemImages(item, GetItemImage(item), image);
}
wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
wxTreeItemId wxTreeCtrl::GetSelection() const
{
+ wxCHECK_MSG( !(m_windowStyle & wxTR_MULTIPLE), (WXHTREEITEM)0,
+ _T("this only works with single selection controls") );
+
return wxTreeItemId((WXHTREEITEM) TreeView_GetSelection(GetHwnd()));
}
return wxTreeItemId((WXHTREEITEM) TreeView_GetPrevVisible(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item));
}
+// ----------------------------------------------------------------------------
+// multiple selections emulation
+// ----------------------------------------------------------------------------
+
+bool wxTreeCtrl::IsItemChecked(const wxTreeItemId& item) const
+{
+ // receive the desired information.
+ wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK);
+ DoGetItem(&tvItem);
+
+ // state image indices are 1 based
+ return ((tvItem.state >> 12) - 1) == 1;
+}
+
+void wxTreeCtrl::SetItemCheck(const wxTreeItemId& item, bool check)
+{
+ // receive the desired information.
+ wxTreeViewItem tvItem(item, TVIF_STATE, TVIS_STATEIMAGEMASK);
+
+ // state images are one-based
+ tvItem.state = (check ? 2 : 1) << 12;
+
+ DoSetItem(&tvItem);
+}
+
+size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds& selections) const
+{
+ class TraverseSelections : public wxTreeTraversal
+ {
+ public:
+ TraverseSelections(const wxTreeCtrl *tree,
+ wxArrayTreeItemIds& selections)
+ : wxTreeTraversal(tree), m_selections(selections)
+ {
+ m_selections.Empty();
+
+ DoTraverse(tree->GetRootItem());
+ }
+
+ virtual bool OnVisit(const wxTreeItemId& item)
+ {
+ if ( GetTree()->IsItemChecked(item) )
+ {
+ m_selections.Add(item);
+ }
+
+ return TRUE;
+ }
+
+ private:
+ wxArrayTreeItemIds& m_selections;
+ } selector(this, selections);
+
+ return selections.GetCount();
+}
+
// ----------------------------------------------------------------------------
// Usual operations
// ----------------------------------------------------------------------------
void wxTreeCtrl::ExpandItem(const wxTreeItemId& item, int action)
{
- DoExpand(item, action);
+ DoExpand(item, action);
}
void wxTreeCtrl::Unselect()
{
+ wxASSERT_MSG( !(m_windowStyle & wxTR_MULTIPLE), _T("doesn't make sense") );
+
+ // just remove the selection
SelectItem(wxTreeItemId((WXHTREEITEM) 0));
}
-void wxTreeCtrl::SelectItem(const wxTreeItemId& item)
+void wxTreeCtrl::UnselectAll()
{
- // inspite of the docs (MSDN Jan 99 edition), we don't seem to receive
- // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so
- // send them ourselves
-
- wxTreeEvent event(wxEVT_NULL, m_windowId);
- event.m_item = item;
- event.SetEventObject(this);
-
- event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGING);
- if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
+ if ( m_windowStyle & wxTR_MULTIPLE )
{
- if ( !TreeView_SelectItem(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item) )
+ wxArrayTreeItemIds selections;
+ size_t count = GetSelections(selections);
+ for ( size_t n = 0; n < count; n++ )
{
- wxLogLastError("TreeView_SelectItem");
+ SetItemCheck(selections[n], FALSE);
}
- else
+ }
+ else
+ {
+ // just remove the selection
+ Unselect();
+ }
+}
+
+void wxTreeCtrl::SelectItem(const wxTreeItemId& item)
+{
+ if ( m_windowStyle & wxTR_MULTIPLE )
+ {
+ // selecting the item means checking it
+ SetItemCheck(item);
+ }
+ else
+ {
+ // inspite of the docs (MSDN Jan 99 edition), we don't seem to receive
+ // the notification from the control (i.e. TVN_SELCHANG{ED|ING}), so
+ // send them ourselves
+
+ wxTreeEvent event(wxEVT_NULL, m_windowId);
+ event.m_item = item;
+ event.SetEventObject(this);
+
+ event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGING);
+ if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
{
- event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
- (void)GetEventHandler()->ProcessEvent(event);
+ if ( !TreeView_SelectItem(GetHwnd(), (HTREEITEM) (WXHTREEITEM) item) )
+ {
+ wxLogLastError("TreeView_SelectItem");
+ }
+ else
+ {
+ event.SetEventType(wxEVT_COMMAND_TREE_SEL_CHANGED);
+ (void)GetEventHandler()->ProcessEvent(event);
+ }
}
+ //else: program vetoed the change
}
- //else: program vetoed the change
}
void wxTreeCtrl::EnsureVisible(const wxTreeItemId& item)