\membersection{wxTreeCtrl::GetItemImage}\label{wxtreectrlgetitemimage}
-\constfunc{int}{GetItemImage}{\param{const wxTreeItemId\& }{item}}
-
-Gets the normal item image.
+\constfunc{int}{GetItemImage}{\param{const wxTreeItemId\& }{item},
+\param{wxTreeItemIcon }{which = wxTreeItemIcon\_Normal}}
+
+Gets the specified item image. The value of {\it which} may be:
+\begin{itemize}\itemsep=0pt
+\item{wxTreeItemIcon\_Normal} to get the normal item image
+\item{wxTreeItemIcon\_Selected} to get the selected item image (i.e. the image
+which is shown when the item is currently selected)
+\item{wxTreeItemIcon\_Expanded} to get the expanded image (this only
+makes sense for items which have children - then this image is shown when the
+item is expanded and the normal image is shown when it is collapsed)
+\item{wxTreeItemIcon\_SelectedExpanded} to get the selected expanded image
+(which is shown when an expanded item is currently selected)
+\end{itemize}
\membersection{wxTreeCtrl::GetItemText}\label{wxtreectrlgetitemtext}
\constfunc{int}{GetItemSelectedImage}{\param{const wxTreeItemId\& }{item}}
-Gets the selected item image.
+Gets the selected item image (this function is obsolete, use
+{\tt GetItemImage(item, wxTreeItemIcon\_Selected} instead).
\membersection{wxTreeCtrl::GetSelection}\label{wxtreectrlgetselection}
\membersection{wxTreeCtrl::SetItemImage}\label{wxtreectrlsetitemimage}
-\func{void}{SetItemImage}{\param{const wxTreeItemId\&}{ item}, \param{int }{image}}
+\func{void}{SetItemImage}{\param{const wxTreeItemId\&}{ item},
+\param{int }{image},
+\param{wxTreeItemIcon }{which = wxTreeItemIcon\_Normal}}
-Sets the normal item image. This is an index into the assciated image list.
+Sets the specified item image. See \helpref{GetItemImage}{wxtreectrlgetitemimage}
+for the description of {\it which} parameter.
\membersection{wxTreeCtrl::SetItemSelectedImage}\label{wxtreectrlsetitemselectedimage}
\func{void}{SetItemSelectedImage}{\param{const wxTreeItemId\&}{ item}, \param{int }{selImage}}
-Sets the item selected image. This is an index into the assciated image list.
+Sets the selected item image (this function is obsolete, use
+{\tt SetItemImage(item, wxTreeItemIcon\_Selected} instead).
\membersection{wxTreeCtrl::SetItemText}\label{wxtreectrlsetitemtext}
// retrieve items label
wxString GetItemText(const wxTreeItemId& item) const;
- // get the normal item image
- int GetItemImage(const wxTreeItemId& item) const;
- // get the selected item image
- int GetItemSelectedImage(const wxTreeItemId& item) const;
+ // get one of the images associated with the item (normal by default)
+ int GetItemImage(const wxTreeItemId& item,
+ wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
// get the data associated with the item
wxTreeItemData *GetItemData(const wxTreeItemId& item) const;
// set items label
void SetItemText(const wxTreeItemId& item, const wxString& text);
- // set the normal item image
- void SetItemImage(const wxTreeItemId& item, int image);
- // set the selected item image
- void SetItemSelectedImage(const wxTreeItemId& item, int image);
+ // get one of the images associated with the item (normal by default)
+ void SetItemImage(const wxTreeItemId& item, int image,
+ wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
// associate some data with the item
void SetItemData(const wxTreeItemId& item, wxTreeItemData *data);
// 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
+
// callbacks
void OnPaint( wxPaintEvent &event );
void OnSetFocus( wxFocusEvent &event );
--- /dev/null
+///////////////////////////////////////////////////////////////////////////////
+// Name: generic/wizard.h
+// Purpose: declaration of generic wxWizard class
+// Author: Vadim Zeitlin
+// Modified by:
+// Created: 28.09.99
+// RCS-ID: $Id$
+// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
+// Licence: wxWindows license
+///////////////////////////////////////////////////////////////////////////////
+
+// ----------------------------------------------------------------------------
+// wxWizard
+// ----------------------------------------------------------------------------
+
+class wxWizard : public wxWizardBase
+{
+public:
+ // ctor
+ wxWizard(wxWindow *parent = NULL,
+ int id = -1,
+ const wxString& title = wxEmptyString,
+ const wxBitmap& bitmap = wxNullBitmap,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize);
+
+ // implement base class pure virtuals
+ virtual bool RunWizard(wxWizardPage *firstPage);
+ virtual wxWizardPage *GetCurrentPage() const;
+
+ // implementation only from now on
+ // -------------------------------
+
+ // is the wizard running?
+ bool IsRunning() const { return m_page != NULL; }
+
+ // show the prev/next page, but call TransferDataFromWindow on the current
+ // page first and return FALSE without changing the page if it returns
+ // FALSE
+ bool ShowPage(wxWizardPage *page, bool goingForward = TRUE);
+
+private:
+ // event handlers
+ void OnCancel(wxCommandEvent& event);
+ void OnBackOrNext(wxCommandEvent& event);
+
+ // wizard dimensions
+ int m_x, m_y; // the origin for the pages
+ int m_width, // the size of the page itself
+ m_height; // (total width is m_width + m_x)
+
+ // wizard state
+ wxWizardPage *m_page; // the current page or NULL
+
+ // wizard controls
+ wxButton *m_btnPrev, // the "<Back" button
+ *m_btnNext; // the "Next>" or "Finish" button
+
+ DECLARE_DYNAMIC_CLASS(wxWizard)
+ DECLARE_EVENT_TABLE()
+};
+
virtual ~wxFont();
+ // assignment
+ wxFont& operator=(const wxFont& font);
+
// implement base class pure virtuals
virtual int GetPointSize() const;
virtual int GetFamily() const;
virtual void DoGetSize(int *width, int *height) const;
virtual void DoGetPosition(int *x, int *y) const;
- virtual void DoSetSize(int x, int y,
- int width, int height,
- int sizeFlags = wxSIZE_AUTO);
virtual void DoSetClientSize(int width, int height);
// a plug in for MDI frame classes which need to do something special when
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
+
#ifndef _DYNARRAY_H
#include <wx/dynarray.h>
#endif //_DYNARRAY_H
-// This is a work-around for missing defines in gcc-2.95 headers
-#ifndef TCS_RIGHT
-#define TCS_RIGHT 0x0002
-#endif
-#ifndef TCS_VERTICAL
-#define TCS_VERTICAL 0x0080
-#endif
-#ifndef TCS_BOTTOM
-#define TCS_BOTTOM TCS_RIGHT
-#endif
// ----------------------------------------------------------------------------
// types
// ----------------------------------------------------------------------------
// accessors: set/get the item associated with this node
void SetId(const wxTreeItemId& id) { m_itemId = id; }
-#ifdef __WATCOMC__
- const wxTreeItemId GetId() const { return m_itemId; }
-#else
- const wxTreeItemId& GetId() const { return (wxTreeItemId&) m_itemId; }
-#endif
+ const wxTreeItemId GetId() const { return *this; }
};
// ----------------------------------------------------------------------------
unsigned int GetIndent() const;
void SetIndent(unsigned int indent);
- // spacing is the number of pixels between the start and the Text
- // not implemented under wxMSW
+ // spacing is the number of pixels between the start and the Text
+ // not implemented under wxMSW
unsigned int GetSpacing() const { return 18; } // return wxGTK default
- void SetSpacing(unsigned int ) {}
+ void SetSpacing(unsigned int WXUNUSED(spacing)) { }
// image list: these functions allow to associate an image list with
// the control and retrieve it. Note that the control does _not_ delete
// retrieve items label
wxString GetItemText(const wxTreeItemId& item) const;
- // get the normal item image
- int GetItemImage(const wxTreeItemId& item) const;
- // get the selected item image
- int GetItemSelectedImage(const wxTreeItemId& item) const;
+ // get one of the images associated with the item (normal by default)
+ int GetItemImage(const wxTreeItemId& item,
+ wxTreeItemIcon which = wxTreeItemIcon_Normal) const;
// get the data associated with the item
wxTreeItemData *GetItemData(const wxTreeItemId& item) const;
// set items label
void SetItemText(const wxTreeItemId& item, const wxString& text);
- // set the normal item image
- void SetItemImage(const wxTreeItemId& item, int image);
- // set the selected item image
- void SetItemSelectedImage(const wxTreeItemId& item, int image);
+ // get one of the images associated with the item (normal by default)
+ void SetItemImage(const wxTreeItemId& item, int image,
+ wxTreeItemIcon which = wxTreeItemIcon_Normal);
// associate some data with the item
void SetItemData(const wxTreeItemId& item, wxTreeItemData *data);
void SetImageList(wxImageList *imageList, int)
{ SetImageList(imageList); }
+ // 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
// --------------
virtual bool MSWCommand(WXUINT param, WXWORD id);
// SetImageList helper
void SetAnyImageList(wxImageList *imageList, int which);
- wxTextCtrl* m_textCtrl; // used while editing the item label
+ wxTextCtrl *m_textCtrl; // used while editing the item label
wxImageList *m_imageListNormal, // images for tree elements
*m_imageListState; // special images for app defined states
int image, int selectedImage,
wxTreeItemData *data);
+ int DoGetItemImageFromData(const wxTreeItemId& item,
+ wxTreeItemIcon which) const;
+ void DoSetItemImageFromData(const wxTreeItemId& item,
+ int image,
+ wxTreeItemIcon which) const;
void DoSetItemImages(const wxTreeItemId& item, int image, int imageSel);
void DeleteTextCtrl();
+ // support for additional item images
+ friend class wxTreeItemIndirectData;
+ void SetIndirectItemData(const wxTreeItemId& item,
+ wxTreeItemIndirectData *data);
+ bool HasIndirectData(const wxTreeItemId& item) const;
+
+ wxArrayTreeItemIds m_itemsWithIndirectData;
+
DECLARE_DYNAMIC_CLASS(wxTreeCtrl)
};
// constants
// ----------------------------------------------------------------------------
+// enum for different images associated with a treectrl item
+enum wxTreeItemIcon
+{
+ wxTreeItemIcon_Normal, // not selected, not expanded
+ wxTreeItemIcon_Selected, // selected, not expanded
+ wxTreeItemIcon_Expanded, // not selected, expanded
+ wxTreeItemIcon_SelectedExpanded, // selected, expanded
+ wxTreeItemIcon_Max
+};
+
+// tree ctrl default name
#ifdef __WXMSW__
-WXDLLEXPORT_DATA(extern const char*) wxTreeCtrlNameStr;
+ WXDLLEXPORT_DATA(extern const char*) wxTreeCtrlNameStr;
#else
-#define wxTreeCtrlNameStr "wxTreeCtrl"
+ #define wxTreeCtrlNameStr "wxTreeCtrl"
#endif
// ----------------------------------------------------------------------------
#define _WX_WIZARD_H_
// ----------------------------------------------------------------------------
-// headers
+// headers and other simple declarations
// ----------------------------------------------------------------------------
#ifndef WX_PRECOMP
#include "wx/event.h" // wxEVT_XXX constants
#endif // WX_PRECOMP
+// forward declarations
+class WXDLLEXPORT wxWizard;
+
+// ----------------------------------------------------------------------------
+// wxWizardPage is one of the wizards screen: it must know what are the
+// following and preceding pages (which may be NULL for the first/last page).
+//
+// Other than GetNext/Prev() functions, wxWizardPage is just a panel and may be
+// used as such (i.e. controls may be placed directly on it &c).
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxWizardPage : public wxPanel
+{
+public:
+ // ctor: no other parameters are needed because the wizard will resize and
+ // reposition the page anyhow
+ wxWizardPage(wxWizard *parent);
+
+ // these functions are used by the wizard to show another page when the
+ // user chooses "Back" or "Next" button
+ virtual wxWizardPage *GetPrev() const = 0;
+ virtual wxWizardPage *GetNext() const = 0;
+
+private:
+ DECLARE_ABSTRACT_CLASS(wxWizardPage)
+};
+
+// ----------------------------------------------------------------------------
+// wxWizardPageSimple just returns the pointers given to the ctor and is useful
+// to create a simple wizard where the order of pages never changes.
+//
+// OTOH, it is also possible to dynamicly decide which page to return (i.e.
+// depending on the user's choices) as the wizard sample shows - in order to do
+// this, you must derive from wxWizardPage directly.
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxWizardPageSimple : public wxWizardPage
+{
+public:
+ // ctor takes the previous and next pages
+ wxWizardPageSimple(wxWizard *parent = NULL, // let it be default ctor too
+ wxWizardPage *prev = (wxWizardPage *)NULL,
+ wxWizardPage *next = (wxWizardPage *)NULL)
+ : wxWizardPage(parent)
+ {
+ m_prev = prev;
+ m_next = next;
+ }
+
+ // the pointers may be also set later - but before starting the wizard
+ void SetPrev(wxWizardPage *prev) { m_prev = prev; }
+ void SetNext(wxWizardPage *next) { m_next = next; }
+
+ // a convenience function to make the pages follow each other
+ static void Chain(wxWizardPageSimple *first, wxWizardPageSimple *second)
+ {
+ wxCHECK_RET( first && second,
+ _T("NULL passed to wxWizardPageSimple::Chain") );
+
+ first->SetNext(second);
+ second->SetPrev(first);
+ }
+
+ // base class pure virtuals
+ virtual wxWizardPage *GetPrev() const;
+ virtual wxWizardPage *GetNext() const;
+
+private:
+ // pointers are private, the derived classes shouldn't mess with them -
+ // just derive from wxWizardPage directly to implement different behaviour
+ wxWizardPage *m_prev,
+ *m_next;
+
+ DECLARE_DYNAMIC_CLASS(wxWizardPageSimple)
+};
+
// ----------------------------------------------------------------------------
// wxWizard
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxWizard : public wxDialog
+class WXDLLEXPORT wxWizardBase : public wxDialog
{
public:
// create the wizard control
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize);
- // wizard construction: add/insert new page into it
- // adds a page at the end
- virtual void AddPage(wxPanel *page) = 0;
- // adds a page before the page nPage (the new page will have this index)
- virtual void InsertPage(int nPage, wxPanel *page) = 0;
-
- // executes the wizard, returns TRUE if it was successfully finished, FALSE
- // if user cancelled it
- virtual bool RunWizard() = 0;
+ // executes the wizard starting from the given page, returns TRUE if it was
+ // successfully finished, FALSE if user cancelled it
+ virtual bool RunWizard(wxWizardPage *firstPage) = 0;
// get the current page (NULL if RunWizard() isn't running)
- virtual wxPanel *GetCurrentPage() const = 0;
-
-private:
- DECLARE_DYNAMIC_CLASS(wxWizard)
+ virtual wxWizardPage *GetCurrentPage() const = 0;
};
+// include the real class declaration
+#include "wx/generic/wizard.h"
+
// ----------------------------------------------------------------------------
-// wxWizardEvent class represents an event generated by the wizard
+// wxWizardEvent class represents an event generated by the wizard: this event
+// is first sent to the page itself and, if not processed there, goes up the
+// window hierarchy as usual
// ----------------------------------------------------------------------------
class WXDLLEXPORT wxWizardEvent : public wxNotifyEvent
{
public:
- wxWizardEvent(wxEventType type = wxEVT_NULL, int id = 0);
-
- // get the previously active page or -1 if none
- int GetOldPage() const { return m_pageOld; }
+ wxWizardEvent(wxEventType type = wxEVT_NULL,
+ int id = -1,
+ bool direction = TRUE);
- // get the current page or -1 if none
- int GetPage() const { return m_page; }
+ // for EVT_WIZARD_PAGE_CHANGING, return TRUE if we're going forward or
+ // FALSE otherwise and for EVT_WIZARD_PAGE_CHANGED return TRUE if we came
+ // from the previous page and FALSE if we returned from the next one
+ // (this function doesn't make sense for CANCEL events)
+ bool GetDirection() const { return m_direction; }
private:
- int m_pageOld, m_page;
+ bool m_direction;
DECLARE_DYNAMIC_CLASS(wxWizardEvent)
};
typedef void (wxEvtHandler::*wxWizardEventFunction)(wxWizardEvent&);
-// notifies that the page has just been changed
+// notifies that the page has just been changed (can't be vetoed)
#define EVT_WIZARD_PAGE_CHANGED(id, fn) { wxEVT_WIZARD_PAGE_CHANGED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxWizardEventFunction) & fn, (wxObject *)NULL },
// the user pressed "<Back" or "Next>" button and the page is going to be
text->WriteText("OnSetInfo\n");
}
-void MyListCtrl::OnSelected(wxListEvent& WXUNUSED(event))
+void MyListCtrl::OnSelected(wxListEvent& event)
{
if ( !wxGetApp().GetTopWindow() )
return;
if ( !text )
return;
+ wxListItem info;
+ info.m_itemId = event.m_itemIndex;
+ info.m_col = 1;
+ info.m_mask = wxLIST_MASK_TEXT;
+ if ( GetItem(info) )
+ {
+ *text << "Value of the 2nd field of the selected item: "
+ << info.m_text << '\n';
+ }
+ else
+ {
+ wxFAIL_MSG("wxListCtrl::GetItem() failed");
+ }
+
text->WriteText("OnSelected\n");
}
subframe->Show(TRUE);
}
-void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event) )
+void MyFrame::OnSize(wxSizeEvent& WXUNUSED(event))
{
int w, h;
GetClientSize(&w, &h);
--- /dev/null
+/* XPM */
+static char *icon2_xpm[] = {
+/* width height num_colors chars_per_pixel */
+" 32 32 6 1",
+/* colors */
+". c #b2c0dc",
+"# c #000000",
+"a c #c0c0c0",
+"b c #808080",
+"c c #ffff00",
+"d c #ffffff",
+/* pixels */
+"................................",
+"................................",
+"......bbbbbbbbbb................",
+"......bbbbbbbbbb................",
+"....bbccaaccaaccbb..............",
+"....bbccaaccaaccbb..............",
+"..bbccaaccaaccaaccbbbbbbbbbbbb..",
+"..bbccaaccaaccaaccbbbbbbbbbbbb..",
+"..bbddddddddddddddddddddddddbb##",
+"..bbddddddddddddddddddddddddbb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddaaccaaccaaccaaccaaccaabb##",
+"..bbddaaccaaccaaccaaccaaccaabb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddaaccaaccaaccaaccaaccaabb##",
+"..bbddaaccaaccaaccaaccaaccaabb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddaaccaaccaaccaaccaaccaabb##",
+"..bbddaaccaaccaaccaaccaaccaabb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbddccaaccaaccaaccaaccaaccbb##",
+"..bbbbbbbbbbbbbbbbbbbbbbbbbbbb##",
+"..bbbbbbbbbbbbbbbbbbbbbbbbbbbb##",
+"....############################",
+"....############################",
+"................................",
+"................................",
+"................................",
+"................................"
+};
#include "math.h"
-//#ifdef __WXMSW__
+#ifdef __WXMSW__
#define NO_MULTIPLE_SELECTION
#define NO_VARIABLE_HEIGHT
-//#endif
+#endif
#include "treetest.h"
// under Windows the icons are in the .rc file
#ifndef __WXMSW__
-#ifdef NO_VARIABLE_HEIGHT
#include "icon1.xpm"
-#endif
#include "icon2.xpm"
+ #include "icon3.xpm"
+ #include "icon4.xpm"
#include "mondrian.xpm"
#endif
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)
+#if 0 // there are so many of those that logging them causes flicker
EVT_TREE_GET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnGetInfo)
+#endif
EVT_TREE_SET_INFO(TreeTest_Ctrl, MyTreeCtrl::OnSetInfo)
EVT_TREE_ITEM_EXPANDED(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanded)
EVT_TREE_ITEM_EXPANDING(TreeTest_Ctrl, MyTreeCtrl::OnItemExpanding)
wxTR_HAS_BUTTONS |
wxTR_EDIT_LABELS |
#ifndef NO_MULTIPLE_SELECTION
- wxTR_MULTIPLE |
+ wxTR_MULTIPLE |
#endif
#ifndef NO_VARIABLE_HEIGHT
- wxTR_HAS_VARIABLE_ROW_HEIGHT |
+ wxTR_HAS_VARIABLE_ROW_HEIGHT |
#endif
- wxSUNKEN_BORDER);
+ wxSUNKEN_BORDER);
wxTextCtrl *textCtrl = new wxTextCtrl(this, -1, "",
wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxSUNKEN_BORDER);
m_imageListNormal->Add(wxBitmap("bitmap1", wxBITMAP_TYPE_BMP_RESOURCE));
# endif
m_imageListNormal->Add(wxBitmap("bitmap2", wxBITMAP_TYPE_BMP_RESOURCE));
+ m_imageListNormal->Add(wxBitmap("bitmap3", wxBITMAP_TYPE_BMP_RESOURCE));
+ m_imageListNormal->Add(wxBitmap("bitmap4", wxBITMAP_TYPE_BMP_RESOURCE));
+ m_imageListNormal->Add(wxBitmap("bitmap5", wxBITMAP_TYPE_BMP_RESOURCE));
#else
# ifndef NO_VARIABLE_HEIGHT
m_imageListNormal->Add(image.ConvertToBitmap());
m_imageListNormal->Add(wxICON(icon1));
# endif
m_imageListNormal->Add(wxICON(icon2));
+ m_imageListNormal->Add(wxICON(icon3));
+ m_imageListNormal->Add(wxICON(icon4));
+ m_imageListNormal->Add(wxICON(icon5));
#endif
SetImageList(m_imageListNormal);
{
if ( depth > 0 )
{
+ bool hasChildren = depth > 1;
+
wxString str;
for ( size_t n = 0; n < numChildren; n++ )
{
// at depth 1 elements won't have any more children
- if (depth == 1)
- str.Printf("%s child %d.%d", "File", folder, n + 1);
- else
+ if ( hasChildren )
str.Printf("%s child %d", "Folder", n + 1);
+ else
+ str.Printf("%s child %d.%d", "File", folder, n + 1);
+ // here we pass to AppendItem() normal and selected item images (we
+ // suppose that selected image follows the normal one in the enum)
int image = depth == 1 ? TreeCtrlIcon_File : TreeCtrlIcon_Folder;
- wxTreeItemId id = AppendItem(idParent, str, image, image,
+ wxTreeItemId id = AppendItem(idParent, str, image, image + 1,
new MyTreeItemData(str));
+ // and now we also set the expanded one (only for the folders)
+ if ( hasChildren )
+ {
+ SetItemImage(id, TreeCtrlIcon_FolderOpened,
+ wxTreeItemIcon_Expanded);
+ }
+
// remember the last child for OnEnsureVisible()
- if ( depth == 1 && n == numChildren - 1 )
+ if ( !hasChildren && n == numChildren - 1 )
{
m_lastItem = id;
}
wxTreeItemId rootId = AddRoot("Root",
TreeCtrlIcon_Folder, TreeCtrlIcon_Folder,
new MyTreeItemData("Root item"));
+ SetItemImage(rootId, TreeCtrlIcon_FolderOpened, wxTreeItemIcon_Expanded);
AddItemsRecursively(rootId, numChildren, depth, 0);
}
enum
{
TreeCtrlIcon_File,
- TreeCtrlIcon_Folder
+ TreeCtrlIcon_FileSelected,
+ TreeCtrlIcon_Folder,
+ TreeCtrlIcon_FolderSelected,
+ TreeCtrlIcon_FolderOpened
};
MyTreeCtrl() { }
mondrian ICON "mondrian.ico"
aaaa ICON "mondrian.ico"
+
#include "wx/msw/wx.rc"
icon1 ICON "bitmaps\\file1.ico"
-icon2 ICON "bitmaps\\folder1.ico"
+icon2 ICON "bitmaps\\file2.ico"
+icon3 ICON "bitmaps\\folder1.ico"
+icon4 ICON "bitmaps\\folder2.ico"
+icon5 ICON "bitmaps\\folder3.ico"
bitmap1 BITMAP "bitmaps\\file1.bmp"
-bitmap2 BITMAP "bitmaps\\folder1.bmp"
+bitmap2 BITMAP "bitmaps\\file2.bmp"
+bitmap3 BITMAP "bitmaps\\folder1.bmp"
+bitmap4 BITMAP "bitmaps\\folder2.bmp"
+bitmap5 BITMAP "bitmaps\\folder3.bmp"
// overriding TransferDataFromWindow() - of course, in a real program, the
// check wouldn't be so trivial and the data will be probably saved somewhere
// too
-class wxCheckboxPage : public wxPanel
+class wxValidationPage : public wxWizardPageSimple
{
public:
- wxCheckboxPage(wxWizard *parent) : wxPanel(parent)
+ wxValidationPage(wxWizard *parent) : wxWizardPageSimple(parent)
{
- m_checkbox = new wxCheckBox(this, -1, "Check me", wxPoint(20, 20));
+ m_checkbox = new wxCheckBox(this, -1, "&Check me");
}
virtual bool TransferDataFromWindow()
{
- if ( m_checkbox->GetValue() )
+ if ( !m_checkbox->GetValue() )
{
- wxMessageBox("Clear the checkbox first", "No way",
+ wxMessageBox("Check the checkbox first!", "No way",
wxICON_WARNING | wxOK, this);
return FALSE;
wxCheckBox *m_checkbox;
};
+// This is a more complicated example of validity checking: using events we may
+// allow to return to the previous page, but not to proceed. It also
+// demonstrates how to intercept [Cancel] button press.
+class wxRadioboxPage : public wxWizardPageSimple
+{
+public:
+ // directions in which we allow the user to proceed from this page
+ enum
+ {
+ Forward, Backward, Both, Neither
+ };
+
+ wxRadioboxPage(wxWizard *parent) : wxWizardPageSimple(parent)
+ {
+ // should correspond to the enum above
+ static wxString choices[] = { "forward", "backward", "both", "neither" };
+
+ m_radio = new wxRadioBox(this, -1, "Allow to proceed:",
+ wxPoint(5, 5), wxDefaultSize,
+ WXSIZEOF(choices), choices,
+ 1, wxRA_SPECIFY_COLS);
+ m_radio->SetSelection(Both);
+ }
+
+ // wizard event handlers
+ void OnWizardCancel(wxWizardEvent& event)
+ {
+ if ( wxMessageBox("Do you really want to cancel?", "Question",
+ wxICON_QUESTION | wxYES_NO, this) != wxYES )
+ {
+ // not confirmed
+ event.Veto();
+ }
+ }
+
+ void OnWizardPageChanging(wxWizardEvent& event)
+ {
+ int sel = m_radio->GetSelection();
+
+ if ( sel == Both )
+ return;
+
+ if ( event.GetDirection() && sel == Forward )
+ return;
+
+ if ( !event.GetDirection() && sel == Backward )
+ return;
+
+ wxMessageBox("You can't go there", "Not allowed",
+ wxICON_WARNING | wxOK, this);
+
+ event.Veto();
+ }
+
+private:
+ wxRadioBox *m_radio;
+
+ DECLARE_EVENT_TABLE()
+};
+
+// this shows how to dynamically (i.e. during run-time) arrange the page order
+class wxCheckboxPage : public wxWizardPage
+{
+public:
+ wxCheckboxPage(wxWizard *parent,
+ wxWizardPage *prev,
+ wxWizardPage *next)
+ : wxWizardPage(parent)
+ {
+ m_prev = prev;
+ m_next = next;
+
+ (void)new wxStaticText(this, -1, "Try checking the box below and\n"
+ "then going back and clearing it");
+
+ m_checkbox = new wxCheckBox(this, -1, "&Skip the next page",
+ wxPoint(5, 30));
+ }
+
+ // implement wxWizardPage functions
+ virtual wxWizardPage *GetPrev() const { return m_prev; }
+ virtual wxWizardPage *GetNext() const
+ {
+ return m_checkbox->GetValue() ? m_next->GetNext() : m_next;
+ }
+
+private:
+ wxWizardPage *m_prev,
+ *m_next;
+
+ wxCheckBox *m_checkbox;
+};
+
// ============================================================================
// implementation
// ============================================================================
+BEGIN_EVENT_TABLE(wxRadioboxPage, wxWizardPageSimple)
+ EVT_WIZARD_PAGE_CHANGING(-1, wxRadioboxPage::OnWizardPageChanging)
+ EVT_WIZARD_CANCEL(-1, wxRadioboxPage::OnWizardCancel)
+END_EVENT_TABLE()
+
// ----------------------------------------------------------------------------
// the application class
// ----------------------------------------------------------------------------
"Absolutely Useless Wizard",
bmpWizard);
- wxPanel *panel = new wxPanel(wizard);
- (void)new wxStaticText(panel, -1,
+ // a wizard page may be either an object of predefined class
+ wxWizardPageSimple *page1 = new wxWizardPageSimple(wizard);
+ (void)new wxStaticText(page1, -1,
"This wizard doesn't help you to do anything at "
"all.\n"
"\n"
"The next pages will present you with more useless "
"controls.");
- wizard->AddPage(panel);
- wizard->AddPage(new wxCheckboxPage(wizard));
+ // ... or a derived class
+ wxRadioboxPage *page3 = new wxRadioboxPage(wizard);
+ wxValidationPage *page4 = new wxValidationPage(wizard);
+
+ // set the page order using a convenience function - could also use
+ // SetNext/Prev directly as below
+ wxWizardPageSimple::Chain(page3, page4);
+
+ // this page is not a wxWizardPageSimple, so we use SetNext/Prev to insert
+ // it into the chain of pages
+ wxCheckboxPage *page2 = new wxCheckboxPage(wizard, page1, page3);
+ page1->SetNext(page2);
+ page3->SetPrev(page2);
- if ( wizard->RunWizard() )
+ if ( wizard->RunWizard(page1) )
{
wxMessageBox("The wizard successfully completed", "That's all",
wxICON_INFORMATION | wxOK);
#include "wx/choicdlg.h"
#include "wx/docview.h"
#include "wx/confbase.h"
+#include "wx/file.h"
#include <stdio.h>
#include <string.h>
wxString wxURL::ConvertFromURI(const wxString& uri)
{
- int code;
- int i;
wxString new_uri;
- new_uri.Empty();
-
- i = 0;
+ size_t i = 0;
while (i<uri.Len()) {
+ int code;
if (uri[i] == _T('%')) {
i++;
if (uri[i] >= _T('A') && uri[i] <= _T('F'))
#endif
#endif // if 0
- // TODO: check if this is right. MB
- //
- (*this) = s;
+ (*this) = (bool)(s != 0);
return ;
}
WX_DEFINE_ARRAY(wxPanel *, wxArrayPages);
-// ----------------------------------------------------------------------------
-// wxWizardGeneric - generic implementation of wxWizard
-// ----------------------------------------------------------------------------
-
-class wxWizardGeneric : public wxWizard
-{
-public:
- // ctor
- wxWizardGeneric(wxWindow *parent,
- int id,
- const wxString& title,
- const wxBitmap& bitmap,
- const wxPoint& pos,
- const wxSize& size);
-
- // implement base class pure virtuals
- virtual void AddPage(wxPanel *page);
- virtual void InsertPage(int nPage, wxPanel *page);
- virtual bool RunWizard();
- virtual wxPanel *GetCurrentPage() const;
-
- // implementation only from now on
- // -------------------------------
-
- // is the wizard running?
- bool IsRunning() const { return m_page != -1; }
-
- // show the given page calling TransferDataFromWindow - if it returns
- // FALSE, the old page is not hidden and the function returns FALSE
- bool ShowPage(size_t page);
-
- // get the current page assuming the wizard is running
- wxPanel *DoGetCurrentPage() const
- {
- wxASSERT_MSG( IsRunning(), _T("no current page!") );
-
- return m_pages[(size_t)m_page];
- }
-
- // place the given page correctly and hide it
- void DoAddPage(wxPanel *page);
-
-private:
- // event handlers
- void OnCancel(wxCommandEvent& event);
- void OnBackOrNext(wxCommandEvent& event);
-
- // wizard dimensions
- int m_x, m_y; // the origin for the pages
- int m_width, // the size of the page itself
- m_height; // (total width is m_width + m_x)
-
- // wizard state
- int m_page; // the current page or -1
- wxArrayPages m_pages; // the array with all wizards pages
-
- // wizard controls
- wxButton *m_btnPrev, // the "<Back" button
- *m_btnNext; // the "Next>" or "Finish" button
-
- DECLARE_EVENT_TABLE()
-};
-
// ----------------------------------------------------------------------------
// event tables and such
// ----------------------------------------------------------------------------
-BEGIN_EVENT_TABLE(wxWizardGeneric, wxDialog)
- EVT_BUTTON(wxID_CANCEL, wxWizardGeneric::OnCancel)
- EVT_BUTTON(-1, wxWizardGeneric::OnBackOrNext)
+BEGIN_EVENT_TABLE(wxWizard, wxDialog)
+ EVT_BUTTON(wxID_CANCEL, wxWizard::OnCancel)
+ EVT_BUTTON(-1, wxWizard::OnBackOrNext)
END_EVENT_TABLE()
-IMPLEMENT_ABSTRACT_CLASS(wxWizard, wxDialog)
+IMPLEMENT_DYNAMIC_CLASS(wxWizard, wxDialog)
+IMPLEMENT_ABSTRACT_CLASS(wxWizardPage, wxPanel)
+IMPLEMENT_DYNAMIC_CLASS(wxWizardPageSimple, wxWizardPage)
IMPLEMENT_DYNAMIC_CLASS(wxWizardEvent, wxNotifyEvent)
// ============================================================================
// implementation
// ============================================================================
+// ----------------------------------------------------------------------------
+// wxWizardPage
+// ----------------------------------------------------------------------------
+
+wxWizardPage::wxWizardPage(wxWizard *parent) : wxPanel(parent)
+{
+ // initially the page is hidden, it's shown only when it becomes current
+ Hide();
+}
+
+// ----------------------------------------------------------------------------
+// wxWizardPageSimple
+// ----------------------------------------------------------------------------
+
+wxWizardPage *wxWizardPageSimple::GetPrev() const
+{
+ return m_prev;
+}
+
+wxWizardPage *wxWizardPageSimple::GetNext() const
+{
+ return m_next;
+}
// ----------------------------------------------------------------------------
// generic wxWizard implementation
// ----------------------------------------------------------------------------
-wxWizardGeneric::wxWizardGeneric(wxWindow *parent,
- int id,
- const wxString& title,
- const wxBitmap& bitmap,
- const wxPoint& pos,
- const wxSize& size)
+wxWizard::wxWizard(wxWindow *parent,
+ int id,
+ const wxString& title,
+ const wxBitmap& bitmap,
+ const wxPoint& pos,
+ const wxSize& size)
{
// constants defining the dialog layout
// ------------------------------------
// init members
// ------------
- m_page = -1;
+ m_page = (wxWizardPage *)NULL;
// create controls
// ---------------
int x = X_MARGIN;
int y = m_y + m_height + BITMAP_Y_MARGIN;
-
-#if wxUSE_STATLINE
+
+#if wxUSE_STATLINE
(void)new wxStaticLine(this, -1, wxPoint(x, y),
wxSize(m_x + m_width - x, 2));
#endif
-
+
x = m_x + m_width - 3*sizeBtn.x - BUTTON_MARGIN;
y += SEPARATOR_LINE_MARGIN;
m_btnPrev = new wxButton(this, -1, _("< &Back"), wxPoint(x, y), sizeBtn);
}
}
-bool wxWizardGeneric::ShowPage(size_t page)
+bool wxWizard::ShowPage(wxWizardPage *page, bool goingForward)
{
- wxCHECK_MSG( page < m_pages.GetCount(), FALSE,
- _T("invalid wizard page index") );
+ wxASSERT_MSG( page != m_page, _T("this is useless") );
- wxASSERT_MSG( page != (size_t)m_page, _T("this is useless") );
+ // we'll use this to decide whether we have to change the label of this
+ // button or not (initially the label is "Next")
+ bool btnLabelWasNext = TRUE;
- size_t last = m_pages.GetCount() - 1;
- bool mustChangeNextBtnLabel = (size_t)m_page == last || page == last;
-
- if ( m_page != -1 )
+ if ( m_page )
{
- wxPanel *panel = DoGetCurrentPage();
- if ( !panel->TransferDataFromWindow() )
+ // ask the current page first
+ if ( !m_page->TransferDataFromWindow() )
+ {
+ // the page data is incorrect
+ return FALSE;
+ }
+
+ // send the event to the old page
+ wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGING, GetId(), goingForward);
+ if ( m_page->GetEventHandler()->ProcessEvent(event) &&
+ !event.IsAllowed() )
+ {
+ // vetoed by the page
return FALSE;
+ }
- panel->Hide();
+ m_page->Hide();
+
+ btnLabelWasNext = m_page->GetNext() != (wxWizardPage *)NULL;
}
+ // set the new one
m_page = page;
- DoGetCurrentPage()->Show();
- // update the buttons state
- m_btnPrev->Enable(m_page != 0);
- if ( mustChangeNextBtnLabel )
+ // is this the end?
+ if ( !m_page )
{
- m_btnNext->SetLabel((size_t)m_page == last ? _("&Finish")
- : _("&Next >"));
- }
+ // terminate successfully
+ EndModal(wxID_OK);
- return TRUE;
-}
+ return TRUE;
+ }
-void wxWizardGeneric::DoAddPage(wxPanel *page)
-{
- page->Hide();
- page->SetSize(m_x, m_y, m_width, m_height);
-}
+ // send the event to the new page now
+ wxWizardEvent event(wxEVT_WIZARD_PAGE_CHANGED, GetId(), goingForward);
+ (void)m_page->GetEventHandler()->ProcessEvent(event);
-void wxWizardGeneric::AddPage(wxPanel *page)
-{
- m_pages.Add(page);
+ // position and show the new page
+ (void)m_page->TransferDataToWindow();
+ m_page->SetSize(m_x, m_y, m_width, m_height);
+ m_page->Show();
- DoAddPage(page);
-}
+ // and update the buttons state
+ m_btnPrev->Enable(m_page->GetPrev() != (wxWizardPage *)NULL);
-void wxWizardGeneric::InsertPage(int nPage, wxPanel *page)
-{
- m_pages.Insert(page, nPage);
- if ( nPage < m_page )
+ if ( btnLabelWasNext != (m_page->GetNext() != (wxWizardPage *)NULL) )
{
- // the indices of all pages after the inserted one are shifted by 1
- m_page++;
+ // need to update
+ m_btnNext->SetLabel(btnLabelWasNext ? _("&Finish") : _("&Next >"));
}
+ // nothing to do: the label was already correct
- DoAddPage(page);
+ return TRUE;
}
-bool wxWizardGeneric::RunWizard()
+bool wxWizard::RunWizard(wxWizardPage *firstPage)
{
- wxCHECK_MSG( m_pages.GetCount() != 0, FALSE, _T("can't run empty wizard") );
+ wxCHECK_MSG( firstPage, FALSE, _T("can't run empty wizard") );
// can't return FALSE here because there is no old page
- (void)ShowPage(0u);
+ (void)ShowPage(firstPage, TRUE /* forward */);
return ShowModal() == wxID_OK;
}
-wxPanel *wxWizardGeneric::GetCurrentPage() const
+wxWizardPage *wxWizard::GetCurrentPage() const
{
- return IsRunning() ? DoGetCurrentPage() : (wxPanel *)NULL;
+ return m_page;
}
-void wxWizardGeneric::OnCancel(wxCommandEvent& WXUNUSED(event))
+void wxWizard::OnCancel(wxCommandEvent& WXUNUSED(event))
{
+ // this function probably can never be called when we don't have an active
+ // page, but a small extra check won't hurt
+ wxWindow *win = m_page ? (wxWindow *)m_page : (wxWindow *)this;
+
wxWizardEvent event(wxEVT_WIZARD_CANCEL, GetId());
- if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
+ if ( !win->GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
{
// no objections - close the dialog
EndModal(wxID_CANCEL);
//else: request to Cancel ignored
}
-void wxWizardGeneric::OnBackOrNext(wxCommandEvent& event)
+void wxWizard::OnBackOrNext(wxCommandEvent& event)
{
wxASSERT_MSG( (event.GetEventObject() == m_btnNext) ||
(event.GetEventObject() == m_btnPrev),
_T("unknown button") );
- int delta = event.GetEventObject() == m_btnNext ? 1 : -1;
- int page = m_page + delta;
+ bool forward = event.GetEventObject() == m_btnNext;
- wxASSERT_MSG( page >= 0, _T("'Back' button should have been disabled!") );
-
- if ( (size_t)page == m_pages.GetCount() )
+ wxWizardPage *page;
+ if ( forward )
{
- // check that we have valid data in the last page too
- if ( m_pages.Last()->TransferDataFromWindow() )
- {
- // that's all, folks!
- EndModal(wxID_OK);
- }
+ page = m_page->GetNext();
}
- else
+ else // back
{
- // just pass to the next page (or may be not - but we don't care here)
- (void)ShowPage(page);
+ page = m_page->GetPrev();
+
+ wxASSERT_MSG( page, _T("\"<Back\" button should have been disabled") );
}
+
+ // just pass to the new page (or may be not - but we don't care here)
+ (void)ShowPage(page, forward);
}
// ----------------------------------------------------------------------------
// our public interface
// ----------------------------------------------------------------------------
-/* static */ wxWizard *wxWizard::Create(wxWindow *parent,
- int id,
- const wxString& title,
- const wxBitmap& bitmap,
- const wxPoint& pos,
- const wxSize& size)
+/* static */
+wxWizard *wxWizardBase::Create(wxWindow *parent,
+ int id,
+ const wxString& title,
+ const wxBitmap& bitmap,
+ const wxPoint& pos,
+ const wxSize& size)
{
- return new wxWizardGeneric(parent, id, title, bitmap, pos, size);
+ return new wxWizard(parent, id, title, bitmap, pos, size);
}
// ----------------------------------------------------------------------------
// wxWizardEvent
// ----------------------------------------------------------------------------
-wxWizardEvent::wxWizardEvent(wxEventType type, int id)
+wxWizardEvent::wxWizardEvent(wxEventType type, int id, bool direction)
: wxNotifyEvent(type, id)
{
- m_page = m_pageOld = -1;
+ m_direction = direction;
}
+
public:
wxFontRefData()
{
- Init();
+ Init(12, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE,
+ "", wxFONTENCODING_DEFAULT);
}
wxFontRefData(const wxFontRefData& data)
*y = point.y;
}
-void wxFrame::DoSetSize(int x, int y, int width, int height, int sizeFlags)
-{
- wxWindow::DoSetSize(x, y, width, height, sizeFlags);
-
- wxSizeEvent event(wxSize(width, height), m_windowId);
- event.SetEventObject( this );
- GetEventHandler()->ProcessEvent(event);
-}
-
bool wxFrame::Show(bool show)
{
int cshow;
// hide the ugly cast
#define m_hwnd (HWND)GetHWND()
+// ----------------------------------------------------------------------------
+// constants
+// ----------------------------------------------------------------------------
+
+// This is a work-around for missing defines in gcc-2.95 headers
+#ifndef TCS_RIGHT
+ #define TCS_RIGHT 0x0002
+#endif
+
+#ifndef TCS_VERTICAL
+ #define TCS_VERTICAL 0x0080
+#endif
+
+#ifndef TCS_BOTTOM
+ #define TCS_BOTTOM TCS_RIGHT
+#endif
+
// ----------------------------------------------------------------------------
// event table
// ----------------------------------------------------------------------------
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
// ----------------------------------------------------------------------------
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.
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
{
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)
DoSetItem(&tvItem);
}
-int wxTreeCtrl::GetItemImage(const wxTreeItemId& item) const
+int wxTreeCtrl::GetItemImage(const wxTreeItemId& item,
+ wxTreeItemIcon which) const
{
- wxTreeViewItem tvItem(item, TVIF_IMAGE);
- DoGetItem(&tvItem);
+ if ( HasIndirectData(item) )
+ {
+ return DoGetItemImageFromData(item, which);
+ }
- return tvItem.iImage;
-}
+ UINT mask;
+ switch ( which )
+ {
+ default:
+ wxFAIL_MSG( _T("unknown tree item image type") );
-void wxTreeCtrl::SetItemImage(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, image, GetItemSelectedImage(item));
-}
+ case wxTreeItemIcon_Normal:
+ mask = TVIF_IMAGE;
+ break;
-int wxTreeCtrl::GetItemSelectedImage(const wxTreeItemId& item) const
-{
- wxTreeViewItem tvItem(item, TVIF_SELECTEDIMAGE);
+ case wxTreeItemIcon_Selected:
+ mask = TVIF_SELECTEDIMAGE;
+ break;
+
+ case wxTreeItemIcon_Expanded:
+ case wxTreeItemIcon_SelectedExpanded:
+ return -1;
+ }
+
+ wxTreeViewItem tvItem(item, mask);
DoGetItem(&tvItem);
- return tvItem.iSelectedImage;
+ return mask == TVIF_IMAGE ? tvItem.iImage : tvItem.iSelectedImage;
}
-void wxTreeCtrl::SetItemSelectedImage(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, GetItemImage(item), image);
+ DoSetItemImages(item, imageNormal, imageSel);
}
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)
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);
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;
}
// 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
}
*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