]> git.saurik.com Git - wxWidgets.git/commitdiff
Add wxControl::GetSizeFromTextSize() to size the control to its text.
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 9 Nov 2012 21:11:37 +0000 (21:11 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 9 Nov 2012 21:11:37 +0000 (21:11 +0000)
This function can be used to size a, say, wxTextCtrl to be exactly of the size
needed to enter the given amount of text in it.

This patch adds wxGTK implementation for wxTextCtrl, wxChoice and wxCombobox;
changes to the samples and the documentation.

Closes #14812.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72935 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

15 files changed:
docs/changes.txt
include/wx/control.h
include/wx/gtk/choice.h
include/wx/gtk/combobox.h
include/wx/gtk/control.h
include/wx/gtk/textctrl.h
interface/wx/control.h
samples/combo/combo.cpp
samples/controls/controls.cpp
samples/text/text.cpp
src/common/ctrlcmn.cpp
src/gtk/choice.cpp
src/gtk/combobox.cpp
src/gtk/control.cpp
src/gtk/textctrl.cpp

index 9d864b6497f1b7765d40c4eedb0b8486ad91d3f6..c8e1d6d10c2163da59583fe795456ebc659d7086 100644 (file)
@@ -582,6 +582,7 @@ All (GUI):
 - Implement clipping for wxSVGFileDC (Steve Benbow).
 - Added wxDirCtrl::GetPath() (troelsk).
 - Added wxEVT_COMMAND_DIRCTRL_CHANGED event (troelsk).
+- Added wxControl::GetSizeFromTextSize() (Manuel Martin).
 
 wxGTK:
 
index 129a61dfedfc39196bd015d15e54d6c7aa629d35..6bd5ed190b21c605c140e7e0c24258b77ea80342 100644 (file)
@@ -134,6 +134,10 @@ public:
     // wxControl-specific processing after processing the update event
     virtual void DoUpdateWindowUI(wxUpdateUIEvent& event);
 
+    wxSize GetSizeFromTextSize(int xlen, int ylen = -1) const
+        { return DoGetSizeFromTextSize(xlen, ylen); }
+    wxSize GetSizeFromTextSize(const wxSize& tsize) const
+        { return DoGetSizeFromTextSize(tsize.x, tsize.y); }
 
 
     // static utilities for mnemonics char (&) handling
@@ -192,6 +196,8 @@ protected:
     virtual bool DoSetLabelMarkup(const wxString& markup);
 #endif // wxUSE_MARKUP
 
+    // override this to return the total control's size from a string size
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
 
     // initialize the common fields of wxCommandEvent
     void InitCommandEvent(wxCommandEvent& event) const;
index 70e93fd534231e47c14071fa2c7a55ab8b14a95d..b9297200ec91007e5ad32a3e7997da7a5c039bbe 100644 (file)
@@ -95,6 +95,7 @@ protected:
     int m_stringCellIndex;
 
     virtual wxSize DoGetBestSize() const;
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
     virtual int DoInsertItems(const wxArrayStringsAdapter& items,
                               unsigned int pos,
                               void **clientData, wxClientDataType type);
index 87aae8d9b9cad4e9b3219971e50945fd0c8c6b9a..72ac945b9333c7dc19172e91b038f31261649468 100644 (file)
@@ -145,6 +145,8 @@ protected:
     // custom list stores.
     virtual void GTKCreateComboBoxWidget();
 
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
+
     virtual GtkEntry *GetEntry() const
         { return m_entry; }
 
index ec6d0a0626c586f37ec7092f3859cdd47184f4a1..5c288d0aa63bf1cbb7be32d1922becd7bf2ac652 100644 (file)
@@ -12,6 +12,7 @@
 
 typedef struct _GtkLabel GtkLabel;
 typedef struct _GtkFrame GtkFrame;
+typedef struct _GtkEntry GtkEntry;
 
 //-----------------------------------------------------------------------------
 // wxControl
@@ -100,6 +101,12 @@ protected:
     // Fix sensitivity due to bug in GTK+ < 2.14
     void GTKFixSensitivity(bool onlyIfUnderMouse = true);
 
+    // Ask GTK+ for preferred size. Use it after setting the font.
+    wxSize GTKGetPreferredSize(GtkWidget* widget) const;
+
+    // Inner margins in a GtkEntry
+    wxPoint GTKGetEntryMargins(GtkEntry* entry) const;
+
 private:
     DECLARE_DYNAMIC_CLASS(wxControl)
 };
index 5d061c5b33025b9a2d59c0676b71cbdb7c65f3c0..60e07203a7dbba84c55c2232433ec1f8e053c618 100644 (file)
@@ -155,6 +155,8 @@ protected:
     virtual void DoApplyWidgetStyle(GtkRcStyle *style);
     virtual GdkWindow *GTKGetWindow(wxArrayGdkWindows& windows) const;
 
+    virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const;
+
     virtual void DoFreeze();
     virtual void DoThaw();
 
index 32fd306b6e78c2f67857debd01a50ff558713a1a..88d17800d0ab96b27bfbaeaf5e9f24d76821c507 100644 (file)
@@ -152,6 +152,47 @@ public:
     */
     wxString GetLabelText() const;
 
+    /**
+        Determine the size needed by the control to leave the given area for
+        its text.
+
+        This function is mostly useful with control displaying short amounts of
+        text that can be edited by the user, e.g. wxTextCtrl, wxComboBox,
+        wxSearchCtrl etc. Typically it is used to size these controls for the
+        maximal amount of input they are supposed to contain, for example:
+        @code
+            // Create a control for post code entry.
+            wxTextCtrl* postcode = new wxTextCtrl(this, ...);
+
+            // And set its initial and minimal size to be big enough for
+            // entering 5 digits.
+            postcode->SetInitialSize(
+                postcode->GetSizeFromTextSize(
+                    postcode->GetTextExtent("99999")));
+        @endcode
+
+        Currently this method is only implemented for wxTextCtrl, wxComboBox
+        and wxChoice in wxGTK.
+
+        @param xlen The horizontal extent of the area to leave for text, in
+            pixels.
+        @param ylen The vertical extent of the area to leave for text, in
+            pixels. By default -1 meaning that the vertical component of the
+            returned size should be the default height of this control.
+        @return The size that the control should have to leave the area of the
+            specified size for its text. May return wxDefaultSize if this
+            method is not implemented for this particular control under the
+            current platform.
+
+        @since 2.9.5
+     */
+    wxSize GetSizeFromTextSize(int xlen, int ylen = -1) const;
+
+    /**
+        @overload
+    */
+    wxSize GetSizeFromTextSize(const wxSize& tsize) const;
+
     /**
         Sets the control's label.
 
index 7710587b7379612cb7d625f26a3b9a33d47b3ba7..419c3e03597a23bd1a440b8a698bb2a3d554add7 100644 (file)
@@ -981,7 +981,8 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
     groupSizer = new wxStaticBoxSizer(new wxStaticBox(dlg,wxID_ANY,wxT(" wxOwnerDrawnComboBox ")),
                                       wxVERTICAL);
 
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
+    groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
+                     wxT("Writable, with margins, sorted:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
 
     odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
@@ -993,12 +994,14 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
     odc->Append(wxT("H - Appended Item")); // test sorting in append
 
     odc->SetValue(wxT("Dot Dash"));
-
-    groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    odc->SetMargins(15, 10);
+    groupSizer->Add( odc, 0, wxALIGN_CENTER_VERTICAL|wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Readonly ODComboBox
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
+    groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
+                     wxT("Read-only, big font:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
 
     odc = new wxOwnerDrawnComboBox(dlg,wxID_ANY,wxEmptyString,
@@ -1007,10 +1010,12 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
                                    wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
                                   );
 
+    odc->SetFont(odc->GetFont().Scale(1.5));
     odc->SetValue(wxT("Dot Dash"));
     odc->SetText(wxT("Dot Dash (Testing SetText)"));
 
-    groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( odc, 0, wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Disabled ODComboBox
@@ -1026,7 +1031,7 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
     odc->SetValue(wxT("Dot Dash"));
     odc->Enable(false);
 
-    groupSizer->Add( odc, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( odc, 3, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
 
     rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
 
@@ -1037,7 +1042,8 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
     //
     // wxComboBox
     //
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Writable, sorted:")), 0,
+    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,
+                     wxT("Writable, with margins, sorted:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT|wxEXPAND, border );
 
     cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
@@ -1049,12 +1055,14 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
     cb->Append(wxT("H - Appended Item")); // test sorting in append
 
     cb->SetValue(wxT("Dot Dash"));
-
-    groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    cb->SetMargins(15, 10);
+    groupSizer->Add( cb, 0, wxALIGN_CENTER_VERTICAL|wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Readonly wxComboBox
-    groupSizer->Add( new wxStaticText(dlg,wxID_ANY,wxT("Read-only:")), 0,
+    groupSizer->Add( new wxStaticText(dlg, wxID_ANY,
+                     wxT("Read-only, big font:")), 0,
                      wxALIGN_CENTER_VERTICAL|wxRIGHT, border );
 
     cb = new wxComboBox(dlg,wxID_ANY,wxEmptyString,
@@ -1063,9 +1071,11 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
                         wxCB_SORT|wxCB_READONLY // wxNO_BORDER|wxCB_READONLY
                        );
 
+    cb->SetFont(cb->GetFont().Scale(1.5));
     cb->SetValue(wxT("Dot Dash"));
 
-    groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( cb, 0, wxALL, border );
+    groupSizer->AddStretchSpacer();
 
     //
     // Disabled wxComboBox
@@ -1081,11 +1091,11 @@ void MyFrame::OnShowComparison( wxCommandEvent& WXUNUSED(event) )
     cb->SetValue(wxT("Dot Dash"));
     cb->Enable(false);
 
-    groupSizer->Add( cb, 1, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
+    groupSizer->Add( cb, 3, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxALL, border );
 
     rowSizer->Add( groupSizer, 1, wxEXPAND|wxALL, border );
 
-    colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, border );
+    colSizer->Add( rowSizer, 1, wxEXPAND|wxALL, border );
 
     dlg->SetSizer( colSizer );
     colSizer->SetSizeHints( dlg );
index f158e9e1e7506fb606871a1577fb223a30bf6e75..6c73d21a03a37f109d49367dfb796795b1d85614 100644 (file)
@@ -770,7 +770,7 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
     // ------------------------------------------------------------------------
 #if wxUSE_CHOICE
     panel = new wxPanel(m_book);
-    m_choice = new MyChoice( panel, ID_CHOICE, wxPoint(10,10), wxSize(120,wxDefaultCoord), 5, choices );
+    m_choice = new MyChoice( panel, ID_CHOICE, wxPoint(10,10), wxDefaultSize, 5, choices );
     m_choiceSorted = new MyChoice( panel, ID_CHOICE_SORTED, wxPoint(10,70), wxSize(120,wxDefaultCoord),
                                    5, choices, wxCB_SORT );
 
@@ -778,12 +778,12 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
     SetChoiceClientData(wxT("choice"), m_choiceSorted);
 
     m_choice->SetSelection(2);
-    (void)new wxButton( panel, ID_CHOICE_SEL_NUM, wxT("Select #&2"), wxPoint(180,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_SEL_STR, wxT("&Select 'This'"), wxPoint(340,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_CLEAR, wxT("&Clear"), wxPoint(180,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_APPEND, wxT("&Append 'Hi!'"), wxPoint(340,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_DELETE, wxT("D&elete selected item"), wxPoint(180,130), wxSize(140,30) );
-    (void)new wxButton( panel, ID_CHOICE_FONT, wxT("Set &Italic font"), wxPoint(340,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_SEL_NUM, wxT("Select #&2"), wxPoint(220,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_SEL_STR, wxT("&Select 'This'"), wxPoint(380,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_CLEAR, wxT("&Clear"), wxPoint(220,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_APPEND, wxT("&Append 'Hi!'"), wxPoint(380,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_DELETE, wxT("D&elete selected item"), wxPoint(220,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_CHOICE_FONT, wxT("Set &Italic font"), wxPoint(380,130), wxSize(140,30) );
     (void)new wxCheckBox( panel, ID_CHOICE_ENABLE, wxT("&Disable"), wxPoint(20,130), wxSize(140,30) );
 
     m_book->AddPage(panel, wxT("wxChoice"), false, Image_Choice);
@@ -793,20 +793,21 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
     // combo page
     // ------------------------------------------------------------------------
     panel = new wxPanel(m_book);
-    (void)new wxStaticBox( panel, wxID_ANY, wxT("&Box around combobox"),
-                           wxPoint(5, 5), wxSize(150, 100));
     m_combo = new MyComboBox( panel, ID_COMBO, wxT("This"),
-                              wxPoint(20,25), wxSize(120, wxDefaultCoord),
+                              wxPoint(15,25), wxDefaultSize,
                               5, choices,
                               wxTE_PROCESS_ENTER);
-
-    (void)new wxButton( panel, ID_COMBO_SEL_NUM, wxT("Select #&2"), wxPoint(180,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_SEL_STR, wxT("&Select 'This'"), wxPoint(340,30), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_CLEAR, wxT("&Clear"), wxPoint(180,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_APPEND, wxT("&Append 'Hi!'"), wxPoint(340,80), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_DELETE, wxT("D&elete selected item"), wxPoint(180,130), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_FONT, wxT("Set &Italic font"), wxPoint(340,130), wxSize(140,30) );
-    (void)new wxButton( panel, ID_COMBO_SET_TEXT, wxT("Set 'Hi!' at #2"), wxPoint(340,180), wxSize(140,30) );
+    wxSize combosize(m_combo->GetBestSize().x + 20, 100);
+    (void)new wxStaticBox( panel, wxID_ANY, wxT("&Box around combobox"),
+                           wxPoint(5, 5), combosize);
+
+    (void)new wxButton( panel, ID_COMBO_SEL_NUM, wxT("Select #&2"), wxPoint(220,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_SEL_STR, wxT("&Select 'This'"), wxPoint(380,30), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_CLEAR, wxT("&Clear"), wxPoint(220,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_APPEND, wxT("&Append 'Hi!'"), wxPoint(380,80), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_DELETE, wxT("D&elete selected item"), wxPoint(220,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_FONT, wxT("Set &Italic font"), wxPoint(380,130), wxSize(140,30) );
+    (void)new wxButton( panel, ID_COMBO_SET_TEXT, wxT("Set 'Hi!' at #2"), wxPoint(380,180), wxSize(140,30) );
     (void)new wxCheckBox( panel, ID_COMBO_ENABLE, wxT("&Disable"), wxPoint(20,130), wxSize(140,30) );
     m_book->AddPage(panel, wxT("wxComboBox"), false, Image_Combo);
 
index 094bcc3e6b905857059de6db4f14086ee004fc70..c8cff2e88a727e6a919d8b1945850a731b7d3d98 100644 (file)
@@ -1074,16 +1074,22 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
     m_password = new MyTextCtrl( this, wxID_ANY, wxT(""),
       wxPoint(10,50), wxSize(140,wxDefaultCoord), wxTE_PASSWORD );
 
-    m_readonly = new MyTextCtrl( this, wxID_ANY, wxT("Read only"),
-      wxPoint(10,90), wxSize(140,wxDefaultCoord), wxTE_READONLY );
-
     m_limited = new MyTextCtrl(this, wxID_ANY, "",
-                              wxPoint(10, 130), wxSize(140, wxDefaultCoord));
+                              wxPoint(10, 90), wxDefaultSize);
     m_limited->SetHint("Max 8 ch");
     m_limited->SetMaxLength(8);
+    wxSize size2 = m_limited->GetSizeFromTextSize(m_limited->GetTextExtent("WWWWWWWW"));
+    m_limited->SetSizeHints(size2, size2);
 
     // multi line text controls
 
+    wxString string3L("Read only\nMultiline\nFitted size");
+    m_readonly = new MyTextCtrl( this, wxID_ANY, string3L,
+               wxPoint(10, 120), wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY );
+    wxWindowDC dc(m_readonly);
+    size2 = m_readonly->GetSizeFromTextSize(dc.GetMultiLineTextExtent(string3L));
+    m_readonly->SetMinSize(size2);
+
     m_horizontal = new MyTextCtrl( this, wxID_ANY, wxT("Multiline text control with a horizontal scrollbar.\n"),
       wxPoint(10,170), wxSize(140,70), wxTE_MULTILINE | wxHSCROLL);
 
@@ -1137,7 +1143,7 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
 #endif
 
     m_tab = new MyTextCtrl( this, 100, wxT("Multiline, allow <TAB> processing."),
-      wxPoint(180,90), wxSize(200,70), wxTE_MULTILINE |  wxTE_PROCESS_TAB );
+      wxPoint(180,90), wxDefaultSize, wxTE_MULTILINE |  wxTE_PROCESS_TAB );
     m_tab->SetClientData((void *)wxT("tab"));
 
     m_enter = new MyTextCtrl( this, 100, wxT("Multiline, allow <ENTER> processing."),
@@ -1173,13 +1179,13 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h )
     wxBoxSizer *column1 = new wxBoxSizer(wxVERTICAL);
     column1->Add( m_text, 0, wxALL | wxEXPAND, 10 );
     column1->Add( m_password, 0, wxALL | wxEXPAND, 10 );
-    column1->Add( m_readonly, 0, wxALL | wxEXPAND, 10 );
-    column1->Add( m_limited, 0, wxALL | wxEXPAND, 10 );
+    column1->Add( m_readonly, 0, wxALL, 10 );
+    column1->Add( m_limited, 0, wxALL, 10 );
     column1->Add( m_horizontal, 1, wxALL | wxEXPAND, 10 );
 
     wxBoxSizer *column2 = new wxBoxSizer(wxVERTICAL);
     column2->Add( m_multitext, 1, wxALL | wxEXPAND, 10 );
-    column2->Add( m_tab, 1, wxALL | wxEXPAND, 10 );
+    column2->Add( m_tab, 0, wxALL | wxEXPAND, 10 );
     column2->Add( m_enter, 1, wxALL | wxEXPAND, 10 );
 
     wxBoxSizer *row1 = new wxBoxSizer(wxHORIZONTAL);
index 1382c3102ca662b6c2d79ca5177dbd791cc11af4..af5c83292f14b37609e9fdaef016eea5fde85823 100644 (file)
@@ -149,6 +149,12 @@ void wxControlBase::DoUpdateWindowUI(wxUpdateUIEvent& event)
 #endif // wxUSE_RADIOBTN
 }
 
+wxSize wxControlBase::DoGetSizeFromTextSize(int WXUNUSED(xlen),
+                                            int WXUNUSED(ylen)) const
+{
+    return wxSize(-1, -1);
+}
+
 /* static */
 wxString wxControlBase::GetLabelText(const wxString& label)
 {
index 28832ef3e4f0d4d34c4b7fc2f4cf5cdd6cb18da2..73ed8300b3aab6fd8d7b02db70f44a411fe08723 100644 (file)
@@ -348,8 +348,38 @@ wxSize wxChoice::DoGetBestSize() const
     // Get the height of the control from GTK+ itself, but use our own version
     // to compute the width large enough to show all our strings as GTK+
     // doesn't seem to take the control contents into account.
-    return wxSize(wxChoiceBase::DoGetBestSize().x + 40,
-                  wxControl::DoGetBestSize().y);
+    return GetSizeFromTextSize(wxChoiceBase::DoGetBestSize().x);
+}
+
+wxSize wxChoice::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") );
+
+    // a GtkEntry for wxComboBox and a GtkCellView for wxChoice
+    GtkWidget* childPart = gtk_bin_get_child(GTK_BIN(m_widget));
+
+    // Set a as small as possible size for the control, so preferred sizes
+    // return "natural" sizes, not taking into account the previous ones (which
+    // seems to be GTK+3 behaviour)
+    gtk_widget_set_size_request(m_widget, 0, 0);
+
+    // We are interested in the difference of sizes between the whole contol
+    // and its child part. I.e. arrow, separators, etc.
+    GtkRequisition req;
+    gtk_widget_size_request(childPart, &req);
+    wxSize totalS = GTKGetPreferredSize(m_widget);
+
+    wxSize tsize(xlen + totalS.x - req.width, totalS.y);
+
+    // For a wxChoice, not for wxComboBox, add some margins
+    if ( !GTK_IS_ENTRY(childPart) )
+        tsize.IncBy(5, 0);
+
+    // Perhaps the user wants something different from CharHeight
+    if ( ylen > 0 )
+        tsize.IncBy(0, ylen - GetCharHeight());
+
+    return tsize;
 }
 
 void wxChoice::DoApplyWidgetStyle(GtkRcStyle *style)
index e2bad2c0c40f8c4689b003b481e713d3b884a733..ae69a86b371b20105efdae3aa735a20813d0021d 100644 (file)
@@ -404,4 +404,17 @@ void wxComboBox::Dismiss()
 {
     gtk_combo_box_popdown( GTK_COMBO_BOX(m_widget) );
 }
+
+wxSize wxComboBox::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxSize tsize( wxChoice::DoGetSizeFromTextSize(xlen, ylen) );
+
+    // Add the margins we have previously set, but only the horizontal border
+    // as vertical one has been taken account in the prevoius call.
+    // Also get other GTK+ margins.
+    tsize.IncBy( GTKGetEntryMargins(GetEntry()).x, 0);
+
+    return tsize;
+}
+
 #endif // wxUSE_COMBOBOX
index b03023f07e0578e252e516ab09b0d27cf0d4fa58..ff33e9af473f1d14dfd561c06b8d72f3e90f85cf 100644 (file)
@@ -86,24 +86,9 @@ wxSize wxControl::DoGetBestSize() const
     }
     else
     {
-        GtkRequisition req;
-#ifdef __WXGTK3__
-        if (gtk_widget_get_request_mode(m_widget) != GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
-        {
-            gtk_widget_get_preferred_height(m_widget, NULL, &req.height);
-            gtk_widget_get_preferred_width_for_height(m_widget, req.height, NULL, &req.width);
-        }
-        else
-        {
-            gtk_widget_get_preferred_width(m_widget, NULL, &req.width);
-            gtk_widget_get_preferred_height_for_width(m_widget, req.width, NULL, &req.height);
-        }
-#else
-        GTK_WIDGET_GET_CLASS(m_widget)->size_request(m_widget, &req);
-#endif
-        best.Set(req.width, req.height);
+        best = GTKGetPreferredSize(m_widget);
     }
-    CacheBestSize(best);
+
     return best;
 }
 
@@ -364,4 +349,58 @@ wxControl::GetDefaultAttributesFromGTKWidget(wxGtkWidgetNewFromAdj_t widget_new,
     return attr;
 }
 
+// This is not the same as GetBestSize() because that size may have
+// been recalculated and cached by us. We want GTK+ information.
+wxSize wxControl::GTKGetPreferredSize(GtkWidget* widget) const
+{
+    GtkRequisition req;
+#ifdef __WXGTK3__
+    if (gtk_widget_get_request_mode(widget) != GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+    {
+        gtk_widget_get_preferred_height(widget, NULL, &req.height);
+        gtk_widget_get_preferred_width_for_height(widget, req.height, NULL, &req.width);
+    }
+    else
+    {
+        gtk_widget_get_preferred_width(widget, NULL, &req.width);
+        gtk_widget_get_preferred_height_for_width(widget, req.width, NULL, &req.height);
+    }
+#else
+    GTK_WIDGET_GET_CLASS(widget)->size_request(widget, &req);
+#endif
+
+    return wxSize(req.width, req.height);
+}
+
+wxPoint wxControl::GTKGetEntryMargins(GtkEntry* entry) const
+{
+    wxPoint marg(0, 0);
+
+#ifndef __WXGTK3__
+#if GTK_CHECK_VERSION(2,10,0)
+    // The margins we have previously set
+    const GtkBorder* border = gtk_entry_get_inner_border(entry);
+    if ( border )
+    {
+        marg.x = border->left + border->right;
+        marg.y = border->top + border->bottom;
+    }
+#endif // GTK+ 2.10+
+#else // GTK+ 3
+    // Gtk3 does not use inner border, but StyleContext and CSS
+    // TODO: implement it, starting with wxTextEntry::DoSetMargins()
+#endif // GTK+ 2/3
+
+    int x, y;
+    gtk_entry_get_layout_offsets(entry, &x, &y);
+    // inner borders are included. Substract them so we can get other margins
+    x -= marg.x;
+    y -= marg.y;
+    marg.x += 2 * x + 2;
+    marg.y += 2 * y + 2;
+
+    return marg;
+}
+
+
 #endif // wxUSE_CONTROLS
index dda27477f3c888562d019f505299460a27a8aaa8..dcfe229e2205afa3b3cc169f0e5ceb64f106a717 100644 (file)
@@ -1820,13 +1820,55 @@ void wxTextCtrl::OnUpdateRedo(wxUpdateUIEvent& event)
 
 wxSize wxTextCtrl::DoGetBestSize() const
 {
-    // FIXME should be different for multi-line controls...
-    wxSize ret( wxControl::DoGetBestSize() );
-    wxSize best(80, ret.y);
-    CacheBestSize(best);
-    return best;
+    return DoGetSizeFromTextSize(80);
 }
 
+wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const
+{
+    wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") );
+
+    wxSize tsize(xlen, 0);
+    int cHeight = GetCharHeight();
+
+    if ( IsSingleLine() )
+    {
+        // default height
+        tsize.y = GTKGetPreferredSize(m_widget).y;
+        // Add the margins we have previously set, but only the horizontal border
+        // as vertical one has been taken account at GTKGetPreferredSize().
+        // Also get other GTK+ margins.
+        tsize.IncBy( GTKGetEntryMargins(GetEntry()).x, 0);
+    }
+
+    //multiline
+    else
+    {
+        // add space for vertical scrollbar
+        if ( m_scrollBar[1] && !(m_windowStyle & wxTE_NO_VSCROLL) )
+            tsize.IncBy(GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[1])).x + 3, 0);
+
+        // height
+        tsize.y = cHeight;
+        if ( ylen <= 0 )
+        {
+            tsize.y = cHeight * wxMax(wxMin(GetNumberOfLines(), 10), 2);
+            // add space for horizontal scrollbar
+            if ( m_scrollBar[0] && (m_windowStyle & wxHSCROLL) )
+                tsize.IncBy(0, GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[0])).y + 3);
+        }
+
+        // hardcode borders, margins, etc
+        tsize.IncBy(5, 5);
+    }
+
+    // Perhaps the user wants something different from CharHeight
+    if ( ylen > 0 )
+        tsize.IncBy(0, ylen - cHeight);
+
+    return tsize;
+}
+
+
 // ----------------------------------------------------------------------------
 // freeze/thaw
 // ----------------------------------------------------------------------------