Notebook word make clickable

Yet another way to use stc.StyledTextCtrl indicator.

The hotspot is lexer-base and the style is limited, but the indicator is context-base and can use many style and hover effect (hover is wx 4.1.0 or later)

import wx
from wx import stc
from wx.py.editwindow import EditWindow

class TestEditor(EditWindow):
    def __init__(self, *args, **kwargs):
        EditWindow.__init__(self, *args, **kwargs)
        
        self.StyleClearAll()
        
        ## context-base style
        if wx.VERSION < (4,1,0):
            self.IndicatorSetStyle(0, stc.STC_INDIC_PLAIN)
            self.IndicatorSetStyle(1, stc.STC_INDIC_CONTAINER)
        else:
            self.IndicatorSetStyle(0, stc.STC_INDIC_TEXTFORE)
            self.IndicatorSetStyle(1, stc.STC_INDIC_ROUNDBOX)
        self.IndicatorSetForeground(0, "red")
        self.IndicatorSetForeground(1, "yellow")
        
        if wx.VERSION >= (4,1,0):
            self.IndicatorSetHoverStyle(1, stc.STC_INDIC_ROUNDBOX)
            self.IndicatorSetHoverForeground(1, "blue")
        
        self.Bind(stc.EVT_STC_INDICATOR_CLICK, self.OnIndicator)
    
    def OnIndicator(self, evt):
        if self.IndicatorValue == 1:
            p = self.IndicatorStart(1, evt.Position)
            q = self.IndicatorEnd(1, evt.Position)
            print(self.GetTextRange(p, q))
    
    def FilterText(self, text):
        if not text:
            for i in range(2):
                self.SetIndicatorCurrent(i)
                self.IndicatorClearRange(0, self.TextLength)
            return
        word = text.encode() # for multi-byte string
        raw = self.TextRaw # for multi-byte string
        lw = len(word)
        pos = -1
        while 1:
            pos = raw.find(word, pos+1)
            if pos < 0:
                break
            for i in range(2):
                self.SetIndicatorCurrent(i)
                self.IndicatorFillRange(pos, lw)

samplePhrase = """
She sells sea shells by the seashore.
The shells that she sells are sea shells I'm sure.
So if she sells sea shells on the seashore,
I'm sure that the shells are seashore shells.
"""

if __name__ == "__main__":
    app = wx.App()
    frame = wx.Frame(None)
    ed = TestEditor(frame)
    ed.Text = samplePhrase
    ed.FilterText("shells")
    ed.FilterText("she")
    frame.Show()
    app.MainLoop()

Clipboard04