Efficiency measures; file loading bug fix

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35955 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2005-10-20 12:55:53 +00:00
parent 3811368401
commit 1e967276d8
5 changed files with 230 additions and 94 deletions

View File

@@ -244,6 +244,9 @@ protected:
long m_end; long m_end;
}; };
#define wxRICHTEXT_ALL wxRichTextRange(-2, -2)
#define wxRICHTEXT_NONE wxRichTextRange(-1, -1)
/*! /*!
* wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes. * wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes.
*/ */
@@ -931,7 +934,7 @@ public:
virtual const wxTextAttrEx& GetBasicStyle() const { return m_attributes; } virtual const wxTextAttrEx& GetBasicStyle() const { return m_attributes; }
/// Invalidate the buffer. With no argument, invalidates whole buffer. /// Invalidate the buffer. With no argument, invalidates whole buffer.
void Invalidate(const wxRichTextRange& invalidRange = wxRichTextRange(-1, -1)); void Invalidate(const wxRichTextRange& invalidRange = wxRICHTEXT_ALL);
/// Get invalid range, rounding to entire paragraphs if argument is true. /// Get invalid range, rounding to entire paragraphs if argument is true.
wxRichTextRange GetInvalidRange(bool wholeParagraphs = false) const; wxRichTextRange GetInvalidRange(bool wholeParagraphs = false) const;
@@ -997,7 +1000,7 @@ public:
// Constructors // Constructors
wxRichTextLine(wxRichTextParagraph* parent); wxRichTextLine(wxRichTextParagraph* parent);
wxRichTextLine(const wxRichTextLine& obj) { Init(); Copy(obj); } wxRichTextLine(const wxRichTextLine& obj) { Init( NULL); Copy(obj); }
virtual ~wxRichTextLine() {} virtual ~wxRichTextLine() {}
// Overrideables // Overrideables
@@ -1015,6 +1018,9 @@ public:
const wxRichTextRange& GetRange() const { return m_range; } const wxRichTextRange& GetRange() const { return m_range; }
wxRichTextRange& GetRange() { return m_range; } wxRichTextRange& GetRange() { return m_range; }
/// Get the absolute range
wxRichTextRange GetAbsoluteRange() const;
/// Get/set the line size as calculated by Layout. /// Get/set the line size as calculated by Layout.
virtual wxSize GetSize() const { return m_size; } virtual wxSize GetSize() const { return m_size; }
virtual void SetSize(const wxSize& sz) { m_size = sz; } virtual void SetSize(const wxSize& sz) { m_size = sz; }
@@ -1036,7 +1042,7 @@ public:
// Operations // Operations
/// Initialisation /// Initialisation
void Init(); void Init(wxRichTextParagraph* parent);
/// Copy /// Copy
void Copy(const wxRichTextLine& obj); void Copy(const wxRichTextLine& obj);
@@ -1047,6 +1053,7 @@ public:
protected: protected:
/// The range of the line (start position to end position) /// The range of the line (start position to end position)
/// This is relative to the parent paragraph.
wxRichTextRange m_range; wxRichTextRange m_range;
/// Size and position measured relative to top of paragraph /// Size and position measured relative to top of paragraph
@@ -1148,6 +1155,12 @@ public:
/// Get the bullet text for this paragraph. /// Get the bullet text for this paragraph.
wxString GetBulletText(); wxString GetBulletText();
/// Allocate or reuse a line object
wxRichTextLine* AllocateLine(int pos);
/// Clear remaining unused line objects, if any
bool ClearUnusedLines(int lineCount);
protected: protected:
/// The lines that make up the wrapped paragraph /// The lines that make up the wrapped paragraph
wxRichTextLineList m_cachedLines; wxRichTextLineList m_cachedLines;
@@ -1616,8 +1629,10 @@ public:
/// Finds a handler by type /// Finds a handler by type
static wxRichTextFileHandler *FindHandler(int imageType); static wxRichTextFileHandler *FindHandler(int imageType);
/// Gets a wildcard incorporating all visible handlers /// Gets a wildcard incorporating all visible handlers. If 'types' is present,
static wxString GetExtWildcard(bool combine = false, bool save = false); /// will be filled with the file type corresponding to each filter. This can be
/// used to determine the type to pass to LoadFile given a selected filter.
static wxString GetExtWildcard(bool combine = false, bool save = false, wxArrayInt* types = NULL);
/// Clean up handlers /// Clean up handlers
static void CleanUpHandlers(); static void CleanUpHandlers();

View File

@@ -698,14 +698,15 @@ bool MyFrame::ProcessEvent(wxEvent& event)
void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event)) void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
{ {
wxString filter = wxRichTextBuffer::GetExtWildcard(false, false); wxString path = wxEmptyString;
wxString filename = wxEmptyString;
wxArrayInt fileTypes;
wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes);
if (!filter.IsEmpty()) if (!filter.IsEmpty())
filter += wxT("|"); filter += wxT("|");
filter += wxT("All files (*.*)|*.*"); filter += wxT("All files (*.*)|*.*");
wxString path = wxEmptyString;
wxString filename = wxEmptyString;
wxFileDialog dialog(this, wxFileDialog dialog(this,
_("Choose a filename"), _("Choose a filename"),
path, path,
@@ -719,7 +720,13 @@ void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
if (!path.IsEmpty()) if (!path.IsEmpty())
{ {
m_richTextCtrl->LoadFile(path); int fileType = 0;
int filterIndex = dialog.GetFilterIndex();
if (filterIndex < (int) fileTypes.GetCount())
fileType = fileTypes[filterIndex];
else
fileType = wxRICHTEXT_TYPE_TEXT;
m_richTextCtrl->LoadFile(path, fileType);
} }
} }
} }

View File

@@ -526,12 +526,15 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
bool layoutAll = true; bool layoutAll = true;
// Get invalid range, rounding to paragraph start/end. // Get invalid range, rounding to paragraph start/end.
wxRichTextRange invalidRange = GetInvalidRange(true); wxRichTextRange invalidRange = GetInvalidRange(true);
if (invalidRange == wxRichTextRange(-1, -1)) if (invalidRange == wxRICHTEXT_NONE)
layoutAll = true; return true;
if (invalidRange == wxRICHTEXT_ALL)
layoutAll = true;
else // If we know what range is affected, start laying out from that point on. else // If we know what range is affected, start laying out from that point on.
if (invalidRange.GetStart() > GetRange().GetStart()) if (invalidRange.GetStart() > GetRange().GetStart())
{ {
@@ -539,7 +542,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
if (firstParagraph) if (firstParagraph)
{ {
wxRichTextObjectList::compatibility_iterator firstNode = m_children.Find(firstParagraph); wxRichTextObjectList::compatibility_iterator firstNode = m_children.Find(firstParagraph);
wxRichTextObjectList::compatibility_iterator previousNode = firstNode ? node->GetPrevious() : (wxRichTextObjectList::compatibility_iterator) NULL; wxRichTextObjectList::compatibility_iterator previousNode = firstNode ? firstNode->GetPrevious() : (wxRichTextObjectList::compatibility_iterator) NULL;
if (firstNode && previousNode) if (firstNode && previousNode)
{ {
wxRichTextParagraph* previousParagraph = wxDynamicCast(previousNode->GetData(), wxRichTextParagraph); wxRichTextParagraph* previousParagraph = wxDynamicCast(previousNode->GetData(), wxRichTextParagraph);
@@ -547,6 +550,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
// Now we're going to start iterating from the first affected paragraph. // Now we're going to start iterating from the first affected paragraph.
node = firstNode; node = firstNode;
layoutAll = false;
} }
} }
} }
@@ -558,7 +563,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph); wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
wxASSERT (child != NULL); wxASSERT (child != NULL);
if (child && (layoutAll || !child->GetRange().IsOutside(invalidRange))) // TODO: what if the child hasn't been laid out (e.g. involved in Undo) but still has 'old' lines
if (child && (layoutAll || child->GetLines().GetCount() == 0 || !child->GetRange().IsOutside(invalidRange)))
{ {
child->Layout(dc, availableSpace, style); child->Layout(dc, availableSpace, style);
@@ -600,7 +606,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
SetCachedSize(wxSize(maxWidth, availableSpace.y)); SetCachedSize(wxSize(maxWidth, availableSpace.y));
m_dirty = false; m_dirty = false;
m_invalidRange = wxRichTextRange(-1, -1); m_invalidRange = wxRICHTEXT_NONE;
return true; return true;
} }
@@ -729,11 +735,13 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineAtPosition(long pos, bool c
{ {
wxRichTextLine* line = node2->GetData(); wxRichTextLine* line = node2->GetData();
if (line->GetRange().Contains(pos) || wxRichTextRange range = line->GetAbsoluteRange();
if (range.Contains(pos) ||
// If the position is end-of-paragraph, then return the last line of // If the position is end-of-paragraph, then return the last line of
// of the paragraph. // of the paragraph.
(line->GetRange().GetEnd() == child->GetRange().GetEnd()-1) && (pos == child->GetRange().GetEnd())) (range.GetEnd() == child->GetRange().GetEnd()-1) && (pos == child->GetRange().GetEnd()))
return line; return line;
node2 = node2->GetNext(); node2 = node2->GetNext();
@@ -803,7 +811,7 @@ int wxRichTextParagraphLayoutBox::GetLineCount() const
/// Get the paragraph for a given line /// Get the paragraph for a given line
wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphForLine(wxRichTextLine* line) const wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphForLine(wxRichTextLine* line) const
{ {
return GetParagraphAtPosition(line->GetRange().GetStart()); return GetParagraphAtPosition(line->GetAbsoluteRange().GetStart());
} }
/// Get the line size at the given position /// Get the line size at the given position
@@ -1182,13 +1190,14 @@ long wxRichTextParagraphLayoutBox::GetVisibleLineNumber(long pos, bool caretPosi
while (node2) while (node2)
{ {
wxRichTextLine* line = node2->GetData(); wxRichTextLine* line = node2->GetData();
wxRichTextRange lineRange = line->GetAbsoluteRange();
if (line->GetRange().Contains(pos)) if (lineRange.Contains(pos))
{ {
// If the caret is displayed at the end of the previous wrapped line, // If the caret is displayed at the end of the previous wrapped line,
// we want to return the line it's _displayed_ at (not the actual line // we want to return the line it's _displayed_ at (not the actual line
// containing the position). // containing the position).
if (line->GetRange().GetStart() == pos && !startOfLine && child->GetRange().GetStart() != pos) if (lineRange.GetStart() == pos && !startOfLine && child->GetRange().GetStart() != pos)
return lineCount - 1; return lineCount - 1;
else else
return lineCount; return lineCount;
@@ -1735,13 +1744,17 @@ void wxRichTextParagraphLayoutBox::Invalidate(const wxRichTextRange& invalidRang
{ {
SetDirty(true); SetDirty(true);
if (invalidRange == wxRichTextRange(-1, -1)) if (invalidRange == wxRICHTEXT_ALL)
{ {
m_invalidRange = invalidRange; m_invalidRange = wxRICHTEXT_ALL;
return; return;
} }
// Already invalidating everything
if (m_invalidRange == wxRICHTEXT_ALL)
return;
if (invalidRange.GetStart() < m_invalidRange.GetStart()) if ((invalidRange.GetStart() < m_invalidRange.GetStart()) || m_invalidRange.GetStart() == -1)
m_invalidRange.SetStart(invalidRange.GetStart()); m_invalidRange.SetStart(invalidRange.GetStart());
if (invalidRange.GetEnd() > m_invalidRange.GetEnd()) if (invalidRange.GetEnd() > m_invalidRange.GetEnd())
m_invalidRange.SetEnd(invalidRange.GetEnd()); m_invalidRange.SetEnd(invalidRange.GetEnd());
@@ -1750,7 +1763,7 @@ void wxRichTextParagraphLayoutBox::Invalidate(const wxRichTextRange& invalidRang
/// Get invalid range, rounding to entire paragraphs if argument is true. /// Get invalid range, rounding to entire paragraphs if argument is true.
wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagraphs) const wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagraphs) const
{ {
if (m_invalidRange == wxRichTextRange(-1, -1)) if (m_invalidRange == wxRICHTEXT_ALL || m_invalidRange == wxRICHTEXT_NONE)
return m_invalidRange; return m_invalidRange;
wxRichTextRange range = m_invalidRange; wxRichTextRange range = m_invalidRange;
@@ -1886,6 +1899,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
while (node) while (node)
{ {
wxRichTextLine* line = node->GetData(); wxRichTextLine* line = node->GetData();
wxRichTextRange lineRange = line->GetAbsoluteRange();
int maxDescent = line->GetDescent(); int maxDescent = line->GetDescent();
@@ -1899,11 +1913,11 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
while (node2) while (node2)
{ {
wxRichTextObject* child = node2->GetData(); wxRichTextObject* child = node2->GetData();
if (!child->GetRange().IsOutside(line->GetRange())) if (!child->GetRange().IsOutside(lineRange))
{ {
// Draw this part of the line at the correct position // Draw this part of the line at the correct position
wxRichTextRange objectRange(child->GetRange()); wxRichTextRange objectRange(child->GetRange());
objectRange.LimitTo(line->GetRange()); objectRange.LimitTo(lineRange);
wxSize objectSize; wxSize objectSize;
int descent = 0; int descent = 0;
@@ -1915,7 +1929,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
objectPosition.x += objectSize.x; objectPosition.x += objectSize.x;
} }
else if (child->GetRange().GetStart() > line->GetRange().GetEnd()) else if (child->GetRange().GetStart() > lineRange.GetEnd())
// Can break out of inner loop now since we've passed this line's range // Can break out of inner loop now since we've passed this line's range
break; break;
@@ -1931,8 +1945,6 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
/// Lay the item out /// Lay the item out
bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
{ {
ClearLines();
// Increase the size of the paragraph due to spacing // Increase the size of the paragraph due to spacing
int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore()); int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore());
int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter()); int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter());
@@ -2049,14 +2061,14 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
maxDescent = wxMax(childDescent, maxDescent); maxDescent = wxMax(childDescent, maxDescent);
// Add a new line // Add a new line
wxRichTextLine* line = new wxRichTextLine(this); wxRichTextLine* line = AllocateLine(lineCount);
line->SetRange(actualRange);
// Set relative range so we won't have to change line ranges when paragraphs are moved
line->SetRange(wxRichTextRange(actualRange.GetStart() - GetRange().GetStart(), actualRange.GetEnd() - GetRange().GetStart()));
line->SetPosition(currentPosition); line->SetPosition(currentPosition);
line->SetSize(wxSize(currentWidth, lineHeight)); line->SetSize(wxSize(currentWidth, lineHeight));
line->SetDescent(maxDescent); line->SetDescent(maxDescent);
m_cachedLines.Append(line);
// Now move down a line. TODO: add margins, spacing // Now move down a line. TODO: add margins, spacing
currentPosition.y += lineHeight; currentPosition.y += lineHeight;
currentPosition.y += lineSpacing; currentPosition.y += lineSpacing;
@@ -2101,9 +2113,13 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
{ {
currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines); currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines);
wxRichTextLine* line = new wxRichTextLine(this); wxRichTextLine* line = AllocateLine(lineCount);
wxRichTextRange actualRange(lastCompletedEndPos+1, GetRange().GetEnd()-1);
// Set relative range so we won't have to change line ranges when paragraphs are moved
line->SetRange(wxRichTextRange(actualRange.GetStart() - GetRange().GetStart(), actualRange.GetEnd() - GetRange().GetStart()));
line->SetRange(lastCompletedEndPos+1, GetRange().GetEnd()-1);
line->SetPosition(currentPosition); line->SetPosition(currentPosition);
if (lineHeight == 0) if (lineHeight == 0)
@@ -2123,10 +2139,11 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
currentPosition.y += lineHeight; currentPosition.y += lineHeight;
currentPosition.y += lineSpacing; currentPosition.y += lineSpacing;
lineCount ++; lineCount ++;
m_cachedLines.Append(line);
} }
// Remove remaining unused line objects, if any
ClearUnusedLines(lineCount);
// Apply styles to wrapped lines // Apply styles to wrapped lines
ApplyParagraphStyle(rect); ApplyParagraphStyle(rect);
@@ -2302,7 +2319,8 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz
while (node) while (node)
{ {
wxRichTextLine* line = node->GetData(); wxRichTextLine* line = node->GetData();
if (!line->GetRange().IsOutside(range)) wxRichTextRange lineRange = line->GetAbsoluteRange();
if (!lineRange.IsOutside(range))
{ {
wxSize lineSize; wxSize lineSize;
@@ -2311,9 +2329,9 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz
{ {
wxRichTextObject* child = node2->GetData(); wxRichTextObject* child = node2->GetData();
if (!child->GetRange().IsOutside(line->GetRange())) if (!child->GetRange().IsOutside(lineRange))
{ {
wxRichTextRange rangeToUse = line->GetRange(); wxRichTextRange rangeToUse = lineRange;
rangeToUse.LimitTo(child->GetRange()); rangeToUse.LimitTo(child->GetRange());
wxSize childSize; wxSize childSize;
@@ -2392,12 +2410,13 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h
while (node) while (node)
{ {
wxRichTextLine* line = node->GetData(); wxRichTextLine* line = node->GetData();
if (index >= line->GetRange().GetStart() && index <= line->GetRange().GetEnd()) wxRichTextRange lineRange = line->GetAbsoluteRange();
if (index >= lineRange.GetStart() && index <= lineRange.GetEnd())
{ {
// If this is the last point in the line, and we're forcing the // If this is the last point in the line, and we're forcing the
// returned value to be the start of the next line, do the required // returned value to be the start of the next line, do the required
// thing. // thing.
if (index == line->GetRange().GetEnd() && forceLineStart) if (index == lineRange.GetEnd() && forceLineStart)
{ {
if (node->GetNext()) if (node->GetNext())
{ {
@@ -2410,7 +2429,7 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h
pt.y = line->GetPosition().y + GetPosition().y; pt.y = line->GetPosition().y + GetPosition().y;
wxRichTextRange r(line->GetRange().GetStart(), index); wxRichTextRange r(lineRange.GetStart(), index);
wxSize rangeSize; wxSize rangeSize;
int descent = 0; int descent = 0;
@@ -2446,29 +2465,30 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition
wxRichTextLine* line = node->GetData(); wxRichTextLine* line = node->GetData();
wxPoint linePos = paraPos + line->GetPosition(); wxPoint linePos = paraPos + line->GetPosition();
wxSize lineSize = line->GetSize(); wxSize lineSize = line->GetSize();
wxRichTextRange lineRange = line->GetAbsoluteRange();
if (pt.y >= linePos.y && pt.y <= linePos.y + lineSize.y) if (pt.y >= linePos.y && pt.y <= linePos.y + lineSize.y)
{ {
if (pt.x < linePos.x) if (pt.x < linePos.x)
{ {
textPosition = line->GetRange().GetStart(); textPosition = lineRange.GetStart();
return wxRICHTEXT_HITTEST_BEFORE; return wxRICHTEXT_HITTEST_BEFORE;
} }
else if (pt.x >= (linePos.x + lineSize.x)) else if (pt.x >= (linePos.x + lineSize.x))
{ {
textPosition = line->GetRange().GetEnd(); textPosition = lineRange.GetEnd();
return wxRICHTEXT_HITTEST_AFTER; return wxRICHTEXT_HITTEST_AFTER;
} }
else else
{ {
long i; long i;
int lastX = linePos.x; int lastX = linePos.x;
for (i = line->GetRange().GetStart(); i <= line->GetRange().GetEnd(); i++) for (i = lineRange.GetStart(); i <= lineRange.GetEnd(); i++)
{ {
wxSize childSize; wxSize childSize;
int descent = 0; int descent = 0;
wxRichTextRange rangeToUse(line->GetRange().GetStart(), i); wxRichTextRange rangeToUse(lineRange.GetStart(), i);
GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED); GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED);
@@ -2763,6 +2783,40 @@ wxString wxRichTextParagraph::GetBulletText()
return text; return text;
} }
/// Allocate or reuse a line object
wxRichTextLine* wxRichTextParagraph::AllocateLine(int pos)
{
if (pos < (int) m_cachedLines.GetCount())
{
wxRichTextLine* line = m_cachedLines.Item(pos)->GetData();
line->Init(this);
return line;
}
else
{
wxRichTextLine* line = new wxRichTextLine(this);
m_cachedLines.Append(line);
return line;
}
}
/// Clear remaining unused line objects, if any
bool wxRichTextParagraph::ClearUnusedLines(int lineCount)
{
int cachedLineCount = m_cachedLines.GetCount();
if ((int) cachedLineCount > lineCount)
{
for (int i = 0; i < (int) (cachedLineCount - lineCount); i ++)
{
wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetLast();
wxRichTextLine* line = node->GetData();
m_cachedLines.Erase(node);
delete line;
}
}
return true;
}
/*! /*!
* wxRichTextLine * wxRichTextLine
@@ -2773,15 +2827,16 @@ wxString wxRichTextParagraph::GetBulletText()
wxRichTextLine::wxRichTextLine(wxRichTextParagraph* parent) wxRichTextLine::wxRichTextLine(wxRichTextParagraph* parent)
{ {
Init(); Init(parent);
m_parent = parent;
} }
/// Initialisation /// Initialisation
void wxRichTextLine::Init() void wxRichTextLine::Init(wxRichTextParagraph* parent)
{ {
m_parent = NULL; m_parent = parent;
m_range.SetRange(-1, -1);
m_pos = wxPoint(0, 0);
m_size = wxSize(0, 0);
m_descent = 0; m_descent = 0;
} }
@@ -2797,6 +2852,14 @@ wxPoint wxRichTextLine::GetAbsolutePosition() const
return m_parent->GetPosition() + m_pos; return m_parent->GetPosition() + m_pos;
} }
/// Get the absolute range
wxRichTextRange wxRichTextLine::GetAbsoluteRange() const
{
wxRichTextRange range(m_range.GetStart() + m_parent->GetRange().GetStart(), 0);
range.SetEnd(range.GetStart() + m_range.GetLength()-1);
return range;
}
/*! /*!
* wxRichTextPlainText * wxRichTextPlainText
* This object represents a single piece of text. * This object represents a single piece of text.
@@ -3095,6 +3158,7 @@ void wxRichTextBuffer::Clear()
DeleteChildren(); DeleteChildren();
GetCommandProcessor()->ClearCommands(); GetCommandProcessor()->ClearCommands();
Modify(false); Modify(false);
Invalidate(wxRICHTEXT_ALL);
} }
void wxRichTextBuffer::Reset() void wxRichTextBuffer::Reset()
@@ -3103,6 +3167,7 @@ void wxRichTextBuffer::Reset()
AddParagraph(wxEmptyString); AddParagraph(wxEmptyString);
GetCommandProcessor()->ClearCommands(); GetCommandProcessor()->ClearCommands();
Modify(false); Modify(false);
Invalidate(wxRICHTEXT_ALL);
} }
/// Submit command to insert the given text /// Submit command to insert the given text
@@ -3614,8 +3679,11 @@ void wxRichTextBuffer::CleanUpHandlers()
sm_handlers.Clear(); sm_handlers.Clear();
} }
wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save) wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save, wxArrayInt* types)
{ {
if (types)
types->Clear();
wxString wildcard; wxString wildcard;
wxList::compatibility_iterator node = GetHandlers().GetFirst(); wxList::compatibility_iterator node = GetHandlers().GetFirst();
@@ -3642,6 +3710,8 @@ wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save)
wildcard += handler->GetExtension(); wildcard += handler->GetExtension();
wildcard += wxT(")|*."); wildcard += wxT(")|*.");
wildcard += handler->GetExtension(); wildcard += handler->GetExtension();
if (types)
types->Add(handler->GetType());
} }
count ++; count ++;
} }
@@ -3659,7 +3729,13 @@ bool wxRichTextBuffer::LoadFile(const wxString& filename, int type)
{ {
wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type); wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type);
if (handler) if (handler)
return handler->LoadFile(this, filename); {
SetDefaultStyle(wxTextAttrEx());
bool success = handler->LoadFile(this, filename);
Invalidate(wxRICHTEXT_ALL);
return success;
}
else else
return false; return false;
} }
@@ -3679,7 +3755,12 @@ bool wxRichTextBuffer::LoadFile(wxInputStream& stream, int type)
{ {
wxRichTextFileHandler* handler = FindHandler(type); wxRichTextFileHandler* handler = FindHandler(type);
if (handler) if (handler)
return handler->LoadFile(this, stream); {
SetDefaultStyle(wxTextAttrEx());
bool success = handler->LoadFile(this, stream);
Invalidate(wxRICHTEXT_ALL);
return success;
}
else else
return false; return false;
} }
@@ -3886,6 +3967,7 @@ bool wxRichTextAction::Do()
{ {
m_buffer->InsertFragment(GetPosition(), m_newParagraphs); m_buffer->InsertFragment(GetPosition(), m_newParagraphs);
m_buffer->UpdateRanges(); m_buffer->UpdateRanges();
m_buffer->Invalidate(GetRange());
long newCaretPosition = GetPosition() + m_newParagraphs.GetRange().GetLength() - 1; long newCaretPosition = GetPosition() + m_newParagraphs.GetRange().GetLength() - 1;
if (m_newParagraphs.GetPartialParagraph()) if (m_newParagraphs.GetPartialParagraph())
@@ -3899,6 +3981,7 @@ bool wxRichTextAction::Do()
{ {
m_buffer->DeleteRange(GetRange()); m_buffer->DeleteRange(GetRange());
m_buffer->UpdateRanges(); m_buffer->UpdateRanges();
m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
UpdateAppearance(GetRange().GetStart()-1, true /* send update event */); UpdateAppearance(GetRange().GetStart()-1, true /* send update event */);
@@ -3907,6 +3990,7 @@ bool wxRichTextAction::Do()
case wxRICHTEXT_CHANGE_STYLE: case wxRICHTEXT_CHANGE_STYLE:
{ {
ApplyParagraphs(GetNewParagraphs()); ApplyParagraphs(GetNewParagraphs());
m_buffer->Invalidate(GetRange());
UpdateAppearance(GetPosition()); UpdateAppearance(GetPosition());
@@ -3929,6 +4013,7 @@ bool wxRichTextAction::Undo()
{ {
m_buffer->DeleteRange(GetRange()); m_buffer->DeleteRange(GetRange());
m_buffer->UpdateRanges(); m_buffer->UpdateRanges();
m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
long newCaretPosition = GetPosition() - 1; long newCaretPosition = GetPosition() - 1;
// if (m_newParagraphs.GetPartialParagraph()) // if (m_newParagraphs.GetPartialParagraph())
@@ -3942,6 +4027,7 @@ bool wxRichTextAction::Undo()
{ {
m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs); m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
m_buffer->UpdateRanges(); m_buffer->UpdateRanges();
m_buffer->Invalidate(GetRange());
UpdateAppearance(GetPosition(), true /* send update event */); UpdateAppearance(GetPosition(), true /* send update event */);
@@ -3950,6 +4036,7 @@ bool wxRichTextAction::Undo()
case wxRICHTEXT_CHANGE_STYLE: case wxRICHTEXT_CHANGE_STYLE:
{ {
ApplyParagraphs(GetOldParagraphs()); ApplyParagraphs(GetOldParagraphs());
m_buffer->Invalidate(GetRange());
UpdateAppearance(GetPosition()); UpdateAppearance(GetPosition());
@@ -4763,13 +4850,19 @@ bool wxRichTextPlainTextHandler::DoLoadFile(wxRichTextBuffer *buffer, wxInputStr
wxString str; wxString str;
int ch = 0; int ch = 0;
int lastCh = 0;
while (!stream.Eof()) while (!stream.Eof())
{ {
ch = stream.GetC(); ch = stream.GetC();
if (ch > 0) if (ch == 10 && lastCh != 13)
str += wxT('\n');
if (ch > 0 && ch != 10)
str += wxChar(ch); str += wxChar(ch);
lastCh = ch;
} }
buffer->Clear(); buffer->Clear();

View File

@@ -291,7 +291,7 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event)
wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position); wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position);
wxRichTextLine* line = GetBuffer().GetLineAtPosition(position); wxRichTextLine* line = GetBuffer().GetLineAtPosition(position);
if (line && para && line->GetRange().GetStart() == position && para->GetRange().GetStart() != position) if (line && para && line->GetAbsoluteRange().GetStart() == position && para->GetRange().GetStart() != position)
caretAtLineStart = true; caretAtLineStart = true;
position --; position --;
} }
@@ -358,7 +358,7 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position); wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position);
wxRichTextLine* line = GetBuffer().GetLineAtPosition(position); wxRichTextLine* line = GetBuffer().GetLineAtPosition(position);
if (line && para && line->GetRange().GetStart() == position && para->GetRange().GetStart() != position) if (line && para && line->GetAbsoluteRange().GetStart() == position && para->GetRange().GetStart() != position)
caretAtLineStart = true; caretAtLineStart = true;
position --; position --;
} }
@@ -792,10 +792,12 @@ void wxRichTextCtrl::MoveCaretForward(long oldPosition)
if (line) if (line)
{ {
wxRichTextRange lineRange = line->GetAbsoluteRange();
// We're at the end of a line. See whether we need to // We're at the end of a line. See whether we need to
// stay at the same actual caret position but change visual // stay at the same actual caret position but change visual
// position, or not. // position, or not.
if (oldPosition == line->GetRange().GetEnd()) if (oldPosition == lineRange.GetEnd())
{ {
if (m_caretAtLineStart) if (m_caretAtLineStart)
{ {
@@ -835,16 +837,18 @@ void wxRichTextCtrl::MoveCaretBack(long oldPosition)
if (line) if (line)
{ {
wxRichTextRange lineRange = line->GetAbsoluteRange();
// We're at the start of a line. See whether we need to // We're at the start of a line. See whether we need to
// stay at the same actual caret position but change visual // stay at the same actual caret position but change visual
// position, or not. // position, or not.
if (oldPosition == line->GetRange().GetStart()) if (oldPosition == lineRange.GetStart())
{ {
m_caretPosition = oldPosition-1; m_caretPosition = oldPosition-1;
m_caretAtLineStart = true; m_caretAtLineStart = true;
return; return;
} }
else if (oldPosition == line->GetRange().GetEnd()) else if (oldPosition == lineRange.GetEnd())
{ {
if (m_caretAtLineStart) if (m_caretAtLineStart)
{ {
@@ -985,13 +989,14 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags)
if (hitTest == wxRICHTEXT_HITTEST_BEFORE) if (hitTest == wxRICHTEXT_HITTEST_BEFORE)
{ {
wxRichTextLine* thisLine = GetBuffer().GetLineAtPosition(newPos-1); wxRichTextLine* thisLine = GetBuffer().GetLineAtPosition(newPos-1);
if (thisLine && (newPos-1) == thisLine->GetRange().GetEnd()) wxRichTextRange lineRange;
if (thisLine)
lineRange = thisLine->GetAbsoluteRange();
if (thisLine && (newPos-1) == lineRange.GetEnd())
{ {
// if (para->GetRange().GetStart() != thisLine->GetRange().GetStart()) newPos --;
{ caretLineStart = true;
newPos --;
caretLineStart = true;
}
} }
else else
{ {
@@ -1069,7 +1074,8 @@ bool wxRichTextCtrl::MoveToLineEnd(int flags)
if (line) if (line)
{ {
long newPos = line->GetRange().GetEnd(); wxRichTextRange lineRange = line->GetAbsoluteRange();
long newPos = lineRange.GetEnd();
if (!ExtendSelection(m_caretPosition, newPos, flags)) if (!ExtendSelection(m_caretPosition, newPos, flags))
SelectNone(); SelectNone();
@@ -1091,14 +1097,15 @@ bool wxRichTextCtrl::MoveToLineStart(int flags)
wxRichTextLine* line = GetVisibleLineForCaretPosition(m_caretPosition); wxRichTextLine* line = GetVisibleLineForCaretPosition(m_caretPosition);
if (line) if (line)
{ {
long newPos = line->GetRange().GetStart()-1; wxRichTextRange lineRange = line->GetAbsoluteRange();
long newPos = lineRange.GetStart()-1;
if (!ExtendSelection(m_caretPosition, newPos, flags)) if (!ExtendSelection(m_caretPosition, newPos, flags))
SelectNone(); SelectNone();
wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(line); wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(line);
SetCaretPosition(newPos, para->GetRange().GetStart() != line->GetRange().GetStart()); SetCaretPosition(newPos, para->GetRange().GetStart() != lineRange.GetStart());
PositionCaret(); PositionCaret();
SetDefaultStyleToCursorStyle(); SetDefaultStyleToCursorStyle();
@@ -1171,7 +1178,8 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags)
wxRichTextLine* newLine = GetBuffer().GetLineAtYPosition(newY); wxRichTextLine* newLine = GetBuffer().GetLineAtYPosition(newY);
if (newLine) if (newLine)
{ {
long pos = newLine->GetRange().GetStart()-1; wxRichTextRange lineRange = newLine->GetAbsoluteRange();
long pos = lineRange.GetStart()-1;
if (pos != m_caretPosition) if (pos != m_caretPosition)
{ {
wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(newLine); wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(newLine);
@@ -1179,7 +1187,7 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags)
if (!ExtendSelection(m_caretPosition, pos, flags)) if (!ExtendSelection(m_caretPosition, pos, flags))
SelectNone(); SelectNone();
SetCaretPosition(pos, para->GetRange().GetStart() != newLine->GetRange().GetStart()); SetCaretPosition(pos, para->GetRange().GetStart() != lineRange.GetStart());
PositionCaret(); PositionCaret();
SetDefaultStyleToCursorStyle(); SetDefaultStyleToCursorStyle();
@@ -1315,7 +1323,7 @@ bool wxRichTextCtrl::WordRight(int WXUNUSED(n), int flags)
/// Sizing /// Sizing
void wxRichTextCtrl::OnSize(wxSizeEvent& event) void wxRichTextCtrl::OnSize(wxSizeEvent& event)
{ {
GetBuffer().SetDirty(true); GetBuffer().Invalidate(wxRICHTEXT_ALL);
RecreateBuffer(); RecreateBuffer();
@@ -2171,8 +2179,9 @@ wxRichTextLine* wxRichTextCtrl::GetVisibleLineForCaretPosition(long caretPositio
wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(caretPosition, true); wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(caretPosition, true);
if (line) if (line)
{ {
if (caretPosition == line->GetRange().GetStart()-1 && wxRichTextRange lineRange = line->GetAbsoluteRange();
(para->GetRange().GetStart() != line->GetRange().GetStart())) if (caretPosition == lineRange.GetStart()-1 &&
(para->GetRange().GetStart() != lineRange.GetStart()))
{ {
if (!m_caretAtLineStart) if (!m_caretAtLineStart)
line = GetBuffer().GetLineAtPosition(caretPosition-1, true); line = GetBuffer().GetLineAtPosition(caretPosition-1, true);
@@ -2204,24 +2213,27 @@ bool wxRichTextCtrl::MoveCaret(long pos, bool showAtLineStart)
/// setting the caret position. /// setting the caret position.
bool wxRichTextCtrl::Layout() bool wxRichTextCtrl::Layout()
{ {
wxRect availableSpace(GetClientSize()); if (GetBuffer().GetDirty())
if (availableSpace.width == 0) {
availableSpace.width = 10; wxRect availableSpace(GetClientSize());
if (availableSpace.height == 0) if (availableSpace.width == 0)
availableSpace.height = 10; availableSpace.width = 10;
if (availableSpace.height == 0)
wxClientDC dc(this); availableSpace.height = 10;
dc.SetFont(GetFont());
wxClientDC dc(this);
PrepareDC(dc); dc.SetFont(GetFont());
GetBuffer().Defragment(); PrepareDC(dc);
GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation
GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); GetBuffer().Defragment();
GetBuffer().SetDirty(false); GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation
GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT);
if (!IsFrozen()) GetBuffer().SetDirty(false);
SetupScrollbars();
if (!IsFrozen())
SetupScrollbars();
}
return true; return true;
} }

View File

@@ -257,6 +257,15 @@ wxString wxRichTextXMLHandler::GetText(wxXmlNode *node, const wxString& param, b
return str1; return str1;
} }
// For use with earlier versions of wxWidgets
#ifndef WXUNUSED_IN_UNICODE
#if wxUSE_UNICODE
#define WXUNUSED_IN_UNICODE(x) WXUNUSED(x)
#else
#define WXUNUSED_IN_UNICODE(x) x
#endif
#endif
// write string to output: // write string to output:
inline static void OutputString(wxOutputStream& stream, const wxString& str, inline static void OutputString(wxOutputStream& stream, const wxString& str,
wxMBConv *WXUNUSED_IN_UNICODE(convMem) = NULL, wxMBConv *convFile = NULL) wxMBConv *WXUNUSED_IN_UNICODE(convMem) = NULL, wxMBConv *convFile = NULL)