bool HasParagraphSpacingAfter() const { return HasFlag(wxTEXT_ATTR_PARA_SPACING_AFTER); }
bool HasParagraphSpacingBefore() const { return HasFlag(wxTEXT_ATTR_PARA_SPACING_BEFORE); }
bool HasLineSpacing() const { return HasFlag(wxTEXT_ATTR_LINE_SPACING); }
- bool HasCharacterStyleName() const { return HasFlag(wxTEXT_ATTR_CHARACTER_STYLE_NAME); }
- bool HasParagraphStyleName() const { return HasFlag(wxTEXT_ATTR_PARAGRAPH_STYLE_NAME); }
+ bool HasCharacterStyleName() const { return HasFlag(wxTEXT_ATTR_CHARACTER_STYLE_NAME) || !m_characterStyleName.IsEmpty(); }
+ bool HasParagraphStyleName() const { return HasFlag(wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) || !m_paragraphStyleName.IsEmpty(); }
bool HasBulletStyle() const { return HasFlag(wxTEXT_ATTR_BULLET_STYLE); }
bool HasBulletNumber() const { return HasFlag(wxTEXT_ATTR_BULLET_NUMBER); }
bool HasBulletSymbol() const { return HasFlag(wxTEXT_ATTR_BULLET_SYMBOL); }
void SetFlags(long flags) { m_flags = flags; }
- void SetCharacterStyleName(const wxString& name) { m_characterStyleName = name; }
- void SetParagraphStyleName(const wxString& name) { m_paragraphStyleName = name; }
- void SetParagraphSpacingAfter(int spacing) { m_paragraphSpacingAfter = spacing; }
- void SetParagraphSpacingBefore(int spacing) { m_paragraphSpacingBefore = spacing; }
- void SetLineSpacing(int spacing) { m_lineSpacing = spacing; }
- void SetBulletStyle(int style) { m_bulletStyle = style; }
- void SetBulletNumber(int n) { m_bulletNumber = n; }
- void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; }
+ void SetCharacterStyleName(const wxString& name) { m_characterStyleName = name; m_flags |= wxTEXT_ATTR_CHARACTER_STYLE_NAME; }
+ void SetParagraphStyleName(const wxString& name) { m_paragraphStyleName = name; m_flags |= wxTEXT_ATTR_PARAGRAPH_STYLE_NAME; }
+ void SetParagraphSpacingAfter(int spacing) { m_paragraphSpacingAfter = spacing; m_flags |= wxTEXT_ATTR_PARA_SPACING_AFTER; }
+ void SetParagraphSpacingBefore(int spacing) { m_paragraphSpacingBefore = spacing; m_flags |= wxTEXT_ATTR_PARA_SPACING_BEFORE; }
+ void SetLineSpacing(int spacing) { m_lineSpacing = spacing; m_flags |= wxTEXT_ATTR_LINE_SPACING; }
+ void SetBulletStyle(int style) { m_bulletStyle = style; m_flags |= wxTEXT_ATTR_BULLET_STYLE; }
+ void SetBulletNumber(int n) { m_bulletNumber = n; m_flags |= wxTEXT_ATTR_BULLET_NUMBER; }
+ void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; m_flags |= wxTEXT_ATTR_BULLET_NUMBER; }
const wxColour& GetTextColour() const { return m_colText; }
const wxColour& GetBackgroundColour() const { return m_colBack; }
bool HasParagraphSpacingAfter() const { return (m_flags & wxTEXT_ATTR_PARA_SPACING_AFTER) != 0; }
bool HasParagraphSpacingBefore() const { return (m_flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) != 0; }
bool HasLineSpacing() const { return (m_flags & wxTEXT_ATTR_LINE_SPACING) != 0; }
- bool HasCharacterStyleName() const { return (m_flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) != 0; }
- bool HasParagraphStyleName() const { return (m_flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) != 0; }
+ bool HasCharacterStyleName() const { return (m_flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) != 0 || !m_characterStyleName.IsEmpty(); }
+ bool HasParagraphStyleName() const { return (m_flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) != 0 || !m_paragraphStyleName.IsEmpty(); }
bool HasBulletStyle() const { return (m_flags & wxTEXT_ATTR_BULLET_STYLE) != 0; }
bool HasBulletNumber() const { return (m_flags & wxTEXT_ATTR_BULLET_NUMBER) != 0; }
bool HasBulletSymbol() const { return (m_flags & wxTEXT_ATTR_BULLET_SYMBOL) != 0; }
#include "wx/caret.h"
#if wxCHECK_VERSION(2,7,0)
-#define wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE 0
+#define wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE 1
#else
#define wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE 0
#endif
#include "wx/textctrl.h"
#endif
+class WXDLLIMPEXP_RICHTEXT wxRichTextStyleDefinition;
+
/*!
* Styles and flags
*/
/// Apply alignment to the selection
virtual bool ApplyAlignmentToSelection(wxTextAttrAlignment alignment);
+ /// Apply a named style to the selection
+ virtual void ApplyStyle(wxRichTextStyleDefinition* def);
+
/// Set style sheet, if any.
void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { GetBuffer().SetStyleSheet(styleSheet); }
wxRichTextStyleSheet* GetStyleSheet() const { return GetBuffer().GetStyleSheet(); }
void SetCaretPosition(long position, bool showAtLineStart = false) ;
long GetCaretPosition() const { return m_caretPosition; }
+ /// 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 GetAdjustedCaretPosition(long caretPos) const;
+
/// Move caret one visual step forward: this may mean setting a flag
/// and keeping the same position if we're going from the end of one line
/// to the start of the next, which may be the exact same caret position.
/// Returns the first visible position in the current view
long GetFirstVisiblePosition() const;
+ /// Returns the caret position since the default formatting was changed. As
+ /// soon as this position changes, we no longer reflect the default style
+ /// in the UI. A value of -2 means that we should only reflect the style of the
+ /// content under the caret.
+ long GetCaretPositionForDefaultStyle() const { return m_caretPositionForDefaultStyle; }
+
+ /// Set the caret position for the default style that the user is selecting.
+ void SetCaretPositionForDefaultStyle(long pos) { m_caretPositionForDefaultStyle = pos; }
+
+ /// Should the UI reflect the default style chosen by the user, rather than the style under
+ /// the caret?
+ bool IsDefaultStyleShowing() const { return m_caretPositionForDefaultStyle != -2; }
+
+ /// Convenience function that tells the control to start reflecting the default
+ /// style, since the user is changing it.
+ void SetAndShowDefaultStyle(const wxRichTextAttr& attr)
+ {
+ SetDefaultStyle(attr);
+ SetCaretPositionForDefaultStyle(GetCaretPosition());
+ }
+
#if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
WX_FORWARD_TO_SCROLL_HELPER()
#endif
/// first caret position).
long m_caretPosition;
+ /// Caret position when the default formatting has been changed. As
+ /// soon as this position changes, we no longer reflect the default style
+ /// in the UI.
+ long m_caretPositionForDefaultStyle;
+
/// Selection range in character positions. -2, -2 means no selection.
wxRichTextRange m_selectionRange;
// (a) All selected.
if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
- {/*
- // Draw all selected
- dc.SetBrush(*wxBLACK_BRUSH);
- dc.SetPen(*wxBLACK_PEN);
- wxCoord w, h;
- dc.GetTextExtent(stringChunk, & w, & h);
- wxRect selRect(x, rect.y, w, rect.GetHeight());
- dc.DrawRectangle(selRect);
- dc.SetTextForeground(*wxWHITE);
- dc.SetBackgroundMode(wxTRANSPARENT);
- dc.DrawText(stringChunk, x, y);*/
+ {
DrawTabbedString(dc, rect,stringChunk, x, y, true);
}
// (b) None selected.
else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
{
// Draw all unselected
- /*
- dc.SetTextForeground(GetAttributes().GetTextColour());
- dc.SetBackgroundMode(wxTRANSPARENT);
- dc.DrawText(stringChunk, x, y);*/
DrawTabbedString(dc, rect,stringChunk, x, y, false);
}
else
if (fragmentLen < 0)
wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
-/*
- dc.SetTextForeground(GetAttributes().GetTextColour());
- dc.DrawText(stringFragment, x, y);
- wxCoord w, h;
- dc.GetTextExtent(stringFragment, & w, & h);
- x += w;*/
DrawTabbedString(dc, rect,stringFragment, x, y, false);
}
if (fragmentLen < 0)
wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
-/*
- wxCoord w, h;
- dc.GetTextExtent(stringFragment, & w, & h);
- wxRect selRect(x, rect.y, w, rect.GetHeight());
-
- dc.SetBrush(*wxBLACK_BRUSH);
- dc.SetPen(*wxBLACK_PEN);
- dc.DrawRectangle(selRect);
- dc.SetTextForeground(*wxWHITE);
- dc.DrawText(stringFragment, x, y);
- x += w;*/
DrawTabbedString(dc, rect,stringFragment, x, y, true);
}
if (fragmentLen < 0)
wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen);
-/*
- dc.SetTextForeground(GetAttributes().GetTextColour());
- dc.DrawText(stringFragment, x, y);*/
+
DrawTabbedString(dc, rect,stringFragment, x, y, false);
}
}
bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
{
wxArrayInt tab_array = GetAttributes().GetTabs();
- if(tab_array.IsEmpty()){// create a default tab list at 10 mm each.
- for( int i = 0; i < 20; ++i){
+ if (tab_array.IsEmpty())
+ {
+ // create a default tab list at 10 mm each.
+ for (int i = 0; i < 20; ++i)
+ {
tab_array.Add(i*100);
}
}
int map_mode = dc.GetMapMode();
dc.SetMapMode(wxMM_LOMETRIC );
int num_tabs = tab_array.GetCount();
- for( int i = 0; i < num_tabs; ++i){
+ for (int i = 0; i < num_tabs; ++i)
+ {
tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
}
+
dc.SetMapMode(map_mode );
int next_tab_pos = -1;
int tab_pos = -1;
wxCoord w, h;
- if(selected){
+
+ if(selected)
+ {
dc.SetBrush(*wxBLACK_BRUSH);
dc.SetPen(*wxBLACK_PEN);
dc.SetTextForeground(*wxWHITE);
dc.SetBackgroundMode(wxTRANSPARENT);
}
- else{
+ else
+ {
dc.SetTextForeground(GetAttributes().GetTextColour());
dc.SetBackgroundMode(wxTRANSPARENT);
}
- while(str.Find(wxT('\t')) >= 0){// the string has a tab
+
+ while (str.Find(wxT('\t')) >= 0)
+ {
+ // the string has a tab
// break up the string at the Tab
wxString stringChunk = str.BeforeFirst(wxT('\t'));
str = str.AfterFirst(wxT('\t'));
dc.GetTextExtent(stringChunk, & w, & h);
tab_pos = x + w;
bool not_found = true;
- for( int i = 0; i < num_tabs && not_found; ++i){
+ for (int i = 0; i < num_tabs && not_found; ++i)
+ {
next_tab_pos = tab_array.Item(i);
- if( next_tab_pos > tab_pos){
+ if (next_tab_pos > tab_pos)
+ {
not_found = false;
- if(selected){
+ if (selected)
+ {
w = next_tab_pos - x;
wxRect selRect(x, rect.y, w, rect.GetHeight());
dc.DrawRectangle(selRect);
}
dc.GetTextExtent(str, & w, & h);
- if(selected){
+ if (selected)
+ {
wxRect selRect(x, rect.y, w, rect.GetHeight());
dc.DrawRectangle(selRect);
}
wxString stringChunk = m_text.Mid(startPos, (size_t) len);
wxCoord w, h;
int width = 0;
- if(stringChunk.Find(wxT('\t')) >= 0){// the string has a tab
+ if (stringChunk.Find(wxT('\t')) >= 0)
+ {
+ // the string has a tab
wxArrayInt tab_array = GetAttributes().GetTabs();
- if(tab_array.IsEmpty())
+ if (tab_array.IsEmpty())
{
// create a default tab list at 10 mm each.
- for( int i = 0; i < 20; ++i)
+ for (int i = 0; i < 20; ++i)
{
tab_array.Add(i*100);
}
}
+
int map_mode = dc.GetMapMode();
dc.SetMapMode(wxMM_LOMETRIC );
int num_tabs = tab_array.GetCount();
- for( int i = 0; i < num_tabs; ++i)
+
+ for (int i = 0; i < num_tabs; ++i)
{
tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
}
dc.SetMapMode(map_mode );
int next_tab_pos = -1;
- while(stringChunk.Find(wxT('\t')) >= 0){// the string has a tab
+ while (stringChunk.Find(wxT('\t')) >= 0)
+ {
+ // the string has a tab
// break up the string at the Tab
wxString stringFragment = stringChunk.BeforeFirst(wxT('\t'));
stringChunk = stringChunk.AfterFirst(wxT('\t'));
width += w;
int absolute_width = width + position.x;
bool not_found = true;
- for( int i = 0; i < num_tabs && not_found; ++i){
+ for (int i = 0; i < num_tabs && not_found; ++i)
+ {
next_tab_pos = tab_array.Item(i);
- if( next_tab_pos > absolute_width){
+ if (next_tab_pos > absolute_width)
+ {
not_found = false;
width = next_tab_pos - position.x;
}
#if wxUSE_RICHTEXT
#include "wx/richtext/richtextctrl.h"
+#include "wx/richtext/richtextstyles.h"
#ifndef WX_PRECOMP
#include "wx/settings.h"
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);
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();
}
void wxRichTextCtrl::DiscardEdits()
{
+ m_caretPositionForDefaultStyle = -2;
m_buffer.Modify(false);
m_buffer.GetCommandProcessor()->ClearCommands();
}
// 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