X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fe5aa22c174da89809b6c5d27e60300df0b879ac..fba41cf33a3952077133d387f2cc49d211f3d893:/src/richtext/richtextstyles.cpp?ds=sidebyside diff --git a/src/richtext/richtextstyles.cpp b/src/richtext/richtextstyles.cpp index ada328a49e..dc39222fb1 100644 --- a/src/richtext/richtextstyles.cpp +++ b/src/richtext/richtextstyles.cpp @@ -27,12 +27,14 @@ #include "wx/filename.h" #include "wx/clipbrd.h" #include "wx/wfstream.h" +#include "wx/settings.h" #include "wx/richtext/richtextctrl.h" IMPLEMENT_CLASS(wxRichTextStyleDefinition, wxObject) IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition, wxRichTextStyleDefinition) IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition, wxRichTextStyleDefinition) +IMPLEMENT_CLASS(wxRichTextListStyleDefinition, wxRichTextParagraphStyleDefinition) /*! * A definition @@ -43,6 +45,7 @@ void wxRichTextStyleDefinition::Copy(const wxRichTextStyleDefinition& def) m_name = def.m_name; m_baseStyle = def.m_baseStyle; m_style = def.m_style; + m_description = def.m_description; } bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition& def) const @@ -50,6 +53,22 @@ bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition& def) const return (m_name == def.m_name && m_baseStyle == def.m_baseStyle && m_style == def.m_style); } +/// Gets the style combined with the base style +wxTextAttr wxRichTextStyleDefinition::GetStyleMergedWithBase(const wxRichTextStyleSheet* sheet) const +{ + if (!m_baseStyle.IsEmpty()) + { + wxRichTextStyleDefinition* baseStyle = sheet->FindStyle(m_baseStyle); + if (baseStyle) + { + wxTextAttr baseAttr = baseStyle->GetStyleMergedWithBase(sheet); + baseAttr.Apply(m_style, NULL); + return baseAttr; + } + } + return m_style; +} + /*! * Paragraph style definition */ @@ -66,15 +85,183 @@ bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphSt return (Eq(def) && m_nextStyle == def.m_nextStyle); } +/*! + * List style definition + */ + +void wxRichTextListStyleDefinition::Copy(const wxRichTextListStyleDefinition& def) +{ + wxRichTextParagraphStyleDefinition::Copy(def); + + int i; + for (i = 0; i < 10; i++) + m_levelStyles[i] = def.m_levelStyles[i]; +} + +bool wxRichTextListStyleDefinition::operator ==(const wxRichTextListStyleDefinition& def) const +{ + if (!Eq(def)) + return false; + int i; + for (i = 0; i < 10; i++) + if (!(m_levelStyles[i] == def.m_levelStyles[i])) + return false; + + return true; +} + +/// Sets/gets the attributes for the given level +void wxRichTextListStyleDefinition::SetLevelAttributes(int i, const wxTextAttr& attr) +{ + wxASSERT( (i >= 0 && i < 10) ); + if (i >= 0 && i < 10) + m_levelStyles[i] = attr; +} + +const wxTextAttr* wxRichTextListStyleDefinition::GetLevelAttributes(int i) const +{ + wxASSERT( (i >= 0 && i < 10) ); + if (i >= 0 && i < 10) + return & m_levelStyles[i]; + else + return NULL; +} + +wxTextAttr* wxRichTextListStyleDefinition::GetLevelAttributes(int i) +{ + wxASSERT( (i >= 0 && i < 10) ); + if (i >= 0 && i < 10) + return & m_levelStyles[i]; + else + return NULL; +} + +/// Convenience function for setting the major attributes for a list level specification +void wxRichTextListStyleDefinition::SetAttributes(int i, int leftIndent, int leftSubIndent, int bulletStyle, const wxString& bulletSymbol) +{ + wxASSERT( (i >= 0 && i < 10) ); + if (i >= 0 && i < 10) + { + wxTextAttr attr; + + attr.SetBulletStyle(bulletStyle); + attr.SetLeftIndent(leftIndent, leftSubIndent); + + if (!bulletSymbol.IsEmpty()) + { + if (bulletStyle & wxTEXT_ATTR_BULLET_STYLE_SYMBOL) + attr.SetBulletText(bulletSymbol); + else + attr.SetBulletName(bulletSymbol); + } + + m_levelStyles[i] = attr; + } +} + +/// Finds the level corresponding to the given indentation +int wxRichTextListStyleDefinition::FindLevelForIndent(int indent) const +{ + int i; + for (i = 0; i < 10; i++) + { + if (indent < m_levelStyles[i].GetLeftIndent()) + { + if (i > 0) + return i - 1; + else + return 0; + } + } + return 9; +} + +/// Combine the list style with a paragraph style, using the given indent (from which +/// an appropriate level is found) +wxTextAttr wxRichTextListStyleDefinition::CombineWithParagraphStyle(int indent, const wxTextAttr& paraStyle, wxRichTextStyleSheet* styleSheet) +{ + int listLevel = FindLevelForIndent(indent); + + wxTextAttr attr(*GetLevelAttributes(listLevel)); + int oldLeftIndent = attr.GetLeftIndent(); + int oldLeftSubIndent = attr.GetLeftSubIndent(); + + // First apply the overall paragraph style, if any + if (styleSheet) + attr.Apply(GetStyleMergedWithBase(styleSheet)); + else + attr.Apply(GetStyle()); + + // Then apply paragraph style, e.g. from paragraph style definition + attr.Apply(paraStyle); + + // We override the indents according to the list definition + attr.SetLeftIndent(oldLeftIndent, oldLeftSubIndent); + + return attr; +} + +/// Combine the base and list style, using the given indent (from which +/// an appropriate level is found) +wxTextAttr wxRichTextListStyleDefinition::GetCombinedStyle(int indent, wxRichTextStyleSheet* styleSheet) +{ + int listLevel = FindLevelForIndent(indent); + return GetCombinedStyleForLevel(listLevel, styleSheet); +} + +/// Combine the base and list style, using the given indent (from which +/// an appropriate level is found) +wxTextAttr wxRichTextListStyleDefinition::GetCombinedStyleForLevel(int listLevel, wxRichTextStyleSheet* styleSheet) +{ + wxTextAttr attr(*GetLevelAttributes(listLevel)); + int oldLeftIndent = attr.GetLeftIndent(); + int oldLeftSubIndent = attr.GetLeftSubIndent(); + + // Apply the overall paragraph style, if any + if (styleSheet) + attr.Apply(GetStyleMergedWithBase(styleSheet)); + else + attr.Apply(GetStyle()); + + // We override the indents according to the list definition + attr.SetLeftIndent(oldLeftIndent, oldLeftSubIndent); + + return attr; +} + +/// Is this a numbered list? +bool wxRichTextListStyleDefinition::IsNumbered(int i) const +{ + return (0 != (GetLevelAttributes(i)->GetFlags() & + (wxTEXT_ATTR_BULLET_STYLE_ARABIC|wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER|wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER| + wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER|wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER))); +} + /*! * The style manager */ IMPLEMENT_CLASS(wxRichTextStyleSheet, wxObject) +wxRichTextStyleSheet::~wxRichTextStyleSheet() +{ + DeleteStyles(); + + if (m_nextSheet) + m_nextSheet->m_previousSheet = m_previousSheet; + + if (m_previousSheet) + m_previousSheet->m_nextSheet = m_nextSheet; + + m_previousSheet = NULL; + m_nextSheet = NULL; +} + /// Initialisation void wxRichTextStyleSheet::Init() { + m_previousSheet = NULL; + m_nextSheet = NULL; } /// Add a definition to one of the style lists @@ -101,8 +288,20 @@ bool wxRichTextStyleSheet::RemoveStyle(wxList& list, wxRichTextStyleDefinition* return false; } +/// Remove a style +bool wxRichTextStyleSheet::RemoveStyle(wxRichTextStyleDefinition* def, bool deleteStyle) +{ + if (RemoveParagraphStyle(def, deleteStyle)) + return true; + if (RemoveCharacterStyle(def, deleteStyle)) + return true; + if (RemoveListStyle(def, deleteStyle)) + return true; + return false; +} + /// Find a definition by name -wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxList& list, const wxString& name) const +wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxList& list, const wxString& name, bool recurse) const { for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext()) { @@ -110,6 +309,10 @@ wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxList& list, c if (def->GetName().Lower() == name.Lower()) return def; } + + if (m_nextSheet && recurse) + return m_nextSheet->FindStyle(list, name, recurse); + return NULL; } @@ -118,6 +321,49 @@ void wxRichTextStyleSheet::DeleteStyles() { WX_CLEAR_LIST(wxList, m_characterStyleDefinitions); WX_CLEAR_LIST(wxList, m_paragraphStyleDefinitions); + WX_CLEAR_LIST(wxList, m_listStyleDefinitions); +} + +/// Insert into list of style sheets +bool wxRichTextStyleSheet::InsertSheet(wxRichTextStyleSheet* before) +{ + m_previousSheet = before->m_previousSheet; + m_nextSheet = before; + + before->m_previousSheet = this; + return true; +} + +/// Append to list of style sheets +bool wxRichTextStyleSheet::AppendSheet(wxRichTextStyleSheet* after) +{ + wxRichTextStyleSheet* last = after; + while (last && last->m_nextSheet) + { + last = last->m_nextSheet; + } + + if (last) + { + m_previousSheet = last; + last->m_nextSheet = this; + + return true; + } + else + return false; +} + +/// Unlink from the list of style sheets +void wxRichTextStyleSheet::Unlink() +{ + if (m_previousSheet) + m_previousSheet->m_nextSheet = m_nextSheet; + if (m_nextSheet) + m_nextSheet->m_previousSheet = m_previousSheet; + + m_previousSheet = NULL; + m_nextSheet = NULL; } /// Add a definition to the character style list @@ -134,6 +380,49 @@ bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition* return AddStyle(m_paragraphStyleDefinitions, def); } +/// Add a definition to the list style list +bool wxRichTextStyleSheet::AddListStyle(wxRichTextListStyleDefinition* def) +{ + def->GetStyle().SetListStyleName(def->GetName()); + return AddStyle(m_listStyleDefinitions, def); +} + +/// Add a definition to the appropriate style list +bool wxRichTextStyleSheet::AddStyle(wxRichTextStyleDefinition* def) +{ + wxRichTextListStyleDefinition* listDef = wxDynamicCast(def, wxRichTextListStyleDefinition); + if (listDef) + return AddListStyle(listDef); + + wxRichTextParagraphStyleDefinition* paraDef = wxDynamicCast(def, wxRichTextParagraphStyleDefinition); + if (paraDef) + return AddParagraphStyle(paraDef); + + wxRichTextCharacterStyleDefinition* charDef = wxDynamicCast(def, wxRichTextCharacterStyleDefinition); + if (charDef) + return AddCharacterStyle(charDef); + + return false; +} + +/// Find any definition by name +wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxString& name, bool recurse) const +{ + wxRichTextListStyleDefinition* listDef = FindListStyle(name, recurse); + if (listDef) + return listDef; + + wxRichTextParagraphStyleDefinition* paraDef = FindParagraphStyle(name, recurse); + if (paraDef) + return paraDef; + + wxRichTextCharacterStyleDefinition* charDef = FindCharacterStyle(name, recurse); + if (charDef) + return charDef; + + return NULL; +} + /// Copy void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet& sheet) { @@ -152,6 +441,15 @@ void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet& sheet) wxRichTextParagraphStyleDefinition* def = (wxRichTextParagraphStyleDefinition*) node->GetData(); AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def)); } + + for (node = sheet.m_listStyleDefinitions.GetFirst(); node; node = node->GetNext()) + { + wxRichTextListStyleDefinition* def = (wxRichTextListStyleDefinition*) node->GetData(); + AddListStyle(new wxRichTextListStyleDefinition(*def)); + } + + SetName(sheet.GetName()); + SetDescription(sheet.GetDescription()); } /// Equality @@ -164,15 +462,14 @@ bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet& WXUNUSED(sheet #if wxUSE_HTML /*! - * wxRichTextStyleListBox class declaration - * A listbox to display styles. + * wxRichTextStyleListBox: a listbox to display styles. */ IMPLEMENT_CLASS(wxRichTextStyleListBox, wxHtmlListBox) BEGIN_EVENT_TABLE(wxRichTextStyleListBox, wxHtmlListBox) - EVT_LISTBOX(wxID_ANY, wxRichTextStyleListBox::OnSelect) EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown) + EVT_LEFT_DCLICK(wxRichTextStyleListBox::OnLeftDoubleClick) EVT_IDLE(wxRichTextStyleListBox::OnIdle) END_EVENT_TABLE() @@ -199,22 +496,10 @@ wxString wxRichTextStyleListBox::OnGetItem(size_t n) const if (!GetStyleSheet()) return wxEmptyString; - // First paragraph styles, then character - if (n < GetStyleSheet()->GetParagraphStyleCount()) - { - wxRichTextParagraphStyleDefinition* def = GetStyleSheet()->GetParagraphStyle(n); - - wxString str = CreateHTML(def); - return str; - } - - if ((n - GetStyleSheet()->GetParagraphStyleCount()) < GetStyleSheet()->GetCharacterStyleCount()) - { - wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->GetCharacterStyle(n - GetStyleSheet()->GetParagraphStyleCount()); + wxRichTextStyleDefinition* def = GetStyle(n); + if (def) + return CreateHTML(def); - wxString str = CreateHTML(def); - return str; - } return wxEmptyString; } @@ -224,14 +509,10 @@ wxRichTextStyleDefinition* wxRichTextStyleListBox::GetStyle(size_t i) const if (!GetStyleSheet()) return NULL; - // First paragraph styles, then character - if (i < GetStyleSheet()->GetParagraphStyleCount()) - return GetStyleSheet()->GetParagraphStyle(i); - - if ((i - GetStyleSheet()->GetParagraphStyleCount()) < GetStyleSheet()->GetCharacterStyleCount()) - return GetStyleSheet()->GetCharacterStyle(i - GetStyleSheet()->GetParagraphStyleCount()); + if (i >= m_styleNames.GetCount() /* || i < 0 */ ) + return NULL; - return NULL; + return GetStyleSheet()->FindStyle(m_styleNames[i]); } /// Updates the list @@ -239,31 +520,44 @@ void wxRichTextStyleListBox::UpdateStyles() { if (GetStyleSheet()) { - SetItemCount(GetStyleSheet()->GetParagraphStyleCount()+GetStyleSheet()->GetCharacterStyleCount()); + SetSelection(wxNOT_FOUND); + + m_styleNames.Clear(); + + size_t i; + if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_PARAGRAPH) + { + for (i = 0; i < GetStyleSheet()->GetParagraphStyleCount(); i++) + m_styleNames.Add(GetStyleSheet()->GetParagraphStyle(i)->GetName()); + } + if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_CHARACTER) + { + for (i = 0; i < GetStyleSheet()->GetCharacterStyleCount(); i++) + m_styleNames.Add(GetStyleSheet()->GetCharacterStyle(i)->GetName()); + } + if (GetStyleType() == wxRICHTEXT_STYLE_ALL || GetStyleType() == wxRICHTEXT_STYLE_LIST) + { + for (i = 0; i < GetStyleSheet()->GetListStyleCount(); i++) + m_styleNames.Add(GetStyleSheet()->GetListStyle(i)->GetName()); + } + + m_styleNames.Sort(); + SetItemCount(m_styleNames.GetCount()); + Refresh(); + + if (GetItemCount() > 0) + { + SetSelection(0); + SendSelectedEvent(); + } } } // Get index for style name int wxRichTextStyleListBox::GetIndexForStyle(const wxString& name) const { - if (GetStyleSheet()) - { - int i; - for (i = 0; i < (int) GetStyleSheet()->GetParagraphStyleCount(); i++) - { - wxRichTextParagraphStyleDefinition* def = GetStyleSheet()->GetParagraphStyle(i); - if (def->GetName() == name) - return i; - } - for (i = 0; i < (int) GetStyleSheet()->GetCharacterStyleCount(); i++) - { - wxRichTextCharacterStyleDefinition* def = GetStyleSheet()->GetCharacterStyle(i); - if (def->GetName() == name) - return i + (int) GetStyleSheet()->GetParagraphStyleCount(); - } - } - return -1; + return m_styleNames.Index(name); } /// Set selection for string @@ -290,31 +584,116 @@ static wxString ColourToHexString(const wxColour& col) /// Creates a suitable HTML fragment for a definition wxString wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition* def) const { - wxString str(wxT("")); + // TODO: indicate list format for list style types + + wxString str; - if (def->GetStyle().GetLeftIndent() > 0) + bool isCentred = false; + + wxTextAttr attr(def->GetStyleMergedWithBase(GetStyleSheet())); + + if (attr.HasAlignment() && attr.GetAlignment() == wxTEXT_ALIGNMENT_CENTRE) + isCentred = true; + + if (isCentred) + str << wxT("
"); + + + str << wxT("
"); + + if (attr.GetLeftIndent() > 0) { wxClientDC dc((wxWindow*) this); - str << wxT(""); + str << wxT(""); } - str << wxT("
"); + if (isCentred) + str << wxT(""); + else + str << wxT(""); - int size = 5; +#ifdef __WXMSW__ + int size = 2; +#else + int size = 3; +#endif - // Standard size is 12, say - size += 12 - def->GetStyle().GetFontSize(); + // Guess a standard font size + int stdFontSize = 0; + + // First see if we have a default/normal style to base the size on + wxString normalTranslated(_("normal")); + wxString defaultTranslated(_("default")); + size_t i; + for (i = 0; i < m_styleNames.GetCount(); i++) + { + wxString name = m_styleNames[i].Lower(); + if (name.Find(wxT("normal")) != wxNOT_FOUND || name.Find(normalTranslated) != wxNOT_FOUND || + name.Find(wxT("default")) != wxNOT_FOUND || name.Find(defaultTranslated) != wxNOT_FOUND) + { + wxRichTextStyleDefinition* d = GetStyleSheet()->FindStyle(m_styleNames[i]); + if (d) + { + wxRichTextAttr attr2(d->GetStyleMergedWithBase(GetStyleSheet())); + if (attr2.HasFontSize()) + { + stdFontSize = attr2.GetFontSize(); + break; + } + } + } + } + + if (stdFontSize == 0) + { + // Look at sizes up to 20 points, and see which is the most common + wxArrayInt sizes; + size_t maxSize = 20; + for (i = 0; i <= maxSize; i++) + sizes.Add(0); + for (i = 0; i < m_styleNames.GetCount(); i++) + { + wxRichTextStyleDefinition* d = GetStyleSheet()->FindStyle(m_styleNames[i]); + if (d) + { + wxRichTextAttr attr2(d->GetStyleMergedWithBase(GetStyleSheet())); + if (attr2.HasFontSize()) + { + if (attr2.GetFontSize() <= (int) maxSize) + sizes[attr2.GetFontSize()] ++; + } + } + } + int mostCommonSize = 0; + for (i = 0; i <= maxSize; i++) + { + if (sizes[i] > mostCommonSize) + mostCommonSize = i; + } + if (mostCommonSize > 0) + stdFontSize = mostCommonSize; + } + + if (stdFontSize == 0) + stdFontSize = 12; + + int thisFontSize = ((attr.GetFlags() & wxTEXT_ATTR_FONT_SIZE) != 0) ? attr.GetFontSize() : stdFontSize; + + if (thisFontSize < stdFontSize) + size --; + else if (thisFontSize > stdFontSize) + size ++; str += wxT("GetStyle().GetFontFaceName() << wxT("\""); + if (!attr.GetFontFaceName().IsEmpty()) + str << wxT(" face=\"") << attr.GetFontFaceName() << wxT("\""); - if (def->GetStyle().GetTextColour().Ok()) - str << wxT(" color=\"#") << ColourToHexString(def->GetStyle().GetTextColour()) << wxT("\""); + if (attr.GetTextColour().Ok()) + str << wxT(" color=\"#") << ColourToHexString(attr.GetTextColour()) << wxT("\""); str << wxT(">"); @@ -322,11 +701,11 @@ wxString wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition* def) cons bool hasItalic = false; bool hasUnderline = false; - if (def->GetStyle().GetFontWeight() == wxBOLD) + if (attr.GetFontWeight() == wxBOLD) hasBold = true; - if (def->GetStyle().GetFontStyle() == wxITALIC) + if (attr.GetFontStyle() == wxITALIC) hasItalic = true; - if (def->GetStyle().GetFontUnderlined()) + if (attr.GetFontUnderlined()) hasUnderline = true; if (hasBold) @@ -345,9 +724,16 @@ wxString wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition* def) cons if (hasBold) str << wxT(""); + if (isCentred) + str << wxT(""); + str << wxT(""); - str += wxT("
"); + str << wxT(""); + + if (isCentred) + str << wxT(""); + return str; } @@ -363,55 +749,74 @@ int wxRichTextStyleListBox::ConvertTenthsMMToPixels(wxDC& dc, int units) const return (int) pixels; } -/// React to selection -void wxRichTextStyleListBox::OnSelect(wxCommandEvent& WXUNUSED(event)) +void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent& event) { -#if 0 - wxRichTextStyleDefinition* def = GetStyle(event.GetSelection()); - if (def) - { - wxMessageBox(def->GetName()); - } -#endif + wxVListBox::OnLeftDown(event); + + int item = HitTest(event.GetPosition()); + if (item != wxNOT_FOUND && GetApplyOnSelection()) + ApplyStyle(item); } -void wxRichTextStyleListBox::OnLeftDown(wxMouseEvent& event) +void wxRichTextStyleListBox::OnLeftDoubleClick(wxMouseEvent& event) { wxVListBox::OnLeftDown(event); int item = HitTest(event.GetPosition()); - if (item != wxNOT_FOUND) - DoSelection(item); + if (item != wxNOT_FOUND && !GetApplyOnSelection()) + ApplyStyle(item); } -/// Auto-select from style under caret in idle time -void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event) +/// Helper for listbox and combo control +wxString wxRichTextStyleListBox::GetStyleToShowInIdleTime(wxRichTextCtrl* ctrl, wxRichTextStyleType styleType) { - if (CanAutoSetSelection() && GetRichTextCtrl()) - { - int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition()); + int adjustedCaretPos = ctrl->GetAdjustedCaretPosition(ctrl->GetCaretPosition()); - wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos); - wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos); + wxString styleName; - wxString styleName; + wxTextAttr attr; + ctrl->GetStyle(adjustedCaretPos, attr); - // Take into account current default style just chosen by user - if (GetRichTextCtrl()->IsDefaultStyleShowing()) - { - if (!GetRichTextCtrl()->GetDefaultStyleEx().GetCharacterStyleName().IsEmpty()) - styleName = GetRichTextCtrl()->GetDefaultStyleEx().GetCharacterStyleName(); - else if (!GetRichTextCtrl()->GetDefaultStyleEx().GetParagraphStyleName().IsEmpty()) - styleName = GetRichTextCtrl()->GetDefaultStyleEx().GetParagraphStyleName(); - } - else if (obj && !obj->GetAttributes().GetCharacterStyleName().IsEmpty()) - { - styleName = obj->GetAttributes().GetCharacterStyleName(); - } - else if (para && !para->GetAttributes().GetParagraphStyleName().IsEmpty()) - { - styleName = para->GetAttributes().GetParagraphStyleName(); - } + // Take into account current default style just chosen by user + if (ctrl->IsDefaultStyleShowing()) + { + wxRichTextApplyStyle(attr, ctrl->GetDefaultStyleEx()); + + if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_CHARACTER) && + !attr.GetCharacterStyleName().IsEmpty()) + styleName = attr.GetCharacterStyleName(); + else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_PARAGRAPH) && + !attr.GetParagraphStyleName().IsEmpty()) + styleName = attr.GetParagraphStyleName(); + else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_LIST) && + !attr.GetListStyleName().IsEmpty()) + styleName = attr.GetListStyleName(); + } + else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_CHARACTER) && + !attr.GetCharacterStyleName().IsEmpty()) + { + styleName = attr.GetCharacterStyleName(); + } + else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_PARAGRAPH) && + !attr.GetParagraphStyleName().IsEmpty()) + { + styleName = attr.GetParagraphStyleName(); + } + else if ((styleType == wxRICHTEXT_STYLE_ALL || styleType == wxRICHTEXT_STYLE_LIST) && + !attr.GetListStyleName().IsEmpty()) + { + styleName = attr.GetListStyleName(); + } + + return styleName; +} + +/// Auto-select from style under caret in idle time +void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event) +{ + if (CanAutoSetSelection() && GetRichTextCtrl() && IsShownOnScreen() && wxWindow::FindFocus() != this) + { + wxString styleName = GetStyleToShowInIdleTime(GetRichTextCtrl(), GetStyleType()); int sel = GetSelection(); if (!styleName.IsEmpty()) @@ -429,7 +834,7 @@ void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event) } /// Do selection -void wxRichTextStyleListBox::DoSelection(int item) +void wxRichTextStyleListBox::ApplyStyle(int item) { if ( item != wxNOT_FOUND ) { @@ -442,17 +847,208 @@ void wxRichTextStyleListBox::DoSelection(int item) } } -#if 0 -wxColour wxRichTextStyleListBox::GetSelectedTextColour(const wxColour& colFg) const +/*! + * wxRichTextStyleListCtrl class: manages a listbox and a choice control to + * switch shown style types + */ + +IMPLEMENT_CLASS(wxRichTextStyleListCtrl, wxControl) + +BEGIN_EVENT_TABLE(wxRichTextStyleListCtrl, wxControl) + EVT_CHOICE(wxID_ANY, wxRichTextStyleListCtrl::OnChooseType) + EVT_SIZE(wxRichTextStyleListCtrl::OnSize) +END_EVENT_TABLE() + +wxRichTextStyleListCtrl::wxRichTextStyleListCtrl(wxWindow* parent, wxWindowID id, const wxPoint& pos, + const wxSize& size, long style) +{ + Init(); + Create(parent, id, pos, size, style); +} + +bool wxRichTextStyleListCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, + const wxSize& size, long style) +{ + if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT) + style |= wxBORDER_THEME; + + wxControl::Create(parent, id, pos, size, style); + + SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); + if (size != wxDefaultSize) + SetInitialSize(size); + + bool showSelector = ((style & wxRICHTEXTSTYLELIST_HIDE_TYPE_SELECTOR) == 0); + + wxBorder listBoxStyle; + if (showSelector) + listBoxStyle = wxBORDER_THEME; + else + listBoxStyle = wxBORDER_NONE; + + m_styleListBox = new wxRichTextStyleListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, listBoxStyle); + + wxBoxSizer* boxSizer = new wxBoxSizer(wxVERTICAL); + + if (showSelector) + { + wxArrayString choices; + choices.Add(_("All styles")); + choices.Add(_("Paragraph styles")); + choices.Add(_("Character styles")); + choices.Add(_("List styles")); + + m_styleChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, choices); + + boxSizer->Add(m_styleListBox, 1, wxALL|wxEXPAND, 5); + boxSizer->Add(m_styleChoice, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 5); + } + else + { + boxSizer->Add(m_styleListBox, 1, wxALL|wxEXPAND, 0); + } + + SetSizer(boxSizer); + Layout(); + + m_dontUpdate = true; + + if (m_styleChoice) + { + int i = StyleTypeToIndex(m_styleListBox->GetStyleType()); + m_styleChoice->SetSelection(i); + } + + m_dontUpdate = false; + + return true; +} + +wxRichTextStyleListCtrl::~wxRichTextStyleListCtrl() +{ + +} + +/// React to style type choice +void wxRichTextStyleListCtrl::OnChooseType(wxCommandEvent& event) { - return *wxBLACK; + if (event.GetEventObject() != m_styleChoice) + event.Skip(); + else + { + if (m_dontUpdate) + return; + + wxRichTextStyleListBox::wxRichTextStyleType styleType = StyleIndexToType(event.GetSelection()); + m_styleListBox->SetStyleType(styleType); + } } -wxColour wxRichTextStyleListBox::GetSelectedTextBgColour(const wxColour& colBg) const +/// Lay out the controls +void wxRichTextStyleListCtrl::OnSize(wxSizeEvent& WXUNUSED(event)) { - return *wxWHITE; + if (GetAutoLayout()) + Layout(); +} + +/// Get the choice index for style type +int wxRichTextStyleListCtrl::StyleTypeToIndex(wxRichTextStyleListBox::wxRichTextStyleType styleType) +{ + if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL) + { + return 0; + } + else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH) + { + return 1; + } + else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER) + { + return 2; + } + else if (styleType == wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST) + { + return 3; + } + return 0; +} + +/// Get the style type for choice index +wxRichTextStyleListBox::wxRichTextStyleType wxRichTextStyleListCtrl::StyleIndexToType(int i) +{ + if (i == 1) + return wxRichTextStyleListBox::wxRICHTEXT_STYLE_PARAGRAPH; + else if (i == 2) + return wxRichTextStyleListBox::wxRICHTEXT_STYLE_CHARACTER; + else if (i == 3) + return wxRichTextStyleListBox::wxRICHTEXT_STYLE_LIST; + + return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL; +} + +/// Associates the control with a style manager +void wxRichTextStyleListCtrl::SetStyleSheet(wxRichTextStyleSheet* styleSheet) +{ + if (m_styleListBox) + m_styleListBox->SetStyleSheet(styleSheet); +} + +wxRichTextStyleSheet* wxRichTextStyleListCtrl::GetStyleSheet() const +{ + if (m_styleListBox) + return m_styleListBox->GetStyleSheet(); + else + return NULL; +} + +/// Associates the control with a wxRichTextCtrl +void wxRichTextStyleListCtrl::SetRichTextCtrl(wxRichTextCtrl* ctrl) +{ + if (m_styleListBox) + m_styleListBox->SetRichTextCtrl(ctrl); +} + +wxRichTextCtrl* wxRichTextStyleListCtrl::GetRichTextCtrl() const +{ + if (m_styleListBox) + return m_styleListBox->GetRichTextCtrl(); + else + return NULL; +} + +/// Set/get the style type to display +void wxRichTextStyleListCtrl::SetStyleType(wxRichTextStyleListBox::wxRichTextStyleType styleType) +{ + if ( !m_styleListBox ) + return; + + m_styleListBox->SetStyleType(styleType); + + m_dontUpdate = true; + + if (m_styleChoice) + { + int i = StyleTypeToIndex(m_styleListBox->GetStyleType()); + m_styleChoice->SetSelection(i); + } + + m_dontUpdate = false; +} + +wxRichTextStyleListBox::wxRichTextStyleType wxRichTextStyleListCtrl::GetStyleType() const +{ + if (m_styleListBox) + return m_styleListBox->GetStyleType(); + else + return wxRichTextStyleListBox::wxRICHTEXT_STYLE_ALL; +} + +/// Updates the style list box +void wxRichTextStyleListCtrl::UpdateStyles() +{ + if (m_styleListBox) + m_styleListBox->UpdateStyles(); } -#endif #if wxUSE_COMBOCTRL @@ -466,6 +1062,17 @@ BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup, wxRichTextStyleListBox) EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick) END_EVENT_TABLE() +bool wxRichTextStyleComboPopup::Create( wxWindow* parent ) +{ + int borderStyle = GetDefaultBorder(); + if (borderStyle == wxBORDER_SUNKEN) + borderStyle = wxBORDER_SIMPLE; + + return wxRichTextStyleListBox::Create(parent, wxID_ANY, + wxPoint(0,0), wxDefaultSize, + borderStyle); +} + void wxRichTextStyleComboPopup::SetStringValue( const wxString& s ) { m_value = SetStyleSelection(s); @@ -508,11 +1115,11 @@ void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent& WXUNUSED(event)) m_value = m_itemHere; // Ordering is important, so we don't dismiss this popup accidentally - // by setting the focus elsewhere e.g. in DoSelection + // by setting the focus elsewhere e.g. in ApplyStyle Dismiss(); if (m_itemHere >= 0) - wxRichTextStyleListBox::DoSelection(m_itemHere); + wxRichTextStyleListBox::ApplyStyle(m_itemHere); } /*! @@ -556,31 +1163,19 @@ bool wxRichTextStyleComboCtrl::Create(wxWindow* parent, wxWindowID id, const wxP void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event) { - if (GetRichTextCtrl() && !IsPopupShown()) - { - int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition()); + event.Skip(); - wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos); - wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos); + if ( !m_stylePopup ) + return; - wxString styleName; + wxRichTextCtrl * const richtext = GetRichTextCtrl(); + if ( !richtext ) + return; - // Take into account current default style just chosen by user - if (GetRichTextCtrl()->IsDefaultStyleShowing()) - { - if (!GetRichTextCtrl()->GetDefaultStyleEx().GetCharacterStyleName().IsEmpty()) - styleName = GetRichTextCtrl()->GetDefaultStyleEx().GetCharacterStyleName(); - else if (!GetRichTextCtrl()->GetDefaultStyleEx().GetParagraphStyleName().IsEmpty()) - styleName = GetRichTextCtrl()->GetDefaultStyleEx().GetParagraphStyleName(); - } - else if (obj && !obj->GetAttributes().GetCharacterStyleName().IsEmpty()) - { - styleName = obj->GetAttributes().GetCharacterStyleName(); - } - else if (para && !para->GetAttributes().GetParagraphStyleName().IsEmpty()) - { - styleName = para->GetAttributes().GetParagraphStyleName(); - } + if ( !IsPopupShown() && IsShownOnScreen() && wxWindow::FindFocus() != this ) + { + wxString styleName = + wxRichTextStyleListBox::GetStyleToShowInIdleTime(richtext, m_stylePopup->GetStyleType()); wxString currentValue = GetValue(); if (!styleName.IsEmpty()) @@ -594,7 +1189,6 @@ void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event) else if (!currentValue.IsEmpty()) SetValue(wxEmptyString); } - event.Skip(); } #endif