diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index 341409530e..22792af375 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -270,6 +270,14 @@ enum wxTextAttrLineSpacing wxTEXT_ATTR_LINE_SPACING_TWICE = 20 }; +enum wxTextAttrUnderlineType +{ + wxTEXT_ATTR_UNDERLINE_NONE, + wxTEXT_ATTR_UNDERLINE_SOLID, + wxTEXT_ATTR_UNDERLINE_DOUBLE, + wxTEXT_ATTR_UNDERLINE_SPECIAL +}; + // ---------------------------------------------------------------------------- // wxTextAttr: a structure containing the visual attributes of a text // ---------------------------------------------------------------------------- @@ -320,7 +328,13 @@ public: void SetFontStyle(wxFontStyle fontStyle) { m_fontStyle = fontStyle; m_flags |= wxTEXT_ATTR_FONT_ITALIC; } void SetFontWeight(wxFontWeight fontWeight) { m_fontWeight = fontWeight; m_flags |= wxTEXT_ATTR_FONT_WEIGHT; } void SetFontFaceName(const wxString& faceName) { m_fontFaceName = faceName; m_flags |= wxTEXT_ATTR_FONT_FACE; } - void SetFontUnderlined(bool underlined) { m_fontUnderlined = underlined; m_flags |= wxTEXT_ATTR_FONT_UNDERLINE; } + void SetFontUnderlined(bool underlined) { SetFontUnderlined(underlined ? wxTEXT_ATTR_UNDERLINE_SOLID : wxTEXT_ATTR_UNDERLINE_NONE); } + void SetFontUnderlined(wxTextAttrUnderlineType type, const wxColour& colour = wxNullColour) + { + m_flags |= wxTEXT_ATTR_FONT_UNDERLINE; + m_fontUnderlineType = type; + m_colUnderline = colour; + } void SetFontStrikethrough(bool strikethrough) { m_fontStrikethrough = strikethrough; m_flags |= wxTEXT_ATTR_FONT_STRIKETHROUGH; } void SetFontEncoding(wxFontEncoding encoding) { m_fontEncoding = encoding; m_flags |= wxTEXT_ATTR_FONT_ENCODING; } void SetFontFamily(wxFontFamily family) { m_fontFamily = family; m_flags |= wxTEXT_ATTR_FONT_FAMILY; } @@ -359,7 +373,9 @@ public: int GetFontSize() const { return m_fontSize; } wxFontStyle GetFontStyle() const { return m_fontStyle; } wxFontWeight GetFontWeight() const { return m_fontWeight; } - bool GetFontUnderlined() const { return m_fontUnderlined; } + bool GetFontUnderlined() const { return m_fontUnderlineType != wxTEXT_ATTR_UNDERLINE_NONE; } + wxTextAttrUnderlineType GetUnderlineType() const { return m_fontUnderlineType; } + const wxColour& GetUnderlineColour() const { return m_colUnderline; } bool GetFontStrikethrough() const { return m_fontStrikethrough; } const wxString& GetFontFaceName() const { return m_fontFaceName; } wxFontEncoding GetFontEncoding() const { return m_fontEncoding; } @@ -508,7 +524,8 @@ private: wxFontStyle m_fontStyle; wxFontWeight m_fontWeight; wxFontFamily m_fontFamily; - bool m_fontUnderlined; + wxTextAttrUnderlineType m_fontUnderlineType; + wxColour m_colUnderline; bool m_fontStrikethrough; wxString m_fontFaceName; diff --git a/interface/wx/textctrl.h b/interface/wx/textctrl.h index 3bf15e7e5e..7ebd41d347 100644 --- a/interface/wx/textctrl.h +++ b/interface/wx/textctrl.h @@ -219,6 +219,19 @@ enum wxTextAttrLineSpacing }; +/** + Underline types that can be used in wxTextAttr::SetFontUnderline(). + + @since 3.1.3 +*/ +enum wxTextAttrUnderlineType +{ + wxTEXT_ATTR_UNDERLINE_NONE, + wxTEXT_ATTR_UNDERLINE_SOLID, + wxTEXT_ATTR_UNDERLINE_DOUBLE, + wxTEXT_ATTR_UNDERLINE_SPECIAL +}; + /** Describes the possible return values of wxTextCtrl::HitTest(). @@ -422,6 +435,20 @@ public: */ bool GetFontUnderlined() const; + /** + Returns the underline type, which is one of the @wxTextAttrUnderlineType values. + + @since 3.1.3 + */ + wxTextAttrUnderlineType GetUnderlineType() const; + + /** + Returns the underline color used. wxNullColour when the text colour is used. + + @since 3.1.3 + */ + const wxColour& GetUnderlineColour() const; + /** Returns the font weight. */ @@ -803,10 +830,34 @@ public: void SetFontStyle(wxFontStyle fontStyle); /** - Sets the font underlining. + Sets the font underlining (solid line, text colour). */ void SetFontUnderlined(bool underlined); + /** + Sets the font underlining. + + @param type Type of underline. + + @param colour Colour to use for underlining, text colour is used by + default. + + @note On wxMSW, wxTEXT_ATTR_UNDERLINE_DOUBLE is shown as + wxTEXT_ATTR_UNDERLINE_SOLID. There is only a limited number of colours + supported, the RGB values are listed + here. + wxTEXT_ATTR_UNDERLINE_SPECIAL is shown as a waved line. + + @note On wxGTK, underline colour is only supported by wxGTK3. + wxTEXT_ATTR_UNDERLINE_SPECIAL is shown as a waved line. GTK might + overrule the colour of wxTEXT_ATTR_UNDERLINE_SPECIAL. + + @note On wxOSX, wxTEXT_ATTR_UNDERLINE_SPECIAL is shown as a dotted line. + + @since 3.1.3 + */ + void SetFontUnderlined(wxTextAttrUnderlineType type, const wxColour& colour = wxNullColour); + /** Sets the font weight. */ diff --git a/samples/text/text.cpp b/samples/text/text.cpp index 7e5256b0b9..f4ee6f9038 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -1228,8 +1228,24 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h ) m_textrich->AppendText("This text should be cyan on blue\n"); m_textrich->SetDefaultStyle(wxTextAttr(*wxBLUE, *wxWHITE)); m_textrich->AppendText("And this should be in blue and the text you " - "type should be in blue as well"); - + "type should be in blue as well.\n"); + m_textrich->SetDefaultStyle(wxTextAttr()); + wxTextAttr attr = m_textrich->GetDefaultStyle(); + attr.SetFontUnderlined(true); + m_textrich->SetDefaultStyle(attr); + m_textrich->AppendText("\nAnd there"); + attr.SetFontUnderlined(false); + m_textrich->SetDefaultStyle(attr); + m_textrich->AppendText(" is a "); + attr.SetFontUnderlined(wxTEXT_ATTR_UNDERLINE_SPECIAL, *wxRED); + m_textrich->SetDefaultStyle(attr); + m_textrich->AppendText("mispeled"); + attr.SetFontUnderlined(false); + m_textrich->SetDefaultStyle(attr); + m_textrich->AppendText(" word."); + attr.SetFontUnderlined(wxTEXT_ATTR_UNDERLINE_DOUBLE, *wxGREEN); + const long endPos = m_textrich->GetLastPosition(); + m_textrich->SetStyle(endPos - 4, endPos - 2, attr); // lay out the controls wxBoxSizer *column1 = new wxBoxSizer(wxVERTICAL); diff --git a/src/common/textcmn.cpp b/src/common/textcmn.cpp index 2774635bbe..9f8de569bd 100644 --- a/src/common/textcmn.cpp +++ b/src/common/textcmn.cpp @@ -162,7 +162,7 @@ void wxTextAttr::Init() m_fontSize = 12; m_fontStyle = wxFONTSTYLE_NORMAL; m_fontWeight = wxFONTWEIGHT_NORMAL; - m_fontUnderlined = false; + m_fontUnderlineType = wxTEXT_ATTR_UNDERLINE_NONE; m_fontStrikethrough = false; m_fontEncoding = wxFONTENCODING_DEFAULT; m_fontFamily = wxFONTFAMILY_DEFAULT; @@ -175,6 +175,7 @@ void wxTextAttr::Init() m_textEffectFlags = wxTEXT_ATTR_EFFECT_NONE; m_outlineLevel = 0; m_bulletNumber = 0; + m_colUnderline = wxNullColour; } // Copy @@ -192,7 +193,8 @@ void wxTextAttr::Copy(const wxTextAttr& attr) m_fontSize = attr.m_fontSize; m_fontStyle = attr.m_fontStyle; m_fontWeight = attr.m_fontWeight; - m_fontUnderlined = attr.m_fontUnderlined; + m_fontUnderlineType = attr.m_fontUnderlineType; + m_colUnderline = attr.m_colUnderline; m_fontStrikethrough = attr.m_fontStrikethrough; m_fontFaceName = attr.m_fontFaceName; m_fontEncoding = attr.m_fontEncoding; @@ -257,7 +259,7 @@ bool wxTextAttr::operator== (const wxTextAttr& attr) const (!HasFontSize() || (GetFontSize() == attr.GetFontSize())) && (!HasFontItalic() || (GetFontStyle() == attr.GetFontStyle())) && (!HasFontWeight() || (GetFontWeight() == attr.GetFontWeight())) && - (!HasFontUnderlined() || (GetFontUnderlined() == attr.GetFontUnderlined())) && + (!HasFontUnderlined() || ((GetUnderlineType() == attr.GetUnderlineType()) && (GetUnderlineColour() == attr.GetUnderlineColour()) )) && (!HasFontStrikethrough() || (GetFontStrikethrough() == attr.GetFontStrikethrough())) && (!HasFontFaceName() || (GetFontFaceName() == attr.GetFontFaceName())) && (!HasFontEncoding() || (GetFontEncoding() == attr.GetFontEncoding())) && @@ -327,7 +329,8 @@ bool wxTextAttr::EqPartial(const wxTextAttr& attr, bool weakTest) const if (HasFontItalic() && attr.HasFontItalic() && GetFontStyle() != attr.GetFontStyle()) return false; - if (HasFontUnderlined() && attr.HasFontUnderlined() && GetFontUnderlined() != attr.GetFontUnderlined()) + if (HasFontUnderlined() && attr.HasFontUnderlined() && + ( (GetUnderlineType() != attr.GetUnderlineType()) || (GetUnderlineColour() != attr.GetUnderlineColour()) )) return false; if (HasFontStrikethrough() && attr.HasFontStrikethrough() && GetFontStrikethrough() != attr.GetFontStrikethrough()) @@ -502,7 +505,7 @@ bool wxTextAttr::GetFontAttributes(const wxFont& font, int flags) m_fontWeight = font.GetWeight(); if (flags & wxTEXT_ATTR_FONT_UNDERLINE) - m_fontUnderlined = font.GetUnderlined(); + m_fontUnderlineType = font.GetUnderlined() ? wxTEXT_ATTR_UNDERLINE_SOLID : wxTEXT_ATTR_UNDERLINE_NONE; if (flags & wxTEXT_ATTR_FONT_STRIKETHROUGH) m_fontStrikethrough = font.GetStrikethrough(); @@ -571,8 +574,10 @@ bool wxTextAttr::Apply(const wxTextAttr& style, const wxTextAttr* compareWith) if (style.HasFontUnderlined()) { - if (!(compareWith && compareWith->HasFontUnderlined() && compareWith->GetFontUnderlined() == style.GetFontUnderlined())) - destStyle.SetFontUnderlined(style.GetFontUnderlined()); + if (!(compareWith && compareWith->HasFontUnderlined() && + compareWith->GetUnderlineType() == style.GetUnderlineType() && + compareWith->GetUnderlineColour() == style.GetUnderlineColour())) + destStyle.SetFontUnderlined(style.GetUnderlineType(), style.GetUnderlineColour()); } if (style.HasFontStrikethrough()) @@ -791,6 +796,8 @@ wxTextAttr wxTextAttr::Combine(const wxTextAttr& attr, } wxTextAttr newAttr(colFg, colBg, font); + if (attr.HasFontUnderlined()) + newAttr.SetFontUnderlined(attr.GetUnderlineType(), attr.GetUnderlineColour()); if (attr.HasAlignment()) newAttr.SetAlignment(attr.GetAlignment()); diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index b19a3f5367..9a7e12f5e3 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -124,6 +124,57 @@ static void wxGtkTextApplyTagsFromAttr(GtkWidget *text, } } + if ( attr.HasFontUnderlined() ) + { + PangoUnderline pangoUnderlineStyle = PANGO_UNDERLINE_NONE; + switch ( attr.GetUnderlineType() ) + { + case wxTEXT_ATTR_UNDERLINE_SOLID: + pangoUnderlineStyle = PANGO_UNDERLINE_SINGLE; + break; + case wxTEXT_ATTR_UNDERLINE_DOUBLE: + pangoUnderlineStyle = PANGO_UNDERLINE_DOUBLE; + break; + case wxTEXT_ATTR_UNDERLINE_SPECIAL: + pangoUnderlineStyle = PANGO_UNDERLINE_ERROR; + break; + default: + pangoUnderlineStyle = PANGO_UNDERLINE_NONE; + break; + } + + g_snprintf(buf, sizeof(buf), "WXFONTUNDERLINESTYLE %u", + (unsigned)pangoUnderlineStyle); + tag = gtk_text_tag_table_lookup( gtk_text_buffer_get_tag_table( text_buffer ), + buf ); + if (!tag) + tag = gtk_text_buffer_create_tag( text_buffer, buf, + "underline-set", TRUE, + "underline", pangoUnderlineStyle, + NULL ); + gtk_text_buffer_apply_tag (text_buffer, tag, start, end); + +#ifdef __WXGTK3__ + if ( wx_is_at_least_gtk3(16) ) + { + wxColour colour = attr.GetUnderlineColour(); + if ( colour.IsOk() ) + { + g_snprintf(buf, sizeof(buf), "WXFONTUNDERLINECOLOUR %u %u %u %u", + colour.Red(), colour.Green(), colour.Blue(), colour.Alpha()); + tag = gtk_text_tag_table_lookup( gtk_text_buffer_get_tag_table( text_buffer ), + buf ); + if (!tag) + tag = gtk_text_buffer_create_tag( text_buffer, buf, + "underline-rgba-set", TRUE, + "underline-rgba", static_cast(colour), + NULL ); + gtk_text_buffer_apply_tag (text_buffer, tag, start, end); + } + } +#endif + } + if (attr.HasTextColour()) { wxGtkTextRemoveTagsWithPrefix(text_buffer, "WXFORECOLOR", start, end); @@ -1845,8 +1896,48 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style) if ( font.SetNativeFontInfo(wxString(pangoFontString)) ) style.SetFont(font); - if ( pattr->appearance.underline != PANGO_UNDERLINE_NONE ) - style.SetFontUnderlined(true); + wxTextAttrUnderlineType underlineType = wxTEXT_ATTR_UNDERLINE_NONE; + switch ( pattr->appearance.underline ) + { + case PANGO_UNDERLINE_SINGLE: + underlineType = wxTEXT_ATTR_UNDERLINE_SOLID; + break; + case PANGO_UNDERLINE_DOUBLE: + underlineType = wxTEXT_ATTR_UNDERLINE_DOUBLE; + break; + case PANGO_UNDERLINE_ERROR: + underlineType = wxTEXT_ATTR_UNDERLINE_SPECIAL; + break; + default: + underlineType = wxTEXT_ATTR_UNDERLINE_NONE; + break; + } + + wxColour underlineColour = wxNullColour; +#ifdef __WXGTK3__ + GSList* tags = gtk_text_iter_get_tags(&positioni); + for ( GSList* tagp = tags; tagp != NULL; tagp = tagp->next ) + { + GtkTextTag* tag = static_cast(tagp->data); + gboolean underlineSet = FALSE; + g_object_get(tag, "underline-rgba-set", &underlineSet, NULL); + if ( underlineSet ) + { + GdkRGBA* gdkColour = NULL; + g_object_get(tag, "underline-rgba", &gdkColour, NULL); + if ( gdkColour ) + underlineColour = wxColour(*gdkColour); + gdk_rgba_free(gdkColour); + break; + } + } + if ( tags ) + g_slist_free(tags); +#endif + + if ( underlineType != wxTEXT_ATTR_UNDERLINE_NONE ) + style.SetFontUnderlined(underlineType, underlineColour); + if ( pattr->appearance.strikethrough ) style.SetFontStrikethrough(true); diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 9044420c46..2110fb4d6a 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -81,6 +81,27 @@ #define CFE_AUTOBACKCOLOR 0x04000000 #endif +// missing defines for MinGW build +#ifndef CFM_UNDERLINETYPE + #define CFM_UNDERLINETYPE 0x00800000 +#endif + +#ifndef CFU_UNDERLINENONE + #define CFU_UNDERLINENONE 0 +#endif + +#ifndef CFU_UNDERLINE + #define CFU_UNDERLINE 1 +#endif + +#ifndef CFU_UNDERLINEDOUBLE + #define CFU_UNDERLINEDOUBLE 3 +#endif + +#ifndef CFU_UNDERLINEWAVE + #define CFU_UNDERLINEWAVE 8 +#endif + #if wxUSE_DRAG_AND_DROP && wxUSE_RICHEDIT // dummy value used for m_dropTarget, different from any valid pointer value @@ -2795,6 +2816,30 @@ bool wxTextCtrl::SetFont(const wxFont& font) // styling support for rich edit controls // ---------------------------------------------------------------------------- +#if _RICHEDIT_VER >= 0x0800 +static const wxColour gs_underlineColourMap[] = +{ + // The colours are coming from https://docs.microsoft.com/en-us/windows/desktop/api/tom/nf-tom-itextdocument2-geteffectcolor. + wxNullColour, // text colour + wxColour(0, 0, 0 ), // black + wxColour(0, 0, 255), // blue + wxColour(0, 255, 255), // cyan + wxColour(0, 255, 0 ), // green + wxColour(255, 0, 255), // magenta + wxColour(255, 0, 0 ), // red + wxColour(255, 255, 0 ), // yellow + wxColour(255, 255, 255), // white + wxColour(0, 0, 128), // navy + wxColour(0, 128, 128), // teal + wxColour(0, 128, 0 ), // light green + wxColour(128, 0, 128), // purple + wxColour(128, 0, 0 ), // maroon + wxColour(128, 128, 0 ), // olive + wxColour(128, 128, 128), // grey + wxColour(192, 192, 192), // light grey +}; +#endif + bool wxTextCtrl::MSWSetCharFormat(const wxTextAttr& style, long start, long end) { // initialize CHARFORMAT struct @@ -2865,6 +2910,42 @@ bool wxTextCtrl::MSWSetCharFormat(const wxTextAttr& style, long start, long end) } } + if ( style.HasFontUnderlined() ) + { + cf.dwMask |= CFM_UNDERLINETYPE; + BYTE underlineType = CFU_UNDERLINENONE; + switch ( style.GetUnderlineType() ) + { + case wxTEXT_ATTR_UNDERLINE_SOLID: + underlineType = CFU_UNDERLINE; + break; + case wxTEXT_ATTR_UNDERLINE_DOUBLE: + underlineType = CFU_UNDERLINEDOUBLE; + break; + case wxTEXT_ATTR_UNDERLINE_SPECIAL: + underlineType = CFU_UNDERLINEWAVE; + break; + default: + underlineType = CFU_UNDERLINENONE; + break; + } + cf.bUnderlineType = underlineType; + +#if _RICHEDIT_VER >= 0x0800 + BYTE colour = 0; + const wxColour& col = style.GetUnderlineColour(); + for ( size_t c = 0; c < WXSIZEOF(gs_underlineColourMap); ++c ) + { + if ( col == gs_underlineColourMap[c] ) + { + colour = static_cast(c); + break; + } + } + cf.bUnderlineColor = colour; +#endif + } + if ( style.HasTextColour() ) { cf.dwMask |= CFM_COLOR; @@ -3028,7 +3109,7 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) // even try to do anything if it's the only thing we want to change if ( m_verRichEdit == 1 && !style.HasFont() && !style.HasTextColour() && !style.HasLeftIndent() && !style.HasRightIndent() && !style.HasAlignment() && - !style.HasTabs() ) + !style.HasTabs() && !style.GetFontUnderlined() ) { // nothing to do: return true if there was really nothing to do and // false if we failed to set bg colour @@ -3181,6 +3262,32 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style) } #endif // wxUSE_RICHEDIT2 + wxTextAttrUnderlineType underlineType = wxTEXT_ATTR_UNDERLINE_NONE; + switch ( cf.bUnderlineType ) + { + case CFU_UNDERLINE: + underlineType = wxTEXT_ATTR_UNDERLINE_SOLID; + break; + case CFU_UNDERLINEDOUBLE: + underlineType = wxTEXT_ATTR_UNDERLINE_DOUBLE; + break; + case CFU_UNDERLINEWAVE: + underlineType = wxTEXT_ATTR_UNDERLINE_SPECIAL; + break; + default: + underlineType = wxTEXT_ATTR_UNDERLINE_NONE; + break; + } + + wxColour underlineColour; +#if _RICHEDIT_VER >= 0x0800 + if ( cf.bUnderlineColor < WXSIZEOF(gs_underlineColourMap) ) + underlineColour = gs_underlineColourMap[cf.bUnderlineColor]; +#endif + + if ( underlineType != wxTEXT_ATTR_UNDERLINE_NONE ) + style.SetFontUnderlined(underlineType, underlineColour); + // now get the paragraph formatting PARAFORMAT2 pf; wxZeroMemory(pf); diff --git a/src/osx/cocoa/textctrl.mm b/src/osx/cocoa/textctrl.mm index 089a1eef7c..27581dae19 100644 --- a/src/osx/cocoa/textctrl.mm +++ b/src/osx/cocoa/textctrl.mm @@ -128,7 +128,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; @implementation wxTextEntryFormatter -- (id)init +- (id)init { if ( self = [super init] ) { @@ -138,7 +138,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; return self; } -- (void) setMaxLength:(int) maxlen +- (void) setMaxLength:(int) maxlen { maxLength = maxlen; } @@ -155,13 +155,13 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; return [NSString stringWithString:anObject]; } -- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error +- (BOOL)getObjectValue:(id *)obj forString:(NSString *)string errorDescription:(NSString **)error { *obj = [NSString stringWithString:string]; return YES; } -- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr +- (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString **)error { if ( maxLength > 0 ) @@ -226,9 +226,9 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; - (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector { wxUnusedVar(textView); - + BOOL handled = NO; - + wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( control ); if ( impl ) { @@ -322,7 +322,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; } } } - + return handled; } @@ -406,7 +406,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; BOOL r = [super becomeFirstResponder]; if ( impl != NULL && r ) impl->DoNotifyFocusSet(); - + return r; } @@ -653,11 +653,11 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; { wxUnusedVar(textView); wxUnusedVar(control); - + BOOL handled = NO; // send back key events wx' common code knows how to handle - + wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); if ( impl ) { @@ -681,7 +681,7 @@ NSView* wxMacEditHelper::ms_viewCurrentlyEdited = nil; } } } - + return handled; } @@ -740,7 +740,7 @@ wxNSTextViewControl::wxNSTextViewControl( wxTextCtrl *wxPeer, WXWidget w, long s [tv setVerticallyResizable:YES]; [tv setHorizontallyResizable:hasHScroll]; [tv setAutoresizingMask:NSViewWidthSizable]; - + if ( hasHScroll ) { [[tv textContainer] setContainerSize:NSMakeSize(MAX_WIDTH, MAX_WIDTH)]; @@ -1036,19 +1036,23 @@ void wxNSTextViewControl::SetFont( const wxFont & font , const wxColour& WXUNUSE bool wxNSTextViewControl::GetStyle(long position, wxTextAttr& style) { if (m_textView && position >=0) - { + { NSFont* font = NULL; NSColor* bgcolor = NULL; NSColor* fgcolor = NULL; + NSNumber* ultype = NULL; + NSColor* ulcolor = NULL; // NOTE: It appears that other platforms accept GetStyle with the position == length // but that NSTextStorage does not accept length as a valid position. // Therefore we return the default control style in that case. - if (position < (long) [[m_textView string] length]) + if (position < (long) [[m_textView string] length]) { NSTextStorage* storage = [m_textView textStorage]; font = [storage attribute:NSFontAttributeName atIndex:position effectiveRange:NULL]; bgcolor = [storage attribute:NSBackgroundColorAttributeName atIndex:position effectiveRange:NULL]; fgcolor = [storage attribute:NSForegroundColorAttributeName atIndex:position effectiveRange:NULL]; + ultype = [storage attribute:NSUnderlineStyleAttributeName atIndex:position effectiveRange:NULL]; + ulcolor = [storage attribute:NSUnderlineColorAttributeName atIndex:position effectiveRange:NULL]; } else { @@ -1056,16 +1060,47 @@ bool wxNSTextViewControl::GetStyle(long position, wxTextAttr& style) font = [attrs objectForKey:NSFontAttributeName]; bgcolor = [attrs objectForKey:NSBackgroundColorAttributeName]; fgcolor = [attrs objectForKey:NSForegroundColorAttributeName]; + ultype = [attrs objectForKey:NSUnderlineStyleAttributeName]; + ulcolor = [attrs objectForKey:NSUnderlineColorAttributeName]; } - + if (font) style.SetFont(wxFont(font)); - + if (bgcolor) style.SetBackgroundColour(wxColour(bgcolor)); - + if (fgcolor) style.SetTextColour(wxColour(fgcolor)); + + wxTextAttrUnderlineType underlineType = wxTEXT_ATTR_UNDERLINE_NONE; + if ( ultype ) + { + NSInteger ulval = [ultype integerValue]; + switch ( ulval ) + { + case NSUnderlineStyleSingle: + underlineType = wxTEXT_ATTR_UNDERLINE_SOLID; + break; + case NSUnderlineStyleDouble: + underlineType = wxTEXT_ATTR_UNDERLINE_DOUBLE; + break; + case NSUnderlineStyleSingle | NSUnderlinePatternDot: + underlineType = wxTEXT_ATTR_UNDERLINE_SPECIAL; + break; + default: + underlineType = wxTEXT_ATTR_UNDERLINE_NONE; + break; + } + } + + wxColour underlineColour; + if ( ulcolor ) + underlineColour = wxColour(ulcolor); + + if ( underlineType != wxTEXT_ATTR_UNDERLINE_NONE ) + style.SetFontUnderlined(underlineType, underlineColour); + return true; } @@ -1082,14 +1117,38 @@ void wxNSTextViewControl::SetStyle(long start, if ( start == -1 && end == -1 ) { NSMutableDictionary* const - attrs = [NSMutableDictionary dictionaryWithCapacity:3]; + attrs = [NSMutableDictionary dictionaryWithCapacity:5]; if ( style.HasFont() ) [attrs setValue:style.GetFont().OSXGetNSFont() forKey:NSFontAttributeName]; if ( style.HasBackgroundColour() ) [attrs setValue:style.GetBackgroundColour().OSXGetNSColor() forKey:NSBackgroundColorAttributeName]; if ( style.HasTextColour() ) [attrs setValue:style.GetTextColour().OSXGetNSColor() forKey:NSForegroundColorAttributeName]; - + if ( style.HasFontUnderlined() ) + { + int underlineStyle = NSUnderlineStyleNone; + switch ( style.GetUnderlineType() ) + { + case wxTEXT_ATTR_UNDERLINE_SOLID: + underlineStyle = NSUnderlineStyleSingle; + break; + case wxTEXT_ATTR_UNDERLINE_DOUBLE: + underlineStyle = NSUnderlineStyleDouble; + break; + case wxTEXT_ATTR_UNDERLINE_SPECIAL: + underlineStyle = NSUnderlineStyleSingle | NSUnderlinePatternDot; + break; + default: + underlineStyle = NSUnderlineStyleNone; + break; + } + [attrs setObject:[NSNumber numberWithInt:( underlineStyle )] forKey:NSUnderlineStyleAttributeName]; + wxColour colour = style.GetUnderlineColour(); + if ( colour.IsOk() ) + { + [attrs setValue:colour.OSXGetNSColor() forKey:NSUnderlineColorAttributeName]; + } + } [m_textView setTypingAttributes:attrs]; } else // Set the attributes just for this range. @@ -1105,8 +1164,37 @@ void wxNSTextViewControl::SetStyle(long start, if ( style.HasTextColour() ) [storage addAttribute:NSForegroundColorAttributeName value:style.GetTextColour().OSXGetNSColor() range:range]; + + if( style.HasFontUnderlined() ) + { + NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; + int underlineStyle = NSUnderlineStyleNone; + switch ( style.GetUnderlineType() ) + { + case wxTEXT_ATTR_UNDERLINE_SOLID: + underlineStyle = NSUnderlineStyleSingle; + break; + case wxTEXT_ATTR_UNDERLINE_DOUBLE: + underlineStyle = NSUnderlineStyleDouble; + break; + case wxTEXT_ATTR_UNDERLINE_SPECIAL: + underlineStyle = NSUnderlineStyleSingle | NSUnderlinePatternDot; + break; + default: + underlineStyle = NSUnderlineStyleNone; + break; + } + [dict setObject:[NSNumber numberWithInt:( underlineStyle )] forKey:NSUnderlineStyleAttributeName]; + wxColour colour = style.GetUnderlineColour(); + if ( colour.IsOk() ) + { + [dict setValue:colour.OSXGetNSColor() forKey:NSUnderlineColorAttributeName]; + } + [storage addAttributes:dict range:range]; + [dict release]; + } } - + if ( style.HasAlignment() ) { switch ( style.GetAlignment() ) @@ -1510,7 +1598,7 @@ wxWidgetImplType* wxWidgetImpl::CreateTextControl( wxTextCtrl* wxpeer, { [v setAlignment:NSCenterTextAlignment]; } - + NSTextFieldCell* cell = [v cell]; [cell setWraps:NO]; [cell setScrollable:YES];