]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextctrl.cpp
Add wxFilterFSHandler.
[wxWidgets.git] / src / richtext / richtextctrl.cpp
index f480f23015e4ee07fc74450d53cd03731b67508f..c59cbfb85192290c17a4a53f8cfdf3b9c357a2e3 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"
@@ -43,6 +44,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_MIDDLE_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_RIGHT_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_LEFT_DCLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_RETURN)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_REPLACED)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_STYLESHEET_CHANGED)
 
 IMPLEMENT_CLASS( wxRichTextCtrl, wxControl )
 
@@ -91,6 +96,8 @@ END_EVENT_TABLE()
  * wxRichTextCtrl
  */
 
+wxArrayString wxRichTextCtrl::sm_availableFontNames;
+
 wxRichTextCtrl::wxRichTextCtrl()
               : wxScrollHelper(this)
 {
@@ -123,6 +130,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);
@@ -131,7 +141,7 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
     attributes.SetLineSpacing(10);
     attributes.SetParagraphSpacingAfter(10);
     attributes.SetParagraphSpacingBefore(0);
-    attributes.SetFlags(wxTEXT_ATTR_ALL);
+
     SetBasicStyle(attributes);
 
     // The default attributes will be merged with base attributes, so
@@ -150,16 +160,23 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
     RecreateBuffer(size);
 #endif
 
-    SetCursor(wxCursor(wxCURSOR_IBEAM));
+    m_textCursor = wxCursor(wxCURSOR_IBEAM);
+    m_urlCursor = wxCursor(wxCURSOR_HAND);
+
+    SetCursor(m_textCursor);
 
     if (!value.IsEmpty())
         SetValue(value);
 
+    GetBuffer().AddEventHandler(this);
+
     return true;
 }
 
 wxRichTextCtrl::~wxRichTextCtrl()
 {
+    GetBuffer().RemoveEventHandler(this);
+    
     delete m_contextMenu;
 }
 
@@ -327,25 +344,59 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event)
 }
 
 /// Left-up
-void wxRichTextCtrl::OnLeftUp(wxMouseEvent& WXUNUSED(event))
+void wxRichTextCtrl::OnLeftUp(wxMouseEvent& event)
 {
     if (m_dragging)
     {
         m_dragging = false;
         if (GetCapture() == this)
             ReleaseMouse();
+
+        // See if we clicked on a URL
+        wxClientDC dc(this);
+        PrepareDC(dc);
+        dc.SetFont(GetFont());
+
+        long position = 0;
+        wxPoint logicalPt = event.GetLogicalPosition(dc);
+        int hit = GetBuffer().HitTest(dc, logicalPt, position);
+    
+        if (hit != wxRICHTEXT_HITTEST_NONE)
+        {
+            wxTextAttrEx attr;
+            if (GetStyle(position, attr))
+            {
+                if (attr.HasFlag(wxTEXT_ATTR_URL))
+                {
+                    wxString urlTarget = attr.GetURL();
+                    if (!urlTarget.IsEmpty())
+                    {
+                        wxMouseEvent mouseEvent(event);
+                        
+                        long startPos = 0, endPos = 0;
+                        wxRichTextObject* obj = GetBuffer().GetLeafObjectAtPosition(position);
+                        if (obj)
+                        {
+                            startPos = obj->GetRange().GetStart();
+                            endPos = obj->GetRange().GetEnd();
+                        }                        
+                        
+                        wxTextUrlEvent urlEvent(GetId(), mouseEvent, startPos, endPos);
+                        InitCommandEvent(urlEvent);
+
+                        urlEvent.SetString(urlTarget);
+                        
+                        GetEventHandler()->ProcessEvent(urlEvent);
+                    }
+                }
+            }
+        }
     }
 }
 
 /// Left-click
 void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
 {
-    if (!event.Dragging())
-    {
-        event.Skip();
-        return;
-    }
-
     wxClientDC dc(this);
     PrepareDC(dc);
     dc.SetFont(GetFont());
@@ -353,6 +404,34 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event)
     long position = 0;
     wxPoint logicalPt = event.GetLogicalPosition(dc);
     int hit = GetBuffer().HitTest(dc, logicalPt, position);
+    
+    // See if we need to change the cursor
+    
+    {
+        if (hit != wxRICHTEXT_HITTEST_NONE)
+        {
+            wxTextAttrEx attr;
+            if (GetStyle(position, attr))
+            {
+                if (attr.HasFlag(wxTEXT_ATTR_URL))
+                {
+                    if (GetCursor() != m_urlCursor)
+                        SetCursor(m_urlCursor);
+                }
+                else if (!attr.HasFlag(wxTEXT_ATTR_URL))
+                {
+                    if (GetCursor() != m_textCursor)
+                        SetCursor(m_textCursor);
+                }
+            }
+        }
+    }
+
+    if (!event.Dragging())
+    {
+        event.Skip();
+        return;
+    }
 
     if (m_dragging && hit != wxRICHTEXT_HITTEST_NONE)
     {
@@ -456,18 +535,24 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
         DeleteSelectedContent(& newPos);
 
         GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
+        EndBatchUndo();
+        SetDefaultStyleToCursorStyle();
+
+        ScrollIntoView(m_caretPosition, WXK_RIGHT);
 
         wxRichTextEvent cmdEvent(
             wxEVT_COMMAND_RICHTEXT_RETURN,
             GetId());
         cmdEvent.SetEventObject(this);
         cmdEvent.SetFlags(flags);
-        GetEventHandler()->ProcessEvent(cmdEvent);
-
-        EndBatchUndo();
-        SetDefaultStyleToCursorStyle();
-
-        ScrollIntoView(m_caretPosition, WXK_RIGHT);
+        if (!GetEventHandler()->ProcessEvent(cmdEvent))
+        {
+            // Generate conventional event
+            wxCommandEvent textEvent(wxEVT_COMMAND_TEXT_ENTER, GetId());
+            InitCommandEvent(textEvent);
+            
+            GetEventHandler()->ProcessEvent(textEvent);
+        }
     }
     else if (event.GetKeyCode() == WXK_BACK)
     {
@@ -630,7 +715,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
                 event.Skip();
                 return;
             }
-            
+
             default:
             {
                 if (event.CmdDown() || event.AltDown())
@@ -639,6 +724,28 @@ 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;
@@ -1721,14 +1828,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));
@@ -1740,7 +1847,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));
@@ -1752,13 +1859,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;
@@ -2738,21 +2845,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;
     }
@@ -2760,9 +2884,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.
@@ -2849,6 +2976,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
-