diff --git a/docs/changes.txt b/docs/changes.txt index 9d864b6497..c8e1d6d10c 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -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: diff --git a/include/wx/control.h b/include/wx/control.h index 129a61dfed..6bd5ed190b 100644 --- a/include/wx/control.h +++ b/include/wx/control.h @@ -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; diff --git a/include/wx/gtk/choice.h b/include/wx/gtk/choice.h index 70e93fd534..b9297200ec 100644 --- a/include/wx/gtk/choice.h +++ b/include/wx/gtk/choice.h @@ -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); diff --git a/include/wx/gtk/combobox.h b/include/wx/gtk/combobox.h index 87aae8d9b9..72ac945b93 100644 --- a/include/wx/gtk/combobox.h +++ b/include/wx/gtk/combobox.h @@ -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; } diff --git a/include/wx/gtk/control.h b/include/wx/gtk/control.h index ec6d0a0626..5c288d0aa6 100644 --- a/include/wx/gtk/control.h +++ b/include/wx/gtk/control.h @@ -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) }; diff --git a/include/wx/gtk/textctrl.h b/include/wx/gtk/textctrl.h index 5d061c5b33..60e07203a7 100644 --- a/include/wx/gtk/textctrl.h +++ b/include/wx/gtk/textctrl.h @@ -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(); diff --git a/interface/wx/control.h b/interface/wx/control.h index 32fd306b6e..88d17800d0 100644 --- a/interface/wx/control.h +++ b/interface/wx/control.h @@ -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. diff --git a/samples/combo/combo.cpp b/samples/combo/combo.cpp index 7710587b73..419c3e0359 100644 --- a/samples/combo/combo.cpp +++ b/samples/combo/combo.cpp @@ -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 ); diff --git a/samples/controls/controls.cpp b/samples/controls/controls.cpp index f158e9e1e7..6c73d21a03 100644 --- a/samples/controls/controls.cpp +++ b/samples/controls/controls.cpp @@ -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); + 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(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) ); + (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); diff --git a/samples/text/text.cpp b/samples/text/text.cpp index 094bcc3e6b..c8cff2e88a 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -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 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 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); diff --git a/src/common/ctrlcmn.cpp b/src/common/ctrlcmn.cpp index 1382c3102c..af5c83292f 100644 --- a/src/common/ctrlcmn.cpp +++ b/src/common/ctrlcmn.cpp @@ -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) { diff --git a/src/gtk/choice.cpp b/src/gtk/choice.cpp index 28832ef3e4..73ed8300b3 100644 --- a/src/gtk/choice.cpp +++ b/src/gtk/choice.cpp @@ -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) diff --git a/src/gtk/combobox.cpp b/src/gtk/combobox.cpp index e2bad2c0c4..ae69a86b37 100644 --- a/src/gtk/combobox.cpp +++ b/src/gtk/combobox.cpp @@ -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 diff --git a/src/gtk/control.cpp b/src/gtk/control.cpp index b03023f07e..ff33e9af47 100644 --- a/src/gtk/control.cpp +++ b/src/gtk/control.cpp @@ -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 diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index dda27477f3..dcfe229e22 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -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 // ----------------------------------------------------------------------------