X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7383cf9d17037a789e4ae022b310e88d192fd0ac..370dc79c5a7fd9ac24fb001e38388a210750e2e7:/src/richtext/richtextctrl.cpp?ds=inline diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index ea46d5f76d..5bdad6e584 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -16,21 +16,19 @@ #pragma hdrstop #endif +#if wxUSE_RICHTEXT + +#include "wx/richtext/richtextctrl.h" + #ifndef WX_PRECOMP #include "wx/wx.h" #endif -#include "wx/image.h" - -#if wxUSE_RICHTEXT - #include "wx/textfile.h" #include "wx/ffile.h" #include "wx/settings.h" #include "wx/filename.h" #include "wx/dcbuffer.h" - -#include "wx/richtext/richtextctrl.h" #include "wx/arrimpl.cpp" DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_ITEM_SELECTED) @@ -57,6 +55,7 @@ BEGIN_EVENT_TABLE( wxRichTextCtrl, wxScrolledWindow ) EVT_PAINT(wxRichTextCtrl::OnPaint) EVT_ERASE_BACKGROUND(wxRichTextCtrl::OnEraseBackground) EVT_IDLE(wxRichTextCtrl::OnIdle) + EVT_SCROLLWIN(wxRichTextCtrl::OnScroll) EVT_LEFT_DOWN(wxRichTextCtrl::OnLeftClick) EVT_MOTION(wxRichTextCtrl::OnMoveMouse) EVT_LEFT_UP(wxRichTextCtrl::OnLeftUp) @@ -151,11 +150,6 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos // Create a buffer RecreateBuffer(size); - wxCaret* caret = new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16); - SetCaret(caret); - caret->Show(); - PositionCaret(); - SetCursor(wxCursor(wxCURSOR_IBEAM)); return true; @@ -191,14 +185,14 @@ void wxRichTextCtrl::Freeze() } /// Call Thaw to refresh -void wxRichTextCtrl::Thaw(bool refresh) +void wxRichTextCtrl::Thaw() { m_freezeCount --; - if (m_freezeCount == 0 && refresh) + if (m_freezeCount == 0) { SetupScrollbars(); - Refresh(); + Refresh(false); } } @@ -214,7 +208,7 @@ void wxRichTextCtrl::Clear() if (m_freezeCount == 0) { SetupScrollbars(); - Refresh(); + Refresh(false); } SendUpdateEvent(); } @@ -222,31 +216,41 @@ void wxRichTextCtrl::Clear() /// Painting void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) { - wxBufferedPaintDC dc(this, m_bufferBitmap); + if (GetCaret()) + GetCaret()->Hide(); - PrepareDC(dc); + { + wxBufferedPaintDC dc(this, m_bufferBitmap); + //wxLogDebug(wxT("OnPaint")); - if (m_freezeCount > 0) - return; + PrepareDC(dc); - dc.SetFont(GetFont()); + if (m_freezeCount > 0) + return; - // Paint the background - PaintBackground(dc); + dc.SetFont(GetFont()); - wxRegion dirtyRegion = GetUpdateRegion(); + // Paint the background + PaintBackground(dc); - wxRect drawingArea(GetLogicalPoint(wxPoint(0, 0)), GetClientSize()); - wxRect availableSpace(GetClientSize()); - if (GetBuffer().GetDirty()) - { - GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); - GetBuffer().SetDirty(false); - SetupScrollbars(); + wxRegion dirtyRegion = GetUpdateRegion(); + + wxRect drawingArea(GetLogicalPoint(wxPoint(0, 0)), GetClientSize()); + wxRect availableSpace(GetClientSize()); + if (GetBuffer().GetDirty()) + { + GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); + GetBuffer().SetDirty(false); + SetupScrollbars(); + } + + GetBuffer().Draw(dc, GetBuffer().GetRange(), GetSelectionRange(), drawingArea, 0 /* descent */, 0 /* flags */); } - PositionCaret(); - GetBuffer().Draw(dc, GetBuffer().GetRange(), GetSelectionRange(), drawingArea, 0 /* descent */, 0 /* flags */); + if (GetCaret()) + GetCaret()->Show(); + + PositionCaret(); } // Empty implementation, to prevent flicker @@ -256,14 +260,21 @@ void wxRichTextCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(event)) void wxRichTextCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event)) { + wxCaret* caret = new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16); + SetCaret(caret); + caret->Show(); + PositionCaret(); + if (!IsFrozen()) - Refresh(); + Refresh(false); } void wxRichTextCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event)) { + SetCaret(NULL); + if (!IsFrozen()) - Refresh(); + Refresh(false); } /// Left-click @@ -376,7 +387,7 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) SetDefaultStyleToCursorStyle(); if (extendSel) - Refresh(); + Refresh(false); } } } @@ -422,7 +433,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) event.GetKeyCode() == WXK_NEXT || event.GetKeyCode() == WXK_END) { - Navigate(event.GetKeyCode(), flags); + KeyboardNavigate(event.GetKeyCode(), flags); } else if (event.GetKeyCode() == WXK_RETURN) { @@ -443,6 +454,8 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) EndBatchUndo(); SetDefaultStyleToCursorStyle(); + + ScrollIntoView(m_caretPosition, WXK_RIGHT); } else if (event.GetKeyCode() == WXK_BACK) { @@ -472,6 +485,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) SetDefaultStyleToCursorStyle(); } + ScrollIntoView(m_caretPosition, WXK_LEFT); } else if (event.GetKeyCode() == WXK_DELETE) { @@ -513,6 +527,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) EndBatchUndo(); SetDefaultStyleToCursorStyle(); + ScrollIntoView(m_caretPosition, WXK_RIGHT); } #if 0 else @@ -571,10 +586,9 @@ Adding Shift does the above but starts/extends selection. */ -bool wxRichTextCtrl::Navigate(int keyCode, int flags) +bool wxRichTextCtrl::KeyboardNavigate(int keyCode, int flags) { bool success = false; - Freeze(); if (keyCode == WXK_RIGHT) { @@ -633,9 +647,6 @@ bool wxRichTextCtrl::Navigate(int keyCode, int flags) SetDefaultStyleToCursorStyle(); } - // Only refresh if something changed - Thaw(success); - return success; } @@ -712,16 +723,27 @@ bool wxRichTextCtrl::ScrollIntoView(long position, int keyCode) // Make it scroll so this item is at the bottom // of the window int y = rect.y - (clientSize.y - rect.height); - SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY)); + y = (int) (0.5 + y/ppuY); + + if (startY != y) + { + SetScrollbars(ppuX, ppuY, sx, sy, 0, y); + scrolled = true; + } } else if (rect.y < startY) { // Make it scroll so this item is at the top // of the window int y = rect.y ; - SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY)); + y = (int) (0.5 + y/ppuY); + + if (startY != y) + { + SetScrollbars(ppuX, ppuY, sx, sy, 0, y); + scrolled = true; + } } - scrolled = true; } // Going up else if (keyCode == WXK_UP || keyCode == WXK_LEFT || keyCode == WXK_HOME || keyCode == WXK_PRIOR || keyCode == WXK_PAGEUP) @@ -731,16 +753,27 @@ bool wxRichTextCtrl::ScrollIntoView(long position, int keyCode) // Make it scroll so this item is at the top // of the window int y = rect.y ; - SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY)); + y = (int) (0.5 + y/ppuY); + + if (startY != y) + { + SetScrollbars(ppuX, ppuY, sx, sy, 0, y); + scrolled = true; + } } else if ((rect.y + rect.height) > (clientSize.y + startY)) { // Make it scroll so this item is at the bottom // of the window int y = rect.y - (clientSize.y - rect.height); - SetScrollbars(ppuX, ppuY, sx, sy, 0, (int) (0.5 + y/ppuY)); + y = (int) (0.5 + y/ppuY); + + if (startY != y) + { + SetScrollbars(ppuX, ppuY, sx, sy, 0, y); + scrolled = true; + } } - scrolled = true; } PositionCaret(); @@ -904,8 +937,8 @@ bool wxRichTextCtrl::MoveRight(int noPositions, int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); // TODO: optimize so that if we didn't change the selection, we don't refresh + if (extendSel) + Refresh(false); return true; } else @@ -933,8 +966,8 @@ bool wxRichTextCtrl::MoveLeft(int noPositions, int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } else @@ -950,6 +983,9 @@ bool wxRichTextCtrl::MoveUp(int noLines, int flags) /// Move up bool wxRichTextCtrl::MoveDown(int noLines, int flags) { + if (!GetCaret()) + return false; + long lineNumber = GetBuffer().GetVisibleLineNumber(m_caretPosition, true, m_caretAtLineStart); wxPoint pt = GetCaret()->GetPosition(); long newLine = lineNumber + noLines; @@ -1013,19 +1049,20 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) long newSelEnd = newPos; - if (!ExtendSelection(m_caretPosition, newSelEnd, flags)) + bool extendSel = ExtendSelection(m_caretPosition, newSelEnd, flags); + if (!extendSel) SelectNone(); SetCaretPosition(newPos, caretLineStart); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } - else - return false; + + return false; } /// Move to the end of the paragraph @@ -1035,15 +1072,16 @@ bool wxRichTextCtrl::MoveToParagraphEnd(int flags) if (para) { long newPos = para->GetRange().GetEnd() - 1; - if (!ExtendSelection(m_caretPosition, newPos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, newPos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(newPos); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } @@ -1057,15 +1095,16 @@ bool wxRichTextCtrl::MoveToParagraphStart(int flags) if (para) { long newPos = para->GetRange().GetStart() - 1; - if (!ExtendSelection(m_caretPosition, newPos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, newPos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(newPos); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } @@ -1081,15 +1120,16 @@ bool wxRichTextCtrl::MoveToLineEnd(int flags) { wxRichTextRange lineRange = line->GetAbsoluteRange(); long newPos = lineRange.GetEnd(); - if (!ExtendSelection(m_caretPosition, newPos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, newPos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(newPos); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } @@ -1105,7 +1145,8 @@ bool wxRichTextCtrl::MoveToLineStart(int flags) wxRichTextRange lineRange = line->GetAbsoluteRange(); long newPos = lineRange.GetStart()-1; - if (!ExtendSelection(m_caretPosition, newPos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, newPos, flags); + if (!extendSel) SelectNone(); wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(line); @@ -1114,8 +1155,8 @@ bool wxRichTextCtrl::MoveToLineStart(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } @@ -1127,15 +1168,16 @@ bool wxRichTextCtrl::MoveHome(int flags) { if (m_caretPosition != -1) { - if (!ExtendSelection(m_caretPosition, -1, flags)) + bool extendSel = ExtendSelection(m_caretPosition, -1, flags); + if (!extendSel) SelectNone(); SetCaretPosition(-1); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } else @@ -1149,15 +1191,16 @@ bool wxRichTextCtrl::MoveEnd(int flags) if (m_caretPosition != endPos) { - if (!ExtendSelection(m_caretPosition, endPos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, endPos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(endPos); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } else @@ -1189,15 +1232,16 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags) { wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(newLine); - if (!ExtendSelection(m_caretPosition, pos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, pos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(pos, para->GetRange().GetStart() != lineRange.GetStart()); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } } @@ -1287,15 +1331,16 @@ bool wxRichTextCtrl::WordLeft(int WXUNUSED(n), int flags) { wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(pos, true); - if (!ExtendSelection(m_caretPosition, pos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, pos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(pos, para->GetRange().GetStart() != pos); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } @@ -1310,15 +1355,16 @@ bool wxRichTextCtrl::WordRight(int WXUNUSED(n), int flags) { wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(pos, true); - if (!ExtendSelection(m_caretPosition, pos, flags)) + bool extendSel = ExtendSelection(m_caretPosition, pos, flags); + if (!extendSel) SelectNone(); SetCaretPosition(pos, para->GetRange().GetStart() != pos); PositionCaret(); SetDefaultStyleToCursorStyle(); - if (!IsFrozen()) - Refresh(); + if (extendSel) + Refresh(false); return true; } @@ -1334,7 +1380,7 @@ void wxRichTextCtrl::OnSize(wxSizeEvent& event) m_fullLayoutRequired = true; m_fullLayoutTime = wxGetLocalTimeMillis(); m_fullLayoutSavedPosition = GetFirstVisiblePosition(); - Layout(true /* onlyVisibleRect */); + LayoutContent(true /* onlyVisibleRect */); } else GetBuffer().Invalidate(wxRICHTEXT_ALL); @@ -1356,11 +1402,18 @@ void wxRichTextCtrl::OnIdle(wxIdleEvent& event) m_fullLayoutTime = 0; GetBuffer().Invalidate(wxRICHTEXT_ALL); ShowPosition(m_fullLayoutSavedPosition); - Refresh(); + Refresh(false); } event.Skip(); } +/// Scrolling +void wxRichTextCtrl::OnScroll(wxScrollWinEvent& event) +{ + // Not used + event.Skip(); +} + /// Set up scrollbars, e.g. after a resize void wxRichTextCtrl::SetupScrollbars(bool atTop) { @@ -1443,10 +1496,10 @@ bool wxRichTextCtrl::LoadFile(const wxString& filename, int type) DiscardEdits(); SetInsertionPoint(0); - Layout(); + LayoutContent(); PositionCaret(); SetupScrollbars(true); - Refresh(); + Refresh(false); SendUpdateEvent(); if (success) @@ -1514,7 +1567,8 @@ void wxRichTextCtrl::SelectAll() /// Select none void wxRichTextCtrl::SelectNone() { - SetSelection(-2, -2); + if (!(GetSelectionRange() == wxRichTextRange(-2, -2))) + SetSelection(-2, -2); m_selectionAnchor = -2; } @@ -1568,14 +1622,20 @@ wxRichTextCtrl::HitTest(const wxPoint& pt, ((wxRichTextCtrl*)this)->PrepareDC(dc); int hit = ((wxRichTextCtrl*)this)->GetBuffer().HitTest(dc, pt, *pos); - if (hit == wxRICHTEXT_HITTEST_BEFORE) - return wxTE_HT_BEFORE; - else if (hit == wxRICHTEXT_HITTEST_AFTER) - return wxTE_HT_BEYOND; - else if (hit == wxRICHTEXT_HITTEST_ON) - return wxTE_HT_ON_TEXT; - else - return wxTE_HT_UNKNOWN; + + switch ( hit ) + { + case wxRICHTEXT_HITTEST_BEFORE: + return wxTE_HT_BEFORE; + + case wxRICHTEXT_HITTEST_AFTER: + return wxTE_HT_BEYOND; + + case wxRICHTEXT_HITTEST_ON: + return wxTE_HT_ON_TEXT; + } + + return wxTE_HT_UNKNOWN; } // ---------------------------------------------------------------------------- @@ -1645,8 +1705,8 @@ bool wxRichTextCtrl::WriteImage(const wxImage& image, int bitmapType) wxImage image2 = image; if (imageBlock.MakeImageBlock(image2, bitmapType)) return WriteImage(imageBlock); - else - return false; + + return false; } bool wxRichTextCtrl::WriteImage(const wxString& filename, int bitmapType) @@ -1656,8 +1716,8 @@ bool wxRichTextCtrl::WriteImage(const wxString& filename, int bitmapType) wxImage image; if (imageBlock.MakeImageBlock(filename, bitmapType, image, false)) return WriteImage(imageBlock); - else - return false; + + return false; } bool wxRichTextCtrl::WriteImage(const wxRichTextImageBlock& imageBlock) @@ -1674,9 +1734,8 @@ bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, int bitmapType) wxImage image = bitmap.ConvertToImage(); if (image.Ok() && imageBlock.MakeImageBlock(image, bitmapType)) return WriteImage(imageBlock); - else - return false; } + return false; } @@ -1708,8 +1767,8 @@ void wxRichTextCtrl::Cut() GetBuffer().CopyToClipboard(range); DeleteSelectedContent(); - Layout(); - Refresh(); + LayoutContent(); + Refresh(false); } } @@ -1832,8 +1891,7 @@ void wxRichTextCtrl::DoSetSelection(long from, long to, bool WXUNUSED(scrollCare { m_selectionAnchor = from; m_selectionRange.SetRange(from, to); - if (!IsFrozen()) - Refresh(); + Refresh(false); PositionCaret(); } @@ -1861,9 +1919,9 @@ void wxRichTextCtrl::Remove(long from, long to) from, // New caret position this); - Layout(); + LayoutContent(); if (!IsFrozen()) - Refresh(); + Refresh(false); } bool wxRichTextCtrl::IsModified() const @@ -2171,14 +2229,21 @@ wxPoint wxRichTextCtrl::GetLogicalPoint(const wxPoint& ptPhysical) const /// Position the caret void wxRichTextCtrl::PositionCaret() { + if (!GetCaret()) + return; + + //wxLogDebug(wxT("PositionCaret")); + wxRect caretRect; if (GetCaretPositionForIndex(GetCaretPosition(), caretRect)) { wxPoint originalPt = caretRect.GetPosition(); wxPoint pt = GetPhysicalPoint(originalPt); - - GetCaret()->Move(pt); - GetCaret()->SetSize(caretRect.GetSize()); + if (GetCaret()->GetPosition() != pt) + { + GetCaret()->Move(pt); + GetCaret()->SetSize(caretRect.GetSize()); + } } } @@ -2198,8 +2263,8 @@ bool wxRichTextCtrl::GetCaretPositionForIndex(long position, wxRect& rect) rect = wxRect(pt, wxSize(wxRICHTEXT_DEFAULT_CARET_WIDTH, height)); return true; } - else - return false; + + return false; } /// Gets the line for the visible caret position. If the caret is @@ -2228,7 +2293,7 @@ wxRichTextLine* wxRichTextCtrl::GetVisibleLineForCaretPosition(long caretPositio bool wxRichTextCtrl::MoveCaret(long pos, bool showAtLineStart) { if (GetBuffer().GetDirty()) - Layout(); + LayoutContent(); if (pos <= GetBuffer().GetRange().GetEnd()) { @@ -2244,7 +2309,7 @@ bool wxRichTextCtrl::MoveCaret(long pos, bool showAtLineStart) /// Layout the buffer: which we must do before certain operations, such as /// setting the caret position. -bool wxRichTextCtrl::Layout(bool onlyVisibleRect) +bool wxRichTextCtrl::LayoutContent(bool onlyVisibleRect) { if (GetBuffer().GetDirty() || onlyVisibleRect) { @@ -2260,17 +2325,17 @@ bool wxRichTextCtrl::Layout(bool onlyVisibleRect) flags |= wxRICHTEXT_LAYOUT_SPECIFIED_RECT; availableSpace.SetPosition(GetLogicalPoint(wxPoint(0, 0))); } - + wxClientDC dc(this); dc.SetFont(GetFont()); - + PrepareDC(dc); - + GetBuffer().Defragment(); GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation GetBuffer().Layout(dc, availableSpace, flags); GetBuffer().SetDirty(false); - + if (!IsFrozen()) SetupScrollbars(); } @@ -2449,8 +2514,8 @@ bool wxRichTextCtrl::SetDefaultStyleToCursorStyle() SetDefaultStyle(attr); return true; } - else - return false; + + return false; } /// Returns the first visible position in the current view