X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/7e4fe193d10c00c94814b519710e4252abc17ed2..f7ae43f080576ef142d3884073df298294860328:/src/richtext/richtextctrl.cpp diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index f82ffe8707..d9cc795957 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -32,6 +32,7 @@ #include "wx/dcbuffer.h" #include "wx/arrimpl.cpp" #include "wx/fontenum.h" +#include "wx/accel.h" // DLL options compatibility check: #include "wx/app.h" @@ -54,10 +55,74 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_CONTENT_INSERTED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_CONTENT_DELETED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLE_CHANGED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_SELECTION_CHANGED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_BUFFER_RESET) -IMPLEMENT_CLASS( wxRichTextCtrl, wxControl ) +#if wxRICHTEXT_USE_OWN_CARET -IMPLEMENT_CLASS( wxRichTextEvent, wxNotifyEvent ) +/*! + * wxRichTextCaret + * + * This implements a non-flashing cursor in case there + * are platform-specific problems with the generic caret. + * wxRICHTEXT_USE_OWN_CARET is set in richtextbuffer.h. + */ + +class wxRichTextCaret: public wxCaret +{ +public: + // ctors + // ----- + // default - use Create() + wxRichTextCaret() { Init(); } + // creates a block caret associated with the given window + wxRichTextCaret(wxRichTextCtrl *window, int width, int height) + : wxCaret(window, width, height) { Init(); m_richTextCtrl = window; } + wxRichTextCaret(wxRichTextCtrl *window, const wxSize& size) + : wxCaret(window, size) { Init(); m_richTextCtrl = window; } + + virtual ~wxRichTextCaret(); + + // implementation + // -------------- + + // called by wxWindow (not using the event tables) + virtual void OnSetFocus(); + virtual void OnKillFocus(); + + // draw the caret on the given DC + void DoDraw(wxDC *dc); + + // get the visible count + int GetVisibleCount() const { return m_countVisible; } + + // delay repositioning + bool GetNeedsUpdate() const { return m_needsUpdate; } + void SetNeedsUpdate(bool needsUpdate = true ) { m_needsUpdate = needsUpdate; } + +protected: + virtual void DoShow(); + virtual void DoHide(); + virtual void DoMove(); + virtual void DoSize(); + + // refresh the caret + void Refresh(); + +private: + void Init(); + + int m_xOld, + m_yOld; + bool m_hasFocus; // true => our window has focus + bool m_needsUpdate; // must be repositioned + + wxRichTextCtrl* m_richTextCtrl; +}; +#endif + +IMPLEMENT_DYNAMIC_CLASS( wxRichTextCtrl, wxControl ) + +IMPLEMENT_DYNAMIC_CLASS( wxRichTextEvent, wxNotifyEvent ) BEGIN_EVENT_TABLE( wxRichTextCtrl, wxControl ) EVT_PAINT(wxRichTextCtrl::OnPaint) @@ -71,11 +136,13 @@ BEGIN_EVENT_TABLE( wxRichTextCtrl, wxControl ) EVT_MIDDLE_DOWN(wxRichTextCtrl::OnMiddleClick) EVT_LEFT_DCLICK(wxRichTextCtrl::OnLeftDClick) EVT_CHAR(wxRichTextCtrl::OnChar) + EVT_KEY_DOWN(wxRichTextCtrl::OnChar) EVT_SIZE(wxRichTextCtrl::OnSize) EVT_SET_FOCUS(wxRichTextCtrl::OnSetFocus) EVT_KILL_FOCUS(wxRichTextCtrl::OnKillFocus) EVT_MOUSE_CAPTURE_LOST(wxRichTextCtrl::OnCaptureLost) EVT_CONTEXT_MENU(wxRichTextCtrl::OnContextMenu) + EVT_SYS_COLOUR_CHANGED(wxRichTextCtrl::OnSysColourChanged) EVT_MENU(wxID_UNDO, wxRichTextCtrl::OnUndo) EVT_UPDATE_UI(wxID_UNDO, wxRichTextCtrl::OnUpdateUndo) @@ -129,9 +196,9 @@ wxRichTextCtrl::wxRichTextCtrl(wxWindow* parent, bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) { - if (!wxTextCtrlBase::Create(parent, id, pos, size, - style|wxFULL_REPAINT_ON_RESIZE, - validator, name)) + if (!wxControl::Create(parent, id, pos, size, + style|wxFULL_REPAINT_ON_RESIZE, + validator, name)) return false; if (!GetFont().Ok()) @@ -139,36 +206,37 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); } - GetBuffer().Reset(); - GetBuffer().SetRichTextCtrl(this); - - SetCaret(new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16)); - GetCaret()->Show(); - if (style & wxTE_READONLY) SetEditable(false); // The base attributes must all have default values - wxTextAttrEx attributes; + wxTextAttr attributes; attributes.SetFont(GetFont()); attributes.SetTextColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); attributes.SetAlignment(wxTEXT_ALIGNMENT_LEFT); attributes.SetLineSpacing(10); attributes.SetParagraphSpacingAfter(10); attributes.SetParagraphSpacingBefore(0); - attributes.SetTextEffects(0); - attributes.SetTextEffectFlags(wxTEXT_ATTR_EFFECT_STRIKETHROUGH|wxTEXT_ATTR_EFFECT_CAPITALS); SetBasicStyle(attributes); // The default attributes will be merged with base attributes, so // can be empty to begin with - wxTextAttrEx defaultAttributes; + wxTextAttr defaultAttributes; SetDefaultStyle(defaultAttributes); SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); SetBackgroundStyle(wxBG_STYLE_CUSTOM); + GetBuffer().Reset(); + GetBuffer().SetRichTextCtrl(this); + +#if wxRICHTEXT_USE_OWN_CARET + SetCaret(new wxRichTextCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16)); +#else + SetCaret(new wxCaret(this, wxRICHTEXT_DEFAULT_CARET_WIDTH, 16)); +#endif + // Tell the sizers to use the given or best size SetInitialSize(size); @@ -187,6 +255,19 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va GetBuffer().AddEventHandler(this); + // Accelerators + wxAcceleratorEntry entries[6]; + + entries[0].Set(wxACCEL_CMD, (int) 'C', wxID_COPY); + entries[1].Set(wxACCEL_CMD, (int) 'X', wxID_CUT); + entries[2].Set(wxACCEL_CMD, (int) 'V', wxID_PASTE); + entries[3].Set(wxACCEL_CMD, (int) 'A', wxID_SELECTALL); + entries[4].Set(wxACCEL_CMD, (int) 'Z', wxID_UNDO); + entries[5].Set(wxACCEL_CMD, (int) 'Y', wxID_REDO); + + wxAcceleratorTable accel(6, entries); + SetAcceleratorTable(accel); + return true; } @@ -200,7 +281,6 @@ wxRichTextCtrl::~wxRichTextCtrl() /// Member initialisation void wxRichTextCtrl::Init() { - m_freezeCount = 0; m_contextMenu = NULL; m_caret = NULL; m_caretPosition = -1; @@ -216,22 +296,14 @@ void wxRichTextCtrl::Init() m_caretPositionForDefaultStyle = -2; } -/// Call Freeze to prevent refresh -void wxRichTextCtrl::Freeze() -{ - m_freezeCount ++; -} - -/// Call Thaw to refresh -void wxRichTextCtrl::Thaw() +void wxRichTextCtrl::DoThaw() { - m_freezeCount --; - - if (m_freezeCount == 0) - { + if (GetBuffer().GetDirty()) + LayoutContent(); + else SetupScrollbars(); - Refresh(false); - } + + wxWindow::DoThaw(); } /// Clear all text @@ -244,21 +316,24 @@ void wxRichTextCtrl::Clear() m_caretAtLineStart = false; m_selectionRange.SetRange(-2, -2); - SetScrollbars(0, 0, 0, 0, 0, 0); + Scroll(0,0); - if (m_freezeCount == 0) + if (!IsFrozen()) { - SetupScrollbars(); + LayoutContent(); Refresh(false); } - SendTextUpdatedEvent(); + + wxTextCtrl::SendTextUpdatedEvent(this); } /// Painting void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) { - if (GetCaret() && GetCaret()->IsVisible()) +#if !wxRICHTEXT_USE_OWN_CARET + if (GetCaret() && !IsFrozen()) GetCaret()->Hide(); +#endif { #if wxRICHTEXT_BUFFERED_PAINTING @@ -266,11 +341,12 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) #else wxPaintDC dc(this); #endif - PrepareDC(dc); - if (m_freezeCount > 0) + if (IsFrozen()) return; + PrepareDC(dc); + dc.SetFont(GetFont()); // Paint the background @@ -290,12 +366,19 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) } GetBuffer().Draw(dc, GetBuffer().GetRange(), GetInternalSelectionRange(), drawingArea, 0 /* descent */, 0 /* flags */); +#if wxRICHTEXT_USE_OWN_CARET + if (GetCaret()->IsVisible()) + { + ((wxRichTextCaret*) GetCaret())->DoDraw(& dc); + } +#endif } - if (GetCaret() && !GetCaret()->IsVisible()) +#if !wxRICHTEXT_USE_OWN_CARET + if (GetCaret()) GetCaret()->Show(); - PositionCaret(); +#endif } // Empty implementation, to prevent flicker @@ -307,22 +390,33 @@ void wxRichTextCtrl::OnSetFocus(wxFocusEvent& WXUNUSED(event)) { if (GetCaret()) { - if (!GetCaret()->IsVisible()) - GetCaret()->Show(); +#if !wxRICHTEXT_USE_OWN_CARET PositionCaret(); +#endif + GetCaret()->Show(); } - // if (!IsFrozen()) - // Refresh(false); +#if defined(__WXGTK__) && !wxRICHTEXT_USE_OWN_CARET + // Work around dropouts when control is focused + if (!IsFrozen()) + { + Refresh(false); + } +#endif } void wxRichTextCtrl::OnKillFocus(wxFocusEvent& WXUNUSED(event)) { - if (GetCaret() && GetCaret()->IsVisible()) + if (GetCaret()) GetCaret()->Hide(); - // if (!IsFrozen()) - // Refresh(false); +#if defined(__WXGTK__) && !wxRICHTEXT_USE_OWN_CARET + // Work around dropouts when control is focused + if (!IsFrozen()) + { + Refresh(false); + } +#endif } void wxRichTextCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) @@ -348,8 +442,6 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event) m_dragging = true; CaptureMouse(); - SelectNone(); - bool caretAtLineStart = false; if (hit & wxRICHTEXT_HITTEST_BEFORE) @@ -365,8 +457,20 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event) position --; } + long oldCaretPos = m_caretPosition; + MoveCaret(position, caretAtLineStart); SetDefaultStyleToCursorStyle(); + + if (event.ShiftDown()) + { + if (m_selectionRange.GetStart() == -2) + ExtendSelection(oldCaretPos, m_caretPosition, wxRICHTEXT_SHIFT_DOWN); + else + ExtendSelection(m_caretPosition, m_caretPosition, wxRICHTEXT_SHIFT_DOWN); + } + else + SelectNone(); } event.Skip(); @@ -390,7 +494,7 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) wxPoint logicalPt = event.GetLogicalPosition(dc); int hit = GetBuffer().HitTest(dc, logicalPt, position); - if (hit != wxRICHTEXT_HITTEST_NONE) + if ((hit != wxRICHTEXT_HITTEST_NONE) && !(hit & wxRICHTEXT_HITTEST_OUTSIDE)) { wxRichTextEvent cmdEvent( wxEVT_COMMAND_RICHTEXT_LEFT_CLICK, @@ -400,7 +504,7 @@ void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event) if (!GetEventHandler()->ProcessEvent(cmdEvent)) { - wxTextAttrEx attr; + wxTextAttr attr; if (GetStyle(position, attr)) { if (attr.HasFlag(wxTEXT_ATTR_URL)) @@ -448,7 +552,7 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) { if (hit != wxRICHTEXT_HITTEST_NONE && !(hit & wxRICHTEXT_HITTEST_OUTSIDE)) { - wxTextAttrEx attr; + wxTextAttr attr; if (GetStyle(position, attr)) { if (attr.HasFlag(wxTEXT_ATTR_URL)) @@ -492,19 +596,16 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) if (m_caretPosition != position) { - bool extendSel = ExtendSelection(m_caretPosition, position, wxRICHTEXT_SHIFT_DOWN); + ExtendSelection(m_caretPosition, position, wxRICHTEXT_SHIFT_DOWN); MoveCaret(position, caretAtLineStart); SetDefaultStyleToCursorStyle(); - - if (extendSel) - Refresh(false); } } } /// Right-click -void wxRichTextCtrl::OnRightClick(wxMouseEvent& WXUNUSED(event)) +void wxRichTextCtrl::OnRightClick(wxMouseEvent& event) { SetFocus(); @@ -514,7 +615,8 @@ void wxRichTextCtrl::OnRightClick(wxMouseEvent& WXUNUSED(event)) cmdEvent.SetEventObject(this); cmdEvent.SetPosition(m_caretPosition+1); - GetEventHandler()->ProcessEvent(cmdEvent); + if (!GetEventHandler()->ProcessEvent(cmdEvent)) + event.Skip(); } /// Left-double-click @@ -556,25 +658,163 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) if (event.AltDown()) flags |= wxRICHTEXT_ALT_DOWN; - if (event.GetKeyCode() == WXK_LEFT || - event.GetKeyCode() == WXK_RIGHT || - event.GetKeyCode() == WXK_UP || - event.GetKeyCode() == WXK_DOWN || - event.GetKeyCode() == WXK_HOME || - event.GetKeyCode() == WXK_PAGEUP || - event.GetKeyCode() == WXK_PAGEDOWN || - event.GetKeyCode() == WXK_END || - - event.GetKeyCode() == WXK_NUMPAD_LEFT || - event.GetKeyCode() == WXK_NUMPAD_RIGHT || - event.GetKeyCode() == WXK_NUMPAD_UP || - event.GetKeyCode() == WXK_NUMPAD_DOWN || - event.GetKeyCode() == WXK_NUMPAD_HOME || - event.GetKeyCode() == WXK_NUMPAD_PAGEUP || - event.GetKeyCode() == WXK_NUMPAD_PAGEDOWN || - event.GetKeyCode() == WXK_NUMPAD_END) - { - KeyboardNavigate(event.GetKeyCode(), flags); + if (event.GetEventType() == wxEVT_KEY_DOWN) + { + if (event.GetKeyCode() == WXK_LEFT || + event.GetKeyCode() == WXK_RIGHT || + event.GetKeyCode() == WXK_UP || + event.GetKeyCode() == WXK_DOWN || + event.GetKeyCode() == WXK_HOME || + event.GetKeyCode() == WXK_PAGEUP || + event.GetKeyCode() == WXK_PAGEDOWN || + event.GetKeyCode() == WXK_END || + + event.GetKeyCode() == WXK_NUMPAD_LEFT || + event.GetKeyCode() == WXK_NUMPAD_RIGHT || + event.GetKeyCode() == WXK_NUMPAD_UP || + event.GetKeyCode() == WXK_NUMPAD_DOWN || + event.GetKeyCode() == WXK_NUMPAD_HOME || + event.GetKeyCode() == WXK_NUMPAD_PAGEUP || + event.GetKeyCode() == WXK_NUMPAD_PAGEDOWN || + event.GetKeyCode() == WXK_NUMPAD_END) + { + KeyboardNavigate(event.GetKeyCode(), flags); + return; + } + + long keycode = event.GetKeyCode(); + switch ( keycode ) + { + case WXK_ESCAPE: + case WXK_START: + case WXK_LBUTTON: + case WXK_RBUTTON: + case WXK_CANCEL: + case WXK_MBUTTON: + case WXK_CLEAR: + case WXK_SHIFT: + case WXK_ALT: + case WXK_CONTROL: + case WXK_MENU: + case WXK_PAUSE: + case WXK_CAPITAL: + case WXK_END: + case WXK_HOME: + case WXK_LEFT: + case WXK_UP: + case WXK_RIGHT: + case WXK_DOWN: + case WXK_SELECT: + case WXK_PRINT: + case WXK_EXECUTE: + case WXK_SNAPSHOT: + case WXK_INSERT: + case WXK_HELP: + case WXK_F1: + case WXK_F2: + case WXK_F3: + case WXK_F4: + case WXK_F5: + case WXK_F6: + case WXK_F7: + case WXK_F8: + case WXK_F9: + case WXK_F10: + case WXK_F11: + case WXK_F12: + case WXK_F13: + case WXK_F14: + case WXK_F15: + case WXK_F16: + case WXK_F17: + case WXK_F18: + case WXK_F19: + case WXK_F20: + case WXK_F21: + case WXK_F22: + case WXK_F23: + case WXK_F24: + case WXK_NUMLOCK: + case WXK_SCROLL: + case WXK_PAGEUP: + case WXK_PAGEDOWN: + case WXK_NUMPAD_F1: + case WXK_NUMPAD_F2: + case WXK_NUMPAD_F3: + case WXK_NUMPAD_F4: + case WXK_NUMPAD_HOME: + case WXK_NUMPAD_LEFT: + case WXK_NUMPAD_UP: + case WXK_NUMPAD_RIGHT: + case WXK_NUMPAD_DOWN: + case WXK_NUMPAD_PAGEUP: + case WXK_NUMPAD_PAGEDOWN: + case WXK_NUMPAD_END: + case WXK_NUMPAD_BEGIN: + case WXK_NUMPAD_INSERT: + case WXK_NUMPAD_DELETE: + case WXK_WINDOWS_LEFT: + { + return; + } + default: + { + } + } + + // Must process this before translation, otherwise it's translated into a WXK_DELETE event. + if (event.CmdDown() && event.GetKeyCode() == WXK_BACK) + { + BeginBatchUndo(_("Delete Text")); + + long newPos = m_caretPosition; + + bool processed = DeleteSelectedContent(& newPos); + + // Submit range in character positions, which are greater than caret positions, + // so subtract 1 for deleted character and add 1 for conversion to character position. + if (newPos > -1) + { + if (event.CmdDown()) + { + long pos = wxRichTextCtrl::FindNextWordPosition(-1); + if (pos < newPos) + { + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(pos+1, newPos), this); + processed = true; + } + } + + if (!processed) + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(newPos, newPos), this); + } + + EndBatchUndo(); + + if (GetLastPosition() == -1) + { + GetBuffer().Reset(); + + m_caretPosition = -1; + PositionCaret(); + SetDefaultStyleToCursorStyle(); + } + + ScrollIntoView(m_caretPosition, WXK_LEFT); + + wxRichTextEvent cmdEvent( + wxEVT_COMMAND_RICHTEXT_DELETE, + GetId()); + cmdEvent.SetEventObject(this); + cmdEvent.SetFlags(flags); + cmdEvent.SetPosition(m_caretPosition+1); + GetEventHandler()->ProcessEvent(cmdEvent); + + Update(); + } + else + event.Skip(); + return; } @@ -599,9 +839,11 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) wxString text; text = wxRichTextLineBreakChar; GetBuffer().InsertTextWithUndo(newPos+1, text, this); + m_caretAtLineStart = true; + PositionCaret(); } else - GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); + GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE|wxRICHTEXT_INSERT_INTERACTIVE); EndBatchUndo(); SetDefaultStyleToCursorStyle(); @@ -629,14 +871,27 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) { BeginBatchUndo(_("Delete Text")); + long newPos = m_caretPosition; + + bool processed = DeleteSelectedContent(& newPos); + // Submit range in character positions, which are greater than caret positions, // so subtract 1 for deleted character and add 1 for conversion to character position. - if (m_caretPosition > -1 && !HasSelection()) + if (newPos > -1) { - GetBuffer().DeleteRangeWithUndo(wxRichTextRange(m_caretPosition, m_caretPosition), this); + if (event.CmdDown()) + { + long pos = wxRichTextCtrl::FindNextWordPosition(-1); + if (pos < newPos) + { + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(pos+1, newPos), this); + processed = true; + } + } + + if (!processed) + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(newPos, newPos), this); } - else - DeleteSelectedContent(); EndBatchUndo(); @@ -665,13 +920,26 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) { BeginBatchUndo(_("Delete Text")); + long newPos = m_caretPosition; + + bool processed = DeleteSelectedContent(& newPos); + // Submit range in character positions, which are greater than caret positions, - if (m_caretPosition < GetBuffer().GetRange().GetEnd()+1 && !HasSelection()) + if (newPos < GetBuffer().GetRange().GetEnd()+1) { - GetBuffer().DeleteRangeWithUndo(wxRichTextRange(m_caretPosition+1, m_caretPosition+1), this); + if (event.CmdDown()) + { + long pos = wxRichTextCtrl::FindNextWordPosition(1); + if (pos != -1 && (pos > newPos)) + { + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(newPos+1, pos), this); + processed = true; + } + } + + if (!processed) + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(newPos+1, newPos+1), this); } - else - DeleteSelectedContent(); EndBatchUndo(); @@ -700,100 +968,6 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) switch ( keycode ) { case WXK_ESCAPE: - case WXK_DELETE: - case WXK_START: - case WXK_LBUTTON: - case WXK_RBUTTON: - case WXK_CANCEL: - case WXK_MBUTTON: - case WXK_CLEAR: - case WXK_SHIFT: - case WXK_ALT: - case WXK_CONTROL: - case WXK_MENU: - case WXK_PAUSE: - case WXK_CAPITAL: - case WXK_END: - case WXK_HOME: - case WXK_LEFT: - case WXK_UP: - case WXK_RIGHT: - case WXK_DOWN: - case WXK_SELECT: - case WXK_PRINT: - case WXK_EXECUTE: - case WXK_SNAPSHOT: - case WXK_INSERT: - case WXK_HELP: - case WXK_NUMPAD0: - case WXK_NUMPAD1: - case WXK_NUMPAD2: - case WXK_NUMPAD3: - case WXK_NUMPAD4: - case WXK_NUMPAD5: - case WXK_NUMPAD6: - case WXK_NUMPAD7: - case WXK_NUMPAD8: - case WXK_NUMPAD9: - case WXK_MULTIPLY: - case WXK_ADD: - case WXK_SEPARATOR: - case WXK_SUBTRACT: - case WXK_DECIMAL: - case WXK_DIVIDE: - case WXK_F1: - case WXK_F2: - case WXK_F3: - case WXK_F4: - case WXK_F5: - case WXK_F6: - case WXK_F7: - case WXK_F8: - case WXK_F9: - case WXK_F10: - case WXK_F11: - case WXK_F12: - case WXK_F13: - case WXK_F14: - case WXK_F15: - case WXK_F16: - case WXK_F17: - case WXK_F18: - case WXK_F19: - case WXK_F20: - case WXK_F21: - case WXK_F22: - case WXK_F23: - case WXK_F24: - case WXK_NUMLOCK: - case WXK_SCROLL: - case WXK_PAGEUP: - case WXK_PAGEDOWN: - case WXK_NUMPAD_SPACE: - case WXK_NUMPAD_TAB: - case WXK_NUMPAD_ENTER: - case WXK_NUMPAD_F1: - case WXK_NUMPAD_F2: - case WXK_NUMPAD_F3: - case WXK_NUMPAD_F4: - case WXK_NUMPAD_HOME: - case WXK_NUMPAD_LEFT: - case WXK_NUMPAD_UP: - case WXK_NUMPAD_RIGHT: - case WXK_NUMPAD_DOWN: - case WXK_NUMPAD_PAGEUP: - case WXK_NUMPAD_PAGEDOWN: - case WXK_NUMPAD_END: - case WXK_NUMPAD_BEGIN: - case WXK_NUMPAD_INSERT: - case WXK_NUMPAD_DELETE: - case WXK_NUMPAD_EQUAL: - case WXK_NUMPAD_MULTIPLY: - case WXK_NUMPAD_ADD: - case WXK_NUMPAD_SEPARATOR: - case WXK_NUMPAD_SUBTRACT: - case WXK_NUMPAD_DECIMAL: - case WXK_WINDOWS_LEFT: { event.Skip(); return; @@ -801,7 +975,11 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event) default: { +#ifdef __WXMAC__ + if (event.CmdDown()) +#else if (event.CmdDown() || event.AltDown()) +#endif { event.Skip(); return; @@ -985,6 +1163,11 @@ bool wxRichTextCtrl::ExtendSelection(long oldPos, long newPos, int flags) { if (flags & wxRICHTEXT_SHIFT_DOWN) { + if (oldPos == newPos) + return false; + + wxRichTextRange oldSelection = m_selectionRange; + // If not currently selecting, start selecting if (m_selectionRange.GetStart() == -2) { @@ -1001,10 +1184,14 @@ bool wxRichTextCtrl::ExtendSelection(long oldPos, long newPos, int flags) // the end. if (newPos > m_selectionAnchor) m_selectionRange.SetRange(m_selectionAnchor+1, newPos); + else if (newPos == m_selectionAnchor) + m_selectionRange = wxRichTextRange(-2, -2); else m_selectionRange.SetRange(newPos+1, m_selectionAnchor); } + RefreshForSelectionChange(oldSelection, m_selectionRange); + if (m_selectionRange.GetStart() > m_selectionRange.GetEnd()) { wxLogDebug(wxT("Strange selection range")); @@ -1119,7 +1306,11 @@ bool wxRichTextCtrl::ScrollIntoView(long position, int keyCode) } } } - PositionCaret(); + +#if !wxRICHTEXT_USE_OWN_CARET + if (scrolled) +#endif + PositionCaret(); return scrolled; } @@ -1140,17 +1331,10 @@ bool wxRichTextCtrl::IsPositionVisible(long pos) const startX = 0; startY = startY * ppuY; - int sx = 0, sy = 0; - GetVirtualSize(& sx, & sy); - sx = 0; - if (ppuY != 0) - sy = sy/ppuY; - wxRect rect = line->GetRect(); - wxSize clientSize = GetClientSize(); - return !(((rect.y + rect.height) > (clientSize.y + startY)) || rect.y < startY); + return (rect.GetBottom() > startY) && (rect.GetTop() < (startY + clientSize.y)); } void wxRichTextCtrl::SetCaretPosition(long position, bool showAtLineStart) @@ -1281,8 +1465,6 @@ bool wxRichTextCtrl::MoveRight(int noPositions, int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } else @@ -1310,8 +1492,6 @@ bool wxRichTextCtrl::MoveLeft(int noPositions, int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } else @@ -1401,8 +1581,6 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1424,8 +1602,6 @@ bool wxRichTextCtrl::MoveToParagraphEnd(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1447,8 +1623,6 @@ bool wxRichTextCtrl::MoveToParagraphStart(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1472,8 +1646,6 @@ bool wxRichTextCtrl::MoveToLineEnd(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1499,8 +1671,6 @@ bool wxRichTextCtrl::MoveToLineStart(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1520,8 +1690,6 @@ bool wxRichTextCtrl::MoveHome(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } else @@ -1543,8 +1711,6 @@ bool wxRichTextCtrl::MoveEnd(int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } else @@ -1584,8 +1750,6 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } } @@ -1703,8 +1867,6 @@ bool wxRichTextCtrl::WordLeft(int WXUNUSED(n), int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1727,8 +1889,6 @@ bool wxRichTextCtrl::WordRight(int WXUNUSED(n), int flags) PositionCaret(); SetDefaultStyleToCursorStyle(); - if (extendSel) - Refresh(false); return true; } @@ -1760,6 +1920,15 @@ void wxRichTextCtrl::OnSize(wxSizeEvent& event) /// Idle-time processing void wxRichTextCtrl::OnIdle(wxIdleEvent& event) { +#if wxRICHTEXT_USE_OWN_CARET + if (((wxRichTextCaret*) GetCaret())->GetNeedsUpdate()) + { + ((wxRichTextCaret*) GetCaret())->SetNeedsUpdate(false); + PositionCaret(); + GetCaret()->Show(); + } +#endif + const int layoutInterval = wxRICHTEXT_DEFAULT_LAYOUT_INTERVAL; if (m_fullLayoutRequired && (wxGetLocalTimeMillis() > (m_fullLayoutTime + layoutInterval))) @@ -1785,14 +1954,21 @@ void wxRichTextCtrl::OnIdle(wxIdleEvent& event) /// Scrolling void wxRichTextCtrl::OnScroll(wxScrollWinEvent& event) { - // Not used +#if wxRICHTEXT_USE_OWN_CARET + if (!((wxRichTextCaret*) GetCaret())->GetNeedsUpdate()) + { + GetCaret()->Hide(); + ((wxRichTextCaret*) GetCaret())->SetNeedsUpdate(); + } +#endif + event.Skip(); } /// Set up scrollbars, e.g. after a resize void wxRichTextCtrl::SetupScrollbars(bool atTop) { - if (m_freezeCount) + if (IsFrozen()) return; if (GetBuffer().IsEmpty()) @@ -1815,14 +1991,31 @@ void wxRichTextCtrl::SetupScrollbars(bool atTop) if (!atTop) GetViewStart(& startX, & startY); - int maxPositionX = 0; // wxMax(sz.x - clientSize.x, 0); + int maxPositionX = 0; int maxPositionY = (int) ((((float)(wxMax((unitsY*pixelsPerUnit) - clientSize.y, 0)))/((float)pixelsPerUnit)) + 0.5); + int newStartX = wxMin(maxPositionX, startX); + int newStartY = wxMin(maxPositionY, startY); + + int oldPPUX, oldPPUY; + int oldStartX, oldStartY; + int oldVirtualSizeX = 0, oldVirtualSizeY = 0; + GetScrollPixelsPerUnit(& oldPPUX, & oldPPUY); + GetViewStart(& oldStartX, & oldStartY); + GetVirtualSize(& oldVirtualSizeX, & oldVirtualSizeY); + if (oldPPUY > 0) + oldVirtualSizeY /= oldPPUY; + + if (oldPPUX == 0 && oldPPUY == pixelsPerUnit && oldVirtualSizeY == unitsY && oldStartX == newStartX && oldStartY == newStartY) + return; + + // Don't set scrollbars if there were none before, and there will be none now. + if (oldPPUY != 0 && (oldVirtualSizeY < clientSize.y) && (unitsY*pixelsPerUnit < clientSize.y)) + return; + // Move to previous scroll position if // possible - SetScrollbars(0, pixelsPerUnit, - 0, unitsY, - wxMin(maxPositionX, startX), wxMin(maxPositionY, startY)); + SetScrollbars(0, pixelsPerUnit, 0, unitsY, newStartX, newStartY); } /// Paint the background @@ -1868,7 +2061,7 @@ bool wxRichTextCtrl::RecreateBuffer(const wxSize& size) bool wxRichTextCtrl::DoLoadFile(const wxString& filename, int fileType) { - bool success = GetBuffer().LoadFile(filename, fileType); + bool success = GetBuffer().LoadFile(filename, (wxRichTextFileType)fileType); if (success) m_filename = filename; @@ -1878,7 +2071,7 @@ bool wxRichTextCtrl::DoLoadFile(const wxString& filename, int fileType) PositionCaret(); SetupScrollbars(true); Refresh(false); - SendTextUpdatedEvent(); + wxTextCtrl::SendTextUpdatedEvent(this); if (success) return true; @@ -1892,7 +2085,7 @@ bool wxRichTextCtrl::DoLoadFile(const wxString& filename, int fileType) bool wxRichTextCtrl::DoSaveFile(const wxString& filename, int fileType) { - if (GetBuffer().SaveFile(filename, fileType)) + if (GetBuffer().SaveFile(filename, (wxRichTextFileType)fileType)) { m_filename = filename; @@ -1913,13 +2106,17 @@ bool wxRichTextCtrl::DoSaveFile(const wxString& filename, int fileType) /// Add a new paragraph of text to the end of the buffer wxRichTextRange wxRichTextCtrl::AddParagraph(const wxString& text) { - return GetBuffer().AddParagraph(text); + wxRichTextRange range = GetBuffer().AddParagraph(text); + LayoutContent(); + return range; } /// Add an image wxRichTextRange wxRichTextCtrl::AddImage(const wxImage& image) { - return GetBuffer().AddImage(image); + wxRichTextRange range = GetBuffer().AddImage(image); + LayoutContent(); + return range; } // ---------------------------------------------------------------------------- @@ -1936,7 +2133,13 @@ void wxRichTextCtrl::SelectAll() void wxRichTextCtrl::SelectNone() { if (!(GetSelectionRange() == wxRichTextRange(-2, -2))) - SetSelection(-2, -2); + { + wxRichTextRange oldSelection = m_selectionRange; + + m_selectionRange = wxRichTextRange(-2, -2); + + RefreshForSelectionChange(oldSelection, m_selectionRange); + } m_selectionAnchor = -2; } @@ -1955,6 +2158,9 @@ bool wxRichTextCtrl::SelectWord(long position) if (!para) return false; + if (position == para->GetRange().GetEnd()) + position --; + long positionStart = position; long positionEnd = position; @@ -1982,6 +2188,9 @@ bool wxRichTextCtrl::SelectWord(long position) if (positionEnd >= para->GetRange().GetEnd()) positionEnd = para->GetRange().GetEnd(); + if (positionEnd < positionStart) + return false; + SetSelection(positionStart, positionEnd+1); if (positionStart >= 0) @@ -2062,13 +2271,27 @@ wxString wxRichTextCtrl::GetRange(long from, long to) const void wxRichTextCtrl::DoSetValue(const wxString& value, int flags) { - Clear(); + // Don't call Clear here, since it always sends a text updated event + m_buffer.ResetAndClearCommands(); + m_buffer.SetDirty(true); + m_caretPosition = -1; + m_caretPositionForDefaultStyle = -2; + m_caretAtLineStart = false; + m_selectionRange.SetRange(-2, -2); + + Scroll(0,0); + + if (!IsFrozen()) + { + LayoutContent(); + Refresh(false); + } if (!value.IsEmpty()) { // Remove empty paragraph GetBuffer().Clear(); - DoWriteText(value); + DoWriteText(value, flags); // for compatibility, don't move the cursor when doing SetValue() SetInsertionPoint(0); @@ -2077,7 +2300,7 @@ void wxRichTextCtrl::DoSetValue(const wxString& value, int flags) { // still send an event for consistency if (flags & SetValue_SendEvent) - SendTextUpdatedEvent(); + wxTextCtrl::SendTextUpdatedEvent(this); } DiscardEdits(); } @@ -2094,7 +2317,7 @@ void wxRichTextCtrl::DoWriteText(const wxString& value, int flags) GetBuffer().InsertTextWithUndo(m_caretPosition+1, valueUnix, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); if ( flags & SetValue_SendEvent ) - SendTextUpdatedEvent(); + wxTextCtrl::SendTextUpdatedEvent(this); } void wxRichTextCtrl::AppendText(const wxString& text) @@ -2105,7 +2328,7 @@ void wxRichTextCtrl::AppendText(const wxString& text) } /// Write an image at the current insertion point -bool wxRichTextCtrl::WriteImage(const wxImage& image, int bitmapType) +bool wxRichTextCtrl::WriteImage(const wxImage& image, wxBitmapType bitmapType) { wxRichTextImageBlock imageBlock; @@ -2116,7 +2339,7 @@ bool wxRichTextCtrl::WriteImage(const wxImage& image, int bitmapType) return false; } -bool wxRichTextCtrl::WriteImage(const wxString& filename, int bitmapType) +bool wxRichTextCtrl::WriteImage(const wxString& filename, wxBitmapType bitmapType) { wxRichTextImageBlock imageBlock; @@ -2132,7 +2355,7 @@ bool wxRichTextCtrl::WriteImage(const wxRichTextImageBlock& imageBlock) return GetBuffer().InsertImageWithUndo(m_caretPosition+1, imageBlock, this); } -bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, int bitmapType) +bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, wxBitmapType bitmapType) { if (bitmap.Ok()) { @@ -2149,7 +2372,7 @@ bool wxRichTextCtrl::WriteImage(const wxBitmap& bitmap, int bitmapType) /// Insert a newline (actually paragraph) at the current insertion point. bool wxRichTextCtrl::Newline() { - return GetBuffer().InsertNewlineWithUndo(m_caretPosition+1, this); + return GetBuffer().InsertNewlineWithUndo(m_caretPosition+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE); } /// Insert a line break at the current insertion point. @@ -2253,6 +2476,8 @@ void wxRichTextCtrl::SetInsertionPoint(long pos) SelectNone(); m_caretPosition = pos - 1; + + PositionCaret(); } void wxRichTextCtrl::SetInsertionPointEnd() @@ -2305,13 +2530,21 @@ void wxRichTextCtrl::SetSelection(long from, long to) void wxRichTextCtrl::DoSetSelection(long from, long to, bool WXUNUSED(scrollCaret)) { - m_selectionAnchor = from; - m_selectionRange.SetRange(from, to-1); - if (from > -2) - m_caretPosition = from-1; + if (from == to) + { + SelectNone(); + } + else + { + wxRichTextRange oldSelection = m_selectionRange; + m_selectionAnchor = from; + m_selectionRange.SetRange(from, to-1); + if (from > -2) + m_caretPosition = from-1; - Refresh(false); - PositionCaret(); + RefreshForSelectionChange(oldSelection, m_selectionRange); + PositionCaret(); + } } // ---------------------------------------------------------------------------- @@ -2334,7 +2567,7 @@ void wxRichTextCtrl::Remove(long from, long to) { SelectNone(); - GetBuffer().DeleteRangeWithUndo(wxRichTextRange(from, to), this); + GetBuffer().DeleteRangeWithUndo(wxRichTextRange(from, to-1), this); LayoutContent(); if (!IsFrozen()) @@ -2552,17 +2785,12 @@ void wxRichTextCtrl::OnContextMenu(wxContextMenuEvent& event) return; } -bool wxRichTextCtrl::SetStyle(long start, long end, const wxTextAttrEx& style) -{ - return GetBuffer().SetStyle(wxRichTextRange(start, end-1), style); -} - bool wxRichTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) { - return GetBuffer().SetStyle(wxRichTextRange(start, end-1), wxTextAttrEx(style)); + return GetBuffer().SetStyle(wxRichTextRange(start, end-1), wxTextAttr(style)); } -bool wxRichTextCtrl::SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style) +bool wxRichTextCtrl::SetStyle(const wxRichTextRange& range, const wxTextAttr& style) { return GetBuffer().SetStyle(range.ToInternal(), style); } @@ -2570,34 +2798,15 @@ bool wxRichTextCtrl::SetStyle(const wxRichTextRange& range, const wxRichTextAttr // extended style setting operation with flags including: // wxRICHTEXT_SETSTYLE_WITH_UNDO, wxRICHTEXT_SETSTYLE_OPTIMIZE, wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY. // see richtextbuffer.h for more details. -bool wxRichTextCtrl::SetStyleEx(long start, long end, const wxTextAttrEx& style, int flags) -{ - return GetBuffer().SetStyle(wxRichTextRange(start, end-1), style, flags); -} -bool wxRichTextCtrl::SetStyleEx(const wxRichTextRange& range, const wxTextAttrEx& style, int flags) +bool wxRichTextCtrl::SetStyleEx(const wxRichTextRange& range, const wxTextAttr& style, int flags) { return GetBuffer().SetStyle(range.ToInternal(), style, flags); } -bool wxRichTextCtrl::SetStyleEx(const wxRichTextRange& range, const wxRichTextAttr& style, int flags) -{ - return GetBuffer().SetStyle(range.ToInternal(), style, flags); -} - -bool wxRichTextCtrl::SetDefaultStyle(const wxTextAttrEx& style) -{ - return GetBuffer().SetDefaultStyle(style); -} - bool wxRichTextCtrl::SetDefaultStyle(const wxTextAttr& style) { - return GetBuffer().SetDefaultStyle(wxTextAttrEx(style)); -} - -const wxTextAttrEx& wxRichTextCtrl::GetDefaultStyleEx() const -{ - return GetBuffer().GetDefaultStyle(); + return GetBuffer().SetDefaultStyle(wxTextAttr(style)); } const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const @@ -2606,65 +2815,18 @@ const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const } bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style) -{ - wxTextAttrEx attr(style); - if (GetBuffer().GetStyle(position, attr)) - { - style = attr; - return true; - } - else - return false; -} - -bool wxRichTextCtrl::GetStyle(long position, wxTextAttrEx& style) -{ - return GetBuffer().GetStyle(position, style); -} - -bool wxRichTextCtrl::GetStyle(long position, wxRichTextAttr& style) { return GetBuffer().GetStyle(position, style); } // get the common set of styles for the range -bool wxRichTextCtrl::GetStyleForRange(const wxRichTextRange& range, wxRichTextAttr& style) -{ - wxTextAttrEx styleEx; - if (GetBuffer().GetStyleForRange(range.ToInternal(), styleEx)) - { - style = styleEx; - return true; - } - else - return false; -} - -bool wxRichTextCtrl::GetStyleForRange(const wxRichTextRange& range, wxTextAttrEx& style) +bool wxRichTextCtrl::GetStyleForRange(const wxRichTextRange& range, wxTextAttr& style) { return GetBuffer().GetStyleForRange(range.ToInternal(), style); } /// Get the content (uncombined) attributes for this position. - bool wxRichTextCtrl::GetUncombinedStyle(long position, wxTextAttr& style) -{ - wxTextAttrEx attr(style); - if (GetBuffer().GetUncombinedStyle(position, attr)) - { - style = attr; - return true; - } - else - return false; -} - -bool wxRichTextCtrl::GetUncombinedStyle(long position, wxTextAttrEx& style) -{ - return GetBuffer().GetUncombinedStyle(position, style); -} - -bool wxRichTextCtrl::GetUncombinedStyle(long position, wxRichTextAttr& style) { return GetBuffer().GetUncombinedStyle(position, style); } @@ -2674,7 +2836,7 @@ bool wxRichTextCtrl::SetFont(const wxFont& font) { wxControl::SetFont(font); - wxTextAttrEx attr = GetBuffer().GetAttributes(); + wxTextAttr attr = GetBuffer().GetAttributes(); attr.SetFont(font); GetBuffer().SetBasicStyle(attr); @@ -2718,8 +2880,11 @@ void wxRichTextCtrl::PositionCaret() wxPoint pt = GetPhysicalPoint(newPt); if (GetCaret()->GetPosition() != pt || GetCaret()->GetSize() != newSz) { + GetCaret()->Hide(); + if (GetCaret()->GetSize() != newSz) + GetCaret()->SetSize(newSz); GetCaret()->Move(pt); - GetCaret()->SetSize(newSz); + GetCaret()->Show(); } } } @@ -2829,7 +2994,7 @@ bool wxRichTextCtrl::IsSelectionBold() { if (HasSelection()) { - wxRichTextAttr attr; + wxTextAttr attr; wxRichTextRange range = GetSelectionRange(); attr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT); attr.SetFontWeight(wxBOLD); @@ -2840,7 +3005,7 @@ bool wxRichTextCtrl::IsSelectionBold() { // If no selection, then we need to combine current style with default style // to see what the effect would be if we started typing. - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT); long pos = GetAdjustedCaretPosition(GetCaretPosition()); @@ -2860,7 +3025,7 @@ bool wxRichTextCtrl::IsSelectionItalics() if (HasSelection()) { wxRichTextRange range = GetSelectionRange(); - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_ITALIC); attr.SetFontStyle(wxITALIC); @@ -2870,7 +3035,7 @@ bool wxRichTextCtrl::IsSelectionItalics() { // If no selection, then we need to combine current style with default style // to see what the effect would be if we started typing. - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_ITALIC); long pos = GetAdjustedCaretPosition(GetCaretPosition()); @@ -2890,7 +3055,7 @@ bool wxRichTextCtrl::IsSelectionUnderlined() if (HasSelection()) { wxRichTextRange range = GetSelectionRange(); - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE); attr.SetFontUnderlined(true); @@ -2900,7 +3065,7 @@ bool wxRichTextCtrl::IsSelectionUnderlined() { // If no selection, then we need to combine current style with default style // to see what the effect would be if we started typing. - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE); long pos = GetAdjustedCaretPosition(GetCaretPosition()); @@ -2917,42 +3082,54 @@ bool wxRichTextCtrl::IsSelectionUnderlined() /// Apply bold to the selection bool wxRichTextCtrl::ApplyBoldToSelection() { - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT); attr.SetFontWeight(IsSelectionBold() ? wxNORMAL : wxBOLD); if (HasSelection()) return SetStyleEx(GetSelectionRange(), attr, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY); else - SetAndShowDefaultStyle(attr); + { + wxRichTextAttr current = GetDefaultStyleEx(); + current.Apply(attr); + SetAndShowDefaultStyle(current); + } return true; } /// Apply italic to the selection bool wxRichTextCtrl::ApplyItalicToSelection() { - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_ITALIC); attr.SetFontStyle(IsSelectionItalics() ? wxNORMAL : wxITALIC); if (HasSelection()) return SetStyleEx(GetSelectionRange(), attr, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY); else - SetAndShowDefaultStyle(attr); + { + wxRichTextAttr current = GetDefaultStyleEx(); + current.Apply(attr); + SetAndShowDefaultStyle(current); + } return true; } /// Apply underline to the selection bool wxRichTextCtrl::ApplyUnderlineToSelection() { - wxRichTextAttr attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE); attr.SetFontUnderlined(!IsSelectionUnderlined()); if (HasSelection()) return SetStyleEx(GetSelectionRange(), attr, wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY); else - SetAndShowDefaultStyle(attr); + { + wxRichTextAttr current = GetDefaultStyleEx(); + current.Apply(attr); + SetAndShowDefaultStyle(current); + } return true; } @@ -2965,7 +3142,7 @@ bool wxRichTextCtrl::IsSelectionAligned(wxTextAttrAlignment alignment) else range = wxRichTextRange(GetCaretPosition()+1, GetCaretPosition()+2); - wxRichTextAttr attr; + wxTextAttr attr; attr.SetAlignment(alignment); return HasParagraphAttributes(range, attr); @@ -2974,7 +3151,7 @@ bool wxRichTextCtrl::IsSelectionAligned(wxTextAttrAlignment alignment) /// Apply alignment to the selection bool wxRichTextCtrl::ApplyAlignmentToSelection(wxTextAttrAlignment alignment) { - wxRichTextAttr attr; + wxTextAttr attr; attr.SetAlignment(alignment); if (HasSelection()) return SetStyle(GetSelectionRange(), attr); @@ -2992,9 +3169,9 @@ bool wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def) { // Flags are defined within each definition, so only certain // attributes are applied. - wxRichTextAttr attr(GetStyleSheet() ? def->GetStyleMergedWithBase(GetStyleSheet()) : def->GetStyle()); + wxTextAttr attr(GetStyleSheet() ? def->GetStyleMergedWithBase(GetStyleSheet()) : def->GetStyle()); - int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE; + int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE|wxRICHTEXT_SETSTYLE_RESET; if (def->IsKindOf(CLASSINFO(wxRichTextListStyleDefinition))) { @@ -3030,7 +3207,9 @@ bool wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def) return SetStyleEx(GetSelectionRange(), attr, flags); else { - SetAndShowDefaultStyle(attr); + wxRichTextAttr current = GetDefaultStyleEx(); + current.Apply(attr); + SetAndShowDefaultStyle(current); return true; } } @@ -3056,7 +3235,7 @@ bool wxRichTextCtrl::ApplyStyleSheet(wxRichTextStyleSheet* styleSheet) /// Sets the default style to the style under the cursor bool wxRichTextCtrl::SetDefaultStyleToCursorStyle() { - wxTextAttrEx attr; + wxTextAttr attr; attr.SetFlags(wxTEXT_ATTR_CHARACTER); // If at the start of a paragraph, use the next position. @@ -3187,5 +3366,187 @@ void wxRichTextCtrl::ClearAvailableFontNames() sm_availableFontNames.Clear(); } +void wxRichTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) +{ + //wxLogDebug(wxT("wxRichTextCtrl::OnSysColourChanged")); + + wxTextAttrEx basicStyle = GetBasicStyle(); + basicStyle.SetTextColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); + SetBasicStyle(basicStyle); + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + + Refresh(); +} + +// Refresh the area affected by a selection change +bool wxRichTextCtrl::RefreshForSelectionChange(const wxRichTextRange& oldSelection, const wxRichTextRange& newSelection) +{ + // Calculate the refresh rectangle - just the affected lines + long firstPos, lastPos; + if (oldSelection.GetStart() == -2 && newSelection.GetStart() != -2) + { + firstPos = newSelection.GetStart(); + lastPos = newSelection.GetEnd(); + } + else if (oldSelection.GetStart() != -2 && newSelection.GetStart() == -2) + { + firstPos = oldSelection.GetStart(); + lastPos = oldSelection.GetEnd(); + } + else if (oldSelection.GetStart() == -2 && newSelection.GetStart() == -2) + { + return false; + } + else + { + firstPos = wxMin(oldSelection.GetStart(), newSelection.GetStart()); + lastPos = wxMax(oldSelection.GetEnd(), newSelection.GetEnd()); + } + + wxRichTextLine* firstLine = GetBuffer().GetLineAtPosition(firstPos); + wxRichTextLine* lastLine = GetBuffer().GetLineAtPosition(lastPos); + + if (firstLine && lastLine) + { + wxSize clientSize = GetClientSize(); + wxPoint pt1 = GetPhysicalPoint(firstLine->GetAbsolutePosition()); + wxPoint pt2 = GetPhysicalPoint(lastLine->GetAbsolutePosition()) + wxPoint(0, lastLine->GetSize().y); + + pt1.x = 0; + pt1.y = wxMax(0, pt1.y); + pt2.x = 0; + pt2.y = wxMin(clientSize.y, pt2.y); + + wxRect rect(pt1, wxSize(clientSize.x, pt2.y - pt1.y)); + RefreshRect(rect, false); + } + else + Refresh(false); + + return true; +} + +#if wxRICHTEXT_USE_OWN_CARET + +// ---------------------------------------------------------------------------- +// initialization and destruction +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::Init() +{ + m_hasFocus = true; + + m_xOld = + m_yOld = -1; + m_richTextCtrl = NULL; + m_needsUpdate = false; +} + +wxRichTextCaret::~wxRichTextCaret() +{ +} + +// ---------------------------------------------------------------------------- +// showing/hiding/moving the caret (base class interface) +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::DoShow() +{ + Refresh(); +} + +void wxRichTextCaret::DoHide() +{ + Refresh(); +} + +void wxRichTextCaret::DoMove() +{ + if (IsVisible()) + { + Refresh(); + + if (m_xOld != -1 && m_yOld != -1) + { + if (m_richTextCtrl) + { + wxRect rect(GetPosition(), GetSize()); + m_richTextCtrl->RefreshRect(rect, false); + } + } + } + + m_xOld = m_x; + m_yOld = m_y; +} + +void wxRichTextCaret::DoSize() +{ + int countVisible = m_countVisible; + if (countVisible > 0) + { + m_countVisible = 0; + DoHide(); + } + + if (countVisible > 0) + { + m_countVisible = countVisible; + DoShow(); + } +} + +// ---------------------------------------------------------------------------- +// handling the focus +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::OnSetFocus() +{ + m_hasFocus = true; + + if ( IsVisible() ) + Refresh(); +} + +void wxRichTextCaret::OnKillFocus() +{ + m_hasFocus = false; +} + +// ---------------------------------------------------------------------------- +// drawing the caret +// ---------------------------------------------------------------------------- + +void wxRichTextCaret::Refresh() +{ + if (m_richTextCtrl) + { + wxRect rect(GetPosition(), GetSize()); + m_richTextCtrl->RefreshRect(rect, false); + } +} + +void wxRichTextCaret::DoDraw(wxDC *dc) +{ + dc->SetPen( *wxBLACK_PEN ); + + dc->SetBrush(*(m_hasFocus ? wxBLACK_BRUSH : wxTRANSPARENT_BRUSH)); + dc->SetPen(*wxBLACK_PEN); + + // VZ: unfortunately, the rectangle comes out a pixel smaller when this is + // done under wxGTK - no idea why + //dc->SetLogicalFunction(wxINVERT); + + wxPoint pt(m_x, m_y); + + if (m_richTextCtrl) + { + pt = m_richTextCtrl->GetLogicalPoint(pt); + } + dc->DrawRectangle(pt.x, pt.y, m_width, m_height); +} +#endif + // wxRICHTEXT_USE_OWN_CARET + #endif // wxUSE_RICHTEXT