#include "wx/filename.h"
#include "wx/dcbuffer.h"
#include "wx/arrimpl.cpp"
+#include "wx/fontenum.h"
// DLL options compatibility check:
#include "wx/app.h"
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 )
* wxRichTextCtrl
*/
+wxArrayString wxRichTextCtrl::sm_availableFontNames;
+
wxRichTextCtrl::wxRichTextCtrl()
: wxScrollHelper(this)
{
GetBuffer().SetRichTextCtrl(this);
+ if (style & wxTE_READONLY)
+ SetEditable(false);
+
wxTextAttrEx attributes;
attributes.SetFont(GetFont());
attributes.SetTextColour(*wxBLACK);
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
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;
}
}
/// 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());
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)
{
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)
{
event.Skip();
return;
}
-
+
default:
{
if (event.CmdDown() || event.AltDown())
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;
{
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));
}
if (positionStart < para->GetRange().GetStart())
positionStart = para->GetRange().GetStart();
-
+
for (positionEnd = position; positionEnd < para->GetRange().GetEnd(); positionEnd ++)
{
wxString text = GetBuffer().GetTextForRange(wxRichTextRange(positionEnd, positionEnd));
}
if (positionEnd >= para->GetRange().GetEnd())
positionEnd = para->GetRange().GetEnd();
-
+
SetSelection(positionStart, positionEnd+1);
if (positionStart >= 0)
{
MoveCaret(positionStart-1, true);
- SetDefaultStyleToCursorStyle();
+ SetDefaultStyleToCursorStyle();
}
return true;
}
/// 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;
}
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.
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
-