split wxTextCtrl data members in wxSingle/MultiData
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/wxUNIVERSAL@8853 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -359,11 +359,7 @@ protected:
|
||||
wxCoord GetMaxWidth() const;
|
||||
|
||||
// force recalculation of the max line width
|
||||
void RecalcMaxWidth()
|
||||
{
|
||||
m_widthMax = -1;
|
||||
(void)GetMaxWidth();
|
||||
}
|
||||
void RecalcMaxWidth();
|
||||
|
||||
// update the max width after the given line was modified
|
||||
void UpdateMaxWidth(wxTextCoord line);
|
||||
@@ -389,11 +385,29 @@ protected:
|
||||
wxTextCoord *col,
|
||||
wxTextCoord *row) const;
|
||||
|
||||
// get the height of one line (the same for all lines)
|
||||
wxCoord GetLineHeight() const
|
||||
{
|
||||
// this one should be already precalculated
|
||||
wxASSERT_MSG( m_heightLine != -1, _T("should have line height") );
|
||||
|
||||
return m_heightLine;
|
||||
}
|
||||
|
||||
// recalc the line height (to call when the font changes)
|
||||
void RecalcLineHeight();
|
||||
|
||||
// event handlers
|
||||
void OnIdle(wxIdleEvent& event);
|
||||
void OnChar(wxKeyEvent& event);
|
||||
void OnSize(wxSizeEvent& event);
|
||||
|
||||
// return the struct containing control-type dependent data
|
||||
struct wxTextSingleLineData& SData() { return *m_data.sdata; }
|
||||
struct wxTextMultiLineData& MData() { return *m_data.mdata; }
|
||||
const wxTextSingleLineData& SData() const { return *m_data.sdata; }
|
||||
const wxTextMultiLineData& MData() const { return *m_data.mdata; }
|
||||
|
||||
// accessors for derived classes (SL stands for single line)
|
||||
const wxString& GetSLValue() const
|
||||
{
|
||||
@@ -423,9 +437,6 @@ private:
|
||||
// the control text (only used for single line controls)
|
||||
wxString m_value;
|
||||
|
||||
// the lines of text (only used for multiline controls)
|
||||
wxArrayString m_lines;
|
||||
|
||||
// current position
|
||||
wxTextPos m_curPos;
|
||||
wxTextCoord m_curCol,
|
||||
@@ -447,32 +458,17 @@ private:
|
||||
// the rectangle (in client coordinates) to draw text inside
|
||||
wxRect m_rectText;
|
||||
|
||||
// this section is for the controls without horz scrollbar only
|
||||
|
||||
// the position of the first visible pixel and the first visible column
|
||||
wxCoord m_ofsHorz;
|
||||
wxTextCoord m_colStart;
|
||||
|
||||
// and the last ones (m_posLastVisible is the width but m_colLastVisible
|
||||
// is an absolute value)
|
||||
wxCoord m_posLastVisible;
|
||||
wxTextCoord m_colLastVisible;
|
||||
|
||||
// this section is for the controls with scrollbar(s)
|
||||
|
||||
// the current ranges of the scrollbars
|
||||
int m_scrollRangeX,
|
||||
m_scrollRangeY;
|
||||
|
||||
// should we adjust the horz/vert scrollbar?
|
||||
bool m_updateScrollbarX,
|
||||
m_updateScrollbarY;
|
||||
|
||||
// the max line length in pixels
|
||||
wxCoord m_widthMax;
|
||||
|
||||
// the index of the line which has the length of m_widthMax
|
||||
wxTextCoord m_lineLongest;
|
||||
// the height of one line (cached value of GetCharHeight)
|
||||
wxCoord m_heightLine;
|
||||
|
||||
// we have some data which depends on the kind of control (single or multi
|
||||
// line)
|
||||
union
|
||||
{
|
||||
wxTextSingleLineData *sdata;
|
||||
wxTextMultiLineData *mdata;
|
||||
void *data;
|
||||
} m_data;
|
||||
|
||||
// the object to which we delegate our undo/redo implementation
|
||||
wxTextCtrlCommandProcessor *m_cmdProcessor;
|
||||
|
@@ -410,25 +410,14 @@ TextTestFrame::TextTestFrame(const wxString& title)
|
||||
);
|
||||
wxSizer *sizerMiddle = new wxBoxSizer(wxVERTICAL);
|
||||
sizerMiddle->Add(sizerMiddleUp, 0, wxGROW);
|
||||
sizerMiddle->Add(sizerMiddleDown, 0, wxGROW | wxTOP, 5);
|
||||
|
||||
// I don't understand what's going on :-(
|
||||
#ifdef __WXGTK__
|
||||
sizerMiddle->SetMinSize(320, 0);
|
||||
#endif
|
||||
sizerMiddle->Add(sizerMiddleDown, 1, wxGROW | wxTOP, 5);
|
||||
|
||||
// right pane
|
||||
wxStaticBox *box3 = new wxStaticBox(m_panel, -1, _T("&Text:"));
|
||||
m_sizerText = new wxStaticBoxSizer(box3, wxHORIZONTAL);
|
||||
Reset();
|
||||
CreateText();
|
||||
m_sizerText->SetMinSize(250,
|
||||
#ifdef __WXGTK__
|
||||
300
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
);
|
||||
m_sizerText->SetMinSize(250, 0);
|
||||
|
||||
// the 3 panes panes compose the upper part of the window
|
||||
wxSizer *sizerUp = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
@@ -28,7 +28,7 @@
|
||||
|
||||
1. wxStringTokenize is the slowest part of Replace
|
||||
2. GetDC/ReleaseDC are very slow, avoid calling them several times
|
||||
3. GetCharHeight() should be cached too
|
||||
+3. GetCharHeight() should be cached too
|
||||
4. wxClientDC construction/destruction in HitTestLine is horribly expensive
|
||||
|
||||
For line wrapping controls HitTest2 takes 50% of program time. The results
|
||||
@@ -180,6 +180,66 @@ static inline void OrderPositions(wxTextPos& from, wxTextPos& to)
|
||||
#define wxTEXT_COMMAND_INSERT _T("insert")
|
||||
#define wxTEXT_COMMAND_REMOVE _T("remove")
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private data of wxTextCtrl
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
struct WXDLLEXPORT wxTextSingleLineData
|
||||
{
|
||||
// the position of the first visible pixel and the first visible column
|
||||
wxCoord m_ofsHorz;
|
||||
wxTextCoord m_colStart;
|
||||
|
||||
// and the last ones (m_posLastVisible is the width but m_colLastVisible
|
||||
// is an absolute value)
|
||||
wxCoord m_posLastVisible;
|
||||
wxTextCoord m_colLastVisible;
|
||||
|
||||
// def ctor
|
||||
wxTextSingleLineData()
|
||||
{
|
||||
m_colStart = 0;
|
||||
m_ofsHorz = 0;
|
||||
|
||||
m_colLastVisible = -1;
|
||||
m_posLastVisible = -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
struct WXDLLEXPORT wxTextMultiLineData
|
||||
{
|
||||
// the lines of text
|
||||
wxArrayString m_lines;
|
||||
|
||||
// the current ranges of the scrollbars
|
||||
int m_scrollRangeX,
|
||||
m_scrollRangeY;
|
||||
|
||||
// should we adjust the horz/vert scrollbar?
|
||||
bool m_updateScrollbarX,
|
||||
m_updateScrollbarY;
|
||||
|
||||
// the max line length in pixels
|
||||
wxCoord m_widthMax;
|
||||
|
||||
// the index of the line which has the length of m_widthMax
|
||||
wxTextCoord m_lineLongest;
|
||||
|
||||
// the def ctor
|
||||
wxTextMultiLineData()
|
||||
{
|
||||
m_scrollRangeX =
|
||||
m_scrollRangeY = 0;
|
||||
|
||||
m_updateScrollbarX =
|
||||
m_updateScrollbarY = FALSE;
|
||||
|
||||
m_widthMax = -1;
|
||||
m_lineLongest = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private classes for undo/redo management
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -327,31 +387,21 @@ void wxTextCtrl::Init()
|
||||
m_isModified = FALSE;
|
||||
m_isEditable = TRUE;
|
||||
|
||||
m_colStart = 0;
|
||||
m_ofsHorz = 0;
|
||||
|
||||
m_colLastVisible = -1;
|
||||
m_posLastVisible = -1;
|
||||
|
||||
m_posLast =
|
||||
m_curPos =
|
||||
m_curCol =
|
||||
m_curRow = 0;
|
||||
|
||||
m_scrollRangeX =
|
||||
m_scrollRangeY = 0;
|
||||
|
||||
m_updateScrollbarX =
|
||||
m_updateScrollbarY = FALSE;
|
||||
|
||||
m_widthMax = -1;
|
||||
m_lineLongest = 0;
|
||||
m_heightLine = -1;
|
||||
|
||||
// init wxScrollHelper
|
||||
SetWindow(this);
|
||||
|
||||
// init the undo manager
|
||||
m_cmdProcessor = new wxTextCtrlCommandProcessor(this);
|
||||
|
||||
// no data yet
|
||||
m_data.data = NULL;
|
||||
}
|
||||
|
||||
bool wxTextCtrl::Create(wxWindow *parent,
|
||||
@@ -381,11 +431,17 @@ bool wxTextCtrl::Create(wxWindow *parent,
|
||||
}
|
||||
|
||||
// TODO: support wxTE_NO_VSCROLL (?)
|
||||
|
||||
// create data object for multiline controls
|
||||
m_data.mdata = new wxTextMultiLineData;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this doesn't make sense for single line controls
|
||||
style &= ~wxHSCROLL;
|
||||
|
||||
// create data object for single line controls
|
||||
m_data.sdata = new wxTextSingleLineData;
|
||||
}
|
||||
|
||||
if ( !wxControl::Create(parent, id, pos, size, style,
|
||||
@@ -399,7 +455,7 @@ bool wxTextCtrl::Create(wxWindow *parent,
|
||||
if ( style & wxTE_MULTILINE )
|
||||
{
|
||||
// we should always have at least one line in a multiline control
|
||||
m_lines.Add(wxEmptyString);
|
||||
MData().m_lines.Add(wxEmptyString);
|
||||
|
||||
// we might support it but it's quite useless and other ports don't
|
||||
// support it anyhow
|
||||
@@ -407,6 +463,7 @@ bool wxTextCtrl::Create(wxWindow *parent,
|
||||
_T("wxTE_PASSWORD can't be used with multiline ctrls") );
|
||||
}
|
||||
|
||||
RecalcLineHeight();
|
||||
SetValue(value);
|
||||
SetBestSize(size);
|
||||
|
||||
@@ -425,6 +482,14 @@ bool wxTextCtrl::Create(wxWindow *parent,
|
||||
wxTextCtrl::~wxTextCtrl()
|
||||
{
|
||||
delete m_cmdProcessor;
|
||||
|
||||
if ( m_data.data )
|
||||
{
|
||||
if ( IsSingleLine() )
|
||||
delete m_data.sdata;
|
||||
else
|
||||
delete m_data.mdata;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -453,13 +518,13 @@ wxString wxTextCtrl::GetValue() const
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
size_t count = m_lines.GetCount();
|
||||
size_t count = MData().m_lines.GetCount();
|
||||
for ( size_t n = 0; n < count; n++ )
|
||||
{
|
||||
if ( n )
|
||||
value += _T('\n'); // from preceding line
|
||||
|
||||
value += m_lines[n];
|
||||
value += MData().m_lines[n];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -529,8 +594,8 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
|
||||
m_value = valueNew;
|
||||
|
||||
// force m_colLastVisible update
|
||||
m_colLastVisible = -1;
|
||||
// force SData().m_colLastVisible update
|
||||
SData().m_colLastVisible = -1;
|
||||
|
||||
// repaint
|
||||
RefreshPixelRange(0, startNewText, widthNewText);
|
||||
@@ -557,12 +622,12 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
textOrig += _T('\n');
|
||||
}
|
||||
|
||||
textOrig += m_lines[line];
|
||||
textOrig += MData().m_lines[line];
|
||||
}
|
||||
|
||||
// we need to append the '\n' for the last line unless there is no
|
||||
// following line
|
||||
size_t countOld = m_lines.GetCount();
|
||||
size_t countOld = MData().m_lines.GetCount();
|
||||
|
||||
// (2) replace text in the combined string
|
||||
|
||||
@@ -572,7 +637,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
// these values will be used to refresh the changed area below
|
||||
wxCoord widthNewText,
|
||||
startNewText = GetTextWidth(textNew);
|
||||
if ( (size_t)colStart == m_lines[lineStart].length() )
|
||||
if ( (size_t)colStart == MData().m_lines[lineStart].length() )
|
||||
{
|
||||
// text appended, refresh just enough to show the new text
|
||||
widthNewText = GetTextWidth(text.BeforeFirst(_T('\n')));
|
||||
@@ -608,7 +673,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
|
||||
// (3b) special case: if we replace everything till the end we need to
|
||||
// keep an empty line or the lines would disappear completely
|
||||
// (this also takes care of never leaving m_lines empty)
|
||||
// (this also takes care of never leaving MData().m_lines empty)
|
||||
if ( ((size_t)lineEnd == countOld - 1) && lines.IsEmpty() )
|
||||
{
|
||||
lines.Add(wxEmptyString);
|
||||
@@ -625,7 +690,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
if ( nReplaceLine < nReplaceCount )
|
||||
{
|
||||
// we have the replacement line for this one
|
||||
m_lines[line] = lines[nReplaceLine];
|
||||
MData().m_lines[line] = lines[nReplaceLine];
|
||||
|
||||
UpdateMaxWidth(line);
|
||||
}
|
||||
@@ -636,13 +701,13 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
bool deletedLongestLine = FALSE;
|
||||
for ( wxTextCoord lineDel = lineEnd; lineDel >= line; lineDel-- )
|
||||
{
|
||||
if ( lineDel == m_lineLongest )
|
||||
if ( lineDel == MData().m_lineLongest )
|
||||
{
|
||||
// we will need to recalc the max line width
|
||||
deletedLongestLine = TRUE;
|
||||
}
|
||||
|
||||
m_lines.RemoveAt(lineDel);
|
||||
MData().m_lines.RemoveAt(lineDel);
|
||||
}
|
||||
|
||||
if ( deletedLongestLine )
|
||||
@@ -658,7 +723,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
// (4c) insert the new lines
|
||||
while ( nReplaceLine < nReplaceCount )
|
||||
{
|
||||
m_lines.Insert(lines[nReplaceLine++], ++lineEnd);
|
||||
MData().m_lines.Insert(lines[nReplaceLine++], ++lineEnd);
|
||||
|
||||
UpdateMaxWidth(lineEnd);
|
||||
}
|
||||
@@ -694,14 +759,14 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
}
|
||||
//else: refresh all lines we changed (OPT?)
|
||||
|
||||
wxTextCoord lineEnd = m_lines.GetCount() - 1;
|
||||
wxTextCoord lineEnd = MData().m_lines.GetCount() - 1;
|
||||
if ( lineStart <= lineEnd )
|
||||
RefreshLineRange(lineStart, lineEnd);
|
||||
|
||||
// refresh text rect left below
|
||||
if ( rowsNew < rowsOld )
|
||||
{
|
||||
wxCoord h = GetCharHeight();
|
||||
wxCoord h = GetLineHeight();
|
||||
wxRect rect;
|
||||
rect.x = 0;
|
||||
rect.width = m_rectText.width;
|
||||
@@ -711,7 +776,7 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text)
|
||||
}
|
||||
|
||||
// the vert scrollbar might [dis]appear
|
||||
m_updateScrollbarY = TRUE;
|
||||
MData().m_updateScrollbarY = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,12 +893,12 @@ wxTextPos wxTextCtrl::GetLastPosition() const
|
||||
{
|
||||
#ifdef WXDEBUG_TEXT
|
||||
pos = 0;
|
||||
size_t nLineCount = m_lines.GetCount();
|
||||
size_t nLineCount = MData().m_lines.GetCount();
|
||||
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 += m_lines[nLine].length() + 1;
|
||||
pos += MData().m_lines[nLine].length() + 1;
|
||||
}
|
||||
|
||||
if ( pos > 0 )
|
||||
@@ -886,22 +951,22 @@ wxString wxTextCtrl::GetSelectionText() const
|
||||
// and end line are the same
|
||||
if ( lineEnd == lineStart )
|
||||
{
|
||||
sel = m_lines[lineStart].Mid(colStart, colEnd - colStart);
|
||||
sel = MData().m_lines[lineStart].Mid(colStart, colEnd - colStart);
|
||||
}
|
||||
else // sel on multiple lines
|
||||
{
|
||||
// take the end of the first line
|
||||
sel = m_lines[lineStart].c_str() + colStart;
|
||||
sel = MData().m_lines[lineStart].c_str() + colStart;
|
||||
sel += _T('\n');
|
||||
|
||||
// all intermediate ones
|
||||
for ( wxTextCoord line = lineStart + 1; line < lineEnd; line++ )
|
||||
{
|
||||
sel << m_lines[line] << _T('\n');
|
||||
sel << MData().m_lines[line] << _T('\n');
|
||||
}
|
||||
|
||||
// and the start of the last one
|
||||
sel += m_lines[lineEnd].Left(colEnd);
|
||||
sel += MData().m_lines[lineEnd].Left(colEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1104,10 +1169,10 @@ int wxTextCtrl::GetLineLength(wxTextCoord line) const
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
wxCHECK_MSG( (size_t)line < m_lines.GetCount(), -1,
|
||||
wxCHECK_MSG( (size_t)line < MData().m_lines.GetCount(), -1,
|
||||
_T("line index out of range") );
|
||||
|
||||
return m_lines[line].length();
|
||||
return MData().m_lines[line].length();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1121,17 +1186,17 @@ wxString wxTextCtrl::GetLineText(wxTextCoord line) const
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
wxCHECK_MSG( (size_t)line < m_lines.GetCount(), _T(""),
|
||||
wxCHECK_MSG( (size_t)line < MData().m_lines.GetCount(), _T(""),
|
||||
_T("line index out of range") );
|
||||
|
||||
return m_lines[line];
|
||||
return MData().m_lines[line];
|
||||
}
|
||||
}
|
||||
|
||||
int wxTextCtrl::GetNumberOfLines() const
|
||||
{
|
||||
// there is always 1 line, even if the text is empty
|
||||
return IsSingleLine() ? 1 : m_lines.GetCount();
|
||||
return IsSingleLine() ? 1 : MData().m_lines.GetCount();
|
||||
}
|
||||
|
||||
wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const
|
||||
@@ -1144,7 +1209,7 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
if ( (size_t)y >= m_lines.GetCount() )
|
||||
if ( (size_t)y >= MData().m_lines.GetCount() )
|
||||
{
|
||||
// this position is below the text
|
||||
return GetLastPosition();
|
||||
@@ -1155,14 +1220,14 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const
|
||||
{
|
||||
// +1 is because the positions at the end of this line and of the
|
||||
// start of the next one are different
|
||||
pos += m_lines[nLine].length() + 1;
|
||||
pos += MData().m_lines[nLine].length() + 1;
|
||||
}
|
||||
|
||||
// take into account also the position in line
|
||||
if ( (size_t)x > m_lines[y].length() )
|
||||
if ( (size_t)x > MData().m_lines[y].length() )
|
||||
{
|
||||
// don't return position in the next line
|
||||
x = m_lines[y].length();
|
||||
x = MData().m_lines[y].length();
|
||||
}
|
||||
|
||||
return pos + x;
|
||||
@@ -1187,12 +1252,12 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos,
|
||||
else // multiline
|
||||
{
|
||||
wxTextPos posCur = 0;
|
||||
size_t nLineCount = m_lines.GetCount();
|
||||
size_t nLineCount = MData().m_lines.GetCount();
|
||||
for ( size_t nLine = 0; nLine < nLineCount; nLine++ )
|
||||
{
|
||||
// +1 is because the start the start of the next line is one
|
||||
// position after the end of this one
|
||||
wxTextPos posNew = posCur + m_lines[nLine].length() + 1;
|
||||
wxTextPos posNew = posCur + MData().m_lines[nLine].length() + 1;
|
||||
if ( posNew > pos )
|
||||
{
|
||||
// we've found the line, now just calc the column
|
||||
@@ -1277,7 +1342,7 @@ bool wxTextCtrl::PositionToLogicalXY(wxTextPos pos,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int hLine = GetCharHeight();
|
||||
int hLine = GetLineHeight();
|
||||
wxCoord x, y;
|
||||
wxString textLine = GetLineText(line);
|
||||
if ( IsSingleLine() || !WrapLines() )
|
||||
@@ -1347,10 +1412,10 @@ bool wxTextCtrl::PositionToDeviceXY(wxTextPos pos,
|
||||
|
||||
// finally translate the logical text rect coords into physical client
|
||||
// coords
|
||||
CalcScrolledPosition(m_rectText.x + x - m_ofsHorz,
|
||||
m_rectText.y + y,
|
||||
xOut,
|
||||
yOut);
|
||||
if ( IsSingleLine() )
|
||||
x -= SData().m_ofsHorz;
|
||||
|
||||
CalcScrolledPosition(m_rectText.x + x, m_rectText.y + y, xOut, yOut);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1375,7 +1440,7 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
|
||||
{
|
||||
ShowHorzPosition(GetTextWidth(GetSLValue().Left(pos)));
|
||||
}
|
||||
else if ( m_scrollRangeX || m_scrollRangeY ) // multiline with scrollbars
|
||||
else if ( MData().m_scrollRangeX || MData().m_scrollRangeY ) // multiline with scrollbars
|
||||
{
|
||||
int xStart, yStart;
|
||||
GetViewStart(&xStart, &yStart);
|
||||
@@ -1390,9 +1455,9 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
|
||||
|
||||
// scroll the position vertically into view: if it is currently above
|
||||
// it, make it the first one, otherwise the last one
|
||||
if ( m_scrollRangeY )
|
||||
if ( MData().m_scrollRangeY )
|
||||
{
|
||||
y /= GetCharHeight();
|
||||
y /= GetLineHeight();
|
||||
|
||||
if ( y < yStart )
|
||||
{
|
||||
@@ -1432,7 +1497,7 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
|
||||
{
|
||||
// finding the last line is easy if each line has exactly
|
||||
// one row
|
||||
yEnd = yStart + rectText.height / GetCharHeight() - 1;
|
||||
yEnd = yStart + rectText.height / GetLineHeight() - 1;
|
||||
}
|
||||
|
||||
if ( yEnd < y )
|
||||
@@ -1445,7 +1510,7 @@ void wxTextCtrl::ShowPosition(wxTextPos pos)
|
||||
}
|
||||
|
||||
// scroll the position horizontally into view
|
||||
if ( m_scrollRangeX )
|
||||
if ( MData().m_scrollRangeX )
|
||||
{
|
||||
// unlike for the rows, xStart doesn't correspond to the starting
|
||||
// column as they all have different widths, so we need to
|
||||
@@ -1795,7 +1860,7 @@ wxSize wxTextCtrl::DoGetBestClientSize() const
|
||||
GetTextExtent(GetTextToShow(GetLineText(0)), &w, &h);
|
||||
|
||||
int wChar = GetCharWidth(),
|
||||
hChar = GetCharHeight();
|
||||
hChar = GetLineHeight();
|
||||
|
||||
int widthMin = wxMax(10*wChar, 100);
|
||||
if ( w < widthMin )
|
||||
@@ -1841,16 +1906,16 @@ void wxTextCtrl::UpdateLastVisible()
|
||||
return;
|
||||
|
||||
// use (efficient) HitTestLine to find the last visible character
|
||||
wxString text = m_value.Mid((size_t)m_colStart /* to the end */);
|
||||
wxString text = m_value.Mid((size_t)SData().m_colStart /* to the end */);
|
||||
wxTextCoord col;
|
||||
switch ( HitTestLine(text, m_rectText.width, &col) )
|
||||
{
|
||||
case wxTE_HT_BEYOND:
|
||||
// everything is visible
|
||||
m_colLastVisible = text.length();
|
||||
SData().m_colLastVisible = text.length();
|
||||
|
||||
// calc it below
|
||||
m_posLastVisible = -1;
|
||||
SData().m_posLastVisible = -1;
|
||||
break;
|
||||
|
||||
/*
|
||||
@@ -1867,43 +1932,46 @@ void wxTextCtrl::UpdateLastVisible()
|
||||
// the last entirely seen character is the previous one because
|
||||
// this one is only partly visible - unless the width of the
|
||||
// string is exactly the max width
|
||||
m_posLastVisible = GetTextWidth(text.Truncate(col + 1));
|
||||
if ( m_posLastVisible > m_rectText.width )
|
||||
SData().m_posLastVisible = GetTextWidth(text.Truncate(col + 1));
|
||||
if ( SData().m_posLastVisible > m_rectText.width )
|
||||
{
|
||||
// this character is not entirely visible, take the
|
||||
// previous one
|
||||
col--;
|
||||
|
||||
// recalc it
|
||||
m_posLastVisible = -1;
|
||||
SData().m_posLastVisible = -1;
|
||||
}
|
||||
//else: we can just see it
|
||||
|
||||
m_colLastVisible = col;
|
||||
SData().m_colLastVisible = col;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// calculate the width of the text really shown
|
||||
if ( m_posLastVisible == -1 )
|
||||
if ( SData().m_posLastVisible == -1 )
|
||||
{
|
||||
m_posLastVisible = GetTextWidth(text.Truncate(m_colLastVisible + 1));
|
||||
SData().m_posLastVisible = GetTextWidth(text.Truncate(SData().m_colLastVisible + 1));
|
||||
}
|
||||
|
||||
// current value is relative the start of the string text which starts at
|
||||
// m_colStart, we need an absolute offset into string
|
||||
m_colLastVisible += m_colStart;
|
||||
// SData().m_colStart, we need an absolute offset into string
|
||||
SData().m_colLastVisible += SData().m_colStart;
|
||||
|
||||
wxLogTrace(_T("text"), _T("Last visible column/position is %d/%ld"),
|
||||
m_colLastVisible, m_posLastVisible);
|
||||
SData().m_colLastVisible, SData().m_posLastVisible);
|
||||
}
|
||||
|
||||
void wxTextCtrl::OnSize(wxSizeEvent& event)
|
||||
{
|
||||
UpdateTextRect();
|
||||
|
||||
m_updateScrollbarX =
|
||||
m_updateScrollbarY = TRUE;
|
||||
if ( !IsSingleLine() )
|
||||
{
|
||||
MData().m_updateScrollbarX =
|
||||
MData().m_updateScrollbarY = TRUE;
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
@@ -1927,7 +1995,7 @@ wxRect wxTextCtrl::GetRealTextArea() const
|
||||
// the real text area always holds an entire number of lines, so the only
|
||||
// difference with the text area is a narrow strip along the bottom border
|
||||
wxRect rectText = m_rectText;
|
||||
int hLine = GetCharHeight();
|
||||
int hLine = GetLineHeight();
|
||||
rectText.height = (m_rectText.height / hLine) * hLine;
|
||||
return rectText;
|
||||
}
|
||||
@@ -2273,7 +2341,7 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTest2(wxCoord y0,
|
||||
if ( colRowStartOut )
|
||||
*colRowStartOut = 0;
|
||||
|
||||
int hLine = GetCharHeight();
|
||||
int hLine = GetLineHeight();
|
||||
wxTextCoord rowLast = GetNumberOfLines() - 1;
|
||||
if ( IsSingleLine() || !WrapLines() )
|
||||
{
|
||||
@@ -2439,18 +2507,18 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTest2(wxCoord y0,
|
||||
wxTextCtrl has not one but two scrolling mechanisms: one is semi-automatic
|
||||
scrolling in both horizontal and vertical direction implemented using
|
||||
wxScrollHelper and the second one is manual scrolling implemented using
|
||||
m_ofsHorz and used by the single line controls without scroll bar.
|
||||
SData().m_ofsHorz and used by the single line controls without scroll bar.
|
||||
|
||||
The first version (the standard one) always scrolls by fixed amount which is
|
||||
fine for vertical scrolling as all lines have the same height but is rather
|
||||
ugly for horizontal scrolling if proportional font is used. This is why we
|
||||
manually update and use m_ofsHorz which contains the length of the string
|
||||
manually update and use SData().m_ofsHorz which contains the length of the string
|
||||
which is hidden beyond the left borde. An important property of text
|
||||
controls using this kind of scrolling is that an entire number of characters
|
||||
is always shown and that parts of characters never appear on display -
|
||||
neither in the leftmost nor rightmost positions.
|
||||
|
||||
Once again, for multi line controls m_ofsHorz is always 0 and scrolling is
|
||||
Once again, for multi line controls SData().m_ofsHorz is always 0 and scrolling is
|
||||
done as usual for wxScrollWindow.
|
||||
*/
|
||||
|
||||
@@ -2458,8 +2526,8 @@ void wxTextCtrl::ShowHorzPosition(wxCoord pos)
|
||||
{
|
||||
// pos is the logical position to show
|
||||
|
||||
// m_ofsHorz is the fisrt logical position shown
|
||||
if ( pos < m_ofsHorz )
|
||||
// SData().m_ofsHorz is the fisrt logical position shown
|
||||
if ( pos < SData().m_ofsHorz )
|
||||
{
|
||||
// scroll backwards
|
||||
wxTextCoord col;
|
||||
@@ -2477,8 +2545,8 @@ void wxTextCtrl::ShowHorzPosition(wxCoord pos)
|
||||
width = m_rectText.width;
|
||||
}
|
||||
|
||||
// m_ofsHorz + width is the last logical position shown
|
||||
if ( pos > m_ofsHorz + width)
|
||||
// SData().m_ofsHorz + width is the last logical position shown
|
||||
if ( pos > SData().m_ofsHorz + width)
|
||||
{
|
||||
// scroll forward
|
||||
wxTextCoord col;
|
||||
@@ -2500,25 +2568,25 @@ void wxTextCtrl::ScrollText(wxTextCoord col)
|
||||
col = 0;
|
||||
|
||||
// OPT: could only get the extent of the part of the string between col
|
||||
// and m_colStart
|
||||
// and SData().m_colStart
|
||||
wxCoord ofsHorz = GetTextWidth(GetLineText(0).Left(col));
|
||||
|
||||
if ( ofsHorz != m_ofsHorz )
|
||||
if ( ofsHorz != SData().m_ofsHorz )
|
||||
{
|
||||
// what is currently shown?
|
||||
if ( m_colLastVisible == -1 )
|
||||
if ( SData().m_colLastVisible == -1 )
|
||||
{
|
||||
UpdateLastVisible();
|
||||
}
|
||||
|
||||
// NB1: to scroll to the right, offset must be negative, hence the
|
||||
// order of operands
|
||||
int dx = m_ofsHorz - ofsHorz;
|
||||
int dx = SData().m_ofsHorz - ofsHorz;
|
||||
|
||||
// NB2: we call Refresh() below which results in a call to
|
||||
// DoDraw(), so we must update m_ofsHorz before calling it
|
||||
m_ofsHorz = ofsHorz;
|
||||
m_colStart = col;
|
||||
// DoDraw(), so we must update SData().m_ofsHorz before calling it
|
||||
SData().m_ofsHorz = ofsHorz;
|
||||
SData().m_colStart = col;
|
||||
|
||||
// scroll only the rectangle inside which there is the text
|
||||
if ( dx > 0 )
|
||||
@@ -2535,11 +2603,11 @@ void wxTextCtrl::ScrollText(wxTextCoord col)
|
||||
// before will be refreshed and redrawn
|
||||
|
||||
// but we still need to force updating after scrolling
|
||||
m_colLastVisible = -1;
|
||||
SData().m_colLastVisible = -1;
|
||||
}
|
||||
|
||||
wxRect rect = m_rectText;
|
||||
rect.width = m_posLastVisible;
|
||||
rect.width = SData().m_posLastVisible;
|
||||
|
||||
rect = ScrollNoRefresh(dx, 0, &rect);
|
||||
|
||||
@@ -2572,14 +2640,14 @@ void wxTextCtrl::ScrollText(wxTextCoord col)
|
||||
Refresh(TRUE, &rect);
|
||||
|
||||
// and now the area on the right
|
||||
rect.x = m_rectText.x + m_posLastVisible;
|
||||
rect.width = m_rectText.width - m_posLastVisible;
|
||||
rect.x = m_rectText.x + SData().m_posLastVisible;
|
||||
rect.width = m_rectText.width - SData().m_posLastVisible;
|
||||
}
|
||||
else
|
||||
{
|
||||
// just extend the rect covering the uncovered area to the edge of
|
||||
// the text rect
|
||||
rect.width += m_rectText.width - m_posLastVisible;
|
||||
rect.width += m_rectText.width - SData().m_posLastVisible;
|
||||
}
|
||||
|
||||
Refresh(TRUE, &rect);
|
||||
@@ -2588,18 +2656,21 @@ void wxTextCtrl::ScrollText(wxTextCoord col)
|
||||
|
||||
void wxTextCtrl::CalcUnscrolledPosition(int x, int y, int *xx, int *yy) const
|
||||
{
|
||||
wxScrollHelper::CalcUnscrolledPosition(x + m_ofsHorz, y, xx, yy);
|
||||
if ( IsSingleLine() )
|
||||
x += SData().m_ofsHorz;
|
||||
|
||||
wxScrollHelper::CalcUnscrolledPosition(x, y, xx, yy);
|
||||
}
|
||||
|
||||
void wxTextCtrl::DoPrepareDC(wxDC& dc)
|
||||
{
|
||||
// for single line controls we only have to deal with m_ofsHorz and it's
|
||||
// for single line controls we only have to deal with SData().m_ofsHorz and it's
|
||||
// useless to call base class version as they don't use normal scrolling
|
||||
if ( m_ofsHorz )
|
||||
if ( IsSingleLine() && SData().m_ofsHorz )
|
||||
{
|
||||
// adjust the DC origin if the text is shifted
|
||||
wxPoint pt = dc.GetDeviceOrigin();
|
||||
dc.SetDeviceOrigin(pt.x - m_ofsHorz, pt.y);
|
||||
dc.SetDeviceOrigin(pt.x - SData().m_ofsHorz, pt.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2610,18 +2681,18 @@ void wxTextCtrl::DoPrepareDC(wxDC& dc)
|
||||
void wxTextCtrl::UpdateMaxWidth(wxTextCoord line)
|
||||
{
|
||||
// check if the max width changes after this line was modified
|
||||
wxCoord widthMaxOld = m_widthMax,
|
||||
wxCoord widthMaxOld = MData().m_widthMax,
|
||||
width;
|
||||
GetTextExtent(GetLineText(line), &width, NULL);
|
||||
|
||||
if ( line == m_lineLongest )
|
||||
if ( line == MData().m_lineLongest )
|
||||
{
|
||||
// this line was the longest one, is it still?
|
||||
if ( width > m_widthMax )
|
||||
if ( width > MData().m_widthMax )
|
||||
{
|
||||
m_widthMax = width;
|
||||
MData().m_widthMax = width;
|
||||
}
|
||||
else if ( width < m_widthMax )
|
||||
else if ( width < MData().m_widthMax )
|
||||
{
|
||||
// we need to find the new longest line
|
||||
RecalcMaxWidth();
|
||||
@@ -2630,20 +2701,31 @@ void wxTextCtrl::UpdateMaxWidth(wxTextCoord line)
|
||||
}
|
||||
else // it wasn't the longest line, but maybe it became it?
|
||||
{
|
||||
// GetMaxWidth() and not m_widthMax as it might be not calculated yet
|
||||
// GetMaxWidth() and not MData().m_widthMax as it might be not calculated yet
|
||||
if ( width > GetMaxWidth() )
|
||||
{
|
||||
m_widthMax = width;
|
||||
m_lineLongest = line;
|
||||
MData().m_widthMax = width;
|
||||
MData().m_lineLongest = line;
|
||||
}
|
||||
}
|
||||
|
||||
m_updateScrollbarX = m_widthMax != widthMaxOld;
|
||||
MData().m_updateScrollbarX = MData().m_widthMax != widthMaxOld;
|
||||
}
|
||||
|
||||
void wxTextCtrl::RecalcLineHeight()
|
||||
{
|
||||
m_heightLine = GetCharHeight();
|
||||
}
|
||||
|
||||
void wxTextCtrl::RecalcMaxWidth()
|
||||
{
|
||||
MData().m_widthMax = -1;
|
||||
(void)GetMaxWidth();
|
||||
}
|
||||
|
||||
wxCoord wxTextCtrl::GetMaxWidth() const
|
||||
{
|
||||
if ( m_widthMax == -1 )
|
||||
if ( MData().m_widthMax == -1 )
|
||||
{
|
||||
// recalculate it
|
||||
|
||||
@@ -2653,25 +2735,25 @@ wxCoord wxTextCtrl::GetMaxWidth() const
|
||||
wxClientDC dc(self);
|
||||
dc.SetFont(GetFont());
|
||||
|
||||
self->m_widthMax = 0;
|
||||
self->MData().m_widthMax = 0;
|
||||
|
||||
size_t count = m_lines.GetCount();
|
||||
size_t count = MData().m_lines.GetCount();
|
||||
for ( size_t n = 0; n < count; n++ )
|
||||
{
|
||||
wxCoord width;
|
||||
dc.GetTextExtent(m_lines[n], &width, NULL);
|
||||
if ( width > m_widthMax )
|
||||
dc.GetTextExtent(MData().m_lines[n], &width, NULL);
|
||||
if ( width > MData().m_widthMax )
|
||||
{
|
||||
// remember the width and the line which has it
|
||||
self->m_widthMax = width;
|
||||
self->m_lineLongest = n;
|
||||
self->MData().m_widthMax = width;
|
||||
self->MData().m_lineLongest = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxASSERT_MSG( m_widthMax != -1, _T("should have at least 1 line") );
|
||||
wxASSERT_MSG( MData().m_widthMax != -1, _T("should have at least 1 line") );
|
||||
|
||||
return m_widthMax;
|
||||
return MData().m_widthMax;
|
||||
}
|
||||
|
||||
void wxTextCtrl::UpdateScrollbars()
|
||||
@@ -2680,7 +2762,7 @@ void wxTextCtrl::UpdateScrollbars()
|
||||
|
||||
// is our height enough to show all items?
|
||||
wxTextCoord nRows = GetNumberOfRowsBefore(GetNumberOfLines());
|
||||
wxCoord lineHeight = GetCharHeight();
|
||||
wxCoord lineHeight = GetLineHeight();
|
||||
bool showScrollbarY = !IsSingleLine() && nRows*lineHeight > size.y;
|
||||
|
||||
// is our width enough to show the longest line?
|
||||
@@ -2706,7 +2788,7 @@ void wxTextCtrl::UpdateScrollbars()
|
||||
: 0;
|
||||
int scrollRangeY = showScrollbarY ? nRows : 0;
|
||||
|
||||
if ( (scrollRangeY != m_scrollRangeY) || (scrollRangeX != m_scrollRangeX) )
|
||||
if ( (scrollRangeY != MData().m_scrollRangeY) || (scrollRangeX != MData().m_scrollRangeX) )
|
||||
{
|
||||
int x, y;
|
||||
GetViewStart(&x, &y);
|
||||
@@ -2714,8 +2796,8 @@ void wxTextCtrl::UpdateScrollbars()
|
||||
scrollRangeX, scrollRangeY,
|
||||
x, y);
|
||||
|
||||
m_scrollRangeX = scrollRangeX;
|
||||
m_scrollRangeY = scrollRangeY;
|
||||
MData().m_scrollRangeX = scrollRangeX;
|
||||
MData().m_scrollRangeY = scrollRangeY;
|
||||
|
||||
// bring the current position in view
|
||||
ShowPosition(-1);
|
||||
@@ -2725,12 +2807,12 @@ void wxTextCtrl::UpdateScrollbars()
|
||||
void wxTextCtrl::OnIdle(wxIdleEvent& event)
|
||||
{
|
||||
// notice that single line text control never has scrollbars
|
||||
if ( !IsSingleLine() && (m_updateScrollbarX || m_updateScrollbarY) )
|
||||
if ( !IsSingleLine() && (MData().m_updateScrollbarX || MData().m_updateScrollbarY) )
|
||||
{
|
||||
UpdateScrollbars();
|
||||
|
||||
m_updateScrollbarX =
|
||||
m_updateScrollbarY = FALSE;
|
||||
MData().m_updateScrollbarX =
|
||||
MData().m_updateScrollbarY = FALSE;
|
||||
}
|
||||
|
||||
event.Skip();
|
||||
@@ -2747,7 +2829,7 @@ void wxTextCtrl::RefreshLineRange(wxTextCoord lineFirst, wxTextCoord lineLast)
|
||||
wxRect rect;
|
||||
// rect.x is already 0
|
||||
rect.width = m_rectText.width;
|
||||
wxCoord h = GetCharHeight();
|
||||
wxCoord h = GetLineHeight();
|
||||
rect.y = GetNumberOfRowsBefore(lineFirst)*h;
|
||||
|
||||
wxCoord bottom = GetNumberOfRowsBefore(lineLast + 1)*h;
|
||||
@@ -2856,7 +2938,7 @@ void wxTextCtrl::RefreshPixelRange(wxTextCoord line,
|
||||
}
|
||||
//else: just refresh the specified part
|
||||
|
||||
wxCoord h = GetCharHeight();
|
||||
wxCoord h = GetLineHeight();
|
||||
wxRect rect;
|
||||
rect.x = start;
|
||||
rect.y = GetNumberOfRowsBefore(line)*h;
|
||||
@@ -2904,7 +2986,7 @@ void wxTextCtrl::RefreshTextRect(const wxRect& rectClient)
|
||||
if ( IsSingleLine() )
|
||||
{
|
||||
// account for horz scrolling
|
||||
rect.x -= m_ofsHorz;
|
||||
rect.x -= SData().m_ofsHorz;
|
||||
}
|
||||
else // multiline
|
||||
{
|
||||
@@ -3037,7 +3119,7 @@ void wxTextCtrl::DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate)
|
||||
}
|
||||
|
||||
// prepare for drawing
|
||||
wxCoord hLine = GetCharHeight();
|
||||
wxCoord hLine = GetLineHeight();
|
||||
|
||||
// these vars will be used for hit testing of the current row
|
||||
wxCoord y = rectUpdate.y;
|
||||
@@ -3084,36 +3166,36 @@ void wxTextCtrl::DoDrawTextInRect(wxDC& dc, const wxRect& rectUpdate)
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't show the columns which are scrolled out to the left
|
||||
if ( colStart < m_colStart )
|
||||
colStart = m_colStart;
|
||||
|
||||
// colEnd may be less than colStart if colStart was changed by the
|
||||
// assignment above
|
||||
if ( 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 show the columns which are scrolled out to the left
|
||||
if ( colStart < SData().m_colStart )
|
||||
colStart = SData().m_colStart;
|
||||
|
||||
// colEnd may be less than colStart if colStart was changed by the
|
||||
// assignment above
|
||||
if ( colEnd < colStart )
|
||||
colEnd = colStart;
|
||||
|
||||
// don't draw the chars beyond the rightmost one
|
||||
if ( m_colLastVisible == -1 )
|
||||
if ( SData().m_colLastVisible == -1 )
|
||||
{
|
||||
// recalculate this rightmost column
|
||||
UpdateLastVisible();
|
||||
}
|
||||
|
||||
if ( colStart > m_colLastVisible )
|
||||
if ( colStart > SData().m_colLastVisible )
|
||||
{
|
||||
// don't bother redrawing something that is beyond the last
|
||||
// visible position
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( colEnd > m_colLastVisible )
|
||||
if ( colEnd > SData().m_colLastVisible )
|
||||
{
|
||||
colEnd = m_colLastVisible;
|
||||
colEnd = SData().m_colLastVisible;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3244,6 +3326,7 @@ bool wxTextCtrl::SetFont(const wxFont& font)
|
||||
// update geometry parameters
|
||||
UpdateTextRect();
|
||||
UpdateScrollbars();
|
||||
RecalcLineHeight();
|
||||
RecalcMaxWidth();
|
||||
|
||||
Refresh();
|
||||
@@ -3268,7 +3351,7 @@ void wxTextCtrl::CreateCaret()
|
||||
if ( IsEditable() )
|
||||
{
|
||||
// FIXME use renderer
|
||||
caret = new wxCaret(this, 1, GetCharHeight());
|
||||
caret = new wxCaret(this, 1, GetLineHeight());
|
||||
#ifndef __WXMSW__
|
||||
caret->SetBlinkTime(0);
|
||||
#endif // __WXMSW__
|
||||
@@ -3366,7 +3449,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
|
||||
// the previous line
|
||||
wxPoint pt = GetCaretPosition() - m_rectText.GetPosition();
|
||||
CalcUnscrolledPosition(pt.x, pt.y, &pt.x, &pt.y);
|
||||
pt.y -= GetCharHeight();
|
||||
pt.y -= GetLineHeight();
|
||||
|
||||
wxTextCoord col, row;
|
||||
if ( HitTestLogical(pt, &col, &row) != wxTE_HT_BEFORE )
|
||||
@@ -3379,7 +3462,7 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig,
|
||||
// see comments for wxACTION_TEXT_UP
|
||||
wxPoint pt = GetCaretPosition() - m_rectText.GetPosition();
|
||||
CalcUnscrolledPosition(pt.x, pt.y, &pt.x, &pt.y);
|
||||
pt.y += GetCharHeight();
|
||||
pt.y += GetLineHeight();
|
||||
|
||||
wxTextCoord col, row;
|
||||
if ( HitTestLogical(pt, &col, &row) != wxTE_HT_BELOW )
|
||||
|
Reference in New Issue
Block a user