From c01b9495b33f525ed12117b8982c91a80ba6b49a Mon Sep 17 00:00:00 2001 From: Paul Cornett Date: Fri, 13 Jan 2023 19:22:15 +0100 Subject: [PATCH 01/10] Account for the border in wxGTK2 wxTextCtrl This fixes the value returned from wxTextCtrl::GetSizeFromTextSize() which could have been too small previously. --- src/gtk/control.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gtk/control.cpp b/src/gtk/control.cpp index f0cb37aac2..0006ed0b66 100644 --- a/src/gtk/control.cpp +++ b/src/gtk/control.cpp @@ -373,6 +373,13 @@ wxSize wxControl::GTKGetEntryMargins(GtkEntry* entry) const GtkStyleContext* sc = gtk_widget_get_style_context(GTK_WIDGET(entry)); gtk_style_context_get_padding(sc, gtk_style_context_get_state(sc), &border); #else + if (gtk_entry_get_has_frame(entry)) + { + GtkStyle* style = GTK_WIDGET(entry)->style; + size.x += 2 * style->xthickness; + size.y += 2 * style->ythickness; + } + // Equivalent to the GTK2 private function _gtk_entry_effective_inner_border() GtkBorder border = { 2, 2, 2, 2 }; From 80249177d0d5673b09e19c026ae51d7d7f2a8c3c Mon Sep 17 00:00:00 2001 From: taler21 Date: Wed, 1 Feb 2023 00:41:27 +0100 Subject: [PATCH 02/10] Improve automatic enlargement of in-place editor in wxTreeCtrl Use GetSizeFromText() when computing the increased size after the text changes and do it from wxEVT_CHAR handler rather than in wxEVT_KEY_UP one in order to be able to account for the newly entered character correctly. --- src/generic/treectlg.cpp | 53 ++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index da0e87c99f..a329290b68 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -100,9 +100,10 @@ public: protected: void OnChar( wxKeyEvent &event ); - void OnKeyUp( wxKeyEvent &event ); void OnKillFocus( wxFocusEvent &event ); + void IncreaseSizeForText( const wxString& text ); + bool AcceptChanges(); void Finish( bool setfocus ); @@ -417,7 +418,6 @@ void wxTreeRenameTimer::Notify() wxBEGIN_EVENT_TABLE(wxTreeTextCtrl,wxTextCtrl) EVT_CHAR (wxTreeTextCtrl::OnChar) - EVT_KEY_UP (wxTreeTextCtrl::OnKeyUp) EVT_KILL_FOCUS (wxTreeTextCtrl::OnKillFocus) wxEND_EVENT_TABLE() @@ -441,12 +441,7 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, (void)Create(m_owner, wxID_ANY, m_startValue, rect.GetPosition(), rect.GetSize()); - int w; - GetTextExtent(m_startValue, &w, nullptr); - const wxSize size(GetSizeFromTextSize(w)); - rect.y += (rect.height - size.y) / 2; - rect.SetSize(size); - SetSize(rect); + IncreaseSizeForText(m_startValue); SelectAll(); } @@ -536,28 +531,38 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) break; default: + if ( !m_aboutToFinish ) + { + wxChar ch = event.GetUnicodeKey(); + if ( ch != WXK_NONE ) + { + wxString value = GetValue(); + + long from, to; + GetSelection( &from, &to ); + if ( from != to ) + { + value.Remove( from, to - from ); + } + + IncreaseSizeForText( value + ch ); + } + } event.Skip(); } } -void wxTreeTextCtrl::OnKeyUp( wxKeyEvent &event ) +void wxTreeTextCtrl::IncreaseSizeForText( const wxString& text ) { - if ( !m_aboutToFinish ) - { - // auto-grow the textctrl: - wxSize parentSize = m_owner->GetSize(); - wxPoint myPos = GetPosition(); - wxSize mySize = GetSize(); - int sx, sy; - GetTextExtent(GetValue() + wxT("M"), &sx, &sy); - if (myPos.x + sx > parentSize.x) - sx = parentSize.x - myPos.x; - if (mySize.x > sx) - sx = mySize.x; + // auto-grow the textctrl: + wxSize parentSize = m_owner->GetSize(); + wxPoint myPos = GetPosition(); + wxSize mySize = GetSize(); + int sx = GetSizeFromText(text).x; + if (myPos.x + sx > parentSize.x) + sx = parentSize.x - myPos.x; + if (sx > mySize.x) SetSize(sx, wxDefaultCoord); - } - - event.Skip(); } void wxTreeTextCtrl::OnKillFocus( wxFocusEvent &event ) From 3433eaafc2ecf76b81a888c7a331875268149782 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 2 Feb 2023 17:03:42 +0100 Subject: [PATCH 03/10] Initialize height once in wxTextCtrl::DoGetSizeFromTextSize() No real changes, just replace the redundant assignments with an initialization. --- src/gtk/textctrl.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index ea97ffe52b..371e789a96 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -2133,14 +2133,13 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const { wxASSERT_MSG( m_widget, wxS("GetSizeFromTextSize called before creation") ); - wxSize tsize(xlen, 0); int cHeight = GetCharHeight(); + wxSize tsize(xlen, cHeight); if ( IsSingleLine() ) { if ( HasFlag(wxBORDER_NONE) ) { - tsize.y = cHeight; #ifdef __WXGTK3__ tsize.IncBy(9, 0); #else @@ -2166,7 +2165,6 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const tsize.IncBy(GTKGetPreferredSize(GTK_WIDGET(m_scrollBar[1])).x + 3, 0); // height - tsize.y = cHeight; if ( ylen <= 0 ) { tsize.y = 1 + cHeight * wxMax(wxMin(GetNumberOfLines(), 10), 2); From 44e9218e0329d4295cf1b63d2c407b26164deff1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 2 Feb 2023 17:09:06 +0100 Subject: [PATCH 04/10] Don't always increase height in DoGetSizeFromTextSize() The intention here almost certainly was to use at least the specified height, not to always add something to it at the end for no apparent reason, so do this instead. --- src/gtk/textctrl.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 371e789a96..db21759851 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -2180,10 +2180,9 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const } } - // Perhaps the user wants something different from CharHeight, or ylen - // is used as the height of a multiline text. - if ( ylen > 0 ) - tsize.IncBy(0, ylen - cHeight); + // We should always use at least the specified height if it's valid. + if ( ylen > tsize.y ) + tsize.y = ylen; return tsize; } From 3e0163497614741de83ac64c6aa04c024a0447f5 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 2 Feb 2023 17:10:04 +0100 Subject: [PATCH 05/10] Use vertical GTK entry margins too in DoGetSizeFromTextSize() This actually makes the height returned from it smaller, as these margins are negative (at least with GTK 3), but this works well with the size returned by GTKGetPreferredSize() which would be too big otherwise, as it seems to include the margins around the control too. --- src/gtk/textctrl.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index db21759851..861645ae8f 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -2150,10 +2150,8 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const { // 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); + // Add the margins we have previously set. + tsize.IncBy( GTKGetEntryMargins(GetEntry()) ); } } From 0e16d866ed0897b805dac0855e40c83e9ec6f24e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 2 Feb 2023 17:11:33 +0100 Subject: [PATCH 06/10] Fix vertical size and position of wxTreeTextCtrl Use vertical component of the size returned from GetSizeFromTextSize() too, not only the horizontal one, to ensure we make the control tall enough to fit its contents. --- src/generic/treectlg.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index a329290b68..c34ccd037d 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -428,6 +428,11 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, m_owner = owner; m_aboutToFinish = false; + // Create the text hidden to show it with the correct size -- which we + // can't determine before creating it. + Hide(); + Create(m_owner, wxID_ANY, m_startValue); + wxRect rect; m_owner->GetBoundingRect(m_itemEdited, rect, true); @@ -438,10 +443,20 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, rect.x -= 5; #endif // platforms - (void)Create(m_owner, wxID_ANY, m_startValue, - rect.GetPosition(), rect.GetSize()); + const wxSize textSize = rect.GetSize(); + wxSize fullSize = GetSizeFromTextSize(textSize); + if ( fullSize.y > textSize.y ) + { + // It's ok to extend the rect to the right horizontally, which happens + // when we just change its size without changing its position below, + // but when extending it vertically, we need to keep it centered. + rect.y -= (fullSize.y - textSize.y + 1) / 2; + } - IncreaseSizeForText(m_startValue); + rect.SetSize(fullSize); + + SetSize(rect); + Show(); SelectAll(); } From a8d80225292ffce2a07ee62203b588e7f0153a00 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 2 Feb 2023 17:13:09 +0100 Subject: [PATCH 07/10] Allow using F2 for renaming items in the treectrl sample This makes it simpler to test this functionality and it's also the standard key for doing this, at least under MSW. --- samples/treectrl/treetest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/treectrl/treetest.cpp b/samples/treectrl/treetest.cpp index d75bc7dd2f..1adf9954c8 100644 --- a/samples/treectrl/treetest.cpp +++ b/samples/treectrl/treetest.cpp @@ -291,7 +291,7 @@ MyFrame::MyFrame(const wxString& title, int x, int y, int w, int h) tree_menu->Append(TreeTest_DecSpacing, "Reduce spacing by 5 points\tCtrl-R"); item_menu->Append(TreeTest_Dump, "&Dump item children"); - item_menu->Append(TreeTest_Rename, "&Rename item..."); + item_menu->Append(TreeTest_Rename, "&Rename item...\tF2"); item_menu->AppendSeparator(); item_menu->Append(TreeTest_SetBold, "Make item &bold"); From 9a3e732c5123ff1c1de3cd1ab5de441453136acc Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Feb 2023 16:26:30 +0000 Subject: [PATCH 08/10] Fix height returned from MSW DoGetSizeFromTextSize() too This is identical to 44e9218e03 (Don't always increase height in DoGetSizeFromTextSize(), 2023-02-02) for wxGTK and ensures that we don't make the returned height too big when a valid height is specified on input. --- src/msw/textctrl.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 2adda7d929..6f15bb6284 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -2555,10 +2555,9 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const hText += EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy) - cy; } - // Perhaps the user wants something different from CharHeight, or ylen - // is used as the height of a multiline text. - if ( ylen > 0 ) - hText += ylen - GetCharHeight(); + // We should always use at least the specified height if it's valid. + if ( ylen > hText ) + hText = ylen; return wxSize(wText, hText); } From 489e4c869e3a6c4fb01793a7b81b701b7f2b616c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 3 Feb 2023 18:18:22 +0100 Subject: [PATCH 09/10] Don't make in-place editor too large initially As we don't call IncreaseSizeForText() in the ctor any longer, redo the same check there too. Also prefer using GetClientSize() to GetSize() for determining the available size, the difference is not big, but the former is more correct. --- src/generic/treectlg.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/generic/treectlg.cpp b/src/generic/treectlg.cpp index c34ccd037d..67c53f0aa3 100644 --- a/src/generic/treectlg.cpp +++ b/src/generic/treectlg.cpp @@ -453,6 +453,13 @@ wxTreeTextCtrl::wxTreeTextCtrl(wxGenericTreeCtrl *owner, rect.y -= (fullSize.y - textSize.y + 1) / 2; } + // Also check that the control fits into the parent window. + const int totalWidth = m_owner->GetClientSize().x; + if ( rect.x + fullSize.x > totalWidth ) + { + fullSize.x = totalWidth - rect.x; + } + rect.SetSize(fullSize); SetSize(rect); @@ -570,7 +577,7 @@ void wxTreeTextCtrl::OnChar( wxKeyEvent &event ) void wxTreeTextCtrl::IncreaseSizeForText( const wxString& text ) { // auto-grow the textctrl: - wxSize parentSize = m_owner->GetSize(); + wxSize parentSize = m_owner->GetClientSize(); wxPoint myPos = GetPosition(); wxSize mySize = GetSize(); int sx = GetSizeFromText(text).x; From 4f6ddcf511e65ce4ee765ddcccbd6c29f69f238d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 4 Feb 2023 13:58:02 +0100 Subject: [PATCH 10/10] Hard code text control margins for GTK 2 Using GTKGetPreferredSize() doesn't always seem to return the correct values, resulting in making the control too big, so just hard code the smaller margins there. --- src/gtk/textctrl.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 861645ae8f..f65cfd6216 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -2150,8 +2150,16 @@ wxSize wxTextCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const { // default height tsize.y = GTKGetPreferredSize(m_widget).y; +#ifdef __WXGTK3__ // Add the margins we have previously set. tsize.IncBy( GTKGetEntryMargins(GetEntry()) ); +#else + // For GTK 2 these margins are too big, so hard code something more + // reasonable, this is not great but should be fine considering + // that it's very unlikely that GTK 2 is going to evolve, making + // this inappropriate. + tsize.IncBy(20, 0); +#endif } }