basic drawing and cursor movement seem to work in multiline textctrl
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8559 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
6
TODO
6
TODO
@@ -6,7 +6,6 @@ wxTextCtrl
|
|||||||
|
|
||||||
* display corrupted when typing text in quickly
|
* display corrupted when typing text in quickly
|
||||||
* text ctrl display pb when text is truncated
|
* text ctrl display pb when text is truncated
|
||||||
* listbox: horz scrollbar doesn't appear
|
|
||||||
|
|
||||||
All
|
All
|
||||||
|
|
||||||
@@ -22,6 +21,8 @@ All
|
|||||||
|
|
||||||
MSW
|
MSW
|
||||||
|
|
||||||
|
wxTextCtrl caret is not shown until *next* refresh
|
||||||
|
|
||||||
GTK
|
GTK
|
||||||
|
|
||||||
* listbox scrolling leaves unpainted areas
|
* listbox scrolling leaves unpainted areas
|
||||||
@@ -35,7 +36,8 @@ DONE
|
|||||||
All
|
All
|
||||||
|
|
||||||
+ text ctrl horz scrolling
|
+ text ctrl horz scrolling
|
||||||
+ DoDraw should iterat over update region instead of using bounding box
|
+ DoDraw should iterate over update region instead of using bounding box
|
||||||
|
+ listbox: horz scrollbar doesn't appear
|
||||||
|
|
||||||
MSW
|
MSW
|
||||||
|
|
||||||
|
@@ -326,7 +326,7 @@ private:
|
|||||||
|
|
||||||
// current position
|
// current position
|
||||||
long m_curPos,
|
long m_curPos,
|
||||||
m_curLine,
|
m_curCol,
|
||||||
m_curRow;
|
m_curRow;
|
||||||
|
|
||||||
// selection
|
// selection
|
||||||
|
@@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
#include "wx/univ/theme.h"
|
#include "wx/univ/theme.h"
|
||||||
|
|
||||||
//#define TEST_TEXT_ONLY
|
#define TEST_TEXT_ONLY
|
||||||
|
|
||||||
//#define DEBUG_SCROLL
|
//#define DEBUG_SCROLL
|
||||||
//#define DEBUG_LISTBOX
|
//#define DEBUG_LISTBOX
|
||||||
@@ -233,14 +233,14 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
|
|||||||
#ifndef TEST_TEXT_ONLY
|
#ifndef TEST_TEXT_ONLY
|
||||||
wxSize(700, 700)
|
wxSize(700, 700)
|
||||||
#else
|
#else
|
||||||
wxSize(240, 200)
|
wxSize(240, 300)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
SetBackgroundColour(wxGetApp().GetBgColour());
|
SetBackgroundColour(wxGetApp().GetBgColour());
|
||||||
|
|
||||||
new wxStaticText(this, _T("Test static text"), wxPoint(10, 10));
|
|
||||||
#ifndef TEST_TEXT_ONLY
|
#ifndef TEST_TEXT_ONLY
|
||||||
|
new wxStaticText(this, _T("Test static text"), wxPoint(10, 10));
|
||||||
new wxStaticText(this,
|
new wxStaticText(this,
|
||||||
_T("&Multi line\n(and very very very very long)\nstatic text"),
|
_T("&Multi line\n(and very very very very long)\nstatic text"),
|
||||||
wxPoint(210, 10));
|
wxPoint(210, 10));
|
||||||
@@ -383,6 +383,7 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
|
|||||||
new wxTextCtrl(this, -1, _T("Hello, Universe!"),
|
new wxTextCtrl(this, -1, _T("Hello, Universe!"),
|
||||||
wxPoint(550, 150), wxDefaultSize);
|
wxPoint(550, 150), wxDefaultSize);
|
||||||
#else // TEST_TEXT_ONLY
|
#else // TEST_TEXT_ONLY
|
||||||
|
#if 0
|
||||||
wxTextCtrl *text = new wxTextCtrl(this, -1, _T("Hello, Universe!"),
|
wxTextCtrl *text = new wxTextCtrl(this, -1, _T("Hello, Universe!"),
|
||||||
wxPoint(10, 40));
|
wxPoint(10, 40));
|
||||||
text->SetFont(wxFont(24, wxFONTFAMILY_DEFAULT,
|
text->SetFont(wxFont(24, wxFONTFAMILY_DEFAULT,
|
||||||
@@ -390,6 +391,12 @@ MyUnivFrame::MyUnivFrame(const wxString& title)
|
|||||||
wxSize sizeText = text->GetBestSize();
|
wxSize sizeText = text->GetBestSize();
|
||||||
sizeText.x = 200;
|
sizeText.x = 200;
|
||||||
text->SetSize(sizeText);
|
text->SetSize(sizeText);
|
||||||
|
#else
|
||||||
|
wxTextCtrl *
|
||||||
|
#endif
|
||||||
|
text = new wxTextCtrl(this, -1, _T("Hello,\nMultiverse!"),
|
||||||
|
wxPoint(10, 10), wxDefaultSize,
|
||||||
|
wxTE_MULTILINE);
|
||||||
#endif // !TEST_TEXT_ONLY/TEST_TEXT_ONLY
|
#endif // !TEST_TEXT_ONLY/TEST_TEXT_ONLY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -206,10 +206,10 @@ wxArrayString wxStringTokenize(const wxString& str,
|
|||||||
wxStringTokenizerMode mode)
|
wxStringTokenizerMode mode)
|
||||||
{
|
{
|
||||||
wxArrayString tokens;
|
wxArrayString tokens;
|
||||||
wxStringTokenizer tk(str, delimes, mode);
|
wxStringTokenizer tk(str, delims, mode);
|
||||||
while ( tk.HasMoreTokens() )
|
while ( tk.HasMoreTokens() )
|
||||||
{
|
{
|
||||||
tokens.Add(GetNextToken());
|
tokens.Add(tk.GetNextToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
return tokens;
|
return tokens;
|
||||||
|
@@ -39,9 +39,9 @@
|
|||||||
#include "wx/dcclient.h"
|
#include "wx/dcclient.h"
|
||||||
#include "wx/validate.h"
|
#include "wx/validate.h"
|
||||||
#include "wx/textctrl.h"
|
#include "wx/textctrl.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "wx/tokenzr.h"
|
#include "wx/tokenzr.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "wx/clipbrd.h"
|
#include "wx/clipbrd.h"
|
||||||
|
|
||||||
@@ -55,6 +55,9 @@
|
|||||||
// turn extra wxTextCtrl-specific debugging on/off
|
// turn extra wxTextCtrl-specific debugging on/off
|
||||||
#define WXDEBUG_TEXT
|
#define WXDEBUG_TEXT
|
||||||
|
|
||||||
|
// turn wxTextCtrl::Replace() debugging on (very inefficient!)
|
||||||
|
#define WXDEBUG_TEXT_REPLACE
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// private functions
|
// private functions
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -100,8 +103,8 @@ void wxTextCtrl::Init()
|
|||||||
m_posLastVisible = -1;
|
m_posLastVisible = -1;
|
||||||
|
|
||||||
m_curPos =
|
m_curPos =
|
||||||
m_curRow =
|
m_curCol =
|
||||||
m_curLine = 0;
|
m_curRow = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxTextCtrl::Create(wxWindow *parent,
|
bool wxTextCtrl::Create(wxWindow *parent,
|
||||||
@@ -121,6 +124,12 @@ bool wxTextCtrl::Create(wxWindow *parent,
|
|||||||
|
|
||||||
SetCursor(wxCURSOR_IBEAM);
|
SetCursor(wxCURSOR_IBEAM);
|
||||||
|
|
||||||
|
// we should always have at least one line in a multiline control
|
||||||
|
if ( style & wxTE_MULTILINE )
|
||||||
|
{
|
||||||
|
m_lines.Add(wxEmptyString);
|
||||||
|
}
|
||||||
|
|
||||||
SetValue(value);
|
SetValue(value);
|
||||||
SetBestSize(size);
|
SetBestSize(size);
|
||||||
|
|
||||||
@@ -178,7 +187,7 @@ wxString wxTextCtrl::GetValue() const
|
|||||||
for ( size_t n = 0; n < count; n++ )
|
for ( size_t n = 0; n < count; n++ )
|
||||||
{
|
{
|
||||||
if ( n )
|
if ( n )
|
||||||
value += _T('\n');
|
value += _T('\n'); // from preceding line
|
||||||
|
|
||||||
value += m_lines[n];
|
value += m_lines[n];
|
||||||
}
|
}
|
||||||
@@ -193,11 +202,28 @@ void wxTextCtrl::Clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Replace() works line by line: in the range [from, to] we have the starting
|
The algorithm of Replace():
|
||||||
line in which we replace the text in [from, last one ? to : end of line],
|
|
||||||
the last one (which may be the same as the first one) and some number
|
1. change the line where replacement starts
|
||||||
(possibly 0) of intermediate ones).
|
a) keep the text in the beginning of it unchanged
|
||||||
|
b) replace the middle (if lineEnd == lineStart) or everything to the
|
||||||
|
end with the first line of replacement text
|
||||||
|
|
||||||
|
2. delete all lines between lineStart and lineEnd (excluding)
|
||||||
|
|
||||||
|
3. insert the lines of the replacement text
|
||||||
|
|
||||||
|
4. change the line where replacement ends:
|
||||||
|
a) remove the part which is in replacement range
|
||||||
|
b) insert the last line of replacement text
|
||||||
|
c) insert the end of the first line if lineEnd == lineStart
|
||||||
|
d) keep the end unchanged
|
||||||
|
|
||||||
|
In the code below the steps 2 and 3 are merged and are done in parallel for
|
||||||
|
efficiency reasons (it is better to change lines in place rather than
|
||||||
|
remove/insert them from a potentially huge array)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
||||||
{
|
{
|
||||||
long colStart, colEnd,
|
long colStart, colEnd,
|
||||||
@@ -212,14 +238,25 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WXDEBUG_TEXT_REPLACE
|
||||||
|
// a straighforward (but very inefficient) way of calculating what the new
|
||||||
|
// value should be
|
||||||
|
wxString textTotal = GetValue();
|
||||||
|
wxString textTotalNew(textTotal, (size_t)from);
|
||||||
|
textTotalNew += text;
|
||||||
|
if ( (size_t)to < textTotal.length() )
|
||||||
|
textTotalNew += textTotal.c_str() + (size_t)to;
|
||||||
|
#endif // WXDEBUG_TEXT_REPLACE
|
||||||
|
|
||||||
// break the replacement text into lines
|
// break the replacement text into lines
|
||||||
wxArrayString lines = wxStringTokenize(text, _T("\n"),
|
wxArrayString lines = wxStringTokenize(text, _T("\n"),
|
||||||
wxTOKEN_RET_EMPTY_ALL);
|
wxTOKEN_RET_EMPTY_ALL);
|
||||||
|
size_t nReplaceCount = lines.GetCount();
|
||||||
|
|
||||||
// first deal with the starting line: (1) take the part before the text
|
// first deal with the starting line: (1) take the part before the text
|
||||||
// being replaced
|
// being replaced
|
||||||
wxString lineFirstOrig = GetLineText(lineStart);
|
wxString lineFirstOrig = GetLineText(lineStart);
|
||||||
wxString lineFirst(lineFirstOrig, colStart);
|
wxString lineFirst(lineFirstOrig, (size_t)colStart);
|
||||||
|
|
||||||
// remember the start of the update region for later use
|
// remember the start of the update region for later use
|
||||||
wxCoord startNewText = GetTextWidth(lineFirst);
|
wxCoord startNewText = GetTextWidth(lineFirst);
|
||||||
@@ -231,11 +268,22 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (3) and add the text which is left if we replace text only in this line
|
// (3) and add the text which is left if we replace text only in this line
|
||||||
|
wxString lineFirstEnd;
|
||||||
if ( lineEnd == lineStart )
|
if ( lineEnd == lineStart )
|
||||||
{
|
{
|
||||||
wxASSERT_MSG((size_t)colEnd < lineFirstOrig.length(), _T("logic bug"));
|
wxASSERT_MSG((size_t)colEnd <= lineFirstOrig.length(), _T("logic bug"));
|
||||||
|
|
||||||
lineFirst += lineFirstOrig.c_str() + (size_t)colEnd;
|
lineFirstEnd = lineFirstOrig.c_str() + (size_t)colEnd;
|
||||||
|
|
||||||
|
if ( nReplaceCount == 1 )
|
||||||
|
{
|
||||||
|
// we keep everything on this line
|
||||||
|
lineFirst += lineFirstEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineEnd++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// (4) refresh the part of the line which changed
|
// (4) refresh the part of the line which changed
|
||||||
@@ -296,8 +344,7 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
|||||||
bool refreshAllBelow = FALSE;
|
bool refreshAllBelow = FALSE;
|
||||||
|
|
||||||
// (1) modify all lines which are really repaced
|
// (1) modify all lines which are really repaced
|
||||||
size_t nReplaceLine = 1,
|
size_t nReplaceLine = 1;
|
||||||
nReplaceCount = lines.GetCount();
|
|
||||||
for ( long line = lineStart + 1; line < lineEnd; line++ )
|
for ( long line = lineStart + 1; line < lineEnd; line++ )
|
||||||
{
|
{
|
||||||
if ( nReplaceLine < nReplaceCount )
|
if ( nReplaceLine < nReplaceCount )
|
||||||
@@ -343,40 +390,63 @@ void wxTextCtrl::Replace(long from, long to, const wxString& text)
|
|||||||
// lines that we had before, we can just refresh these lines,
|
// lines that we had before, we can just refresh these lines,
|
||||||
// otherwise the lines below will change as well, so we have to
|
// otherwise the lines below will change as well, so we have to
|
||||||
// refresh them too (by passing -1 as RefreshLineRange() argument)
|
// refresh them too (by passing -1 as RefreshLineRange() argument)
|
||||||
|
if ( refreshAllBelow || (lineStart < lineEnd - 1) )
|
||||||
|
{
|
||||||
RefreshLineRange(lineStart + 1, refreshAllBelow ? -1 : lineEnd - 1);
|
RefreshLineRange(lineStart + 1, refreshAllBelow ? -1 : lineEnd - 1);
|
||||||
|
}
|
||||||
|
|
||||||
// now deal with the last line: (1) replace its beginning with the end of
|
// now deal with the last line: (1) replace its beginning with the end of
|
||||||
// the replacement text
|
// the replacement text
|
||||||
wxString lineLast;
|
wxString lineLast;
|
||||||
if ( nReplaceLine < nReplaceCount )
|
if ( nReplaceLine < nReplaceCount )
|
||||||
{
|
{
|
||||||
wxASSERT_MSG(nReplaceCount == nReplaceCount - 1, _T("logic error"));
|
wxASSERT_MSG(nReplaceLine == nReplaceCount - 1, _T("logic error"));
|
||||||
|
|
||||||
lineLast = lines[nReplaceLine];
|
lineLast = lines[nReplaceLine];
|
||||||
}
|
}
|
||||||
|
|
||||||
// (2) add the tail of the old last line if anything is left
|
// (2) add the text which was at the end of first line if we replaced its
|
||||||
|
// middle with multiline text
|
||||||
|
if ( lineEnd == lineStart )
|
||||||
|
{
|
||||||
|
lineLast += lineFirstEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (3) add the tail of the old last line if anything is left
|
||||||
|
if ( (size_t)lineEnd < m_lines.GetCount() )
|
||||||
|
{
|
||||||
wxString lineLastOrig = GetLineText(lineEnd);
|
wxString lineLastOrig = GetLineText(lineEnd);
|
||||||
if ( (size_t)colEnd < lineLastOrig.length() )
|
if ( (size_t)colEnd < lineLastOrig.length() )
|
||||||
{
|
{
|
||||||
lineLast += lineLastOrig.c_str() + (size_t)colEnd;
|
lineLast += lineLastOrig.c_str() + (size_t)colEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// (3) always refresh the last line entirely if it hadn't been already
|
m_lines[lineEnd] = lineLast;
|
||||||
|
}
|
||||||
|
else // the number of lines increased, just append the new one
|
||||||
|
{
|
||||||
|
m_lines.Add(lineLast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (4) always refresh the last line entirely if it hadn't been already
|
||||||
// refreshed above
|
// refreshed above
|
||||||
if ( !refreshAllBelow )
|
if ( !refreshAllBelow )
|
||||||
{
|
{
|
||||||
RefreshPixelRange(lineEnd, 0, 0); // entire line
|
RefreshPixelRange(lineEnd, 0, 0); // entire line
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lines[lineEnd] = lineLast;
|
|
||||||
|
|
||||||
// update the current position
|
// update the current position
|
||||||
SetInsertionPoint(to);
|
SetInsertionPoint(to);
|
||||||
|
|
||||||
// and the selection (do it after setting the cursor to have correct value
|
// and the selection (do it after setting the cursor to have correct value
|
||||||
// for selection anchor)
|
// for selection anchor)
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
|
|
||||||
|
#ifdef WXDEBUG_TEXT_REPLACE
|
||||||
|
// optimized code above should give the same result as straightforward
|
||||||
|
// computation in the beginning
|
||||||
|
wxASSERT_MSG( GetValue() == textTotalNew, _T("error in Replace()") );
|
||||||
|
#endif // WXDEBUG_TEXT_REPLACE
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxTextCtrl::Remove(long from, long to)
|
void wxTextCtrl::Remove(long from, long to)
|
||||||
@@ -429,7 +499,7 @@ void wxTextCtrl::DoSetInsertionPoint(long pos)
|
|||||||
HideCaret();
|
HideCaret();
|
||||||
|
|
||||||
m_curPos = pos;
|
m_curPos = pos;
|
||||||
PositionToXY(m_curPos, &m_curRow, &m_curLine);
|
PositionToXY(m_curPos, &m_curCol, &m_curRow);
|
||||||
ShowPosition(m_curPos);
|
ShowPosition(m_curPos);
|
||||||
|
|
||||||
ShowCaret();
|
ShowCaret();
|
||||||
@@ -702,6 +772,14 @@ void wxTextCtrl::SetEditable(bool editable)
|
|||||||
// col/lines <-> position correspondence
|
// 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(long line) const
|
int wxTextCtrl::GetLineLength(long line) const
|
||||||
{
|
{
|
||||||
if ( IsSingleLine() )
|
if ( IsSingleLine() )
|
||||||
@@ -738,8 +816,7 @@ wxString wxTextCtrl::GetLineText(long line) const
|
|||||||
|
|
||||||
int wxTextCtrl::GetNumberOfLines() const
|
int wxTextCtrl::GetNumberOfLines() const
|
||||||
{
|
{
|
||||||
// for single line controls there is always 1 line, even if the text is
|
// there is always 1 line, even if the text is empty
|
||||||
// empty
|
|
||||||
return IsSingleLine() ? 1 : m_lines.GetCount();
|
return IsSingleLine() ? 1 : m_lines.GetCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -753,6 +830,12 @@ long wxTextCtrl::XYToPosition(long x, long y) const
|
|||||||
}
|
}
|
||||||
else // multiline
|
else // multiline
|
||||||
{
|
{
|
||||||
|
if ( (size_t)y >= m_lines.GetCount() )
|
||||||
|
{
|
||||||
|
// this position is below the text
|
||||||
|
return GetLastPosition();
|
||||||
|
}
|
||||||
|
|
||||||
long pos = 0;
|
long pos = 0;
|
||||||
for ( size_t nLine = 0; nLine < (size_t)y; nLine++ )
|
for ( size_t nLine = 0; nLine < (size_t)y; nLine++ )
|
||||||
{
|
{
|
||||||
@@ -761,14 +844,13 @@ long wxTextCtrl::XYToPosition(long x, long y) const
|
|||||||
pos += m_lines[nLine].length() + 1;
|
pos += m_lines[nLine].length() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pos > 0 )
|
// take into account also the position in line
|
||||||
|
if ( (size_t)x > m_lines[y].length() )
|
||||||
{
|
{
|
||||||
// the last position is at the end of the last line, not in the
|
// don't return position in the next line
|
||||||
// beginning of the next line after it
|
x = m_lines[y].length();
|
||||||
pos--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// take into account also the position in line
|
|
||||||
return pos + x;
|
return pos + x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -789,24 +871,32 @@ bool wxTextCtrl::PositionToXY(long pos, long *x, long *y) const
|
|||||||
}
|
}
|
||||||
else // multiline
|
else // multiline
|
||||||
{
|
{
|
||||||
|
long posCur = 0;
|
||||||
size_t nLineCount = m_lines.GetCount();
|
size_t nLineCount = m_lines.GetCount();
|
||||||
for ( size_t nLine = 0; nLine < nLineCount; nLine++ )
|
for ( size_t nLine = 0; nLine < nLineCount; nLine++ )
|
||||||
{
|
{
|
||||||
long posNew = pos - (m_lines[nLine].length() + 1);
|
// +1 is because the start the start of the next line is one
|
||||||
if ( posNew < 0 )
|
// position after the end of this one
|
||||||
|
long posNew = posCur + m_lines[nLine].length() + 1;
|
||||||
|
if ( posNew > pos )
|
||||||
{
|
{
|
||||||
// we've found the line, now just calc the column
|
// we've found the line, now just calc the column
|
||||||
if ( x )
|
if ( x )
|
||||||
*x = nLine;
|
*x = pos - posCur;
|
||||||
|
|
||||||
if ( y )
|
if ( y )
|
||||||
*y = pos;
|
*y = nLine;
|
||||||
|
|
||||||
|
#ifdef WXDEBUG_TEXT
|
||||||
|
wxASSERT_MSG( XYToPosition(pos - posCur, nLine) == pos,
|
||||||
|
_T("XYToPosition() or PositionToXY() broken") );
|
||||||
|
#endif // WXDEBUG_TEXT
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else // go further down
|
else // go further down
|
||||||
{
|
{
|
||||||
pos = posNew;
|
posCur = posNew;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -821,9 +911,9 @@ void wxTextCtrl::ShowPosition(long pos)
|
|||||||
{
|
{
|
||||||
ShowHorzPosition(GetCaretPosition(pos));
|
ShowHorzPosition(GetCaretPosition(pos));
|
||||||
}
|
}
|
||||||
else
|
else // multiline
|
||||||
{
|
{
|
||||||
wxFAIL_MSG(_T("not implemented for multiline"));
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,6 +1089,17 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
|
|||||||
if ( h < hChar )
|
if ( h < hChar )
|
||||||
h = hChar;
|
h = hChar;
|
||||||
|
|
||||||
|
if ( !IsSingleLine() )
|
||||||
|
{
|
||||||
|
// let the control have a reasonable number of lines
|
||||||
|
int lines = GetNumberOfLines();
|
||||||
|
if ( lines < 5 )
|
||||||
|
lines = 5;
|
||||||
|
else if ( lines > 10 )
|
||||||
|
lines = 10;
|
||||||
|
h *= 10;
|
||||||
|
}
|
||||||
|
|
||||||
wxRect rectText;
|
wxRect rectText;
|
||||||
rectText.width = w;
|
rectText.width = w;
|
||||||
rectText.height = h;
|
rectText.height = h;
|
||||||
@@ -1019,7 +1120,8 @@ void wxTextCtrl::UpdateLastVisible()
|
|||||||
{
|
{
|
||||||
// this method is only used for horizontal "scrollbarless" scrolling which
|
// this method is only used for horizontal "scrollbarless" scrolling which
|
||||||
// is used only with single line controls
|
// is used only with single line controls
|
||||||
wxASSERT_MSG( IsSingleLine(), _T("shouldn't be called for multiline") );
|
if ( !IsSingleLine() )
|
||||||
|
return;
|
||||||
|
|
||||||
// OPT: estimate the correct value first, just adjust it later
|
// OPT: estimate the correct value first, just adjust it later
|
||||||
|
|
||||||
@@ -1427,6 +1529,9 @@ void wxTextCtrl::DoPrepareDC(wxDC& dc)
|
|||||||
|
|
||||||
void wxTextCtrl::RefreshLineRange(long lineFirst, long lineLast)
|
void wxTextCtrl::RefreshLineRange(long lineFirst, long lineLast)
|
||||||
{
|
{
|
||||||
|
wxASSERT_MSG( (lineLast == -1) || (lineFirst <= lineLast),
|
||||||
|
_T("no lines to refresh") );
|
||||||
|
|
||||||
wxRect rect;
|
wxRect rect;
|
||||||
// rect.x is already 0
|
// rect.x is already 0
|
||||||
rect.width = m_rectText.width;
|
rect.width = m_rectText.width;
|
||||||
@@ -1671,6 +1776,10 @@ void wxTextCtrl::DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate)
|
|||||||
if ( colEnd < colStart )
|
if ( colEnd < colStart )
|
||||||
colEnd = colStart;
|
colEnd = colStart;
|
||||||
|
|
||||||
|
// for single line controls we may additionally cut off everything
|
||||||
|
// which is to the right of the last visible position
|
||||||
|
if ( IsSingleLine() )
|
||||||
|
{
|
||||||
// don't draw the chars beyond the rightmost one
|
// don't draw the chars beyond the rightmost one
|
||||||
if ( m_colLastVisible == -1 )
|
if ( m_colLastVisible == -1 )
|
||||||
{
|
{
|
||||||
@@ -1687,6 +1796,7 @@ void wxTextCtrl::DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate)
|
|||||||
|
|
||||||
if ( colEnd > m_colLastVisible )
|
if ( colEnd > m_colLastVisible )
|
||||||
colEnd = m_colLastVisible;
|
colEnd = m_colLastVisible;
|
||||||
|
}
|
||||||
|
|
||||||
// extract the part of line we need to redraw
|
// extract the part of line we need to redraw
|
||||||
wxString textLine = GetLineText(line);
|
wxString textLine = GetLineText(line);
|
||||||
@@ -1795,10 +1905,10 @@ void wxTextCtrl::CreateCaret()
|
|||||||
SetCaret(caret);
|
SetCaret(caret);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCoord wxTextCtrl::GetCaretPosition(long pos = -1) const
|
wxCoord wxTextCtrl::GetCaretPosition(long pos) const
|
||||||
{
|
{
|
||||||
wxString textBeforeCaret(GetLineText(m_curLine),
|
wxString textBeforeCaret(GetLineText(m_curRow),
|
||||||
(size_t)(pos == -1 ? m_curRow : pos));
|
(size_t)(pos == -1 ? m_curCol : pos));
|
||||||
|
|
||||||
return GetTextWidth(textBeforeCaret);
|
return GetTextWidth(textBeforeCaret);
|
||||||
}
|
}
|
||||||
@@ -1810,7 +1920,7 @@ void wxTextCtrl::ShowCaret(bool show)
|
|||||||
{
|
{
|
||||||
// position it correctly
|
// position it correctly
|
||||||
caret->Move(m_rectText.x + GetCaretPosition() - m_ofsHorz,
|
caret->Move(m_rectText.x + GetCaretPosition() - m_ofsHorz,
|
||||||
m_rectText.y + m_curLine*GetCharHeight());
|
m_rectText.y + m_curRow*GetCharHeight());
|
||||||
|
|
||||||
// and show it there
|
// and show it there
|
||||||
caret->Show(show);
|
caret->Show(show);
|
||||||
@@ -1856,11 +1966,21 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
|
|||||||
|
|
||||||
if ( action == wxACTION_TEXT_HOME )
|
if ( action == wxACTION_TEXT_HOME )
|
||||||
{
|
{
|
||||||
newPos = m_curPos - m_curRow;
|
newPos = m_curPos - m_curCol;
|
||||||
}
|
}
|
||||||
else if ( action == wxACTION_TEXT_END )
|
else if ( action == wxACTION_TEXT_END )
|
||||||
{
|
{
|
||||||
newPos = m_curPos + GetLineLength(m_curLine) - m_curRow;
|
newPos = m_curPos + GetLineLength(m_curRow) - m_curCol;
|
||||||
|
}
|
||||||
|
else if ( action == wxACTION_TEXT_UP )
|
||||||
|
{
|
||||||
|
if ( m_curRow > 0 )
|
||||||
|
newPos = XYToPosition(m_curCol, m_curRow - 1);
|
||||||
|
}
|
||||||
|
else if ( action == wxACTION_TEXT_DOWN )
|
||||||
|
{
|
||||||
|
if ( (size_t)m_curRow < m_lines.GetCount() )
|
||||||
|
newPos = XYToPosition(m_curCol, m_curRow + 1);
|
||||||
}
|
}
|
||||||
else if ( action == wxACTION_TEXT_LEFT )
|
else if ( action == wxACTION_TEXT_LEFT )
|
||||||
{
|
{
|
||||||
@@ -2050,6 +2170,14 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxControl *control,
|
|||||||
action << wxACTION_TEXT_END;
|
action << wxACTION_TEXT_END;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WXK_UP:
|
||||||
|
action << wxACTION_TEXT_UP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WXK_DOWN:
|
||||||
|
action << wxACTION_TEXT_DOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
case WXK_LEFT:
|
case WXK_LEFT:
|
||||||
action << (ctrlDown ? wxACTION_TEXT_WORD_LEFT
|
action << (ctrlDown ? wxACTION_TEXT_WORD_LEFT
|
||||||
: wxACTION_TEXT_LEFT);
|
: wxACTION_TEXT_LEFT);
|
||||||
|
Reference in New Issue
Block a user