1. Implemented support for different icons for different states (expanded,

selected, combination of them) for the tree control (and doc'd it)
2. removed code which was sending extra event if wxFrame::SetSize() was
   used
3. important changes to wxWizard interface
4. small compilation corrections


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3756 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
1999-09-29 22:47:56 +00:00
parent 4f3ac40926
commit 74b31181b3
31 changed files with 936 additions and 353 deletions

View File

@@ -110,6 +110,115 @@ private:
const wxTreeCtrl *m_tree;
};
// internal class for getting the selected items
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;
};
// internal class for counting tree items
class TraverseCounter : public wxTreeTraversal
{
public:
TraverseCounter(const wxTreeCtrl *tree,
const wxTreeItemId& root,
bool recursively)
: wxTreeTraversal(tree)
{
m_count = 0;
DoTraverse(root, recursively);
}
virtual bool OnVisit(const wxTreeItemId& item)
{
m_count++;
return TRUE;
}
size_t GetCount() const { return m_count; }
private:
size_t m_count;
};
// ----------------------------------------------------------------------------
// This class is needed for support of different images: the Win32 common
// control natively supports only 2 images (the normal one and another for the
// selected state). We wish to provide support for 2 more of them for folder
// items (i.e. those which have children): for expanded state and for expanded
// selected state. For this we use this structure to store the additional items
// images.
//
// There is only one problem with this: when we retrieve the item's data, we
// don't know whether we get a pointer to wxTreeItemData or
// wxTreeItemIndirectData. So we have to maintain a list of all items which
// have indirect data inside the listctrl itself.
// ----------------------------------------------------------------------------
class wxTreeItemIndirectData
{
public:
// ctor associates this data with the item and the real item data becomes
// available through our GetData() method
wxTreeItemIndirectData(wxTreeCtrl *tree, const wxTreeItemId& item)
{
for ( size_t n = 0; n < WXSIZEOF(m_images); n++ )
{
m_images[n] = -1;
}
// save the old data
m_data = tree->GetItemData(item);
// and set ourselves as the new one
tree->SetIndirectItemData(item, this);
}
// dtor deletes the associated data as well
~wxTreeItemIndirectData() { delete m_data; }
// accessors
// get the real data associated with the item
wxTreeItemData *GetData() const { return m_data; }
// change it
void SetData(wxTreeItemData *data) { m_data = data; }
// do we have such image?
bool HasImage(wxTreeItemIcon which) const { return m_images[which] != -1; }
// get image
int GetImage(wxTreeItemIcon which) const { return m_images[which]; }
// change it
void SetImage(int image, wxTreeItemIcon which) { m_images[which] = image; }
private:
// all the images associated with the item
int m_images[wxTreeItemIcon_Max];
wxTreeItemData *m_data;
};
// ----------------------------------------------------------------------------
// macros
// ----------------------------------------------------------------------------
@@ -216,7 +325,6 @@ bool wxTreeCtrl::Create(wxWindow *parent,
SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
SetForegroundColour(wxWindow::GetParent()->GetForegroundColour());
// 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.
@@ -350,35 +458,6 @@ void wxTreeCtrl::SetStateImageList(wxImageList *imageList)
SetAnyImageList(m_imageListState = imageList, TVSIL_STATE);
}
// internal class for counting tree items
class TraverseCounter : public wxTreeTraversal
{
public:
TraverseCounter(const wxTreeCtrl *tree,
const wxTreeItemId& root,
bool recursively)
: wxTreeTraversal(tree)
{
m_count = 0;
DoTraverse(root, recursively);
}
virtual bool OnVisit(const wxTreeItemId& item)
{
m_count++;
return TRUE;
}
size_t GetCount() const { return m_count; }
private:
size_t m_count;
};
size_t wxTreeCtrl::GetChildrenCount(const wxTreeItemId& item,
bool recursively) const
{
@@ -414,6 +493,46 @@ void wxTreeCtrl::SetItemText(const wxTreeItemId& item, const wxString& text)
DoSetItem(&tvItem);
}
int wxTreeCtrl::DoGetItemImageFromData(const wxTreeItemId& item,
wxTreeItemIcon which) const
{
wxTreeViewItem tvItem(item, TVIF_PARAM);
if ( !DoGetItem(&tvItem) )
{
return -1;
}
return ((wxTreeItemIndirectData *)tvItem.lParam)->GetImage(which);
}
void wxTreeCtrl::DoSetItemImageFromData(const wxTreeItemId& item,
int image,
wxTreeItemIcon which) const
{
wxTreeViewItem tvItem(item, TVIF_PARAM);
if ( !DoGetItem(&tvItem) )
{
return;
}
wxTreeItemIndirectData *data = ((wxTreeItemIndirectData *)tvItem.lParam);
data->SetImage(image, which);
// make sure that we have selected images as well
if ( which == wxTreeItemIcon_Normal &&
!data->HasImage(wxTreeItemIcon_Selected) )
{
data->SetImage(image, wxTreeItemIcon_Selected);
}
if ( which == wxTreeItemIcon_Expanded &&
!data->HasImage(wxTreeItemIcon_SelectedExpanded) )
{
data->SetImage(image, wxTreeItemIcon_SelectedExpanded);
}
}
void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item,
int image,
int imageSel)
@@ -424,36 +543,90 @@ void wxTreeCtrl::DoSetItemImages(const wxTreeItemId& item,
DoSetItem(&tvItem);
}
int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const
int wxTreeCtrl::GetItemImage(const wxTreeItemId& item,
wxTreeItemIcon which) const
{
wxTreeViewItem tvItem(item, TVIF_IMAGE);
if ( HasIndirectData(item) )
{
return DoGetItemImageFromData(item, which);
}
UINT mask;
switch ( which )
{
default:
wxFAIL_MSG( _T("unknown tree item image type") );
case wxTreeItemIcon_Normal:
mask = TVIF_IMAGE;
break;
case wxTreeItemIcon_Selected:
mask = TVIF_SELECTEDIMAGE;
break;
case wxTreeItemIcon_Expanded:
case wxTreeItemIcon_SelectedExpanded:
return -1;
}
wxTreeViewItem tvItem(item, mask);
DoGetItem(&tvItem);
return tvItem.iImage;
return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage;
}
void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image)
void wxTreeCtrl::SetItemImage(const wxTreeItemId& item, int image,
wxTreeItemIcon which)
{
int imageNormal, imageSel;
switch ( which )
{
default:
wxFAIL_MSG( _T("unknown tree item image type") );
case wxTreeItemIcon_Normal:
imageNormal = image;
imageSel = GetItemSelectedImage(item);
break;
case wxTreeItemIcon_Selected:
imageNormal = GetItemImage(item);
imageSel = image;
break;
case wxTreeItemIcon_Expanded:
case wxTreeItemIcon_SelectedExpanded:
if ( !HasIndirectData(item) )
{
// we need to get the old images first, because after we create
// the wxTreeItemIndirectData GetItemXXXImage() will use it to
// get the images
imageNormal = GetItemImage(item);
imageSel = GetItemSelectedImage(item);
// if it doesn't have it yet, add it
wxTreeItemIndirectData *data = new
wxTreeItemIndirectData(this, item);
// copy the data to the new location
data->SetImage(imageNormal, wxTreeItemIcon_Normal);
data->SetImage(imageSel, wxTreeItemIcon_Selected);
}
DoSetItemImageFromData(item, image, which);
// reset the normal/selected images because we won't use them any
// more - now they're stored inside the indirect data
imageNormal =
imageSel = I_IMAGECALLBACK;
break;
}
// 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
{
wxTreeViewItem tvItem(item, TVIF_SELECTEDIMAGE);
DoGetItem(&tvItem);
return tvItem.iSelectedImage;
}
void wxTreeCtrl::SetItemSelectedImage(const wxTreeItemId& item, int image)
{
// 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);
DoSetItemImages(item, imageNormal, imageSel);
}
wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
@@ -464,14 +637,55 @@ wxTreeItemData *wxTreeCtrl::GetItemData(const wxTreeItemId& item) const
return NULL;
}
return (wxTreeItemData *)tvItem.lParam;
if ( HasIndirectData(item) )
{
return ((wxTreeItemIndirectData *)tvItem.lParam)->GetData();
}
else
{
return (wxTreeItemData *)tvItem.lParam;
}
}
void wxTreeCtrl::SetItemData(const wxTreeItemId& item, wxTreeItemData *data)
{
wxTreeViewItem tvItem(item, TVIF_PARAM);
tvItem.lParam = (LPARAM)data;
DoSetItem(&tvItem);
if ( HasIndirectData(item) )
{
if ( DoGetItem(&tvItem) )
{
((wxTreeItemIndirectData *)tvItem.lParam)->SetData(data);
}
else
{
wxFAIL_MSG( _T("failed to change tree items data") );
}
}
else
{
tvItem.lParam = (LPARAM)data;
DoSetItem(&tvItem);
}
}
void wxTreeCtrl::SetIndirectItemData(const wxTreeItemId& item,
wxTreeItemIndirectData *data)
{
// this should never happen because it's unnecessary and will probably lead
// to crash too because the code elsewhere supposes that the pointer the
// wxTreeItemIndirectData has is a real wxItemData and not
// wxTreeItemIndirectData as well
wxASSERT_MSG( !HasIndirectData(item), _T("setting indirect data twice?") );
SetItemData(item, (wxTreeItemData *)data);
m_itemsWithIndirectData.Add(item);
}
bool wxTreeCtrl::HasIndirectData(const wxTreeItemId& item) const
{
return m_itemsWithIndirectData.Index(item) != wxNOT_FOUND;
}
void wxTreeCtrl::SetItemHasChildren(const wxTreeItemId& item, bool has)
@@ -655,34 +869,6 @@ void wxTreeCtrl::SetItemCheck(const wxTreeItemId& item, bool check)
DoSetItem(&tvItem);
}
// internal class for getting the selected
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;
};
size_t wxTreeCtrl::GetSelections(wxArrayTreeItemIds& selections) const
{
TraverseSelections selector(this, selections);
@@ -704,8 +890,9 @@ wxTreeItemId wxTreeCtrl::DoInsertItem(const wxTreeItemId& parent,
tvIns.hParent = (HTREEITEM) (WXHTREEITEM)parent;
tvIns.hInsertAfter = (HTREEITEM) (WXHTREEITEM) hInsertAfter;
// This is how we insert the item as the first child: supply a NULL hInsertAfter
if (tvIns.hInsertAfter == (HTREEITEM) 0)
// this is how we insert the item as the first child: supply a NULL
// hInsertAfter
if ( !tvIns.hInsertAfter )
{
tvIns.hInsertAfter = TVI_FIRST;
}
@@ -1302,8 +1489,21 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
// prefer to do it here ourself (otherwise deleting a tree
// with many items is just too slow)
NM_TREEVIEW* tv = (NM_TREEVIEW *)lParam;
wxTreeItemData *data = (wxTreeItemData *)tv->itemOld.lParam;
delete data; // may be NULL, ok
wxTreeItemId item = event.m_item;
if ( HasIndirectData(item) )
{
wxTreeItemIndirectData *data = (wxTreeItemIndirectData *)
tv->itemOld.lParam;
delete data; // can't be NULL here
m_itemsWithIndirectData.Remove(item);
}
else
{
wxTreeItemData *data = (wxTreeItemData *)tv->itemOld.lParam;
delete data; // may be NULL, ok
}
processed = TRUE; // Make sure we don't get called twice
}
@@ -1329,6 +1529,36 @@ bool wxTreeCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
*result = !event.IsAllowed();
break;
case TVN_GETDISPINFO:
// NB: so far the user can't set the image himself anyhow, so do it
// anyway - but this may change later
if ( /* !processed && */ 1 )
{
wxTreeItemId item = event.m_item;
TV_DISPINFO *info = (TV_DISPINFO *)lParam;
if ( info->item.mask & TVIF_IMAGE )
{
info->item.iImage =
DoGetItemImageFromData
(
item,
IsExpanded(item) ? wxTreeItemIcon_Expanded
: wxTreeItemIcon_Normal
);
}
if ( info->item.mask & TVIF_SELECTEDIMAGE )
{
info->item.iSelectedImage =
DoGetItemImageFromData
(
item,
IsExpanded(item) ? wxTreeItemIcon_SelectedExpanded
: wxTreeItemIcon_Selected
);
}
}
break;
//default:
// for the other messages the return value is ignored and there is
// nothing special to do