RichTextCtrl how to reset character style to original paragraph style?

Hi,

I need some help manipulating styles in text. The example below can be used to demonstrate the issue.
I am using python3 and wxPython 4.1.1.

When you run it there will be some text inserted into the RichTextCtrl using the Paragraph style ‘paragraph’ defined in the code. Notice that it is black text on white background which is kind of the default, these colors are not set explicitly in the code.
There is also a second CharacterStyle ‘Link’ used for urls which is blue and underlined and fires an event when clicked.

Click the blue url in the RichTextCtrl and click Ok. The whole paragraph turns red despite the style is being applied just to the range of the url in the code. I am using red just to demonstrate that it is applied to the whole paragraph.

But what I actually want to achieve is change the style of just the url and return it to it’s original non-url style that looks just like regular text. Also notice that even though the ‘Clear formatting’ dialog applied the style ‘paragraph’ to the text, the style box below the text field still shows the url is a Url style and you can still click on it.

What is the correct way of doing this? How do I return a modified character style to the default character style of the paragraph/list style which the text is a part of?

I looked through at the style with a debugger but could not find anything obvious to use to extract just the Character style from a Paragraph style or something similar to that.

Thank you.

import wx
import wx.richtext as rt
import wx.html


class RichTextFrame(wx.Frame):
    def __init__(self, *args, **kw):
        wx.Frame.__init__(self, *args, **kw)
        self.rtc = rt.RichTextCtrl(self, style=wx.VSCROLL | wx.HSCROLL | wx.NO_BORDER)
        self.sizer = wx.BoxSizer(wx.VERTICAL)

        # Create style stylesheet and control
        self._stylesheet = rt.RichTextStyleSheet()
        self._stylesheet.SetName('Stylesheet')

        self.style_control = rt.RichTextStyleListBox(self, 1, size=(140, 60))
        self.style_control.SetStyleType(0)
        self.style_control.SetMargins(-5, -5)

        self.rtc.SetStyleSheet(self._stylesheet)
        self.style_control.SetRichTextCtrl(self.rtc)
        self.style_control.SetStyleSheet(self._stylesheet)

        self.sizer.Add(self.rtc, 1, flag=wx.EXPAND)
        self.sizer.Add(self.style_control)
        self.SetSizer(self.sizer)

        self._create_styles()
        self._insert_sample_text()
        self.rtc.Bind(wx.EVT_TEXT_URL, self.url_in_text_click_handler, self.rtc)

    def url_in_text_click_handler(self, evt: wx.TextUrlEvent) -> None:
        """
        Handles click on url links inside text.
        :param evt: Not used
        :return: None
        """
        dialog = wx.MessageDialog(self, 'Clear formating', caption='Clear formatting', style=wx.OK | wx.CANCEL)
        if dialog.ShowModal() == wx.ID_OK:
            style: rt.RichTextAttr = self._stylesheet.FindParagraphStyle('paragraph').GetStyle()
            style.SetBackgroundColour(wx.RED)
            self.rtc.SetStyle(evt.GetURLStart(), evt.GetURLEnd(), style)

    def _create_styles(self) -> None:
        """
        Create styles for rich text control.
        :return: None
        """
        # Paragraph style
        stl_paragraph: rt.RichTextAttr = self.rtc.GetDefaultStyleEx()
        stl_paragraph.SetParagraphSpacingBefore(10)
        stl_paragraph.SetParagraphSpacingAfter(10)
        style_paragraph: rt.RichTextParagraphStyleDefinition = rt.RichTextParagraphStyleDefinition('paragraph')
        style_paragraph.SetStyle(stl_paragraph)
        style_paragraph.SetNextStyle('paragraph')
        self._stylesheet.AddParagraphStyle(style_paragraph)
        self.rtc.ApplyStyle(style_paragraph)
        self.rtc.SetDefaultStyle(stl_paragraph)

        # Link style
        stl_link = rt.RichTextAttr()
        stl_link.SetFlags(wx.TEXT_ATTR_URL)
        stl_link.SetFontUnderlined(True)
        stl_link.SetURL('http://')
        stl_link.SetTextColour(wx.BLUE)
        style_link: rt.RichTextCharacterStyleDefinition = rt.RichTextCharacterStyleDefinition('url')
        style_link.SetStyle(stl_link)
        self._stylesheet.AddCharacterStyle(style_link)
        self.style_control.UpdateStyles()

    def _insert_sample_text(self) -> None:
        """
        Insert sample text.
        :return: None
        """
        self.rtc.ApplyStyle(self._stylesheet.FindParagraphStyle('paragraph'))
        self.rtc.BeginParagraphStyle('paragraph')
        self.rtc.WriteText('Paragraph adding some text ')
        self._insert_link('google', 'fe80')
        self.rtc.WriteText(' some more text after a link')
        self.rtc.Newline()
        self.rtc.EndParagraphStyle()

    def _insert_link(self, text: str, link_id: str) -> None:
        """
        Insert a link into text at current position.
        :param text: The visible text.
        :param link_id: The ID of the link
        :return: None
        """
        self.rtc.BeginStyle(self._stylesheet.FindCharacterStyle('url').GetStyle())
        self.rtc.BeginURL(link_id)
        self.rtc.WriteText(text)
        self.rtc.EndURL()
        self.rtc.EndStyle()
        self.rtc.ApplyStyle(self._stylesheet.FindParagraphStyle('paragraph'))


class MyApp(wx.App):
    """
    Main class for running the gui
    """

    def __init__(self):
        wx.App.__init__(self)
        self.frame = None

    def OnInit(self):
        self.frame = RichTextFrame(None, -1, "RichTextCtrl", size=(900, 500), style=wx.DEFAULT_FRAME_STYLE)
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True


if __name__ == "__main__":
    app = MyApp()
    app.MainLoop()

Never mind, found the solution. You do it like this:

style: rt.RichTextAttr = self._stylesheet.FindCharacterStyle(Strings.style_url).GetStyle()
style_range = rt.RichTextRange(evt.GetURLStart(), evt.GetURLEnd() + 1)
self.SetStyleEx(style_range, style, rt.RICHTEXT_SETSTYLE_REMOVE)