0

Is there a mechanism that detects (highlight and generate mouse event) a file or a folder path in a wx.TextCtrl?

A similar mechanism exists for URL detection (using style = wx.TE_AUTO_URL with wx.TE_RICH).

Example:

"This is an example how I want TextCtrl to detect C:\Temp\Folder\temp.txt as a path."

Thanks, Omer.

1 Answers1

0

To the best of my knowledge, there is no built-in style that would do what you want. However, you can always subclass wx.TextCtrl.

The custom widget provided below changes the style for string subsections matching a regular expression. When the cursor hovers over one of these substrings, the custom command event "EVT_TXT_PATH" is generated.

The regex may need adjusting depending on what paths you want the control to recognize. I grabbed one from the regular expression library that might work for you:

http://regexlib.com/REDetails.aspx?regexp_id=127

import wx
import wx.lib.newevent

import re

re_path = re.compile(r'([A-Z]:\\[^/:\*\?<>\|]+\.\w{2,6})|(\\{2}[^/:\*\?<>\|]+\.\w{2,6})')

TextPathEvent, EVT_TXT_PATH = wx.lib.newevent.NewCommandEvent()

class PathTextCtrl(wx.TextCtrl):

    def __init__(self, parent, id=wx.ID_ANY, value="",
                 pos=wx.DefaultPosition, size=wx.DefaultSize,
                 style=0, validator=wx.DefaultValidator,
                 name=""):

        style = style | wx.TE_RICH

        super(PathTextCtrl, self).__init__(parent, id, value, pos, size,
                                           style,validator, name)

        self.groups = []

        self.SetDefaultStyle(wx.TextAttr(wx.BLACK, wx.NullColor))

        self.Bind(wx.EVT_TEXT, self.OnText, self)
        self.Bind(wx.EVT_MOTION, self.OnMotion, self)

    def OnText(self, evt):

        self.StyleText()

        evt.Skip()

    def StyleText(self):

        self.groups = []

        string = self.GetValue()
        n = len(string)

        defstyle = self.GetDefaultStyle()
        self.SetStyle(0, n, defstyle)

        font = self.GetFont()
        font.SetUnderlined(True)
        style = wx.TextAttr(colText=wx.BLUE, font=font)       

        index = 0

        while True:

            match = re_path.search(string, index, n)

            if match:

                start, end = match.span()

                self.groups.append((start, end))

                self.SetStyle(start, end, style)

                index = end+1

            else: return

    def OnMotion(self, evt):

        pos = evt.GetPosition()

        result = self.HitTestPos(pos)

        for group in self.groups:

            x, y = group

            if x <= result[1] <= y:

                string = self.GetValue()[x:y]

                print string

                event = TextPathEvent(id=self.GetId(), url=string)

                wx.PostEvent(self, event)

        evt.Skip()

class TestFrame(wx.Frame):

    def __init__(self, parent, id=wx.ID_ANY, title=""):

        super(TestFrame, self).__init__(parent, id, title)

        panel = wx.Panel(self)

        text = PathTextCtrl(panel, size=(400, -1))

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(text, 0, wx.ALL, 10)
        panel.SetSizer(sizer)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel)
        self.SetSizer(sizer)

        self.Fit()

if __name__ == '__main__':

    app = wx.App(redirect=True)
    top = TestFrame(None, title="PathTextCtrl Demonstration")
    top.Show()
    app.MainLoop()
DavidM2
  • 1
  • 1