From 86909f4c893e043dd3695d7510f2cc758e8b2cfb Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sun, 16 Sep 2007 10:50:01 +0000
Subject: [PATCH] added XRCSIZERITEM() allowing to directly retrieve the sizer
 from XRC by name (patch 1782080)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48718 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/changes.txt            |  1 +
 docs/latex/wx/sizer.tex     | 12 ++++++++++++
 docs/latex/wx/sizeritem.tex | 13 +++++++++++++
 docs/latex/wx/txrc.tex      | 15 +++++++++++++++
 include/wx/sizer.h          |  7 +++++++
 include/wx/xrc/xmlres.h     | 12 ++++++++++++
 src/common/sizer.cpp        | 31 +++++++++++++++++++++++++++++++
 src/xrc/xh_sizer.cpp        |  3 +++
 8 files changed, 94 insertions(+)

diff --git a/docs/changes.txt b/docs/changes.txt
index 8c60431cb6..eda95227fb 100644
--- a/docs/changes.txt
+++ b/docs/changes.txt
@@ -166,6 +166,7 @@ All (GUI):
 - Added support for drop down toolbar buttons (Tim Kosse).
 - Added support for labels for toolbar controls (Vince Harron).
 - Added wxMessageDialog::SetMessage() and SetExtendedMessage().
+- Added XRCSIZERITEM() macro for obtaining sizers from XRC (Brian Vanderburg II)
 - Added wxEventBlocker class (Francesco Montorsi)..
 - Added wxFile/DirPickerCtrl::Get/SetFile/DirName() (Francesco Montorsi)..
 - Added wxSizerFlags::Top() and Bottom().
diff --git a/docs/latex/wx/sizer.tex b/docs/latex/wx/sizer.tex
index 3688d09adc..ccf896b2aa 100644
--- a/docs/latex/wx/sizer.tex
+++ b/docs/latex/wx/sizer.tex
@@ -274,6 +274,18 @@ Use parameter \arg{recursive} to search in subsizers too.
 
 Returns pointer to item or NULL.
 
+\membersection{wxSizer::GetItemById}\label{wxsizergetitembyid}
+
+\func{wxSizerItem *}{GetItemById}{\param{int }{id}, \param{bool }{recursive = false}}
+
+Finds item of the sizer which has the given \arg{id}.  This \arg{id} is not the
+window id but the id of the wxSizerItem itself.  This is mainly useful for
+retrieving the sizers created from XRC resources. 
+
+Use parameter \arg{recursive} to search in subsizers too.
+
+Returns pointer to item or \NULL.
+
 
 \membersection{wxSizer::GetSize}\label{wxsizergetsize}
 
diff --git a/docs/latex/wx/sizeritem.tex b/docs/latex/wx/sizeritem.tex
index f72d03ba39..6573448b8c 100644
--- a/docs/latex/wx/sizeritem.tex
+++ b/docs/latex/wx/sizeritem.tex
@@ -88,6 +88,13 @@ Return the border attribute.
 
 Return the flags attribute.
 
+\membersection{wxSizerItem::GetId}\label{wxsizeritemgetid}
+
+\constfunc{int}{GetId}{\void}
+
+Return the numeric id of wxSizerItem, or \texttt{wxID\_NONE} if the id has
+not been set.
+
 
 \membersection{wxSizerItem::GetMinSize}\label{wxsizeritemgetminsize}
 
@@ -205,6 +212,12 @@ taking alignment and borders into account.
 
 Set the flag  item attribute.
 
+\membersection{wxSizerItem::SetId}\label{wxsizeritemSetId}
+
+\func{void}{SetId}{\param{int}{id}}
+
+Sets the numeric id of the wxSizerItem to \arg{id}.
+
 
 \membersection{wxSizerItem::SetInitSize}\label{wxsizeritemsetinitsize}
 
diff --git a/docs/latex/wx/txrc.tex b/docs/latex/wx/txrc.tex
index 01558bba48..e77cfd21f5 100644
--- a/docs/latex/wx/txrc.tex
+++ b/docs/latex/wx/txrc.tex
@@ -506,7 +506,22 @@ END_EVENT_TABLE()
 
 \end{verbatim}
 
+It is also possible to access the wxSizerItem of a sizer that is part of
+a resource.  This can be done using {\tt XRCSIZERITEM} as shown.  The
+resource file can have something like this for a sizer item.
 
+\begin{verbatim}
+<object class="spacer" name="area">
+  <size>400, 300</size>
+</object>
+\end{verbatim}
+
+The code can then access the sizer item by using {\tt XRCSIZERITEM} and
+{\tt XRCID} together.
+
+\begin{verbatim}
+wxSizerItem* item = XRCSIZERITEM(*this, XRCID("area"));
+\end{verbatim}
 
 \subsection{Adding new resource handlers}\label{newresourcehandlers}
 
diff --git a/include/wx/sizer.h b/include/wx/sizer.h
index 40f32e6e19..443cd5757d 100644
--- a/include/wx/sizer.h
+++ b/include/wx/sizer.h
@@ -298,6 +298,11 @@ public:
 
     virtual wxRect GetRect() { return m_rect; }
 
+    // set a sizer item id (different from a window id, all sizer items,
+    // including spacers, can have an associated id)
+    void SetId(int id) { m_id = id; }
+    int GetId() const { return m_id; }
+
     bool IsWindow() const { return m_kind == Item_Window; }
     bool IsSizer() const { return m_kind == Item_Sizer; }
     bool IsSpacer() const { return m_kind == Item_Spacer; }
@@ -407,6 +412,7 @@ protected:
     int          m_proportion;
     int          m_border;
     int          m_flag;
+    int          m_id;
 
     // on screen rectangle of this item (not including borders)
     wxRect       m_rect;
@@ -593,6 +599,7 @@ public:
     wxSizerItem* GetItem( wxWindow *window, bool recursive = false );
     wxSizerItem* GetItem( wxSizer *sizer, bool recursive = false );
     wxSizerItem* GetItem( size_t index );
+    wxSizerItem* GetItemById( int id, bool recursive = false );
 
     // Manage whether individual scene items are considered
     // in the layout calculations or not.
diff --git a/include/wx/xrc/xmlres.h b/include/wx/xrc/xmlres.h
index 159e9722f6..7420d84729 100644
--- a/include/wx/xrc/xmlres.h
+++ b/include/wx/xrc/xmlres.h
@@ -320,6 +320,18 @@ private:
 #define XRCCTRL(window, id, type) \
     (wxStaticCast((window).FindWindow(XRCID(id)), type))
 
+// This macro returns pointer to sizer item
+// Example:
+//
+// <object class="spacer" name="area">
+//   <size>400, 300</size>
+// </object>
+//
+// wxSizerItem* item = XRCSIZERITEM(*this, wxT("area"))
+
+#define XRCSIZERITEM(window, id) \
+    ((window).GetSizer() ? (window).GetSizer()->GetItemById(id) : NULL)    
+
 // wxXmlResourceHandler is an abstract base class for resource handlers
 // capable of creating a control from an XML node.
 
diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp
index 1df3fd4885..ed30da1d39 100644
--- a/src/common/sizer.cpp
+++ b/src/common/sizer.cpp
@@ -103,6 +103,7 @@ wxSizerItem::wxSizerItem()
     m_proportion = 0;
     m_border = 0;
     m_flag = 0;
+    m_id = wxID_NONE;
 }
 
 // window item
@@ -132,6 +133,7 @@ wxSizerItem::wxSizerItem(wxWindow *window,
              m_proportion(proportion),
              m_border(border),
              m_flag(flag),
+             m_id(wxID_NONE),
              m_userData(userData)
 {
     DoSetWindow(window);
@@ -154,6 +156,7 @@ wxSizerItem::wxSizerItem(wxSizer *sizer,
              m_proportion(proportion),
              m_border(border),
              m_flag(flag),
+             m_id(wxID_NONE),
              m_ratio(0.0),
              m_userData(userData)
 {
@@ -183,6 +186,7 @@ wxSizerItem::wxSizerItem(int width,
              m_proportion(proportion),
              m_border(border),
              m_flag(flag),
+             m_id(wxID_NONE),
              m_userData(userData)
 {
     DoSetSpacer(wxSize(width, height));
@@ -1085,6 +1089,33 @@ wxSizerItem* wxSizer::GetItem( size_t index )
     return m_children.Item( index )->GetData();
 }
 
+wxSizerItem* wxSizer::GetItemById( int id, bool recursive )
+{
+    // This gets a sizer item by the id of the sizer item
+    // and NOT the id of a window if the item is a window.
+
+    wxSizerItemList::compatibility_iterator node = m_children.GetFirst();
+    while (node)
+    {
+        wxSizerItem     *item = node->GetData();
+
+        if (item->GetId() == id)
+        {
+            return item;
+        }
+        else if (recursive && item->IsSizer())
+        {
+            wxSizerItem *subitem = item->GetSizer()->GetItemById( id, true );
+            if (subitem)
+                return subitem;
+        }
+
+        node = node->GetNext();
+    }
+
+    return NULL;
+}
+
 bool wxSizer::Show( wxWindow *window, bool show, bool recursive )
 {
     wxSizerItem *item = GetItem( window, recursive );
diff --git a/src/xrc/xh_sizer.cpp b/src/xrc/xh_sizer.cpp
index c01742c7e1..9ff053c5b2 100644
--- a/src/xrc/xh_sizer.cpp
+++ b/src/xrc/xh_sizer.cpp
@@ -361,6 +361,9 @@ void wxSizerXmlHandler::SetSizerItemAttributes(wxSizerItem* sitem)
         gbsitem->SetPos(GetGBPos(wxT("cellpos")));
         gbsitem->SetSpan(GetGBSpan(wxT("cellspan")));
     }
+
+    // record the id of the item, if any, for use by XRCSIZERITEM()
+    sitem->SetId(GetID());
 }
 
 void wxSizerXmlHandler::AddSizerItem(wxSizerItem* sitem)
-- 
2.50.0

