From 30bf76303915c3d70e0ff9a180a48a2f80b8cd11 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Thu, 10 Apr 2008 14:05:44 +0000 Subject: [PATCH] Added wxRichTextCtrl superscript and subscript support (Knut Petter Lehre). git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@53106 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/richtext/richtextbuffer.h | 6 + include/wx/richtext/richtextfontpage.h | 11 ++ src/richtext/richtextbuffer.cpp | 65 ++++++++-- src/richtext/richtextdialogs.pjd | 164 ++++++++++++++++++++++--- src/richtext/richtextfontpage.cpp | 89 ++++++++++++++ src/richtext/richtextformatdlg.cpp | 11 ++ 6 files changed, 322 insertions(+), 24 deletions(-) diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index 871025796f..ecf8444c38 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -202,6 +202,12 @@ class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextBuffer; // flag to InsertFragment and DeleteRange to indicate the appropriate mode. #define wxTEXT_ATTR_KEEP_FIRST_PARA_STYLE 0x10000000 +/*! + * Default superscript/subscript font multiplication factor + */ + +#define wxSCRIPT_MUL_FACTOR 1.5 + /*! * wxRichTextFontTable * Manages quick access to a pool of fonts for rendering rich text diff --git a/include/wx/richtext/richtextfontpage.h b/include/wx/richtext/richtextfontpage.h index ce2cab02c4..5f7016f249 100644 --- a/include/wx/richtext/richtextfontpage.h +++ b/include/wx/richtext/richtextfontpage.h @@ -35,6 +35,7 @@ class wxRichTextFontPreviewCtrl; ////@begin control identifiers #define SYMBOL_WXRICHTEXTFONTPAGE_STYLE wxTAB_TRAVERSAL +#define SYMBOL_WXRICHTEXTFONTPAGE_TITLE _("wxRichTextFontPage") #define SYMBOL_WXRICHTEXTFONTPAGE_IDNAME ID_RICHTEXTFONTPAGE #define SYMBOL_WXRICHTEXTFONTPAGE_SIZE wxSize(200, 100) #define SYMBOL_WXRICHTEXTFONTPAGE_POSITION wxDefaultPosition @@ -102,6 +103,12 @@ public: /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTFONTPAGE_CAPSCTRL void OnCapsctrlClick( wxCommandEvent& event ); + /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTFONTPAGE_SUPERSCRIPT + void OnRichtextfontpageSuperscriptClick( wxCommandEvent& event ); + + /// wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTFONTPAGE_SUBSCRIPT + void OnRichtextfontpageSubscriptClick( wxCommandEvent& event ); + ////@end wxRichTextFontPage event handler declarations ////@begin wxRichTextFontPage member function declarations @@ -127,6 +134,8 @@ public: wxRichTextColourSwatchCtrl* m_colourCtrl; wxCheckBox* m_strikethroughCtrl; wxCheckBox* m_capitalsCtrl; + wxCheckBox* m_superscriptCtrl; + wxCheckBox* m_subscriptCtrl; wxRichTextFontPreviewCtrl* m_previewCtrl; /// Control identifiers enum { @@ -141,6 +150,8 @@ public: ID_RICHTEXTFONTPAGE_COLOURCTRL = 10009, ID_RICHTEXTFONTPAGE_STRIKETHROUGHCTRL = 10010, ID_RICHTEXTFONTPAGE_CAPSCTRL = 10011, + ID_RICHTEXTFONTPAGE_SUPERSCRIPT = 10012, + ID_RICHTEXTFONTPAGE_SUBSCRIPT = 10013, ID_RICHTEXTFONTPAGE_PREVIEWCTRL = 10003 }; ////@end wxRichTextFontPage member variables diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index ac9cb9522a..7d61b5e8a6 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -4317,16 +4317,44 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR long len = range.GetLength(); wxString stringChunk = str.Mid(range.GetStart() - offset, (size_t) len); - int charHeight = dc.GetCharHeight(); - - int x = rect.x; - int y = rect.y + (rect.height - charHeight - (descent - m_descent)); - // Test for the optimized situations where all is selected, or none // is selected. - wxFont font(GetBuffer()->GetFontTable().FindFont(textAttr)); - wxCheckSetFont(dc, font); + wxFont textFont(GetBuffer()->GetFontTable().FindFont(textAttr)); + wxCheckSetFont(dc, textFont); + int charHeight = dc.GetCharHeight(); + + int x, y; + if ( textFont.Ok() ) + { + if ( textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) ) + { + double size = static_cast(textFont.GetPointSize()) / wxSCRIPT_MUL_FACTOR; + textFont.SetPointSize( static_cast(size) ); + x = rect.x; + y = rect.y; + wxCheckSetFont(dc, textFont); + } + else if ( textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT) ) + { + double size = static_cast(textFont.GetPointSize()) / wxSCRIPT_MUL_FACTOR; + textFont.SetPointSize( static_cast(size) ); + x = rect.x; + int sub_height = static_cast( static_cast(charHeight) / wxSCRIPT_MUL_FACTOR); + y = rect.y + (rect.height - sub_height + (descent - m_descent)); + wxCheckSetFont(dc, textFont); + } + else + { + x = rect.x; + y = rect.y + (rect.height - charHeight - (descent - m_descent)); + } + } + else + { + x = rect.x; + y = rect.y + (rect.height - charHeight - (descent - m_descent)); + } // (a) All selected. if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd()) @@ -4581,8 +4609,24 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz // of line breaks - and we don't need it, since we'll calculate size within // formatted text by doing it in chunks according to the line ranges + bool bScript(false); wxFont font(GetBuffer()->GetFontTable().FindFont(textAttr)); - wxCheckSetFont(dc, font); + if (font.Ok()) + { + if ( textAttr.HasTextEffects() && ( (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) + || (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT) ) ) + { + wxFont textFont = font; + double size = static_cast(textFont.GetPointSize()) / wxSCRIPT_MUL_FACTOR; + textFont.SetPointSize( static_cast(size) ); + wxCheckSetFont(dc, textFont); + bScript = true; + } + else + { + wxCheckSetFont(dc, font); + } + } int startPos = range.GetStart() - GetRange().GetStart(); long len = range.GetLength(); @@ -4650,8 +4694,13 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz } } } + dc.GetTextExtent(stringChunk, & w, & h, & descent); width += w; + + if ( bScript ) + dc.SetFont(font); + size = wxSize(width, dc.GetCharHeight()); return true; diff --git a/src/richtext/richtextdialogs.pjd b/src/richtext/richtextdialogs.pjd index b1d6241d26..064da14839 100644 --- a/src/richtext/richtextdialogs.pjd +++ b/src/richtext/richtextdialogs.pjd @@ -136,6 +136,7 @@ 0 "" 1 + -8519680 "" "Debug" "ANSI" @@ -177,6 +178,8 @@ "%AUTO%" "%AUTO%" "%AUTO%" + 0 + 1 @@ -248,7 +251,6 @@ 0 0 0 - 0 0 0 0 @@ -291,14 +293,6 @@ "wbBoxSizerProxy" "Vertical" "" - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 1 - 1 0 0 0 @@ -1688,6 +1682,136 @@ "" "" + + "wxCheckBox: ID_RICHTEXTFONTPAGE_SUPERSCRIPT" + "dialog-control-document" + "" + "checkbox" + 0 + 1 + 0 + 0 + "10/4/2008" + "wbCheckBoxProxy" + "wxEVT_COMMAND_CHECKBOX_CLICKED|OnRichtextfontpageSuperscriptClick|NONE||wxRichTextFontPage" + "ID_RICHTEXTFONTPAGE_SUPERSCRIPT" + 10012 + "" + "wxCheckBox" + "wxCheckBox" + 1 + 0 + "" + "" + "m_superscriptCtrl" + "Supe&rscript" + 0 + "Check to show the text in superscript." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + + + "wxCheckBox: ID_RICHTEXTFONTPAGE_SUBSCRIPT" + "dialog-control-document" + "" + "checkbox" + 0 + 1 + 0 + 0 + "10/4/2008" + "wbCheckBoxProxy" + "wxEVT_COMMAND_CHECKBOX_CLICKED|OnRichtextfontpageSubscriptClick|NONE||wxRichTextFontPage" + "ID_RICHTEXTFONTPAGE_SUBSCRIPT" + 10013 + "" + "wxCheckBox" + "wxCheckBox" + 1 + 0 + "" + "" + "m_subscriptCtrl" + "Subscrip&t" + 0 + "Check to show the text in subscript." + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + 0 + 1 + "<Any platform>" + 0 + 0 + 1 + 0 + 0 + 0 + 0 + "" + -1 + -1 + -1 + -1 + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 + 0 + 0 + 0 + "" + "" + "Spacer" @@ -1836,7 +1960,6 @@ 0 0 1 - 0 0 0 0 @@ -1867,6 +1990,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" @@ -4347,7 +4471,6 @@ 0 0 1 - 0 0 0 0 @@ -4378,6 +4501,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" @@ -5084,7 +5208,6 @@ 0 0 1 - 0 0 0 0 @@ -5115,6 +5238,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" @@ -6757,7 +6881,6 @@ 0 0 1 - 0 0 0 0 @@ -6788,6 +6911,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" @@ -7393,7 +7517,6 @@ 1 0 1 - 0 0 0 0 @@ -7424,6 +7547,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" @@ -7437,6 +7561,14 @@ "wbBoxSizerProxy" "Vertical" "" + "Centre" + "Centre" + 0 + 5 + 1 + 1 + 1 + 1 0 0 0 @@ -8589,7 +8721,6 @@ 1 0 1 - 0 1 0 0 @@ -8620,6 +8751,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" @@ -10016,7 +10148,6 @@ 0 0 1 - 0 0 0 0 @@ -10047,6 +10178,7 @@ 300 0 "" + 0 "wxBoxSizer V" "dialog-control-document" diff --git a/src/richtext/richtextfontpage.cpp b/src/richtext/richtextfontpage.cpp index 9766ff38f8..eccebbcced 100644 --- a/src/richtext/richtextfontpage.cpp +++ b/src/richtext/richtextfontpage.cpp @@ -42,6 +42,10 @@ BEGIN_EVENT_TABLE( wxRichTextFontPage, wxPanel ) EVT_CHECKBOX( ID_RICHTEXTFONTPAGE_CAPSCTRL, wxRichTextFontPage::OnCapsctrlClick ) + EVT_CHECKBOX( ID_RICHTEXTFONTPAGE_SUPERSCRIPT, wxRichTextFontPage::OnRichtextfontpageSuperscriptClick ) + + EVT_CHECKBOX( ID_RICHTEXTFONTPAGE_SUBSCRIPT, wxRichTextFontPage::OnRichtextfontpageSubscriptClick ) + ////@end wxRichTextFontPage event table entries END_EVENT_TABLE() @@ -81,6 +85,8 @@ void wxRichTextFontPage::Init() m_colourCtrl = NULL; m_strikethroughCtrl = NULL; m_capitalsCtrl = NULL; + m_superscriptCtrl = NULL; + m_subscriptCtrl = NULL; m_previewCtrl = NULL; ////@end wxRichTextFontPage member initialisation } @@ -230,6 +236,20 @@ void wxRichTextFontPage::CreateControls() m_capitalsCtrl->SetToolTip(_("Check to show the text in capitals.")); itemBoxSizer26->Add(m_capitalsCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + m_superscriptCtrl = new wxCheckBox( itemPanel1, ID_RICHTEXTFONTPAGE_SUPERSCRIPT, _("Supe&rscript"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE ); + m_superscriptCtrl->SetValue(false); + m_superscriptCtrl->SetHelpText(_("Check to show the text in superscript.")); + if (wxRichTextFontPage::ShowToolTips()) + m_superscriptCtrl->SetToolTip(_("Check to show the text in superscript.")); + itemBoxSizer26->Add(m_superscriptCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + + m_subscriptCtrl = new wxCheckBox( itemPanel1, ID_RICHTEXTFONTPAGE_SUBSCRIPT, _("Subscrip&t"), wxDefaultPosition, wxDefaultSize, wxCHK_3STATE ); + m_subscriptCtrl->SetValue(false); + m_subscriptCtrl->SetHelpText(_("Check to show the text in subscript.")); + if (wxRichTextFontPage::ShowToolTips()) + m_subscriptCtrl->SetToolTip(_("Check to show the text in subscript.")); + itemBoxSizer26->Add(m_subscriptCtrl, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5); + itemBoxSizer3->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL, 5); m_previewCtrl = new wxRichTextFontPreviewCtrl( itemPanel1, ID_RICHTEXTFONTPAGE_PREVIEWCTRL, wxDefaultPosition, wxSize(100, 60), 0 ); @@ -358,6 +378,24 @@ bool wxRichTextFontPage::TransferDataFromWindow() attr->SetTextEffects(attr->GetTextEffects() & ~wxTEXT_ATTR_EFFECT_CAPITALS); } + if (m_superscriptCtrl->Get3StateValue() == wxCHK_CHECKED) + { + attr->SetTextEffectFlags(attr->GetTextEffectFlags() | wxTEXT_ATTR_EFFECT_SUPERSCRIPT); + attr->SetTextEffects(attr->GetTextEffects() | wxTEXT_ATTR_EFFECT_SUPERSCRIPT); + attr->SetTextEffects(attr->GetTextEffects() & ~wxTEXT_ATTR_EFFECT_SUBSCRIPT); + } + else if (m_subscriptCtrl->Get3StateValue() == wxCHK_CHECKED) + { + attr->SetTextEffectFlags(attr->GetTextEffectFlags() | wxTEXT_ATTR_EFFECT_SUBSCRIPT); + attr->SetTextEffects(attr->GetTextEffects() | wxTEXT_ATTR_EFFECT_SUBSCRIPT); + attr->SetTextEffects(attr->GetTextEffects() & ~wxTEXT_ATTR_EFFECT_SUPERSCRIPT); + } + else + { + attr->SetTextEffectFlags(attr->GetTextEffectFlags() | wxTEXT_ATTR_EFFECT_SUBSCRIPT | wxTEXT_ATTR_EFFECT_SUPERSCRIPT ); + attr->SetTextEffects(attr->GetTextEffects() & ~( wxTEXT_ATTR_EFFECT_SUPERSCRIPT | wxTEXT_ATTR_EFFECT_SUBSCRIPT)); + } + return true; } @@ -455,11 +493,37 @@ bool wxRichTextFontPage::TransferDataToWindow() } else m_capitalsCtrl->Set3StateValue(wxCHK_UNDETERMINED); + + if ( attr->GetTextEffectFlags() & (wxTEXT_ATTR_EFFECT_SUPERSCRIPT | wxTEXT_ATTR_EFFECT_SUBSCRIPT) ) + { + if (attr->GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) + { + m_superscriptCtrl->Set3StateValue(wxCHK_CHECKED); + m_subscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + } + else if (attr->GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT) + { + m_superscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + m_subscriptCtrl->Set3StateValue(wxCHK_CHECKED); + } + else + { + m_superscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + m_subscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + } + } + else + { + m_superscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + m_subscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + } } else { m_strikethroughCtrl->Set3StateValue(wxCHK_UNDETERMINED); m_capitalsCtrl->Set3StateValue(wxCHK_UNDETERMINED); + m_superscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); + m_subscriptCtrl->Set3StateValue(wxCHK_UNCHECKED); } UpdatePreview(); @@ -541,6 +605,11 @@ void wxRichTextFontPage::UpdatePreview() textEffects |= wxTEXT_ATTR_EFFECT_CAPITALS; } + if ( m_superscriptCtrl->Get3StateValue() == wxCHK_CHECKED ) + textEffects |= wxTEXT_ATTR_EFFECT_SUPERSCRIPT; + else if ( m_subscriptCtrl->Get3StateValue() == wxCHK_CHECKED ) + textEffects |= wxTEXT_ATTR_EFFECT_SUBSCRIPT; + m_previewCtrl->SetFont(font); m_previewCtrl->SetTextEffects(textEffects); m_previewCtrl->Refresh(); @@ -715,4 +784,24 @@ void wxRichTextFontPage::OnCapsctrlClick( wxCommandEvent& WXUNUSED(event) ) UpdatePreview(); } +/*! + * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTFONTPAGE_SUPERSCRIPT + */ +void wxRichTextFontPage::OnRichtextfontpageSuperscriptClick( wxCommandEvent& WXUNUSED(event) ) +{ + if ( m_superscriptCtrl->Get3StateValue() == wxCHK_CHECKED && m_subscriptCtrl->Get3StateValue() == wxCHK_CHECKED ) + m_subscriptCtrl->Set3StateValue( wxCHK_UNCHECKED ); + UpdatePreview(); +} + +/*! + * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_RICHTEXTFONTPAGE_SUBSCRIPT + */ + +void wxRichTextFontPage::OnRichtextfontpageSubscriptClick( wxCommandEvent& WXUNUSED(event) ) +{ + if ( m_superscriptCtrl->Get3StateValue() == wxCHK_CHECKED && m_subscriptCtrl->Get3StateValue() == wxCHK_CHECKED ) + m_superscriptCtrl->Set3StateValue( wxCHK_UNCHECKED ); + UpdatePreview(); +} diff --git a/src/richtext/richtextformatdlg.cpp b/src/richtext/richtextformatdlg.cpp index 3a7d7ee6c5..d45b0cae23 100644 --- a/src/richtext/richtextformatdlg.cpp +++ b/src/richtext/richtextformatdlg.cpp @@ -411,6 +411,12 @@ void wxRichTextFontPreviewCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) wxSize size = GetSize(); wxFont font = GetFont(); + if ((GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) || (GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT)) + { + double size = static_cast(font.GetPointSize()) / wxSCRIPT_MUL_FACTOR; + font.SetPointSize( static_cast(size) ); + } + if ( font.Ok() ) { dc.SetFont(font); @@ -425,6 +431,11 @@ void wxRichTextFontPreviewCtrl::OnPaint(wxPaintEvent& WXUNUSED(event)) int cx = wxMax(2, (size.x/2) - (w/2)); int cy = wxMax(2, (size.y/2) - (h/2)); + if ( GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT ) + cy -= h/2; + if ( GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT ) + cy += h/2; + dc.SetTextForeground(GetForegroundColour()); dc.SetClippingRegion(2, 2, size.x-4, size.y-4); dc.DrawText(text, cx, cy);