#include "wx/wxprec.h"
#ifdef __BORLANDC__
- #pragma hdrstop
+ #pragma hdrstop
#endif
#if wxUSE_RICHTEXT
#include "wx/richtext/richtextctrl.h"
+#include "wx/richtext/richtextstyles.h"
#ifndef WX_PRECOMP
- #include "wx/wx.h"
+ #include "wx/settings.h"
+ #include "wx/menu.h"
+ #include "wx/intl.h"
+ #include "wx/log.h"
+ #include "wx/stopwatch.h"
#endif
#include "wx/textfile.h"
#include "wx/ffile.h"
-#include "wx/settings.h"
#include "wx/filename.h"
#include "wx/dcbuffer.h"
#include "wx/arrimpl.cpp"
+// DLL options compatibility check:
+#include "wx/app.h"
+WX_CHECK_BUILD_OPTIONS("wxRichTextCtrl")
+
DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_ITEM_SELECTED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_ITEM_DESELECTED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_RICHTEXT_LEFT_CLICK)
Init();
}
-wxRichTextCtrl::wxRichTextCtrl( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+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
{
Init();
- Create(parent, id, pos, size, style);
+ Create(parent, id, value, pos, size, style);
}
/// Creation
-bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
+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
SetCursor(wxCursor(wxCURSOR_IBEAM));
+ if (!value.IsEmpty())
+ SetValue(value);
+
return true;
}
m_fullLayoutTime = 0;
m_fullLayoutSavedPosition = 0;
m_delayedLayoutThreshold = wxRICHTEXT_DEFAULT_DELAYED_LAYOUT_THRESHOLD;
+ m_caretPositionForDefaultStyle = -2;
}
/// Call Freeze to prevent refresh
m_buffer.Reset();
m_buffer.SetDirty(true);
m_caretPosition = -1;
+ m_caretPositionForDefaultStyle = -2;
m_caretAtLineStart = false;
m_selectionRange.SetRange(-2, -2);
+ SetScrollbars(0, 0, 0, 0, 0, 0);
+
if (m_freezeCount == 0)
{
SetupScrollbars();
event.GetKeyCode() == WXK_END)
{
KeyboardNavigate(event.GetKeyCode(), flags);
+ return;
}
- else if (event.GetKeyCode() == WXK_RETURN)
+
+ // all the other keys modify the controls contents which shouldn't be
+ // possible if we're read-only
+ if ( !IsEditable() )
+ {
+ event.Skip();
+ return;
+ }
+
+ if (event.GetKeyCode() == WXK_RETURN)
{
BeginBatchUndo(_("Insert Text"));
SetDefaultStyleToCursorStyle();
ScrollIntoView(m_caretPosition, WXK_RIGHT);
}
-#if 0
- else
- event.Skip();
-#endif
}
/// Delete content if there is a selection, e.g. when pressing a key.
int ppuX, ppuY;
GetScrollPixelsPerUnit(& ppuX, & ppuY);
- int startX, startY;
- GetViewStart(& startX, & startY);
- startX = 0;
- startY = startY * ppuY;
+ int startXUnits, startYUnits;
+ GetViewStart(& startXUnits, & startYUnits);
+ int startY = startYUnits * ppuY;
int sx = 0, sy = 0;
GetVirtualSize(& sx, & sy);
- sx = 0;
+ int sxUnits = 0;
+ int syUnits = 0;
if (ppuY != 0)
- sy = sy/ppuY;
+ syUnits = sy/ppuY;
wxRect rect = line->GetRect();
// Make it scroll so this item is at the bottom
// of the window
int y = rect.y - (clientSize.y - rect.height);
- y = (int) (0.5 + y/ppuY);
+ int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
- if (startY != y)
+ // If we're still off the screen, scroll another line down
+ if ((rect.y + rect.height) > (clientSize.y + (yUnits*ppuY)))
+ yUnits ++;
+
+ if (startYUnits != yUnits)
{
- SetScrollbars(ppuX, ppuY, sx, sy, 0, y);
+ SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
scrolled = true;
}
}
// Make it scroll so this item is at the top
// of the window
int y = rect.y ;
- y = (int) (0.5 + y/ppuY);
+ int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
- if (startY != y)
+ if (startYUnits != yUnits)
{
- SetScrollbars(ppuX, ppuY, sx, sy, 0, y);
+ SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
scrolled = true;
}
}
// Make it scroll so this item is at the top
// of the window
int y = rect.y ;
- y = (int) (0.5 + y/ppuY);
+ int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
- if (startY != y)
+ if (startYUnits != yUnits)
{
- SetScrollbars(ppuX, ppuY, sx, sy, 0, y);
+ SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
scrolled = true;
}
}
// Make it scroll so this item is at the bottom
// of the window
int y = rect.y - (clientSize.y - rect.height);
- y = (int) (0.5 + y/ppuY);
+ int yUnits = (int) (0.5 + ((float) y)/(float) ppuY);
+
+ // If we're still off the screen, scroll another line down
+ if ((rect.y + rect.height) > (clientSize.y + (yUnits*ppuY)))
+ yUnits ++;
- if (startY != y)
+ if (startYUnits != yUnits)
{
- SetScrollbars(ppuX, ppuY, sx, sy, 0, y);
+ SetScrollbars(ppuX, ppuY, sxUnits, syUnits, 0, yUnits);
scrolled = true;
}
}
ShowPosition(m_fullLayoutSavedPosition);
Refresh(false);
}
+
+ if (m_caretPositionForDefaultStyle != -2)
+ {
+ // If the caret position has changed, no longer reflect the default style
+ // in the UI.
+ if (GetCaretPosition() != m_caretPositionForDefaultStyle)
+ m_caretPositionForDefaultStyle = -2;
+ }
+
event.Skip();
}
// TODO: reimplement scrolling so we scroll by line, not by fixed number
// of pixels. See e.g. wxVScrolledWindow for ideas.
- int pixelsPerUnit = 5; // 10;
+ int pixelsPerUnit = 5;
wxSize clientSize = GetClientSize();
int maxHeight = GetBuffer().GetCachedSize().y;
- int unitsY = maxHeight/pixelsPerUnit;
+ // Round up so we have at least maxHeight pixels
+ int unitsY = (int) (((float)maxHeight/(float)pixelsPerUnit) + 0.5);
int startX = 0, startY = 0;
if (!atTop)
GetViewStart(& startX, & startY);
int maxPositionX = 0; // wxMax(sz.x - clientSize.x, 0);
- int maxPositionY = (wxMax(maxHeight - clientSize.y, 0))/pixelsPerUnit;
+ int maxPositionY = (int) ((((float)(wxMax((unitsY*pixelsPerUnit) - clientSize.y, 0)))/((float)pixelsPerUnit)) + 0.5);
// Move to previous scroll position if
// possible
wxClientDC dc((wxRichTextCtrl*) this);
((wxRichTextCtrl*)this)->PrepareDC(dc);
- int hit = ((wxRichTextCtrl*)this)->GetBuffer().HitTest(dc, pt, *pos);
+ // Buffer uses logical position (relative to start of buffer)
+ // so convert
+ wxPoint pt2 = GetLogicalPoint(pt);
+
+ int hit = ((wxRichTextCtrl*)this)->GetBuffer().HitTest(dc, pt2, *pos);
switch ( hit )
{
void wxRichTextCtrl::DiscardEdits()
{
+ m_caretPositionForDefaultStyle = -2;
m_buffer.Modify(false);
m_buffer.GetCommandProcessor()->ClearCommands();
}
}
// ----------------------------------------------------------------------------
-// implemenation details
+// implementation details
// ----------------------------------------------------------------------------
-void wxRichTextCtrl::Command(wxCommandEvent & event)
+void wxRichTextCtrl::Command(wxCommandEvent& event)
{
SetValue(event.GetString());
GetEventHandler()->ProcessEvent(event);
return GetBuffer().SetStyle(wxRichTextRange(start, end), style);
}
+bool wxRichTextCtrl::SetStyle(long start, long end, const wxTextAttr& style)
+{
+ return GetBuffer().SetStyle(wxRichTextRange(start, end), wxTextAttrEx(style));
+}
+
bool wxRichTextCtrl::SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style)
{
return GetBuffer().SetStyle(range, style);
return GetBuffer().SetDefaultStyle(style);
}
+bool wxRichTextCtrl::SetDefaultStyle(const wxTextAttr& style)
+{
+ return GetBuffer().SetDefaultStyle(wxTextAttrEx(style));
+}
+
const wxTextAttrEx& wxRichTextCtrl::GetDefaultStyleEx() const
{
return GetBuffer().GetDefaultStyle();
}
+const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const
+{
+ return GetBuffer().GetDefaultStyle();
+}
+
+bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style) const
+{
+ wxTextAttrEx attr;
+ if (GetBuffer().GetStyle(position, attr))
+ {
+ style = attr;
+ return true;
+ }
+ else
+ return false;
+}
+
bool wxRichTextCtrl::GetStyle(long position, wxTextAttrEx& style) const
{
return GetBuffer().GetStyle(position, style);
// to see what the effect would be if we started typing.
wxRichTextAttr attr;
attr.SetFlags(wxTEXT_ATTR_FONT_WEIGHT);
- if (GetStyle(GetCaretPosition()+1, attr))
+
+ long pos = GetAdjustedCaretPosition(GetCaretPosition());
+ if (GetStyle(pos, attr))
{
- wxRichTextApplyStyle(attr, GetDefaultStyleEx());
+ if (IsDefaultStyleShowing())
+ wxRichTextApplyStyle(attr, GetDefaultStyleEx());
return attr.GetFontWeight() == wxBOLD;
}
}
// to see what the effect would be if we started typing.
wxRichTextAttr attr;
attr.SetFlags(wxTEXT_ATTR_FONT_ITALIC);
- if (GetStyle(GetCaretPosition()+1, attr))
+
+ long pos = GetAdjustedCaretPosition(GetCaretPosition());
+ if (GetStyle(pos, attr))
{
- wxRichTextApplyStyle(attr, GetDefaultStyleEx());
+ if (IsDefaultStyleShowing())
+ wxRichTextApplyStyle(attr, GetDefaultStyleEx());
return attr.GetFontStyle() == wxITALIC;
}
}
// to see what the effect would be if we started typing.
wxRichTextAttr attr;
attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE);
- if (GetStyle(GetCaretPosition()+1, attr))
+
+ long pos = GetAdjustedCaretPosition(GetCaretPosition());
+ if (GetStyle(pos, attr))
{
- wxRichTextApplyStyle(attr, GetDefaultStyleEx());
+ if (IsDefaultStyleShowing())
+ wxRichTextApplyStyle(attr, GetDefaultStyleEx());
return attr.GetFontUnderlined();
}
}
if (HasSelection())
return SetStyle(GetSelectionRange(), attr);
else
- SetDefaultStyle(attr);
+ SetAndShowDefaultStyle(attr);
return true;
}
if (HasSelection())
return SetStyle(GetSelectionRange(), attr);
else
- SetDefaultStyle(attr);
+ SetAndShowDefaultStyle(attr);
return true;
}
if (HasSelection())
return SetStyle(GetSelectionRange(), attr);
else
- SetDefaultStyle(attr);
+ SetAndShowDefaultStyle(attr);
return true;
}
return true;
}
+/// Apply a named style to the selection
+void wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def)
+{
+ // Flags are defined within each definition, so only certain
+ // attributes are applied.
+ wxRichTextAttr attr(def->GetStyle());
+
+ // Make sure the attr has the style name
+ if (def->IsKindOf(CLASSINFO(wxRichTextParagraphStyleDefinition)))
+ attr.SetParagraphStyleName(def->GetName());
+ else
+ attr.SetCharacterStyleName(def->GetName());
+
+ if (HasSelection())
+ SetStyle(GetSelectionRange(), attr);
+ else
+ SetAndShowDefaultStyle(attr);
+}
+
/// Sets the default style to the style under the cursor
bool wxRichTextCtrl::SetDefaultStyleToCursorStyle()
{
wxTextAttrEx attr;
attr.SetFlags(wxTEXT_ATTR_CHARACTER);
- if (GetStyle(GetCaretPosition(), attr))
+ // If at the start of a paragraph, use the next position.
+ long pos = GetAdjustedCaretPosition(GetCaretPosition());
+
+ if (GetStyle(pos, attr))
{
SetDefaultStyle(attr);
return true;
return 0;
}
+/// The adjusted caret position is the character position adjusted to take
+/// into account whether we're at the start of a paragraph, in which case
+/// style information should be taken from the next position, not current one.
+long wxRichTextCtrl::GetAdjustedCaretPosition(long caretPos) const
+{
+ wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(caretPos+1);
+
+ if (para && (caretPos+1 == para->GetRange().GetStart()))
+ caretPos ++;
+ return caretPos;
+}
+
#endif
// wxUSE_RICHTEXT