]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextctrl.cpp
Fix the rectangle size when offsetting
[wxWidgets.git] / src / richtext / richtextctrl.cpp
index 08111b1b3490e64a2841ec7c3dd83e9cb7d1875d..58057e12a15306e30fa5c867911c27f316f8c33a 100644 (file)
@@ -31,6 +31,7 @@
 #include "wx/filename.h"
 #include "wx/dcbuffer.h"
 #include "wx/arrimpl.cpp"
+#include "wx/fontenum.h"
 
 // DLL options compatibility check:
 #include "wx/app.h"
@@ -44,19 +45,11 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_RETURN)
 
-#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
 IMPLEMENT_CLASS( wxRichTextCtrl, wxControl )
-#else
-IMPLEMENT_CLASS( wxRichTextCtrl, wxScrolledWindow )
-#endif
 
 IMPLEMENT_CLASS( wxRichTextEvent, wxNotifyEvent )
 
-#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
 BEGIN_EVENT_TABLE( wxRichTextCtrl, wxControl )
-#else
-BEGIN_EVENT_TABLE( wxRichTextCtrl, wxScrolledWindow )
-#endif
     EVT_PAINT(wxRichTextCtrl::OnPaint)
     EVT_ERASE_BACKGROUND(wxRichTextCtrl::OnEraseBackground)
     EVT_IDLE(wxRichTextCtrl::OnIdle)
@@ -99,18 +92,21 @@ END_EVENT_TABLE()
  * wxRichTextCtrl
  */
 
+wxArrayString wxRichTextCtrl::sm_availableFontNames;
+
 wxRichTextCtrl::wxRichTextCtrl()
-#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-    : wxScrollHelper(this)
-#endif
+              : wxScrollHelper(this)
 {
     Init();
 }
 
-wxRichTextCtrl::wxRichTextCtrl( wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style)
-#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-    : wxScrollHelper(this)
-#endif
+wxRichTextCtrl::wxRichTextCtrl(wxWindow* parent,
+                               wxWindowID id,
+                               const wxString& value,
+                               const wxPoint& pos,
+                               const wxSize& size,
+                               long style)
+              : wxScrollHelper(this)
 {
     Init();
     Create(parent, id, value, pos, size, style);
@@ -119,15 +115,9 @@ wxRichTextCtrl::wxRichTextCtrl( wxWindow* parent, wxWindowID id, const wxString&
 /// Creation
 bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style)
 {
-#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-    if (!wxTextCtrlBase::Create(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE
-        ))
+    if (!wxTextCtrlBase::Create(parent, id, pos, size,
+                                style|wxFULL_REPAINT_ON_RESIZE))
         return false;
-#else
-    if (!wxScrolledWindow::Create(parent, id, pos, size, style|wxFULL_REPAINT_ON_RESIZE
-        ))
-        return false;
-#endif
 
     if (!GetFont().Ok())
     {
@@ -136,6 +126,9 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
 
     GetBuffer().SetRichTextCtrl(this);
 
+    if (style & wxTE_READONLY)
+        SetEditable(false);
+
     wxTextAttrEx attributes;
     attributes.SetFont(GetFont());
     attributes.SetTextColour(*wxBLACK);
@@ -230,7 +223,7 @@ void wxRichTextCtrl::Clear()
         SetupScrollbars();
         Refresh(false);
     }
-    SendUpdateEvent();
+    SendTextUpdatedEvent();
 }
 
 /// Painting
@@ -255,8 +248,6 @@ void wxRichTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
         // Paint the background
         PaintBackground(dc);
 
-        wxRegion dirtyRegion = GetUpdateRegion();
-
         wxRect drawingArea(GetLogicalPoint(wxPoint(0, 0)), GetClientSize());
         wxRect availableSpace(GetClientSize());
         if (GetBuffer().GetDirty())
@@ -645,7 +636,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                 event.Skip();
                 return;
             }
-            
+
             default:
             {
                 if (event.CmdDown() || event.AltDown())
@@ -654,6 +645,27 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                     return;
                 }
 
+                if (keycode == wxT('\t'))
+                {
+                    // See if we need to promote or demote the selection or paragraph at the cursor
+                    // position, instead of inserting a tab.
+                    long pos = GetAdjustedCaretPosition(GetCaretPosition());
+                    wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(pos);
+                    if (para && para->GetRange().GetStart() == pos && para->GetAttributes().HasListStyleName())
+                    {
+                        wxRichTextRange range;
+                        if (HasSelection())
+                            range = GetSelectionRange();
+                        else
+                            range = para->GetRange().FromInternal();
+
+                        int promoteBy = event.ShiftDown() ? 1 : -1;
+
+                        PromoteList(promoteBy, range, NULL);
+                        return;
+                    }
+                }
+
                 BeginBatchUndo(_("Insert Text"));
 
                 long newPos = m_caretPosition;
@@ -1652,27 +1664,6 @@ bool wxRichTextCtrl::RecreateBuffer(const wxSize& size)
 // file IO functions
 // ----------------------------------------------------------------------------
 
-#if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-bool wxRichTextCtrl::LoadFile(const wxString& filename, int fileType)
-{
-    return DoLoadFile(filename, fileType);
-}
-
-bool wxRichTextCtrl::SaveFile(const wxString& filename, int fileType)
-{
-    wxString filenameToUse = filename.empty() ? m_filename : filename;
-    if ( filenameToUse.empty() )
-    {
-        // what kind of message to give? is it an error or a program bug?
-        wxLogDebug(wxT("Can't save textctrl to file without filename."));
-
-        return false;
-    }
-
-    return DoSaveFile(filenameToUse, fileType);
-}
-#endif
-
 bool wxRichTextCtrl::DoLoadFile(const wxString& filename, int fileType)
 {
     bool success = GetBuffer().LoadFile(filename, fileType);
@@ -1685,7 +1676,7 @@ bool wxRichTextCtrl::DoLoadFile(const wxString& filename, int fileType)
     PositionCaret();
     SetupScrollbars(true);
     Refresh(false);
-    SendUpdateEvent();
+    SendTextUpdatedEvent();
 
     if (success)
         return true;
@@ -1757,14 +1748,14 @@ bool wxRichTextCtrl::SelectWord(long position)
 {
     if (position < 0 || position > GetBuffer().GetRange().GetEnd())
         return false;
-    
+
     wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position);
     if (!para)
         return false;
 
     long positionStart = position;
     long positionEnd = position;
-    
+
     for (positionStart = position; positionStart >= para->GetRange().GetStart(); positionStart --)
     {
         wxString text = GetBuffer().GetTextForRange(wxRichTextRange(positionStart, positionStart));
@@ -1776,7 +1767,7 @@ bool wxRichTextCtrl::SelectWord(long position)
     }
     if (positionStart < para->GetRange().GetStart())
         positionStart = para->GetRange().GetStart();
-    
+
     for (positionEnd = position; positionEnd < para->GetRange().GetEnd(); positionEnd ++)
     {
         wxString text = GetBuffer().GetTextForRange(wxRichTextRange(positionEnd, positionEnd));
@@ -1788,13 +1779,13 @@ bool wxRichTextCtrl::SelectWord(long position)
     }
     if (positionEnd >= para->GetRange().GetEnd())
         positionEnd = para->GetRange().GetEnd();
-    
+
     SetSelection(positionStart, positionEnd+1);
 
     if (positionStart >= 0)
     {
         MoveCaret(positionStart-1, true);
-        SetDefaultStyleToCursorStyle();        
+        SetDefaultStyleToCursorStyle();
     }
 
     return true;
@@ -1808,22 +1799,6 @@ wxString wxRichTextCtrl::GetStringSelection() const
     return GetRange(from, to);
 }
 
-// do the window-specific processing after processing the update event
-#if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-void wxRichTextCtrl::DoUpdateWindowUI(wxUpdateUIEvent& event)
-{
-    // call inherited
-    wxWindowBase::DoUpdateWindowUI(event);
-
-    // update text
-    if ( event.GetSetText() )
-    {
-        if ( event.GetText() != GetValue() )
-            SetValue(event.GetText());
-    }
-}
-#endif // !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-
 // ----------------------------------------------------------------------------
 // hit testing
 // ----------------------------------------------------------------------------
@@ -1888,7 +1863,7 @@ wxString wxRichTextCtrl::GetRange(long from, long to) const
     return GetBuffer().GetTextForRange(wxRichTextRange(from, to-1));
 }
 
-void wxRichTextCtrl::SetValue(const wxString& value)
+void wxRichTextCtrl::DoSetValue(const wxString& value, int flags)
 {
     Clear();
 
@@ -1898,15 +1873,18 @@ void wxRichTextCtrl::SetValue(const wxString& value)
     // edit controls mostly)
     if ( (value.length() > 0x400) || (value != GetValue()) )
     {
-        DoWriteText(value, false /* not selection only */);
+        DoWriteText(value);
 
         // for compatibility, don't move the cursor when doing SetValue()
         SetInsertionPoint(0);
     }
     else // same text
     {
-        // still send an event for consistency
-        SendUpdateEvent();
+        if ( flags & SetValue_SendEvent )
+        {
+            // still send an event for consistency
+            SendTextUpdatedEvent();
+        }
     }
 
     // we should reset the modified flag even if the value didn't really change
@@ -1921,11 +1899,14 @@ void wxRichTextCtrl::WriteText(const wxString& value)
     DoWriteText(value);
 }
 
-void wxRichTextCtrl::DoWriteText(const wxString& value, bool WXUNUSED(selectionOnly))
+void wxRichTextCtrl::DoWriteText(const wxString& value, int flags)
 {
     wxString valueUnix = wxTextFile::Translate(value, wxTextFileType_Unix);
 
     GetBuffer().InsertTextWithUndo(m_caretPosition+1, valueUnix, this);
+
+    if ( flags & SetValue_SendEvent )
+        SendTextUpdatedEvent();
 }
 
 void wxRichTextCtrl::AppendText(const wxString& text)
@@ -2140,13 +2121,14 @@ void wxRichTextCtrl::DoSetSelection(long from, long to, bool WXUNUSED(scrollCare
 // Editing
 // ----------------------------------------------------------------------------
 
-void wxRichTextCtrl::Replace(long WXUNUSED(from), long WXUNUSED(to), const wxString& value)
+void wxRichTextCtrl::Replace(long WXUNUSED(from), long WXUNUSED(to),
+                             const wxString& value)
 {
     BeginBatchUndo(_("Replace"));
 
     DeleteSelectedContent();
 
-    DoWriteText(value, true /* selection only */);
+    DoWriteText(value, SetValue_SelectionOnly);
 
     EndBatchUndo();
 }
@@ -2270,39 +2252,6 @@ void wxRichTextCtrl::OnDropFiles(wxDropFilesEvent& event)
     }
 }
 
-// ----------------------------------------------------------------------------
-// text control event processing
-// ----------------------------------------------------------------------------
-
-bool wxRichTextCtrl::SendUpdateEvent()
-{
-    wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId());
-    InitCommandEvent(event);
-
-    return GetEventHandler()->ProcessEvent(event);
-}
-
-void wxRichTextCtrl::InitCommandEvent(wxCommandEvent& event) const
-{
-    event.SetEventObject((wxControlBase *)this);    // const_cast
-
-    switch ( m_clientDataType )
-    {
-        case wxClientData_Void:
-            event.SetClientData(GetClientData());
-            break;
-
-        case wxClientData_Object:
-            event.SetClientObject(GetClientObject());
-            break;
-
-        case wxClientData_None:
-            // nothing to do
-            ;
-    }
-}
-
-
 wxSize wxRichTextCtrl::DoGetBestSize() const
 {
     return wxSize(10, 10);
@@ -2505,22 +2454,12 @@ bool wxRichTextCtrl::GetUncombinedStyle(long position, wxRichTextAttr& style)
 /// Set font, and also the buffer attributes
 bool wxRichTextCtrl::SetFont(const wxFont& font)
 {
-#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
     wxControl::SetFont(font);
-#else
-    wxScrolledWindow::SetFont(font);
-#endif
 
     wxTextAttrEx attr = GetBuffer().GetAttributes();
     attr.SetFont(font);
     GetBuffer().SetBasicStyle(attr);
 
-#if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
-    // Don't set the default style, since it will be inherited from
-    // the basic style.
-    GetBuffer().SetDefaultStyle(attr);
-#endif
-
     GetBuffer().Invalidate(wxRICHTEXT_ALL);
     Refresh(false);
 
@@ -2826,21 +2765,38 @@ bool wxRichTextCtrl::ApplyAlignmentToSelection(wxTextAttrAlignment alignment)
 }
 
 /// Apply a named style to the selection
-void wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def)
+bool wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def)
 {
     // Flags are defined within each definition, so only certain
     // attributes are applied.
     wxRichTextAttr attr(def->GetStyle());
-    
+
     int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO|wxRICHTEXT_SETSTYLE_OPTIMIZE;
 
+    if (def->IsKindOf(CLASSINFO(wxRichTextListStyleDefinition)))
+    {
+        flags |= wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY;
+
+        wxRichTextRange range;
+
+        if (HasSelection())
+            range = GetSelectionRange();
+        else
+        {
+            long pos = GetAdjustedCaretPosition(GetCaretPosition());
+            range = wxRichTextRange(pos, pos+1);
+        }
+
+        return SetListStyle(range, (wxRichTextListStyleDefinition*) def, flags);
+    }
+
     // Make sure the attr has the style name
     if (def->IsKindOf(CLASSINFO(wxRichTextParagraphStyleDefinition)))
     {
         attr.SetParagraphStyleName(def->GetName());
-        
+
         // If applying a paragraph style, we only want the paragraph nodes to adopt these
-        // attributes, and not the leaf nodes. This will allow the context (e.g. text)
+        // attributes, and not the leaf nodes. This will allow the content (e.g. text)
         // to change its style independently.
         flags |= wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY;
     }
@@ -2848,9 +2804,12 @@ void wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def)
         attr.SetCharacterStyleName(def->GetName());
 
     if (HasSelection())
-        SetStyleEx(GetSelectionRange(), attr, flags);
+        return SetStyleEx(GetSelectionRange(), attr, flags);
     else
+    {
         SetAndShowDefaultStyle(attr);
+        return true;
+    }
 }
 
 /// Apply the style sheet to the buffer, for example if the styles have changed.
@@ -2937,6 +2896,59 @@ void wxRichTextCtrl::SetSelectionRange(const wxRichTextRange& range)
     SetInternalSelectionRange(range1);
 }
 
+/// Set list style
+bool wxRichTextCtrl::SetListStyle(const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int startFrom, int specifiedLevel)
+{
+    return GetBuffer().SetListStyle(range.ToInternal(), def, flags, startFrom, specifiedLevel);
+}
+
+bool wxRichTextCtrl::SetListStyle(const wxRichTextRange& range, const wxString& defName, int flags, int startFrom, int specifiedLevel)
+{
+    return GetBuffer().SetListStyle(range.ToInternal(), defName, flags, startFrom, specifiedLevel);
+}
+
+/// Clear list for given range
+bool wxRichTextCtrl::ClearListStyle(const wxRichTextRange& range, int flags)
+{
+    return GetBuffer().ClearListStyle(range.ToInternal(), flags);
+}
+
+/// Number/renumber any list elements in the given range
+bool wxRichTextCtrl::NumberList(const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int startFrom, int specifiedLevel)
+{
+    return GetBuffer().NumberList(range.ToInternal(), def, flags, startFrom, specifiedLevel);
+}
+
+bool wxRichTextCtrl::NumberList(const wxRichTextRange& range, const wxString& defName, int flags, int startFrom, int specifiedLevel)
+{
+    return GetBuffer().NumberList(range.ToInternal(), defName, flags, startFrom, specifiedLevel);
+}
+
+/// Promote the list items within the given range. promoteBy can be a positive or negative number, e.g. 1 or -1
+bool wxRichTextCtrl::PromoteList(int promoteBy, const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags, int specifiedLevel)
+{
+    return GetBuffer().PromoteList(promoteBy, range.ToInternal(), def, flags, specifiedLevel);
+}
+
+bool wxRichTextCtrl::PromoteList(int promoteBy, const wxRichTextRange& range, const wxString& defName, int flags, int specifiedLevel)
+{
+    return GetBuffer().PromoteList(promoteBy, range.ToInternal(), defName, flags, specifiedLevel);
+}
+
+const wxArrayString& wxRichTextCtrl::GetAvailableFontNames()
+{
+    if (sm_availableFontNames.GetCount() == 0)
+    {
+        sm_availableFontNames = wxFontEnumerator::GetFacenames();
+        sm_availableFontNames.Sort();
+    }
+    return sm_availableFontNames;
+}
+
+void wxRichTextCtrl::ClearAvailableFontNames()
+{
+    sm_availableFontNames.Clear();
+}
+
 #endif
     // wxUSE_RICHTEXT
-