1. better kbd interface to wxTextCtrl (selection...)
2. mouse input handling git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8397 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
4
TODO
4
TODO
@@ -1,7 +1,9 @@
|
|||||||
All
|
All
|
||||||
|
|
||||||
* problem with horz scrolling: the focus rect isn't drawn entirely...
|
* problem with lbox horz scrolling: the focus rect isn't drawn entirely...
|
||||||
* write sample testing all listbox styles/events
|
* write sample testing all listbox styles/events
|
||||||
|
* text ctrl horz scrolling
|
||||||
|
* text ctrl wxTE_XXX styles support
|
||||||
|
|
||||||
MSW
|
MSW
|
||||||
|
|
||||||
|
@@ -25,6 +25,7 @@ class WXDLLEXPORT wxCheckListBox;
|
|||||||
class WXDLLEXPORT wxListBox;
|
class WXDLLEXPORT wxListBox;
|
||||||
class WXDLLEXPORT wxRenderer;
|
class WXDLLEXPORT wxRenderer;
|
||||||
class WXDLLEXPORT wxScrollBar;
|
class WXDLLEXPORT wxScrollBar;
|
||||||
|
class WXDLLEXPORT wxTextCtrl;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// types of the standard input handlers which can be passed to
|
// types of the standard input handlers which can be passed to
|
||||||
@@ -297,6 +298,13 @@ public:
|
|||||||
const wxMouseEvent& event);
|
const wxMouseEvent& event);
|
||||||
virtual bool HandleMouseMove(wxControl *control,
|
virtual bool HandleMouseMove(wxControl *control,
|
||||||
const wxMouseEvent& event);
|
const wxMouseEvent& event);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// get the position of the mouse click
|
||||||
|
static long HitTest(const wxTextCtrl *text, const wxPoint& pos);
|
||||||
|
|
||||||
|
// capture data
|
||||||
|
wxTextCtrl *m_winCapture;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WX_UNIV_INPHAND_H_
|
#endif // _WX_UNIV_INPHAND_H_
|
||||||
|
@@ -97,10 +97,13 @@ public:
|
|||||||
int indexAccel = -1,
|
int indexAccel = -1,
|
||||||
wxRect *rectBounds = NULL) = 0;
|
wxRect *rectBounds = NULL) = 0;
|
||||||
|
|
||||||
// draw a line of the text ctrl
|
// draw a line of the text ctrl optionally highlighting the characters in
|
||||||
|
// the given range
|
||||||
virtual void DrawTextLine(wxDC& dc,
|
virtual void DrawTextLine(wxDC& dc,
|
||||||
const wxString& text,
|
const wxString& text,
|
||||||
const wxRect &rect,
|
const wxRect &rect,
|
||||||
|
int selStart = -1,
|
||||||
|
int selEnd = -1,
|
||||||
int flags = 0) = 0;
|
int flags = 0) = 0;
|
||||||
|
|
||||||
// draw the border and optionally return the rectangle containing the
|
// draw the border and optionally return the rectangle containing the
|
||||||
@@ -300,6 +303,8 @@ public:
|
|||||||
virtual void DrawTextLine(wxDC& dc,
|
virtual void DrawTextLine(wxDC& dc,
|
||||||
const wxString& text,
|
const wxString& text,
|
||||||
const wxRect &rect,
|
const wxRect &rect,
|
||||||
|
int selStart = -1,
|
||||||
|
int selEnd = -1,
|
||||||
int flags = 0)
|
int flags = 0)
|
||||||
{ m_renderer->DrawTextLine(dc, text, rect, flags); }
|
{ m_renderer->DrawTextLine(dc, text, rect, flags); }
|
||||||
virtual void DrawBorder(wxDC& dc,
|
virtual void DrawBorder(wxDC& dc,
|
||||||
@@ -423,7 +428,7 @@ public:
|
|||||||
// operations
|
// operations
|
||||||
void DrawLabel(const wxBitmap& bitmap = wxNullBitmap,
|
void DrawLabel(const wxBitmap& bitmap = wxNullBitmap,
|
||||||
wxCoord marginX = 0, wxCoord marginY = 0);
|
wxCoord marginX = 0, wxCoord marginY = 0);
|
||||||
void DrawTextLine(const wxString& text);
|
void DrawTextLine(const wxString& text, int selStart = -1, int selEnd = -1);
|
||||||
void DrawItems(const wxListBox *listbox,
|
void DrawItems(const wxListBox *listbox,
|
||||||
size_t itemFirst, size_t itemLast);
|
size_t itemFirst, size_t itemLast);
|
||||||
void DrawCheckItems(const wxCheckListBox *listbox,
|
void DrawCheckItems(const wxCheckListBox *listbox,
|
||||||
|
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
class WXDLLEXPORT wxCaret;
|
class WXDLLEXPORT wxCaret;
|
||||||
|
|
||||||
|
#include "wx/scrolwin.h" // for wxScrollHelper
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxTextCtrl actions
|
// wxTextCtrl actions
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -48,11 +50,15 @@ class WXDLLEXPORT wxCaret;
|
|||||||
#define wxACTION_TEXT_PREFIX_SEL _T("sel")
|
#define wxACTION_TEXT_PREFIX_SEL _T("sel")
|
||||||
#define wxACTION_TEXT_PREFIX_DEL _T("del")
|
#define wxACTION_TEXT_PREFIX_DEL _T("del")
|
||||||
|
|
||||||
|
// mouse selection
|
||||||
|
#define wxACTION_TEXT_ANCHOR_SEL _T("anchorsel")
|
||||||
|
#define wxACTION_TEXT_EXTEND_SEL _T("extendsel")
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxTextCtrl
|
// wxTextCtrl
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
class WXDLLEXPORT wxTextCtrl : public wxTextCtrlBase
|
class WXDLLEXPORT wxTextCtrl : public wxTextCtrlBase, public wxScrollHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// creation
|
// creation
|
||||||
@@ -155,6 +161,11 @@ public:
|
|||||||
long GetWordStart() const;
|
long GetWordStart() const;
|
||||||
long GetWordEnd() const;
|
long GetWordEnd() const;
|
||||||
|
|
||||||
|
// selection helpers
|
||||||
|
bool HasSelection() const { return m_selStart != -1; }
|
||||||
|
void ClearSelection();
|
||||||
|
void RemoveSelection();
|
||||||
|
|
||||||
// implementation only from now on
|
// implementation only from now on
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
|
|
||||||
@@ -162,6 +173,11 @@ public:
|
|||||||
virtual bool IsContainerWindow() const { return TRUE; }
|
virtual bool IsContainerWindow() const { return TRUE; }
|
||||||
virtual wxBorder GetDefaultBorder() const { return wxBORDER_SUNKEN; }
|
virtual wxBorder GetDefaultBorder() const { return wxBORDER_SUNKEN; }
|
||||||
|
|
||||||
|
// perform an action
|
||||||
|
virtual bool PerformAction(const wxControlAction& action,
|
||||||
|
long numArg = -1,
|
||||||
|
const wxString& strArg = wxEmptyString);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// draw the text
|
// draw the text
|
||||||
virtual void DoDraw(wxControlRenderer *renderer);
|
virtual void DoDraw(wxControlRenderer *renderer);
|
||||||
@@ -170,9 +186,6 @@ protected:
|
|||||||
virtual wxSize DoGetBestClientSize() const;
|
virtual wxSize DoGetBestClientSize() const;
|
||||||
|
|
||||||
// input support
|
// input support
|
||||||
virtual bool PerformAction(const wxControlAction& action,
|
|
||||||
long numArg = -1,
|
|
||||||
const wxString& strArg = wxEmptyString);
|
|
||||||
virtual wxString GetInputHandlerType() const;
|
virtual wxString GetInputHandlerType() const;
|
||||||
|
|
||||||
// common part of all ctors
|
// common part of all ctors
|
||||||
@@ -194,7 +207,8 @@ private:
|
|||||||
m_curRow;
|
m_curRow;
|
||||||
|
|
||||||
// selection
|
// selection
|
||||||
long m_selStart,
|
long m_selAnchor,
|
||||||
|
m_selStart,
|
||||||
m_selEnd;
|
m_selEnd;
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
|
@@ -407,7 +407,8 @@ void MyUnivFrame::OnListBox(wxCommandEvent& event)
|
|||||||
|
|
||||||
void MyUnivFrame::OnTextChange(wxCommandEvent& event)
|
void MyUnivFrame::OnTextChange(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
wxLogDebug(_T("Text control value changed: now '%s'"), event.GetString());
|
wxLogDebug(_T("Text control value changed: now '%s'"),
|
||||||
|
event.GetString().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyUnivFrame::OnLeftUp(wxMouseEvent& event)
|
void MyUnivFrame::OnLeftUp(wxMouseEvent& event)
|
||||||
|
@@ -42,7 +42,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include "wx/wx.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "wx/image.h"
|
#include "wx/image.h"
|
||||||
|
@@ -630,10 +630,12 @@ void wxControlRenderer::DoDrawItems(const wxListBox *lbox,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxControlRenderer::DrawTextLine(const wxString& text)
|
void wxControlRenderer::DrawTextLine(const wxString& text,
|
||||||
|
int selStart, int selEnd)
|
||||||
{
|
{
|
||||||
m_dc.SetFont(m_window->GetFont());
|
m_dc.SetFont(m_window->GetFont());
|
||||||
m_dc.SetTextForeground(m_window->GetForegroundColour());
|
m_dc.SetTextForeground(m_window->GetForegroundColour());
|
||||||
|
|
||||||
m_renderer->DrawTextLine(m_dc, text, m_rect, m_window->GetStateFlags());
|
m_renderer->DrawTextLine(m_dc, text, m_rect, selStart, selEnd,
|
||||||
|
m_window->GetStateFlags());
|
||||||
}
|
}
|
||||||
|
@@ -57,6 +57,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
|
|||||||
|
|
||||||
void wxTextCtrl::Init()
|
void wxTextCtrl::Init()
|
||||||
{
|
{
|
||||||
|
m_selAnchor =
|
||||||
m_selStart =
|
m_selStart =
|
||||||
m_selEnd = -1;
|
m_selEnd = -1;
|
||||||
|
|
||||||
@@ -103,18 +104,7 @@ void wxTextCtrl::SetValue(const wxString& value)
|
|||||||
if ( m_value == value )
|
if ( m_value == value )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_value = value;
|
Replace(0, GetLastPosition(), value);
|
||||||
|
|
||||||
if ( IsSingleLine() )
|
|
||||||
{
|
|
||||||
SetInsertionPointEnd();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetInsertionPoint(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxString wxTextCtrl::GetValue() const
|
wxString wxTextCtrl::GetValue() const
|
||||||
@@ -129,7 +119,7 @@ void wxTextCtrl::Clear()
|
|||||||
|
|
||||||
void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
||||||
{
|
{
|
||||||
wxCHECK_RET( from >= 0 && to >= 0 && from <= to,
|
wxCHECK_RET( from >= 0 && to >= 0 && from <= to && to <= GetLastPosition(),
|
||||||
_T("invalid range in wxTextCtrl::Replace") );
|
_T("invalid range in wxTextCtrl::Replace") );
|
||||||
|
|
||||||
// replace the part of the text with the new value
|
// replace the part of the text with the new value
|
||||||
@@ -141,9 +131,13 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
|||||||
}
|
}
|
||||||
m_value = valueNew;
|
m_value = valueNew;
|
||||||
|
|
||||||
// update current position
|
// update the current position
|
||||||
SetInsertionPoint(from + text.length());
|
SetInsertionPoint(from + text.length());
|
||||||
|
|
||||||
|
// and the selection (do it after setting the cursor to have correct value
|
||||||
|
// for selection anchor)
|
||||||
|
ClearSelection();
|
||||||
|
|
||||||
// FIXME shouldn't refresh everything of course
|
// FIXME shouldn't refresh everything of course
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
@@ -240,13 +234,49 @@ void wxTextCtrl::GetSelection(long* from, long* to) const
|
|||||||
|
|
||||||
void wxTextCtrl::SetSelection(long from, long to)
|
void wxTextCtrl::SetSelection(long from, long to)
|
||||||
{
|
{
|
||||||
if ( from != m_selStart || to != m_selEnd )
|
if ( from == -1 || to == -1 )
|
||||||
{
|
{
|
||||||
m_selStart = from;
|
ClearSelection();
|
||||||
m_selEnd = to;
|
|
||||||
|
|
||||||
// TODO: update display
|
|
||||||
}
|
}
|
||||||
|
else // valid sel range
|
||||||
|
{
|
||||||
|
if ( from >= to )
|
||||||
|
{
|
||||||
|
long tmp = from;
|
||||||
|
from = to;
|
||||||
|
to = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_RET( to <= GetLastPosition(),
|
||||||
|
_T("invalid range in wxTextCtrl::SetSelection") );
|
||||||
|
|
||||||
|
if ( from != m_selStart || to != m_selEnd )
|
||||||
|
{
|
||||||
|
m_selStart = from;
|
||||||
|
m_selEnd = to;
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
//else: nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxTextCtrl::ClearSelection()
|
||||||
|
{
|
||||||
|
m_selStart =
|
||||||
|
m_selEnd = -1;
|
||||||
|
|
||||||
|
m_selAnchor = m_curPos;
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void wxTextCtrl::RemoveSelection()
|
||||||
|
{
|
||||||
|
if ( !HasSelection() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Remove(m_selStart, m_selEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -330,11 +360,11 @@ int wxTextCtrl::GetNumberOfLines() const
|
|||||||
|
|
||||||
long wxTextCtrl::XYToPosition(long x, long y) const
|
long wxTextCtrl::XYToPosition(long x, long y) const
|
||||||
{
|
{
|
||||||
|
// note that this method should accept any values of x and y and return -1
|
||||||
|
// if they are out of range
|
||||||
if ( IsSingleLine() )
|
if ( IsSingleLine() )
|
||||||
{
|
{
|
||||||
wxASSERT_MSG( y == 0, _T("invalid XYToPosition() parameter") );
|
return x > GetLastPosition() || y > 0 ? -1 : x;
|
||||||
|
|
||||||
return x;
|
|
||||||
}
|
}
|
||||||
else // multiline
|
else // multiline
|
||||||
{
|
{
|
||||||
@@ -517,7 +547,7 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
|
|||||||
if ( IsSingleLine() )
|
if ( IsSingleLine() )
|
||||||
{
|
{
|
||||||
// just redraw everything
|
// just redraw everything
|
||||||
renderer->DrawTextLine(m_value);
|
renderer->DrawTextLine(m_value, (int)m_selStart, (int)m_selEnd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -561,11 +591,16 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
|
|||||||
bool textChanged = FALSE;
|
bool textChanged = FALSE;
|
||||||
|
|
||||||
wxString action;
|
wxString action;
|
||||||
bool del = FALSE;
|
bool del = FALSE,
|
||||||
|
sel = FALSE;
|
||||||
if ( actionOrig.StartsWith(wxACTION_TEXT_PREFIX_DEL, &action) )
|
if ( actionOrig.StartsWith(wxACTION_TEXT_PREFIX_DEL, &action) )
|
||||||
{
|
{
|
||||||
del = TRUE;
|
del = TRUE;
|
||||||
}
|
}
|
||||||
|
else if ( actionOrig.StartsWith(wxACTION_TEXT_PREFIX_SEL, &action) )
|
||||||
|
{
|
||||||
|
sel = TRUE;
|
||||||
|
}
|
||||||
else // not selection nor delete action
|
else // not selection nor delete action
|
||||||
{
|
{
|
||||||
action = actionOrig;
|
action = actionOrig;
|
||||||
@@ -600,11 +635,22 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
|
|||||||
{
|
{
|
||||||
if ( !strArg.empty() )
|
if ( !strArg.empty() )
|
||||||
{
|
{
|
||||||
|
// replace the selection with the new text
|
||||||
|
RemoveSelection();
|
||||||
|
|
||||||
WriteText(strArg);
|
WriteText(strArg);
|
||||||
|
|
||||||
textChanged = TRUE;
|
textChanged = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( action == wxACTION_TEXT_ANCHOR_SEL )
|
||||||
|
{
|
||||||
|
newPos = numArg;
|
||||||
|
}
|
||||||
|
else if ( action == wxACTION_TEXT_EXTEND_SEL )
|
||||||
|
{
|
||||||
|
SetSelection(m_selAnchor, numArg);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return wxControl::PerformAction(action, numArg, strArg);
|
return wxControl::PerformAction(action, numArg, strArg);
|
||||||
@@ -622,18 +668,37 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
|
|||||||
|
|
||||||
if ( del )
|
if ( del )
|
||||||
{
|
{
|
||||||
// delete everything between current opsition and the new one
|
// if we have the selection, remove just it
|
||||||
if ( m_curPos != newPos )
|
if ( HasSelection() )
|
||||||
{
|
{
|
||||||
Remove(m_curPos, newPos);
|
RemoveSelection();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// otherwise delete everything between current position and
|
||||||
|
// the new one
|
||||||
|
if ( m_curPos != newPos )
|
||||||
|
{
|
||||||
|
Remove(m_curPos, newPos);
|
||||||
|
|
||||||
textChanged = TRUE;
|
textChanged = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // cursor movement command
|
||||||
{
|
{
|
||||||
// just go there
|
// just go there
|
||||||
SetInsertionPoint(newPos);
|
SetInsertionPoint(newPos);
|
||||||
|
|
||||||
|
if ( sel )
|
||||||
|
{
|
||||||
|
SetSelection(m_selAnchor, m_curPos);
|
||||||
|
}
|
||||||
|
else // simple movement
|
||||||
|
{
|
||||||
|
// clear the existing selection
|
||||||
|
ClearSelection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -673,6 +738,114 @@ void wxTextCtrl::OnChar(wxKeyEvent& event)
|
|||||||
wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand)
|
wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand)
|
||||||
: wxStdInputHandler(inphand)
|
: wxStdInputHandler(inphand)
|
||||||
{
|
{
|
||||||
|
m_winCapture = (wxTextCtrl *)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
long wxStdTextCtrlInputHandler::HitTest(const wxTextCtrl *text,
|
||||||
|
const wxPoint& pos)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
text->CalcUnscrolledPosition(pos.x, pos.y, &x, &y);
|
||||||
|
|
||||||
|
// row calculation is simple as we assume that all lines have the same
|
||||||
|
// height
|
||||||
|
int row = y / text->GetCharHeight();
|
||||||
|
int rowMax = text->GetNumberOfLines() - 1;
|
||||||
|
if ( row > rowMax )
|
||||||
|
{
|
||||||
|
// clicking below the text is the same as clicking on the last line
|
||||||
|
row = rowMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the line is empty, the column can only be the first one
|
||||||
|
wxString line = text->GetLineText(row);
|
||||||
|
int col;
|
||||||
|
wxClientDC dc(wxConstCast(text, wxTextCtrl));
|
||||||
|
dc.SetFont(text->GetFont());
|
||||||
|
|
||||||
|
wxCoord width;
|
||||||
|
dc.GetTextExtent(line, &width, NULL);
|
||||||
|
if ( x >= width )
|
||||||
|
{
|
||||||
|
// clicking beyond the end of line is equivalent to clicking at
|
||||||
|
// the end of it
|
||||||
|
col = line.length();
|
||||||
|
}
|
||||||
|
else // we're inside the line
|
||||||
|
{
|
||||||
|
// now calculate the column: first, approximate it with fixed-width
|
||||||
|
// value and then calculate the correct value iteratively: note that
|
||||||
|
// we use the first character of the line instead of (average)
|
||||||
|
// GetCharWidth(): it is common to have lines of dashes, for example,
|
||||||
|
// and this should give us much better approximation in such case
|
||||||
|
dc.GetTextExtent(line[0], &width, NULL);
|
||||||
|
col = x / width;
|
||||||
|
|
||||||
|
// matchDir is -1 if we must move left, +1 to move right and 0 when
|
||||||
|
// we're exactly on the character we need
|
||||||
|
int matchDir = 0;
|
||||||
|
for ( ;; )
|
||||||
|
{
|
||||||
|
// check that we didn't go beyond the line boundary
|
||||||
|
if ( col < 0 )
|
||||||
|
{
|
||||||
|
col = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( col > line.length() )
|
||||||
|
{
|
||||||
|
col = line.length();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxString strBefore(line, (size_t)col);
|
||||||
|
dc.GetTextExtent(strBefore, &width, NULL);
|
||||||
|
if ( width >= x )
|
||||||
|
{
|
||||||
|
if ( matchDir == 1 )
|
||||||
|
{
|
||||||
|
// we were going to the right and, finally, moved beyond
|
||||||
|
// the original position: so the current is the next after
|
||||||
|
// the correct one
|
||||||
|
col--;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( matchDir == 0 )
|
||||||
|
{
|
||||||
|
// we just started iterating, now we know that we should
|
||||||
|
// move to the left
|
||||||
|
matchDir = -1;
|
||||||
|
}
|
||||||
|
//else: we are still to the right of the target, continue
|
||||||
|
}
|
||||||
|
else // width < x
|
||||||
|
{
|
||||||
|
// same logic as above ...
|
||||||
|
if ( matchDir == -1 )
|
||||||
|
{
|
||||||
|
// ... except that we don't need to back track
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ( matchDir == 0 )
|
||||||
|
{
|
||||||
|
// go to the right
|
||||||
|
matchDir = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is not supposed to happen
|
||||||
|
wxASSERT_MSG( matchDir, _T("logic error in wxTextCtrl::HitTest") );
|
||||||
|
|
||||||
|
if ( matchDir == 1 )
|
||||||
|
col++;
|
||||||
|
else
|
||||||
|
col--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return text->XYToPosition(col, row);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
|
bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
|
||||||
@@ -720,9 +893,15 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
|
|||||||
case WXK_BACK:
|
case WXK_BACK:
|
||||||
action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
|
action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// something else
|
||||||
|
default:
|
||||||
|
// reset the action as it could be already set to one of the
|
||||||
|
// prefixes
|
||||||
|
action = wxACTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !!action )
|
if ( action != wxACTION_NONE )
|
||||||
{
|
{
|
||||||
control->PerformAction(action, -1, str);
|
control->PerformAction(action, -1, str);
|
||||||
|
|
||||||
@@ -735,12 +914,55 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
|
|||||||
bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
|
bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
|
||||||
const wxMouseEvent& event)
|
const wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
|
if ( event.LeftDown() )
|
||||||
|
{
|
||||||
|
wxASSERT_MSG( !m_winCapture, _T("left button going down twice?") );
|
||||||
|
|
||||||
|
wxTextCtrl *text = wxStaticCast(control, wxTextCtrl);
|
||||||
|
|
||||||
|
m_winCapture = text;
|
||||||
|
m_winCapture->CaptureMouse();
|
||||||
|
|
||||||
|
text->HideCaret();
|
||||||
|
|
||||||
|
long pos = HitTest(text, event.GetPosition());
|
||||||
|
if ( pos != -1 )
|
||||||
|
{
|
||||||
|
text->PerformAction(wxACTION_TEXT_ANCHOR_SEL, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( event.LeftDClick() )
|
||||||
|
{
|
||||||
|
// TODO: select the word the cursor is on
|
||||||
|
}
|
||||||
|
else if ( event.LeftUp() )
|
||||||
|
{
|
||||||
|
if ( m_winCapture )
|
||||||
|
{
|
||||||
|
m_winCapture->ShowCaret();
|
||||||
|
|
||||||
|
m_winCapture->ReleaseMouse();
|
||||||
|
m_winCapture = (wxTextCtrl *)NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return wxStdInputHandler::HandleMouse(control, event);
|
return wxStdInputHandler::HandleMouse(control, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxStdTextCtrlInputHandler::HandleMouseMove(wxControl *control,
|
bool wxStdTextCtrlInputHandler::HandleMouseMove(wxControl *control,
|
||||||
const wxMouseEvent& event)
|
const wxMouseEvent& event)
|
||||||
{
|
{
|
||||||
|
if ( m_winCapture )
|
||||||
|
{
|
||||||
|
// track it
|
||||||
|
wxTextCtrl *text = wxStaticCast(m_winCapture, wxTextCtrl);
|
||||||
|
long pos = HitTest(text, event.GetPosition());
|
||||||
|
if ( pos != -1 )
|
||||||
|
{
|
||||||
|
text->PerformAction(wxACTION_TEXT_EXTEND_SEL, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return wxStdInputHandler::HandleMouseMove(control, event);
|
return wxStdInputHandler::HandleMouseMove(control, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -75,6 +75,8 @@ public:
|
|||||||
virtual void DrawTextLine(wxDC& dc,
|
virtual void DrawTextLine(wxDC& dc,
|
||||||
const wxString& text,
|
const wxString& text,
|
||||||
const wxRect &rect,
|
const wxRect &rect,
|
||||||
|
int selStart = -1,
|
||||||
|
int selEnd = -1,
|
||||||
int flags = 0);
|
int flags = 0);
|
||||||
virtual void DrawBorder(wxDC& dc,
|
virtual void DrawBorder(wxDC& dc,
|
||||||
wxBorder border,
|
wxBorder border,
|
||||||
@@ -914,9 +916,54 @@ void wxGTKRenderer::DrawButtonLabel(wxDC& dc,
|
|||||||
void wxGTKRenderer::DrawTextLine(wxDC& dc,
|
void wxGTKRenderer::DrawTextLine(wxDC& dc,
|
||||||
const wxString& text,
|
const wxString& text,
|
||||||
const wxRect &rect,
|
const wxRect &rect,
|
||||||
|
int selStart,
|
||||||
|
int selEnd,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
dc.DrawText(text, rect.x, rect.y);
|
if ( selStart == -1 )
|
||||||
|
{
|
||||||
|
// just draw it as is
|
||||||
|
dc.DrawText(text, rect.x, rect.y);
|
||||||
|
}
|
||||||
|
else // we have selection
|
||||||
|
{
|
||||||
|
wxCoord width,
|
||||||
|
x = rect.x;
|
||||||
|
|
||||||
|
// draw the part before selection
|
||||||
|
wxString s(text, (size_t)selStart);
|
||||||
|
if ( !s.empty() )
|
||||||
|
{
|
||||||
|
dc.DrawText(s, x, rect.y);
|
||||||
|
|
||||||
|
dc.GetTextExtent(s, &width, NULL);
|
||||||
|
x += width;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the selection itself
|
||||||
|
s = wxString(text.c_str() + selStart, text.c_str() + selEnd);
|
||||||
|
if ( !s.empty() )
|
||||||
|
{
|
||||||
|
wxColour colFg = dc.GetTextForeground();
|
||||||
|
dc.SetTextForeground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT_TEXT));
|
||||||
|
dc.SetTextBackground(wxSCHEME_COLOUR(m_scheme, HIGHLIGHT));
|
||||||
|
dc.SetBackgroundMode(wxSOLID);
|
||||||
|
|
||||||
|
dc.DrawText(s, x, rect.y);
|
||||||
|
dc.GetTextExtent(s, &width, NULL);
|
||||||
|
x += width;
|
||||||
|
|
||||||
|
dc.SetBackgroundMode(wxTRANSPARENT);
|
||||||
|
dc.SetTextForeground(colFg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw the final part
|
||||||
|
s = text.c_str() + selEnd;
|
||||||
|
if ( !s.empty() )
|
||||||
|
{
|
||||||
|
dc.DrawText(s, x, rect.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxGTKRenderer::DrawItem(wxDC& dc,
|
void wxGTKRenderer::DrawItem(wxDC& dc,
|
||||||
|
@@ -92,6 +92,8 @@ public:
|
|||||||
virtual void DrawTextLine(wxDC& dc,
|
virtual void DrawTextLine(wxDC& dc,
|
||||||
const wxString& text,
|
const wxString& text,
|
||||||
const wxRect &rect,
|
const wxRect &rect,
|
||||||
|
int selStart = -1,
|
||||||
|
int selEnd = -1,
|
||||||
int flags = 0);
|
int flags = 0);
|
||||||
virtual void DrawBorder(wxDC& dc,
|
virtual void DrawBorder(wxDC& dc,
|
||||||
wxBorder border,
|
wxBorder border,
|
||||||
@@ -1394,6 +1396,8 @@ void wxWin32Renderer::DrawButtonLabel(wxDC& dc,
|
|||||||
void wxWin32Renderer::DrawTextLine(wxDC& dc,
|
void wxWin32Renderer::DrawTextLine(wxDC& dc,
|
||||||
const wxString& text,
|
const wxString& text,
|
||||||
const wxRect &rect,
|
const wxRect &rect,
|
||||||
|
int selStart,
|
||||||
|
int selEnd,
|
||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
dc.DrawText(text, rect.x + 2, rect.y + 1);
|
dc.DrawText(text, rect.x + 2, rect.y + 1);
|
||||||
|
Reference in New Issue
Block a user