Merge branch 'gtk-entry-hittest'
Implement wxTextCtrl::HitTest() for single line controls in wxGTK. See https://github.com/wxWidgets/wxWidgets/pull/826
This commit is contained in:
@@ -92,6 +92,7 @@ All (GUI):
|
|||||||
|
|
||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
|
- Implement wxTextCtrl::HitTest() for single line controls.
|
||||||
- Fix the build with glib < 2.32 (e.g. CentOS 6).
|
- Fix the build with glib < 2.32 (e.g. CentOS 6).
|
||||||
|
|
||||||
wxMSW:
|
wxMSW:
|
||||||
|
@@ -1337,7 +1337,7 @@ public:
|
|||||||
parameter is not modified.
|
parameter is not modified.
|
||||||
|
|
||||||
Please note that this function is currently only implemented in wxUniv,
|
Please note that this function is currently only implemented in wxUniv,
|
||||||
wxMSW and wxGTK2 ports and always returns @c wxTE_HT_UNKNOWN in the
|
wxMSW and wxGTK ports and always returns @c wxTE_HT_UNKNOWN in the
|
||||||
other ports.
|
other ports.
|
||||||
|
|
||||||
@beginWxPerlOnly
|
@beginWxPerlOnly
|
||||||
@@ -1363,7 +1363,7 @@ public:
|
|||||||
parameters are not modified.
|
parameters are not modified.
|
||||||
|
|
||||||
Please note that this function is currently only implemented in wxUniv,
|
Please note that this function is currently only implemented in wxUniv,
|
||||||
wxMSW and wxGTK2 ports and always returns @c wxTE_HT_UNKNOWN in the
|
wxMSW and wxGTK ports and always returns @c wxTE_HT_UNKNOWN in the
|
||||||
other ports.
|
other ports.
|
||||||
|
|
||||||
@beginWxPerlOnly
|
@beginWxPerlOnly
|
||||||
|
@@ -276,11 +276,17 @@ public:
|
|||||||
int flags)
|
int flags)
|
||||||
: wxTextCtrl(parent, id, value, wxDefaultPosition, wxDefaultSize, flags)
|
: wxTextCtrl(parent, id, value, wxDefaultPosition, wxDefaultSize, flags)
|
||||||
{
|
{
|
||||||
|
Bind(wxEVT_LEFT_DOWN, &WidgetsTextCtrl::OnLeftClick, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
void OnRightClick(wxMouseEvent& event)
|
// Show the result of HitTest() at the mouse position if Alt is pressed.
|
||||||
|
void OnLeftClick(wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
|
event.Skip();
|
||||||
|
if ( !event.AltDown() )
|
||||||
|
return;
|
||||||
|
|
||||||
wxString where;
|
wxString where;
|
||||||
wxTextCoord x, y;
|
wxTextCoord x, y;
|
||||||
switch ( HitTest(event.GetPosition(), &x, &y) )
|
switch ( HitTest(event.GetPosition(), &x, &y) )
|
||||||
@@ -312,12 +318,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
wxLogMessage(wxT("Mouse is %s (%ld, %ld)"), where.c_str(), x, y);
|
wxLogMessage(wxT("Mouse is %s (%ld, %ld)"), where.c_str(), x, y);
|
||||||
|
|
||||||
event.Skip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -353,10 +354,6 @@ wxBEGIN_EVENT_TABLE(TextWidgetsPage, WidgetsPage)
|
|||||||
EVT_RADIOBOX(wxID_ANY, TextWidgetsPage::OnCheckOrRadioBox)
|
EVT_RADIOBOX(wxID_ANY, TextWidgetsPage::OnCheckOrRadioBox)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(WidgetsTextCtrl, wxTextCtrl)
|
|
||||||
EVT_RIGHT_UP(WidgetsTextCtrl::OnRightClick)
|
|
||||||
wxEND_EVENT_TABLE()
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -593,6 +590,17 @@ void TextWidgetsPage::CreateContent()
|
|||||||
0, wxALL, 5
|
0, wxALL, 5
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sizerMiddleDown->Add
|
||||||
|
(
|
||||||
|
new wxStaticText
|
||||||
|
(
|
||||||
|
this,
|
||||||
|
wxID_ANY,
|
||||||
|
"Alt-click in the text to see HitTest() result"
|
||||||
|
),
|
||||||
|
wxSizerFlags().Border()
|
||||||
|
);
|
||||||
|
|
||||||
wxSizer *sizerMiddle = new wxBoxSizer(wxVERTICAL);
|
wxSizer *sizerMiddle = new wxBoxSizer(wxVERTICAL);
|
||||||
sizerMiddle->Add(sizerMiddleUp, 0, wxGROW);
|
sizerMiddle->Add(sizerMiddleUp, 0, wxGROW);
|
||||||
sizerMiddle->Add(sizerMiddleDown, 1, wxGROW | wxTOP, 5);
|
sizerMiddle->Add(sizerMiddleDown, 1, wxGROW | wxTOP, 5);
|
||||||
|
@@ -1465,8 +1465,53 @@ wxTextCtrl::HitTest(const wxPoint& pt, long *pos) const
|
|||||||
{
|
{
|
||||||
if ( !IsMultiLine() )
|
if ( !IsMultiLine() )
|
||||||
{
|
{
|
||||||
// not supported
|
// These variables will contain the position inside PangoLayout.
|
||||||
return wxTE_HT_UNKNOWN;
|
int x = pt.x,
|
||||||
|
y = pt.y;
|
||||||
|
|
||||||
|
// Get the offsets of PangoLayout inside the control.
|
||||||
|
//
|
||||||
|
// Note that contrary to what GTK+ documentation implies, the
|
||||||
|
// horizontal offset already accounts for scrolling, i.e. it will be
|
||||||
|
// negative if text is scrolled.
|
||||||
|
gint ofsX = 0,
|
||||||
|
ofsY = 0;
|
||||||
|
gtk_entry_get_layout_offsets(GTK_ENTRY(m_text), &ofsX, &ofsY);
|
||||||
|
|
||||||
|
x -= ofsX;
|
||||||
|
y -= ofsY;
|
||||||
|
|
||||||
|
// And scale the coordinates for Pango.
|
||||||
|
x *= PANGO_SCALE;
|
||||||
|
y *= PANGO_SCALE;
|
||||||
|
|
||||||
|
PangoLayout* const layout = gtk_entry_get_layout(GTK_ENTRY(m_text));
|
||||||
|
|
||||||
|
int idx = -1,
|
||||||
|
ofs = 0;
|
||||||
|
if ( !pango_layout_xy_to_index(layout, x, y, &idx, &ofs) )
|
||||||
|
{
|
||||||
|
// Try to guess why did it fail.
|
||||||
|
if ( x < 0 || y < 0 )
|
||||||
|
{
|
||||||
|
if ( pos )
|
||||||
|
*pos = 0;
|
||||||
|
|
||||||
|
return wxTE_HT_BEFORE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( pos )
|
||||||
|
*pos = wxTextEntry::GetLastPosition();
|
||||||
|
|
||||||
|
return wxTE_HT_BEYOND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( pos )
|
||||||
|
*pos = idx;
|
||||||
|
|
||||||
|
return wxTE_HT_ON_TEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
@@ -59,6 +59,7 @@ private:
|
|||||||
WXUISIM_TEST( MaxLength );
|
WXUISIM_TEST( MaxLength );
|
||||||
CPPUNIT_TEST( PositionToXYSingleLine );
|
CPPUNIT_TEST( PositionToXYSingleLine );
|
||||||
CPPUNIT_TEST( XYToPositionSingleLine );
|
CPPUNIT_TEST( XYToPositionSingleLine );
|
||||||
|
CPPUNIT_TEST( HitTestSingleLine );
|
||||||
SINGLE_AND_MULTI_TESTS();
|
SINGLE_AND_MULTI_TESTS();
|
||||||
|
|
||||||
// Now switch to the multi-line text controls.
|
// Now switch to the multi-line text controls.
|
||||||
@@ -112,6 +113,7 @@ private:
|
|||||||
void MaxLength();
|
void MaxLength();
|
||||||
void StreamInput();
|
void StreamInput();
|
||||||
void Redirector();
|
void Redirector();
|
||||||
|
void HitTestSingleLine();
|
||||||
//void ProcessEnter();
|
//void ProcessEnter();
|
||||||
void Url();
|
void Url();
|
||||||
void Style();
|
void Style();
|
||||||
@@ -164,12 +166,8 @@ long TextCtrlTestCase::ms_style = 0;
|
|||||||
|
|
||||||
void TextCtrlTestCase::CreateText(long extraStyles)
|
void TextCtrlTestCase::CreateText(long extraStyles)
|
||||||
{
|
{
|
||||||
wxSize size;
|
|
||||||
if ( ms_style == wxTE_MULTILINE )
|
|
||||||
size = wxSize(400, TEXT_HEIGHT);
|
|
||||||
|
|
||||||
m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
|
m_text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
|
||||||
wxDefaultPosition, size,
|
wxDefaultPosition, wxSize(400, TEXT_HEIGHT),
|
||||||
ms_style | extraStyles);
|
ms_style | extraStyles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +340,51 @@ void TextCtrlTestCase::Redirector()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextCtrlTestCase::HitTestSingleLine()
|
||||||
|
{
|
||||||
|
m_text->ChangeValue("Hit me");
|
||||||
|
|
||||||
|
// We don't know the size of the text borders, so we can't really do any
|
||||||
|
// exact tests, just try to verify that the results are roughly as
|
||||||
|
// expected.
|
||||||
|
const wxSize sizeChar = m_text->GetTextExtent("X");
|
||||||
|
const int yMid = sizeChar.y / 2;
|
||||||
|
|
||||||
|
long pos = -1;
|
||||||
|
|
||||||
|
// Hitting a point near the left side of the control should find one of the
|
||||||
|
// first few characters under it.
|
||||||
|
SECTION("Normal")
|
||||||
|
{
|
||||||
|
REQUIRE( m_text->HitTest(wxPoint(2*sizeChar.x, yMid), &pos) == wxTE_HT_ON_TEXT );
|
||||||
|
CHECK( pos >= 0 );
|
||||||
|
CHECK( pos < 3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hitting a point well beyond the end of the text shouldn't find any valid
|
||||||
|
// character.
|
||||||
|
SECTION("Beyond")
|
||||||
|
{
|
||||||
|
REQUIRE( m_text->HitTest(wxPoint(20*sizeChar.x, yMid), &pos) == wxTE_HT_BEYOND );
|
||||||
|
CHECK( pos == m_text->GetLastPosition() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Making the control scroll, by ensuring that its contents is too long to
|
||||||
|
// show inside its window, should change the hit test result for the same
|
||||||
|
// position as used above.
|
||||||
|
SECTION("Scrolled")
|
||||||
|
{
|
||||||
|
m_text->ChangeValue(wxString(200, 'X'));
|
||||||
|
m_text->SetInsertionPointEnd();
|
||||||
|
|
||||||
|
// wxGTK must be given an opportunity to lay the text out.
|
||||||
|
wxYield();
|
||||||
|
|
||||||
|
REQUIRE( m_text->HitTest(wxPoint(2*sizeChar.x, yMid), &pos) == wxTE_HT_ON_TEXT );
|
||||||
|
CHECK( pos > 3 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
void TextCtrlTestCase::ProcessEnter()
|
void TextCtrlTestCase::ProcessEnter()
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user