From a65ffcb229be96bbea86808bab3b1239407e8d9a Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Tue, 27 Jun 2006 14:07:45 +0000
Subject: [PATCH] use wxBoxSizer in wxPickerBase instead of doing the layout
 manually + other picker controls fixes (patch 1513042)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39846 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/pickerbase.tex |  48 +++++++++++++--
 include/wx/gtk/fontpicker.h  |   2 -
 include/wx/pickerbase.h      | 105 ++++++++++++++++++++++++--------
 src/common/clrpickercmn.cpp  |   4 ++
 src/common/filepickercmn.cpp |   4 ++
 src/common/fontpickercmn.cpp |   6 +-
 src/common/pickerbase.cpp    | 113 +++++++++--------------------------
 src/gtk/clrpicker.cpp        |   1 +
 src/gtk/filepicker.cpp       |   7 ++-
 src/gtk/fontpicker.cpp       |   1 +
 10 files changed, 166 insertions(+), 125 deletions(-)

diff --git a/docs/latex/wx/pickerbase.tex b/docs/latex/wx/pickerbase.tex
index 123c7bcd50..07f12bb15c 100644
--- a/docs/latex/wx/pickerbase.tex
+++ b/docs/latex/wx/pickerbase.tex
@@ -47,6 +47,7 @@ class.}
 \func{void}{SetInternalMargin}{\param{int}{margin}}
 
 Sets the margin (in pixel) between the picker and the text control.
+This function can be used only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
 
 
 \membersection{wxPickerBase::GetInternalMargin}\label{wxpickerbasegetinternalmargin}
@@ -54,6 +55,7 @@ Sets the margin (in pixel) between the picker and the text control.
 \constfunc{int}{GetInternalMargin}{}
 
 Returns the margin (in pixel) between the picker and the text control.
+This function can be used only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
 
 
 \membersection{wxPickerBase::SetTextCtrlProportion}\label{wxpickerbasesettextctrlproportion}
@@ -62,26 +64,62 @@ Returns the margin (in pixel) between the picker and the text control.
 
 Sets the proportion between the text control and the picker.
 Look at the overview of wxPickerBase for more details about this.
+This function can be used only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
 
 
-\membersection{wxPickerBase::GetTextCtrlProportion}\label{wxpickerbasesgettextctrlproportion}
+\membersection{wxPickerBase::GetTextCtrlProportion}\label{wxpickerbasegettextctrlproportion}
 
 \constfunc{int}{GetTextCtrlProportion}{}
 
 Returns the proportion between the text control and the picker.
+This function can be used only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
 
 
-\membersection{wxPickerBase::HasTextCtrl}\label{wxpickerbaseshastextctrl}
+
+\membersection{wxPickerBase::HasTextCtrl}\label{wxpickerbasehastextctrl}
 
 \constfunc{bool}{HasTextCtrl}{}
 
-Returns true if this class has a valid text control (i.e. if the \windowstyle{wxPB\_USE\_TEXTCTRL} style was
+Returns true if this window has a valid text control (i.e. if the \windowstyle{wxPB\_USE\_TEXTCTRL} style was
 given when creating this control).
 
 
-\membersection{wxPickerBase::GetTextCtrl}\label{wxpickerbasesgetextctrl}
+\membersection{wxPickerBase::GetTextCtrl}\label{wxpickerbasegetextctrl}
 
 \func{wxTextCtrl *}{GetTextCtrl}{}
 
-Returns a pointer to the text control handled by this class or \texttt{NULL} if the \windowstyle{wxPB\_USE\_TEXTCTRL} style was not specified when this control was created.
+Returns a pointer to the text control handled by this window or \texttt{NULL} if the \windowstyle{wxPB\_USE\_TEXTCTRL} style was not specified when this control was created.
 Very important: the contents of the text control could be containing an invalid representation of the entity which can be chosen through the picker (e.g. the user entered an invalid colour syntax because of a typo). Thus you should never parse the content of the textctrl to get the user's input; rather use the derived-class getter (e.g. \helpref{wxColourPickerCtrl::GetColour}{wxcolourpickerctrlgetcolour}, \helpref{wxFilePickerCtrl::GetPath}{wxfilepickerctrlgetpath}, etc).
+
+
+\membersection{wxPickerBase::IsTextCtrlGrowable}\label{wxpickerbaseistextctrlgrowable}
+
+\constfunc{bool}{IsTextCtrlGrowable}{}
+
+Returns \true if the text control is growable.
+This function can be used only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
+
+
+\membersection{wxPickerBase::SetTextCtrlGrowable}\label{wxpickerbasesettextctrlgrowable}
+
+\func{void}{SetTextCtrlGrowable}{\param{bool}{ grow = true}}
+
+Sets the text control as growable when {\tt grow} is \true.
+This function can be used only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
+
+
+
+\membersection{wxPickerBase::IsPickerCtrlGrowable}\label{wxpickerbaseispickerctrlgrowable}
+
+\constfunc{bool}{IsPickerCtrlGrowable}{}
+
+Returns \true if the picker control is growable.
+
+
+\membersection{wxPickerBase::SetPickerCtrlGrowable}\label{wxpickerbasesetpickerctrlgrowable}
+
+\func{void}{SetPickerCtrlGrowable}{\param{bool}{ grow = true}}
+
+Sets the picker control as growable when {\tt grow} is \true.
+This function has effects only when \helpref{wxpickerbasehastextctrl}{HasTextCtrl} returns \true.
+
diff --git a/include/wx/gtk/fontpicker.h b/include/wx/gtk/fontpicker.h
index 06ba2ed99f..200615fcff 100644
--- a/include/wx/gtk/fontpicker.h
+++ b/include/wx/gtk/fontpicker.h
@@ -60,8 +60,6 @@ public:     // used by the GTK callback only
     void SetNativeFontInfo(const gchar *gtkdescription)
         { m_selectedFont.SetNativeFontInfo(wxString::FromAscii(gtkdescription)); }
 
-    wxWindow *m_topParent;
-
 private:
     DECLARE_DYNAMIC_CLASS(wxFontButton)
 };
diff --git a/include/wx/pickerbase.h b/include/wx/pickerbase.h
index 64714f4399..705924b362 100644
--- a/include/wx/pickerbase.h
+++ b/include/wx/pickerbase.h
@@ -33,9 +33,9 @@ class WXDLLIMPEXP_CORE wxPickerBase : public wxControl
 {
 public:
     // ctor: text is the associated text control
-    wxPickerBase() : m_text(NULL), m_picker(NULL),
-                     m_margin(5), m_textProportion(2) {}
-    virtual ~wxPickerBase();
+    wxPickerBase() : m_text(NULL), m_picker(NULL), m_sizer(NULL)
+        { m_container.SetContainerWindow(this); }
+    virtual ~wxPickerBase() {}
 
 
     // if present, intercepts wxPB_USE_TEXTCTRL style and creates the text control
@@ -51,13 +51,39 @@ public:
 public:     // public API
 
     // margin between the text control and the picker
-    void SetInternalMargin(int newmargin);
-    int GetInternalMargin() const { return m_margin; }
+    void SetInternalMargin(int newmargin)
+        { GetTextCtrlItem()->SetBorder(newmargin); m_sizer->Layout(); }
+    int GetInternalMargin() const
+        { return GetTextCtrlItem()->GetBorder(); }
 
     // proportion of the text control respect the picker
     // (which has a fixed proportion value of 1)
-    void SetTextCtrlProportion(int prop) { wxASSERT(prop>=1); m_textProportion=prop; }
-    int GetTextCtrlProportion() const { return m_textProportion; }
+    void SetTextCtrlProportion(int prop)
+        { GetTextCtrlItem()->SetProportion(prop); m_sizer->Layout(); }
+    int GetTextCtrlProportion() const
+        { return GetTextCtrlItem()->GetProportion(); }
+
+    bool IsTextCtrlGrowable() const
+        { return GetTextCtrlItem()->GetFlag() & wxGROW; }
+    void SetTextCtrlGrowable(bool grow = true)
+    {
+        int f = GetDefaultTextCtrlFlag();
+        if (grow)
+            GetTextCtrlItem()->SetFlag(f | wxGROW);
+        else
+            GetTextCtrlItem()->SetFlag(f & ~wxGROW);
+    }
+
+    bool IsPickerCtrlGrowable() const
+        { return GetPickerCtrlItem()->GetFlag() & wxGROW; }
+    void SetPickerCtrlGrowable(bool grow = true)
+    {
+        int f = GetDefaultPickerCtrlFlag();
+        if (grow)
+            GetPickerCtrlItem()->SetFlag(f | wxGROW);
+        else
+            GetPickerCtrlItem()->SetFlag(f & ~wxGROW);
+    }
 
     bool HasTextCtrl() const
         { return m_text != NULL; }
@@ -66,20 +92,6 @@ public:     // public API
     wxControl *GetPickerCtrl()
         { return m_picker; }
 
-public:     // wxWindow overrides
-
-    void DoSetSizeHints(int minW, int minH,
-                        int maxW = wxDefaultCoord, int maxH = wxDefaultCoord,
-                        int incW = wxDefaultCoord, int incH = wxDefaultCoord );
-
-protected:
-    void DoSetSize(int x, int y,
-                   int width, int height,
-                   int sizeFlags = wxSIZE_AUTO);
-
-    wxSize DoGetBestSize() const;
-
-
 public:     // methods that derived class must/may override
 
     virtual void UpdatePickerFromTextCtrl() = 0;
@@ -87,13 +99,13 @@ public:     // methods that derived class must/may override
 
 protected:        // utility functions
 
-    inline int GetTextCtrlWidth(int given);
-
     // event handlers
     void OnTextCtrlDelete(wxWindowDestroyEvent &);
     void OnTextCtrlUpdate(wxCommandEvent &);
     void OnTextCtrlKillFocus(wxFocusEvent &);
 
+    void OnSize(wxSizeEvent &);
+
     // returns the set of styles for the attached wxTextCtrl
     // from given wxPickerBase's styles
     virtual long GetTextCtrlStyle(long style) const
@@ -103,15 +115,56 @@ protected:        // utility functions
     virtual long GetPickerStyle(long style) const
         { return (style & wxWINDOW_STYLE_MASK); }
 
+
+    wxSizerItem *GetPickerCtrlItem() const
+    {
+        if (this->HasTextCtrl())
+            return m_sizer->GetItem((size_t)1);
+        return m_sizer->GetItem((size_t)0);
+    }
+
+    wxSizerItem *GetTextCtrlItem() const
+    {
+        wxASSERT(this->HasTextCtrl());
+        return m_sizer->GetItem((size_t)0);
+    }
+
+    int GetDefaultPickerCtrlFlag() const
+    {
+        // on macintosh, without additional borders
+        // there's not enough space for focus rect
+        return wxALIGN_CENTER_VERTICAL|wxGROW
+#ifdef __WXMAC__
+            | wxTOP | wxRIGHT | wxBOTTOM
+#endif
+            ;
+    }
+
+    int GetDefaultTextCtrlFlag() const
+    {
+        // on macintosh, without wxALL there's not enough space for focus rect
+        return wxALIGN_CENTER_VERTICAL
+#ifdef __WXMAC__
+            | wxALL
+#else
+            | wxRIGHT
+#endif
+            ;
+    }
+
+    void PostCreation();
+
 protected:
     wxTextCtrl *m_text;     // can be NULL
     wxControl *m_picker;
-
-    int m_margin;           // distance between subcontrols
-    int m_textProportion;   // proportion between textctrl and other item
+    wxBoxSizer *m_sizer;
 
 private:
     DECLARE_ABSTRACT_CLASS(wxPickerBase)
+    DECLARE_EVENT_TABLE()
+
+    // This class must be something just like a panel...
+    WX_DECLARE_CONTROL_CONTAINER();
 };
 
 
diff --git a/src/common/clrpickercmn.cpp b/src/common/clrpickercmn.cpp
index 6b7ea1c768..75295088d8 100644
--- a/src/common/clrpickercmn.cpp
+++ b/src/common/clrpickercmn.cpp
@@ -61,6 +61,10 @@ bool wxColourPickerCtrl::Create( wxWindow *parent, wxWindowID id,
     // to its "changed" event dynamically...
     m_picker = new wxColourPickerWidget(this, wxID_ANY, col, wxPoint(40,0), wxSize(30,-1),
                                         GetPickerStyle(style));
+
+    // complete sizer creation
+    wxPickerBase::PostCreation();
+
     m_picker->Connect(wxEVT_COMMAND_COLOURPICKER_CHANGED,
             wxColourPickerEventHandler(wxColourPickerCtrl::OnColourChange),
             NULL, this);
diff --git a/src/common/filepickercmn.cpp b/src/common/filepickercmn.cpp
index 27fb86a331..06931b3b56 100644
--- a/src/common/filepickercmn.cpp
+++ b/src/common/filepickercmn.cpp
@@ -76,6 +76,10 @@ bool wxFileDirPickerCtrlBase::CreateBase( wxWindow *parent, wxWindowID id,
     // create a wxFilePickerWidget or a wxDirPickerWidget...
     if (!CreatePicker(this, path, message, wildcard))
         return false;
+
+    // complete sizer creation
+    wxPickerBase::PostCreation();
+
     m_picker->Connect(GetEventType(),
             wxFileDirPickerEventHandler(wxFileDirPickerCtrlBase::OnFileDirChange),
             NULL, this);
diff --git a/src/common/fontpickercmn.cpp b/src/common/fontpickercmn.cpp
index 159b5403df..92cf9898b6 100644
--- a/src/common/fontpickercmn.cpp
+++ b/src/common/fontpickercmn.cpp
@@ -55,9 +55,6 @@ bool wxFontPickerCtrl::Create( wxWindow *parent, wxWindowID id,
                         long style, const wxValidator& validator,
                         const wxString &name )
 {
-    // by default, the textctrl is, if present, as big as the picker, for wxFontPickerCtrl
-    SetTextCtrlProportion(1);
-
     if (!wxPickerBase::CreateBase(parent, id, Font2String(initial),
                                   pos, size, style, validator, name))
         return false;
@@ -66,6 +63,9 @@ bool wxFontPickerCtrl::Create( wxWindow *parent, wxWindowID id,
     m_picker = new wxFontPickerWidget(this, wxID_ANY, initial,
                                       wxDefaultPosition, wxDefaultSize,
                                       GetPickerStyle(style));
+    // complete sizer creation
+    wxPickerBase::PostCreation();
+
     m_picker->Connect(wxEVT_COMMAND_FONTPICKER_CHANGED,
             wxFontPickerEventHandler(wxFontPickerCtrl::OnFontChange),
             NULL, this);
diff --git a/src/common/pickerbase.cpp b/src/common/pickerbase.cpp
index ce5c4a2d55..62a4429f59 100644
--- a/src/common/pickerbase.cpp
+++ b/src/common/pickerbase.cpp
@@ -41,20 +41,17 @@
 
 IMPLEMENT_ABSTRACT_CLASS(wxPickerBase, wxWindow)
 
+BEGIN_EVENT_TABLE(wxPickerBase, wxControl)
+    EVT_SIZE(wxPickerBase::OnSize)
+    WX_EVENT_TABLE_CONTROL_CONTAINER(wxPickerBase)
+END_EVENT_TABLE()
+WX_DELEGATE_TO_CONTROL_CONTAINER(wxPickerBase)
+
+
 // ----------------------------------------------------------------------------
 // wxPickerBase
 // ----------------------------------------------------------------------------
 
-wxPickerBase::~wxPickerBase()
-{
-    // destroy the windows we are managing: these are not automatically
-    // destroyed by wxWindow because they are not built as our children
-    // but rather as children of the parent of the wxPickerBase class
-    // (since wxPickerBase does not represent a real window)
-    if (m_text) m_text->Destroy();
-    if (m_picker) m_picker->Destroy();
-}
-
 bool wxPickerBase::CreateBase(wxWindow *parent,
                          wxWindowID id,
                          const wxString &text,
@@ -68,16 +65,18 @@ bool wxPickerBase::CreateBase(wxWindow *parent,
     // invisible (user styles must be set on the textctrl or the platform-dependent picker)
     style &= ~wxBORDER_MASK;
     if (!wxControl::Create(parent, id, pos, size, style | wxNO_BORDER | wxTAB_TRAVERSAL,
-                            validator, name))
+                           validator, name))
         return false;
 
+    m_sizer = new wxBoxSizer(wxHORIZONTAL);
+
     if (HasFlag(wxPB_USE_TEXTCTRL))
     {
         // NOTE: the style of this class (wxPickerBase) and the style of the
         //       attached text control are different: GetTextCtrlStyle() extracts
         //       the styles related to the textctrl from the styles passed here
-        m_text = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxPoint(0, 0),
-                                wxSize(40, size.GetHeight()), GetTextCtrlStyle(style));
+        m_text = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
+                                wxDefaultSize, GetTextCtrlStyle(style));
         if (!m_text)
         {
             wxFAIL_MSG( wxT("wxPickerBase's textctrl creation failed") );
@@ -104,11 +103,22 @@ bool wxPickerBase::CreateBase(wxWindow *parent,
         m_text->Connect(wxEVT_DESTROY,
                 wxWindowDestroyEventHandler(wxPickerBase::OnTextCtrlDelete),
                 NULL, this);
+
+        m_sizer->Add(m_text, 2, GetDefaultTextCtrlFlag(), 5);
     }
 
     return true;
 }
 
+void wxPickerBase::PostCreation()
+{
+    // the picker's proportion value is fixed
+    m_sizer->Add(m_picker, 1, GetDefaultPickerCtrlFlag(), 5);
+
+    SetSizer(m_sizer);
+    m_sizer->SetSizeHints(this);
+}
+
 void wxPickerBase::OnTextCtrlKillFocus(wxFocusEvent &)
 {
     wxASSERT(m_text);
@@ -130,80 +140,11 @@ void wxPickerBase::OnTextCtrlUpdate(wxCommandEvent &)
     UpdatePickerFromTextCtrl();
 }
 
-int wxPickerBase::GetTextCtrlWidth(int given)
-{
-    // compute the width of m_text like a wxBoxSizer(wxHORIZONTAL) would do
-    // NOTE: the proportion of m_picker is fixed to 1
-    return ((given - m_margin) / (m_textProportion + 1)) * m_textProportion;
-}
-
-void wxPickerBase::DoSetSizeHints(int minW, int minH, int maxW, int maxH, int incW, int incH)
-{
-    wxControl::DoSetSizeHints(minW, minH, maxW, maxH, incW, incH);
-
-    if (m_text)
-    {
-        // compute minWidth and maxWidth of the ausiliary textctrl
-        int textCtrlMinW = -1, textCtrlMaxW = -1;
-        if (minW != -1)
-        {
-            textCtrlMinW = GetTextCtrlWidth(minW);
-            minW -= textCtrlMinW + m_margin;
-        }
-
-        if (maxW != -1)
-        {
-            textCtrlMaxW = GetTextCtrlWidth(maxW);
-            maxW -= textCtrlMaxW + m_margin;
-        }
-
-        m_text->SetSizeHints(textCtrlMinW, minH, textCtrlMaxW, maxH, incW, incH);
-    }
-
-    if (m_picker)
-        m_picker->SetSizeHints(minW, minH, maxW, maxH, incW, incH);
-}
-
-void wxPickerBase::DoSetSize(int x, int y, int width, int height, int sizeFlags)
-{
-    wxControl::DoSetSize(x, y, width, height, sizeFlags);
-
-    int pickerx = 0;
-    if (m_text)
-    {
-        // compute width of the ausiliary textctrl
-        int textCtrlW = GetTextCtrlWidth(width);
-
-        // set the m_text's position relatively to this window
-        m_text->SetSize(0, 0, textCtrlW, height, sizeFlags);
-
-        // change position of the real picker
-        pickerx += textCtrlW + m_margin;
-        width -= textCtrlW + m_margin;
-    }
-
-    if (m_picker)
-        m_picker->SetSize(pickerx, 0, width, height, sizeFlags);
-}
-
-wxSize wxPickerBase::DoGetBestSize() const
-{
-    wxSize ret = m_picker->GetBestSize();
-
-    if (m_text)
-    {
-        wxSize sz = m_text->GetBestSize();
-
-        ret.SetWidth( ret.GetWidth() + sz.GetWidth() + m_margin );
-        ret.SetHeight( wxMax(ret.GetHeight(), sz.GetHeight()) );
-    }
-
-    return ret;
-}
-
-void wxPickerBase::SetInternalMargin(int newmargin)
+void wxPickerBase::OnSize(wxSizeEvent &event)
 {
-    m_margin = newmargin;
+    if (GetAutoLayout())
+        Layout();
+    event.Skip();
 }
 
 #endif // Any picker in use
diff --git a/src/gtk/clrpicker.cpp b/src/gtk/clrpicker.cpp
index 672a8593cb..b88a8a37aa 100644
--- a/src/gtk/clrpicker.cpp
+++ b/src/gtk/clrpicker.cpp
@@ -62,6 +62,7 @@ bool wxColourButton::Create( wxWindow *parent, wxWindowID id,
     if (!gtk_check_version(2,4,0))
     {
         m_needParent = true;
+        m_acceptsFocus = true;
 
         if (!PreCreation( parent, pos, size ) ||
             !wxControl::CreateBase(parent, id, pos, size, style, validator, name))
diff --git a/src/gtk/filepicker.cpp b/src/gtk/filepicker.cpp
index f5f6a0a97b..6779e75111 100644
--- a/src/gtk/filepicker.cpp
+++ b/src/gtk/filepicker.cpp
@@ -45,10 +45,11 @@ bool wxFileButton::Create( wxWindow *parent, wxWindowID id,
 {
     if (!gtk_check_version(2,6,0))
     {
-        // VERY IMPORTANT: this code is identic to relative code in wxFileButton;
-        //                 if you find a problem here, fix it also in wxFileButton !
+        // VERY IMPORTANT: this code is identic to relative code in wxDirButton;
+        //                 if you find a problem here, fix it also in wxDirButton !
 
         m_needParent = true;
+        m_acceptsFocus = true;
 
         if (!PreCreation( parent, pos, size ) ||
             !wxControl::CreateBase(parent, id, pos, size, style & wxWINDOW_STYLE_MASK,
@@ -127,7 +128,6 @@ void wxFileButton::OnDialogOK(wxCommandEvent& ev)
     }
 }
 
-
 void wxFileButton::SetPath(const wxString &str)
 {
     m_path = str;
@@ -200,6 +200,7 @@ bool wxDirButton::Create( wxWindow *parent, wxWindowID id,
         //                 if you find a problem here, fix it also in wxFileButton !
 
         m_needParent = true;
+        m_acceptsFocus = true;
 
         if (!PreCreation( parent, pos, size ) ||
             !wxControl::CreateBase(parent, id, pos, size, style & wxWINDOW_STYLE_MASK,
diff --git a/src/gtk/fontpicker.cpp b/src/gtk/fontpicker.cpp
index 27d8bb19bf..88e2b93c7c 100644
--- a/src/gtk/fontpicker.cpp
+++ b/src/gtk/fontpicker.cpp
@@ -61,6 +61,7 @@ bool wxFontButton::Create( wxWindow *parent, wxWindowID id,
     if (!gtk_check_version(2,4,0))
     {
         m_needParent = true;
+        m_acceptsFocus = true;
 
         if (!PreCreation( parent, pos, size ) ||
             !wxControl::CreateBase(parent, id, pos, size, style, validator, name))
-- 
2.45.2

