X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b01ca8b6a9b2828aa7fe6399d8920951c24661ce..ce22ac4592fccaedd8324e7a8f08b510748827e4:/src/richtext/richtextstyles.cpp diff --git a/src/richtext/richtextstyles.cpp b/src/richtext/richtextstyles.cpp index 1a4d342fca..183daea53a 100644 --- a/src/richtext/richtextstyles.cpp +++ b/src/richtext/richtextstyles.cpp @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: richtextstyles.cpp +// Name: src/richtext/richtextstyles.cpp // Purpose: Style management for wxRichTextCtrl // Author: Julian Smart -// Modified by: +// Modified by: // Created: 2005-09-30 -// RCS-ID: +// RCS-ID: $Id$ // Copyright: (c) Julian Smart // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -13,7 +13,7 @@ #include "wx/wxprec.h" #ifdef __BORLANDC__ - #pragma hdrstop + #pragma hdrstop #endif #if wxUSE_RICHTEXT @@ -21,13 +21,13 @@ #include "wx/richtext/richtextstyles.h" #ifndef WX_PRECOMP - #include "wx/wx.h" + #include "wx/dcclient.h" + #include "wx/module.h" #endif #include "wx/filename.h" #include "wx/clipbrd.h" #include "wx/wfstream.h" -#include "wx/module.h" #include "wx/richtext/richtextctrl.h" @@ -79,7 +79,7 @@ wxRichTextStyleDefinition* wxRichTextStyleSheet::FindStyle(const wxList& list, c if (def->GetName().Lower() == name.Lower()) return def; } - return NULL; + return NULL; } /// Delete all styles @@ -100,13 +100,20 @@ IMPLEMENT_CLASS(wxRichTextStyleListBox, wxHtmlListBox) BEGIN_EVENT_TABLE(wxRichTextStyleListBox, wxHtmlListBox) EVT_LISTBOX(wxID_ANY, wxRichTextStyleListBox::OnSelect) EVT_LEFT_DOWN(wxRichTextStyleListBox::OnLeftDown) + EVT_IDLE(wxRichTextStyleListBox::OnIdle) END_EVENT_TABLE() wxRichTextStyleListBox::wxRichTextStyleListBox(wxWindow* parent, wxWindowID id, const wxPoint& pos, - const wxSize& size, long style): wxHtmlListBox(parent, id, pos, size, style) + const wxSize& size, long style) +{ + Init(); + Create(parent, id, pos, size, style); +} + +bool wxRichTextStyleListBox::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, + const wxSize& size, long style) { - m_styleSheet = NULL; - m_richTextCtrl = NULL; + return wxHtmlListBox::Create(parent, id, pos, size, style); } wxRichTextStyleListBox::~wxRichTextStyleListBox() @@ -164,6 +171,37 @@ void wxRichTextStyleListBox::UpdateStyles() } } +// 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; +} + +/// Set selection for string +int wxRichTextStyleListBox::SetStyleSelection(const wxString& name) +{ + int i = GetIndexForStyle(name); + if (i > -1) + SetSelection(i); + return i; +} + // Convert a colour to a 6-digit hex string static wxString ColourToHexString(const wxColour& col) { @@ -193,7 +231,7 @@ wxString wxRichTextStyleListBox::CreateHTML(wxRichTextStyleDefinition* def) cons int size = 5; // Standard size is 12, say - size += 12 - def->GetStyle().GetFontSize(); + size += 12 - def->GetStyle().GetFontSize(); str += wxT("GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition()); + wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition()); + + wxString styleName; + + // 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(); + } + + int sel = GetSelection(); + if (!styleName.IsEmpty()) + { + // Don't do the selection if it's already set + if (sel == GetIndexForStyle(styleName)) + return; + + SetStyleSelection(styleName); + } + else if (sel != -1) + SetSelection(-1); + } + event.Skip(); +} + +/// Do selection +void wxRichTextStyleListBox::DoSelection(int item) +{ if ( item != wxNOT_FOUND ) { wxRichTextStyleDefinition* def = GetStyle(item); if (def && GetRichTextCtrl()) { - wxRichTextRange range(m_richTextCtrl->GetInsertionPoint(), m_richTextCtrl->GetInsertionPoint()); - - // Flags are defined within each definition, so only certain - // attributes are applied. - wxRichTextAttr attr(def->GetStyle()); - - if (m_richTextCtrl->HasSelection()) - m_richTextCtrl->SetStyle(m_richTextCtrl->GetSelectionRange(), attr); - else - m_richTextCtrl->SetDefaultStyle(attr); - - m_richTextCtrl->SetFocus(); + GetRichTextCtrl()->ApplyStyle(def); + GetRichTextCtrl()->SetFocus(); } } } @@ -303,9 +379,152 @@ wxColour wxRichTextStyleListBox::GetSelectedTextBgColour(const wxColour& colBg) } #endif +#if wxUSE_COMBOCTRL + +/*! + * Style drop-down for a wxComboCtrl + */ + + +BEGIN_EVENT_TABLE(wxRichTextStyleComboPopup, wxRichTextStyleListBox) + EVT_MOTION(wxRichTextStyleComboPopup::OnMouseMove) + EVT_LEFT_DOWN(wxRichTextStyleComboPopup::OnMouseClick) +END_EVENT_TABLE() + +void wxRichTextStyleComboPopup::SetStringValue( const wxString& s ) +{ + m_value = SetStyleSelection(s); +} + +wxString wxRichTextStyleComboPopup::GetStringValue() const +{ + int sel = m_value; + if (sel > -1) + { + wxRichTextStyleDefinition* def = GetStyle(sel); + if (def) + return def->GetName(); + } + return wxEmptyString; +} + +// +// Popup event handlers +// + +// Mouse hot-tracking +void wxRichTextStyleComboPopup::OnMouseMove(wxMouseEvent& event) +{ + // Move selection to cursor if it is inside the popup + + int itemHere = wxRichTextStyleListBox::HitTest(event.GetPosition()); + if ( itemHere >= 0 ) + { + wxRichTextStyleListBox::SetSelection(itemHere); + m_itemHere = itemHere; + } + event.Skip(); +} + +// On mouse left, set the value and close the popup +void wxRichTextStyleComboPopup::OnMouseClick(wxMouseEvent& WXUNUSED(event)) +{ + if (m_itemHere >= 0) + m_value = m_itemHere; + + // Ordering is important, so we don't dismiss this popup accidentally + // by setting the focus elsewhere e.g. in DoSelection + Dismiss(); + + if (m_itemHere >= 0) + wxRichTextStyleListBox::DoSelection(m_itemHere); +} + +/*! + * wxRichTextStyleComboCtrl + * A combo for applying styles. + */ + +IMPLEMENT_CLASS(wxRichTextStyleComboCtrl, wxComboCtrl) + +BEGIN_EVENT_TABLE(wxRichTextStyleComboCtrl, wxComboCtrl) + EVT_IDLE(wxRichTextStyleComboCtrl::OnIdle) +END_EVENT_TABLE() + +bool wxRichTextStyleComboCtrl::Create(wxWindow* parent, wxWindowID id, const wxPoint& pos, + const wxSize& size, long style) +{ + if (!wxComboCtrl::Create(parent, id, wxEmptyString, pos, size, style)) + return false; + + SetPopupMaxHeight(400); + + m_stylePopup = new wxRichTextStyleComboPopup; + + SetPopupControl(m_stylePopup); + + return true; +} + +/// Auto-select from style under caret in idle time + +// TODO: must be able to show italic, bold, combinations +// in style box. Do we have a concept of automatic, temporary +// styles that are added whenever we wish to show a style +// that doesn't exist already? E.g. "Bold, Italic, Underline". +// Word seems to generate these things on the fly. +// If there's a named style already, it uses e.g. Heading1 + Bold, Italic +// If you unembolden text in a style that has bold, it uses the +// term "Not bold". +// TODO: order styles alphabetically. This means indexes can change, +// so need a different way to specify selections, i.e. by name. + +void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event) +{ + if (GetRichTextCtrl() && !IsPopupShown()) + { + wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition()); + wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition()); + + wxString styleName; + + // 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(); + } + + wxString currentValue = GetValue(); + if (!styleName.IsEmpty()) + { + // Don't do the selection if it's already set + if (currentValue == styleName) + return; + + SetValue(styleName); + } + else if (!currentValue.IsEmpty()) + SetValue(wxEmptyString); + } + event.Skip(); +} + +#endif + // wxUSE_COMBOCTRL + #endif // wxUSE_HTML #endif // wxUSE_RICHTEXT -