1. wxNcPaintEvent for wxMSW

2. wxTextCtrl (single line) cursor movement/basic editing


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8382 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2000-09-17 04:03:07 +00:00
parent 8c1e69867c
commit c7a0b9e59e
17 changed files with 527 additions and 95 deletions

View File

@@ -46,6 +46,7 @@
// ============================================================================
BEGIN_EVENT_TABLE(wxTextCtrl, wxControl)
EVT_CHAR(OnChar)
END_EVENT_TABLE()
IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl)
@@ -80,7 +81,8 @@ bool wxTextCtrl::Create(wxWindow *parent,
return FALSE;
}
wxCaret *caret = new wxCaret(this, 1, GetCharHeight());
// FIXME use renderer
wxCaret *caret = new wxCaret(this, 2, GetCharHeight());
SetCaret(caret);
caret->Show();
@@ -98,6 +100,9 @@ bool wxTextCtrl::Create(wxWindow *parent,
void wxTextCtrl::SetValue(const wxString& value)
{
if ( m_value == value )
return;
m_value = value;
if ( IsSingleLine() )
@@ -108,6 +113,8 @@ void wxTextCtrl::SetValue(const wxString& value)
{
SetInsertionPoint(0);
}
Refresh();
}
wxString wxTextCtrl::GetValue() const
@@ -120,15 +127,38 @@ void wxTextCtrl::Clear()
SetValue(_T(""));
}
void wxTextCtrl::Replace(long from, long to, const wxString& value)
void wxTextCtrl::Replace(long from, long to, const wxString& text)
{
wxFAIL_MSG(_T("not implemented"));
wxCHECK_RET( from >= 0 && to >= 0 && from <= to,
_T("invalid range in wxTextCtrl::Replace") );
// replace the part of the text with the new value
wxString valueNew(m_value, (size_t)from);
valueNew += text;
if ( (unsigned long)to < m_value.length() )
{
valueNew += m_value.c_str() + (size_t)to;
}
m_value = valueNew;
// update current position
SetInsertionPoint(from + text.length());
// FIXME shouldn't refresh everything of course
Refresh();
}
void wxTextCtrl::Remove(long from, long to)
{
if ( from > to )
{
// Replace() only works with correctly ordered arguments, so exchange
// them
long tmp = from;
from = to;
to = tmp;
}
Replace(from, to, _T(""));
}
@@ -149,11 +179,27 @@ void wxTextCtrl::AppendText(const wxString& text)
void wxTextCtrl::SetInsertionPoint(long pos)
{
HideCaret();
wxCHECK_RET( pos >= 0 && pos <= GetLastPosition(),
_T("insertion poitn position out of range") );
m_curPos = pos;
if ( pos != m_curPos )
{
HideCaret();
ShowCaret();
m_curPos = pos;
if ( IsSingleLine() )
{
m_curLine = 0;
m_curRow = m_curPos;
}
else // multi line
{
wxFAIL_MSG(_T("unimplemented for multi line"));
}
ShowCaret();
}
}
void wxTextCtrl::SetInsertionPointEnd()
@@ -322,6 +368,82 @@ void wxTextCtrl::ShowPosition(long pos)
wxFAIL_MSG(_T("not implemented"));
}
// ----------------------------------------------------------------------------
// word stuff
// ----------------------------------------------------------------------------
/*
TODO: we could have (easy to do) vi-like options for word movement, i.e.
distinguish between inlusive/exclusive words and between words and
WORDS (in vim sense) and also, finally, make the set of characters
which make up a word configurable - currently we use the exclusive
WORDS only (coincidentally, this is what Windows edit control does)
For future references, here is what vim help says:
A word consists of a sequence of letters, digits and underscores, or
a sequence of other non-blank characters, separated with white space
(spaces, tabs, <EOL>). This can be changed with the 'iskeyword'
option.
A WORD consists of a sequence of non-blank characters, separated with
white space. An empty line is also considered to be a word and a
WORD.
*/
static inline bool IsWordChar(wxChar ch)
{
return !wxIsspace(ch);
}
long wxTextCtrl::GetWordStart() const
{
if ( m_curPos == -1 || m_curPos == 0 )
return 0;
// start at the previous position
const wxChar *p0 = m_value.c_str();
const wxChar *p = p0 + m_curPos - 1;
// find the end of the previous word
while ( (p > p0) && !IsWordChar(*p) )
p--;
// now find the beginning of this word
while ( (p > p0) && IsWordChar(*p) )
p--;
// we might have gone too far
if ( !IsWordChar(*p) )
p++;
return p - p0;
}
long wxTextCtrl::GetWordEnd() const
{
if ( m_curPos == -1 )
return 0;
// start at the current position
const wxChar *p0 = m_value.c_str();
const wxChar *p = p0 + m_curPos;
// find the start of the next word
while ( *p && !IsWordChar(*p) )
p++;
// now find the end of it
while ( *p && IsWordChar(*p) )
p++;
// and find the start of the next word
while ( *p && !IsWordChar(*p) )
p++;
return p - p0;
}
// ----------------------------------------------------------------------------
// clipboard stuff
// ----------------------------------------------------------------------------
@@ -381,6 +503,7 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
h = hChar;
w += 2*wChar;
h += hChar / 2;
return wxSize(w, h);
}
@@ -394,7 +517,7 @@ void wxTextCtrl::DoDraw(wxControlRenderer *renderer)
if ( IsSingleLine() )
{
// just redraw everything
renderer->GetDC().DrawText(m_value, 0, 0);
renderer->DrawTextLine(m_value);
}
else
{
@@ -416,7 +539,8 @@ void wxTextCtrl::ShowCaret(bool show)
wxCoord x;
GetTextExtent(textBeforeCaret, &x, NULL);
caret->Move(x + 1, 0);
// FIXME: use renderer
caret->Move(x + 3, 3);
}
}
}
@@ -430,11 +554,194 @@ wxString wxTextCtrl::GetInputHandlerType() const
return wxINP_HANDLER_TEXTCTRL;
}
bool wxTextCtrl::PerformAction(const wxControlAction& action,
bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
long numArg,
const wxString& strArg)
{
return wxControl::PerformAction(action, numArg, strArg);
bool textChanged = FALSE;
wxString action;
bool del = FALSE;
if ( actionOrig.StartsWith(wxACTION_TEXT_PREFIX_DEL, &action) )
{
del = TRUE;
}
else // not selection nor delete action
{
action = actionOrig;
}
long newPos = -1;
if ( action == wxACTION_TEXT_HOME )
{
newPos = m_curPos - m_curRow;
}
else if ( action == wxACTION_TEXT_END )
{
newPos = m_curPos + GetLineLength(m_curLine) - m_curRow;
}
else if ( action == wxACTION_TEXT_LEFT )
{
newPos = m_curPos - 1;
}
else if ( action == wxACTION_TEXT_WORD_LEFT )
{
newPos = GetWordStart();
}
else if ( action == wxACTION_TEXT_RIGHT )
{
newPos = m_curPos + 1;
}
else if ( action == wxACTION_TEXT_WORD_RIGHT )
{
newPos = GetWordEnd();
}
else if ( action == wxACTION_TEXT_INSERT )
{
if ( !strArg.empty() )
{
WriteText(strArg);
textChanged = TRUE;
}
}
else
{
return wxControl::PerformAction(action, numArg, strArg);
}
if ( newPos != -1 )
{
// bring the new position into the range
if ( newPos < 0 )
newPos = 0;
long posLast = GetLastPosition();
if ( newPos > posLast )
newPos = posLast;
if ( del )
{
// delete everything between current opsition and the new one
if ( m_curPos != newPos )
{
Remove(m_curPos, newPos);
textChanged = TRUE;
}
}
else
{
// just go there
SetInsertionPoint(newPos);
}
}
if ( textChanged )
{
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
InitCommandEvent(event);
event.SetString(GetValue());
GetEventHandler()->ProcessEvent(event);
}
return TRUE;
}
void wxTextCtrl::OnChar(wxKeyEvent& event)
{
// only process the key events from "simple keys" here
if ( !event.HasModifiers() )
{
int keycode = event.GetKeyCode();
if ( keycode != WXK_DELETE && keycode != WXK_BACK )
{
PerformAction(wxACTION_TEXT_INSERT, -1, (wxChar)keycode);
// skip event.Skip() below
return;
}
}
event.Skip();
}
// ----------------------------------------------------------------------------
// wxStdTextCtrlInputHandler
// ----------------------------------------------------------------------------
wxStdTextCtrlInputHandler::wxStdTextCtrlInputHandler(wxInputHandler *inphand)
: wxStdInputHandler(inphand)
{
}
bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
const wxKeyEvent& event,
bool pressed)
{
if ( !pressed )
return FALSE;
wxControlAction action;
wxString str;
bool ctrlDown = event.ControlDown();
if ( event.ShiftDown() )
{
action = wxACTION_TEXT_PREFIX_SEL;
}
int keycode = event.GetKeyCode();
switch ( keycode )
{
// cursor movement
case WXK_HOME:
action << wxACTION_TEXT_HOME;
break;
case WXK_END:
action << wxACTION_TEXT_END;
break;
case WXK_LEFT:
action << (ctrlDown ? wxACTION_TEXT_WORD_LEFT
: wxACTION_TEXT_LEFT);
break;
case WXK_RIGHT:
action << (ctrlDown ? wxACTION_TEXT_WORD_RIGHT
: wxACTION_TEXT_RIGHT);
break;
// delete
case WXK_DELETE:
action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_RIGHT;
break;
case WXK_BACK:
action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT;
break;
}
if ( !!action )
{
control->PerformAction(action, -1, str);
return TRUE;
}
return wxStdInputHandler::HandleKey(control, event, pressed);
}
bool wxStdTextCtrlInputHandler::HandleMouse(wxControl *control,
const wxMouseEvent& event)
{
return wxStdInputHandler::HandleMouse(control, event);
}
bool wxStdTextCtrlInputHandler::HandleMouseMove(wxControl *control,
const wxMouseEvent& event)
{
return wxStdInputHandler::HandleMouseMove(control, event);
}
#endif // wxUSE_TEXTCTRL