textctrl.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 2,131 行 · 第 1/5 页
CPP
2,131 行
// position didn't actually change!)
MData().m_xCaret = -1;
}
ClearSelection();
}
void wxTextCtrl::InitInsertionPoint()
{
// so far always put it in the beginning
DoSetInsertionPoint(0);
// this will also set the selection anchor correctly
ClearSelection();
}
void wxTextCtrl::MoveInsertionPoint(wxTextPos pos)
{
wxASSERT_MSG( pos >= 0 && pos <= GetLastPosition(),
_T("DoSetInsertionPoint() can only be called with valid pos") );
m_curPos = pos;
PositionToXY(m_curPos, &m_curCol, &m_curRow);
}
void wxTextCtrl::DoSetInsertionPoint(wxTextPos pos)
{
MoveInsertionPoint(pos);
ShowPosition(pos);
}
void wxTextCtrl::SetInsertionPointEnd()
{
SetInsertionPoint(GetLastPosition());
}
wxTextPos wxTextCtrl::GetInsertionPoint() const
{
return m_curPos;
}
wxTextPos wxTextCtrl::GetLastPosition() const
{
wxTextPos pos;
if ( IsSingleLine() )
{
pos = m_value.length();
}
else // multiline
{
#ifdef WXDEBUG_TEXT
pos = 0;
size_t nLineCount = GetLineCount();
for ( size_t nLine = 0; nLine < nLineCount; nLine++ )
{
// +1 is because the positions at the end of this line and of the
// start of the next one are different
pos += GetLines()[nLine].length() + 1;
}
if ( pos > 0 )
{
// the last position is at the end of the last line, not in the
// beginning of the next line after it
pos--;
}
// more probable reason of this would be to forget to update m_posLast
wxASSERT_MSG( pos == m_posLast, _T("bug in GetLastPosition()") );
#endif // WXDEBUG_TEXT
pos = m_posLast;
}
return pos;
}
// ----------------------------------------------------------------------------
// selection
// ----------------------------------------------------------------------------
void wxTextCtrl::GetSelection(wxTextPos* from, wxTextPos* to) const
{
if ( from )
*from = m_selStart;
if ( to )
*to = m_selEnd;
}
wxString wxTextCtrl::GetSelectionText() const
{
wxString sel;
if ( HasSelection() )
{
if ( IsSingleLine() )
{
sel = m_value.Mid(m_selStart, m_selEnd - m_selStart);
}
else // multiline
{
wxTextCoord colStart, lineStart,
colEnd, lineEnd;
PositionToXY(m_selStart, &colStart, &lineStart);
PositionToXY(m_selEnd, &colEnd, &lineEnd);
// as always, we need to check for the special case when the start
// and end line are the same
if ( lineEnd == lineStart )
{
sel = GetLines()[lineStart].Mid(colStart, colEnd - colStart);
}
else // sel on multiple lines
{
// take the end of the first line
sel = GetLines()[lineStart].c_str() + colStart;
sel += _T('\n');
// all intermediate ones
for ( wxTextCoord line = lineStart + 1; line < lineEnd; line++ )
{
sel << GetLines()[line] << _T('\n');
}
// and the start of the last one
sel += GetLines()[lineEnd].Left(colEnd);
}
}
}
return sel;
}
void wxTextCtrl::SetSelection(wxTextPos from, wxTextPos to)
{
// selecting till -1 is the same as selecting to the end
if ( to == -1 && from != -1 )
{
to = GetLastPosition();
}
if ( from == -1 || to == from )
{
ClearSelection();
}
else // valid sel range
{
// remember the 'to' position as the current position, used to move the
// caret there later
wxTextPos toOrig = to;
OrderPositions(from, to);
wxCHECK_RET( to <= GetLastPosition(),
_T("invalid range in wxTextCtrl::SetSelection") );
if ( from != m_selStart || to != m_selEnd )
{
// we need to use temp vars as RefreshTextRange() may call DoDraw()
// directly and so m_selStart/End must be reset by then
wxTextPos selStartOld = m_selStart,
selEndOld = m_selEnd;
m_selStart = from;
m_selEnd = to;
wxLogTrace(_T("text"), _T("Selection range is %ld-%ld"),
m_selStart, m_selEnd);
// refresh only the part of text which became (un)selected if
// possible
if ( selStartOld == m_selStart )
{
RefreshTextRange(selEndOld, m_selEnd);
}
else if ( selEndOld == m_selEnd )
{
RefreshTextRange(m_selStart, selStartOld);
}
else
{
// OPT: could check for other cases too but it is probably not
// worth it as the two above are the most common ones
if ( selStartOld != -1 )
RefreshTextRange(selStartOld, selEndOld);
if ( m_selStart != -1 )
RefreshTextRange(m_selStart, m_selEnd);
}
// we need to fully repaint the invalidated areas of the window
// before scrolling it (from DoSetInsertionPoint which is typically
// called after SetSelection()), otherwise they may stay unpainted
m_targetWindow->Update();
}
//else: nothing to do
// the insertion point is put at the location where the caret was moved
DoSetInsertionPoint(toOrig);
}
}
void wxTextCtrl::ClearSelection()
{
if ( HasSelection() )
{
// we need to use temp vars as RefreshTextRange() may call DoDraw()
// directly (see above as well)
wxTextPos selStart = m_selStart,
selEnd = m_selEnd;
// no selection any more
m_selStart =
m_selEnd = -1;
// refresh the old selection
RefreshTextRange(selStart, selEnd);
}
// the anchor should be moved even if there was no selection previously
m_selAnchor = m_curPos;
}
void wxTextCtrl::RemoveSelection()
{
if ( !HasSelection() )
return;
Remove(m_selStart, m_selEnd);
}
bool wxTextCtrl::GetSelectedPartOfLine(wxTextCoord line,
wxTextPos *start, wxTextPos *end) const
{
if ( start )
*start = -1;
if ( end )
*end = -1;
if ( !HasSelection() )
{
// no selection at all, hence no selection in this line
return false;
}
wxTextCoord lineStart, colStart;
PositionToXY(m_selStart, &colStart, &lineStart);
if ( lineStart > line )
{
// this line is entirely above the selection
return false;
}
wxTextCoord lineEnd, colEnd;
PositionToXY(m_selEnd, &colEnd, &lineEnd);
if ( lineEnd < line )
{
// this line is entirely below the selection
return false;
}
if ( line == lineStart )
{
if ( start )
*start = colStart;
if ( end )
*end = lineEnd == lineStart ? colEnd : GetLineLength(line);
}
else if ( line == lineEnd )
{
if ( start )
*start = lineEnd == lineStart ? colStart : 0;
if ( end )
*end = colEnd;
}
else // the line is entirely inside the selection
{
if ( start )
*start = 0;
if ( end )
*end = GetLineLength(line);
}
return true;
}
// ----------------------------------------------------------------------------
// flags
// ----------------------------------------------------------------------------
bool wxTextCtrl::IsModified() const
{
return m_isModified;
}
bool wxTextCtrl::IsEditable() const
{
// disabled control can never be edited
return m_isEditable && IsEnabled();
}
void wxTextCtrl::MarkDirty()
{
m_isModified = true;
}
void wxTextCtrl::DiscardEdits()
{
m_isModified = false;
}
void wxTextCtrl::SetEditable(bool editable)
{
if ( editable != m_isEditable )
{
m_isEditable = editable;
// the caret (dis)appears
CreateCaret();
// the appearance of the control might have changed
Refresh();
}
}
// ----------------------------------------------------------------------------
// col/lines <-> position correspondence
// ----------------------------------------------------------------------------
/*
A few remarks about this stuff:
o The numbering of the text control columns/rows starts from 0.
o Start of first line is position 0, its last position is line.length()
o Start of the next line is the last position of the previous line + 1
*/
int wxTextCtrl::GetLineLength(wxTextCoord line) const
{
if ( IsSingleLine() )
{
wxASSERT_MSG( line == 0, _T("invalid GetLineLength() parameter") );
return m_value.length();
}
else // multiline
{
wxCHECK_MSG( (size_t)line < GetLineCount(), -1,
_T("line index out of range") );
return GetLines()[line].length();
}
}
wxString wxTextCtrl::GetLineText(wxTextCoord line) const
{
if ( IsSingleLine() )
{
wxASSERT_MSG( line == 0, _T("invalid GetLineLength() parameter") );
return m_value;
}
else // multiline
{
//this is called during DoGetBestSize
if (line == 0 && GetLineCount() == 0) return wxEmptyString ;
wxCHECK_MSG( (size_t)line < GetLineCount(), wxEmptyString,
_T("line index out of range") );
return GetLines()[line];
}
}
int wxTextCtrl::GetNumberOfLines() const
{
// there is always 1 line, even if the text is empty
return IsSingleLine() ? 1 : GetLineCount();
}
wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord 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() )
{
return ( x > GetLastPosition() || y > 0 ) ? wxOutOfRangeTextCoord : x;
}
else // multiline
{
if ( (size_t)y >= GetLineCount() )
{
// this position is below the text
return GetLastPosition();
}
wxTextPos pos = 0;
for ( size_t nLine = 0; nLine < (size_t)y; nLine++ )
{
// +1 is because the positions at the end of this line and of the
// start of the next one are different
pos += GetLines()[nLine].length() + 1;
}
// take into account also the position in line
if ( (size_t)x > GetLines()[y].length() )
{
// don't return position in the next line
x = GetLines()[y].length();
}
return pos + x;
}
}
bool wxTextCtrl::PositionToXY(wxTextPos pos,
wxTextCoord *x, wxTextCoord *y) const
{
if ( IsSingleLine() )
{
if ( (size_t)pos > m_value.length() )
return false;
if ( x )
*x = pos;
if ( y )
*y = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?