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()