From f672c969519f7565cd80f85adeca5a6efdace8f5 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 27 Feb 2011 12:48:46 +0000 Subject: [PATCH] Add markup support to wxOSX/Cocoa wxStaticText and wxButton. Add wxMarkupToAttrString helper that converts wx markup to OS X attribute strings and use it in wxStaticText and wxButton. This required adding new SetLabelMarkup() method to wxWidgetCocoaImpl, it seems to make sense to have it there as it could be implemented by more controls in the future. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67069 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/osx/button.h | 5 + include/wx/osx/cocoa/private/markuptoattr.h | 120 ++++++++++++++++++++ include/wx/osx/core/private.h | 3 + include/wx/osx/stattext.h | 4 + src/osx/button_osx.cpp | 14 +++ src/osx/cocoa/button.mm | 22 ++++ src/osx/cocoa/stattext.mm | 36 ++++-- src/osx/stattext_osx.cpp | 14 +++ 8 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 include/wx/osx/cocoa/private/markuptoattr.h diff --git a/include/wx/osx/button.h b/include/wx/osx/button.h index 987c8e9792..1d0353ef87 100644 --- a/include/wx/osx/button.h +++ b/include/wx/osx/button.h @@ -68,6 +68,11 @@ protected: InvalidateBestSize(); } +#if wxUSE_MARKUP && wxOSX_USE_COCOA + virtual bool DoSetLabelMarkup(const wxString& markup); +#endif // wxUSE_MARKUP && wxOSX_USE_COCOA + + // the margins around the bitmap int m_marginX; int m_marginY; diff --git a/include/wx/osx/cocoa/private/markuptoattr.h b/include/wx/osx/cocoa/private/markuptoattr.h new file mode 100644 index 0000000000..63269e3999 --- /dev/null +++ b/include/wx/osx/cocoa/private/markuptoattr.h @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/osx/cocoa/private/markuptoattr.h +// Purpose: Class to convert markup to Cocoa attributed strings. +// Author: Vadim Zeitlin +// Created: 2011-02-22 +// RCS-ID: $Id: wxhead.h,v 1.12 2010-04-22 12:44:51 zeitlin Exp $ +// Copyright: (c) 2011 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_OSX_COCOA_PRIVATE_MARKUPTOATTR_H_ +#define _WX_OSX_COCOA_PRIVATE_MARKUPTOATTR_H_ + +#include "wx/private/markupparserattr.h" + +// ---------------------------------------------------------------------------- +// wxMarkupToAttrString: create NSAttributedString from markup. +// ---------------------------------------------------------------------------- + +class wxMarkupToAttrString : public wxMarkupParserAttrOutput +{ +public: + // We don't care about the original colours because we never use them but + // we do need the correct initial font as we apply modifiers (e.g. create a + // font larger than it) to it and so it must be valid. + wxMarkupToAttrString(wxWindow *win, const wxString& markup) + : wxMarkupParserAttrOutput(win->GetFont(), wxColour(), wxColour()) + { + const wxCFStringRef + label(wxControl::RemoveMnemonics(wxMarkupParser::Strip(markup))); + m_attrString = [[NSMutableAttributedString alloc] + initWithString: label.AsNSString()]; + + m_pos = 0; + + [m_attrString beginEditing]; + + // First thing we do is change the default string font: as mentioned in + // Apple documentation, attributed strings use "Helvetica 12" font by + // default which is different from the system "Lucida Grande" font. So + // we need to explicitly change the font for the entire string. + [m_attrString addAttribute:NSFontAttributeName + value:win->GetFont().OSXGetNSFont() + range:NSMakeRange(0, [m_attrString length])]; + + // Now translate the markup tags to corresponding attributes. + wxMarkupParser parser(*this); + parser.Parse(markup); + + [m_attrString endEditing]; + } + + ~wxMarkupToAttrString() + { + [m_attrString release]; + } + + // Accessor for the users of this class. + // + // We keep ownership of the returned string. + NSMutableAttributedString *GetNSAttributedString() const + { + return m_attrString; + } + + + // Implement base class pure virtual methods to process markup tags. + virtual void OnText(const wxString& text) + { + m_pos += wxControl::RemoveMnemonics(text).length(); + } + + virtual void OnAttrStart(const Attr& WXUNUSED(attr)) + { + // Just remember the starting position of the range, we can't really + // set the attribute until we find the end of it. + m_rangeStarts.push(m_pos); + } + + virtual void OnAttrEnd(const Attr& attr) + { + unsigned start = m_rangeStarts.top(); + m_rangeStarts.pop(); + + const NSRange range = NSMakeRange(start, m_pos - start); + + [m_attrString addAttribute:NSFontAttributeName + value:attr.font.OSXGetNSFont() + range:range]; + + if ( attr.foreground.IsOk() ) + { + [m_attrString addAttribute:NSForegroundColorAttributeName + value:attr.foreground.OSXGetNSColor() + range:range]; + } + + if ( attr.background.IsOk() ) + { + [m_attrString addAttribute:NSBackgroundColorAttributeName + value:attr.background.OSXGetNSColor() + range:range]; + } + } + +private: + // The attributed string we're building. + NSMutableAttributedString *m_attrString; + + // The current position in the output string. + unsigned m_pos; + + // The positions of starting ranges. + wxStack m_rangeStarts; + + + wxDECLARE_NO_COPY_CLASS(wxMarkupToAttrString); +}; + +#endif // _WX_OSX_COCOA_PRIVATE_MARKUPTOATTR_H_ diff --git a/include/wx/osx/core/private.h b/include/wx/osx/core/private.h index 285561a45d..a42f8287ab 100644 --- a/include/wx/osx/core/private.h +++ b/include/wx/osx/core/private.h @@ -270,6 +270,9 @@ public : virtual void SetDefaultButton( bool isDefault ) = 0; virtual void PerformClick() = 0; virtual void SetLabel( const wxString& title, wxFontEncoding encoding ) = 0; +#if wxOSX_USE_COCOA + virtual void SetLabelMarkup( const wxString& WXUNUSED(markup) ) { } +#endif virtual void SetCursor( const wxCursor & cursor ) = 0; virtual void CaptureMouse() = 0; diff --git a/include/wx/osx/stattext.h b/include/wx/osx/stattext.h index 3f76b748a4..fe366452a4 100644 --- a/include/wx/osx/stattext.h +++ b/include/wx/osx/stattext.h @@ -47,6 +47,10 @@ protected : virtual wxSize DoGetBestSize() const ; +#if wxUSE_MARKUP && wxOSX_USE_COCOA + virtual bool DoSetLabelMarkup(const wxString& markup); +#endif // wxUSE_MARKUP && wxOSX_USE_COCOA + DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticText) }; diff --git a/src/osx/button_osx.cpp b/src/osx/button_osx.cpp index 045ea79675..358fffffd3 100644 --- a/src/osx/button_osx.cpp +++ b/src/osx/button_osx.cpp @@ -142,6 +142,20 @@ void wxButton::DoSetBitmapPosition(wxDirection dir) InvalidateBestSize(); } +#if wxUSE_MARKUP && wxOSX_USE_COCOA + +bool wxButton::DoSetLabelMarkup(const wxString& markup) +{ + if ( !wxButtonBase::DoSetLabelMarkup(markup) ) + return false; + + m_peer->SetLabelMarkup(markup); + + return true; +} + +#endif // wxUSE_MARKUP && wxOSX_USE_COCOA + wxWindow *wxButton::SetDefault() { wxWindow *btnOldDefault = wxButtonBase::SetDefault(); diff --git a/src/osx/cocoa/button.mm b/src/osx/cocoa/button.mm index babc50e429..8e25f09c48 100644 --- a/src/osx/cocoa/button.mm +++ b/src/osx/cocoa/button.mm @@ -18,6 +18,11 @@ #include "wx/osx/private.h" +#if wxUSE_MARKUP + #include "wx/osx/cocoa/private/markuptoattr.h" +#endif // wxUSE_MARKUP + + wxSize wxButton::DoGetBestSize() const { // We only use help button bezel if we don't have any (non standard) label @@ -125,6 +130,23 @@ public: wxWidgetCocoaImpl::SetBitmap(bitmap); } + virtual void SetLabelMarkup(const wxString& markup) + { + wxMarkupToAttrString toAttr(GetWXPeer(), markup); + NSMutableAttributedString *attrString = toAttr.GetNSAttributedString(); + + // Button text is always centered. + NSMutableParagraphStyle * + paragraphStyle = [[NSMutableParagraphStyle alloc] init]; + [paragraphStyle setAlignment: NSCenterTextAlignment]; + [attrString addAttribute:NSParagraphStyleAttributeName + value:paragraphStyle + range:NSMakeRange(0, [attrString length])]; + [paragraphStyle release]; + + [GetNSButton() setAttributedTitle:attrString]; + } + void SetPressedBitmap( const wxBitmap& bitmap ) { NSButton* button = GetNSButton(); diff --git a/src/osx/cocoa/stattext.mm b/src/osx/cocoa/stattext.mm index 57ba5c4069..c096753e0b 100644 --- a/src/osx/cocoa/stattext.mm +++ b/src/osx/cocoa/stattext.mm @@ -25,6 +25,10 @@ #include "wx/osx/private.h" +#if wxUSE_MARKUP + #include "wx/osx/cocoa/private/markuptoattr.h" +#endif // wxUSE_MARKUP + #include @interface wxNSStaticTextView : NSTextField @@ -75,26 +79,42 @@ public: virtual void SetLabel(const wxString& title, wxFontEncoding encoding) { - wxNSStaticTextView* v = (wxNSStaticTextView*)GetWXWidget(); - wxWindow* wxpeer = GetWXPeer(); - NSCell* cell = [v cell]; wxCFStringRef text( title , encoding ); + NSMutableAttributedString * + attrstring = [[NSMutableAttributedString alloc] initWithString:text.AsNSString()]; + DoSetAttrString(attrstring); + [attrstring release]; + } + +#if wxUSE_MARKUP + virtual void SetLabelMarkup( const wxString& markup) + { + wxMarkupToAttrString toAttr(GetWXPeer(), markup); + + DoSetAttrString(toAttr.GetNSAttributedString()); + } +#endif // wxUSE_MARKUP + +private: + void DoSetAttrString(NSMutableAttributedString *attrstring) + { NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; [paragraphStyle setLineBreakMode:m_lineBreak]; - int style = wxpeer->GetWindowStyleFlag(); + int style = GetWXPeer()->GetWindowStyleFlag(); if (style & wxALIGN_CENTER) [paragraphStyle setAlignment: NSCenterTextAlignment]; else if (style & wxALIGN_RIGHT) [paragraphStyle setAlignment: NSRightTextAlignment]; - NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:paragraphStyle, NSParagraphStyleAttributeName, nil]; - NSAttributedString *attrstring = [[NSAttributedString alloc] initWithString:text.AsNSString() attributes:dict]; + [attrstring addAttribute:NSParagraphStyleAttributeName + value:paragraphStyle + range:NSMakeRange(0, [attrstring length])]; + NSCell* cell = [(wxNSStaticTextView *)GetWXWidget() cell]; [cell setAttributedStringValue:attrstring]; - [attrstring release]; [paragraphStyle release]; } -private : + NSLineBreakMode m_lineBreak; }; diff --git a/src/osx/stattext_osx.cpp b/src/osx/stattext_osx.cpp index bf1e915c0d..0ff943ff6d 100644 --- a/src/osx/stattext_osx.cpp +++ b/src/osx/stattext_osx.cpp @@ -104,6 +104,20 @@ void wxStaticText::DoSetLabel(const wxString& label) m_peer->SetLabel(m_label , GetFont().GetEncoding() ); } +#if wxUSE_MARKUP && wxOSX_USE_COCOA + +bool wxStaticText::DoSetLabelMarkup(const wxString& markup) +{ + if ( !wxStaticTextBase::DoSetLabelMarkup(markup) ) + return false; + + m_peer->SetLabelMarkup(markup); + + return true; +} + +#endif // wxUSE_MARKUP && wxOSX_USE_COCOA + wxString wxStaticText::DoGetLabel() const { return m_label; -- 2.45.2