Browse Source

Handling of style-oriented ascii espace sequences.

Using the RichTextCtrl widget we are able to use advanced formatting in the console pannel. The formatting information is extracted from the text stream by searching for terminal escape sequences. The sequence values are taken from the colored package, which becomes a lazy dependency (imported only when the feature is activated).

The previous implementation (using the TextCtrl widget) has been extracted into a separate class.

The client code chooses between the basic or the rich class based on the richtext_controls configuration parameter. The default is to use the previous implementation based on TextCtrl.
pull/473/head
Nathan Richard 6 years ago
committed by Chris
parent
commit
5e3ef77c36
7 changed files with 101 additions and 4 deletions
  1. 1
      gooey/gui/application.py
  2. 9
      gooey/gui/components/console.py
  3. 5
      gooey/gui/components/widgets/basictextconsole.py
  4. 85
      gooey/gui/components/widgets/richtextconsole.py
  5. 1
      gooey/python_bindings/config_generator.py
  6. 1
      requirements.txt
  7. 3
      setup.py

1
gooey/gui/application.py

@ -3,6 +3,7 @@ Main runner entry point for Gooey.
'''
import wx
import wx.richtext # Need to be imported before the wx.App object is created.
import wx.lib.inspection
from gooey.gui.lang import i18n

9
gooey/gui/components/console.py

@ -1,6 +1,7 @@
import wx
from gooey.gui.lang import i18n
from .widgets.basictextconsole import BasicTextConsole
class Console(wx.Panel):
@ -13,9 +14,11 @@ class Console(wx.Panel):
self.buildSpec = buildSpec
self.text = wx.StaticText(self, label=i18n._("status"))
self.textbox = wx.TextCtrl(
self, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH
)
if buildSpec["richtext_controls"]:
from .widgets.richtextconsole import RichTextConsole
self.textbox = RichTextConsole(self)
else:
self.textbox = BasicTextConsole(self)
self.defaultFont = self.textbox.GetFont()

5
gooey/gui/components/widgets/basictextconsole.py

@ -0,0 +1,5 @@
import wx
class BasicTextConsole(wx.TextCtrl):
def __init__(self, parent):
super().__init__(parent, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_RICH)

85
gooey/gui/components/widgets/richtextconsole.py

@ -0,0 +1,85 @@
import wx
import wx.richtext
import colored
kColorList = ["#000000", "#800000", "#008000", "#808000", "#000080", "#800080", "#008080", "#c0c0c0",
"#808080", "#ff0000", "#00ff00", "#ffff00", "#0000ff", "#ff00ff", "#00ffff", "#ffffff", "#000000",
"#00005f", "#000087", "#0000af", "#0000d7", "#0000ff", "#005f00", "#005f5f", "#005f87", "#005faf",
"#005fd7", "#005fff", "#008700", "#00875f", "#008787", "#0087af", "#0087d7", "#0087ff", "#00af00",
"#00af5f", "#00af87", "#00afaf", "#00afd7", "#00afff", "#00d700", "#00d75f", "#00d787", "#00d7af",
"#00d7d7", "#00d7ff", "#00ff00", "#00ff5f", "#00ff87", "#00ffaf", "#00ffd7", "#00ffff", "#5f0000",
"#5f005f", "#5f0087", "#5f00af", "#5f00d7", "#5f00ff", "#5f5f00", "#5f5f5f", "#5f5f87", "#5f5faf",
"#5f5fd7", "#5f5fff", "#5f8700", "#5f875f", "#5f8787", "#5f87af", "#5f87d7", "#5f87ff", "#5faf00",
"#5faf5f", "#5faf87", "#5fafaf", "#5fafd7", "#5fafff", "#5fd700", "#5fd75f", "#5fd787", "#5fd7af",
"#5fd7d7", "#5fd7ff", "#5fff00", "#5fff5f", "#5fff87", "#5fffaf", "#5fffd7", "#5fffff", "#870000",
"#87005f", "#870087", "#8700af", "#8700d7", "#8700ff", "#875f00", "#875f5f", "#875f87", "#875faf",
"#875fd7", "#875fff", "#878700", "#87875f", "#878787", "#8787af", "#8787d7", "#8787ff", "#87af00",
"#87af5f", "#87af87", "#87afaf", "#87afd7", "#87afff", "#87d700", "#87d75f", "#87d787", "#87d7af",
"#87d7d7", "#87d7ff", "#87ff00", "#87ff5f", "#87ff87", "#87ffaf", "#87ffd7", "#87ffff", "#af0000",
"#af005f", "#af0087", "#af00af", "#af00d7", "#af00ff", "#af5f00", "#af5f5f", "#af5f87", "#af5faf",
"#af5fd7", "#af5fff", "#af8700", "#af875f", "#af8787", "#af87af", "#af87d7", "#af87ff", "#afaf00",
"#afaf5f", "#afaf87", "#afafaf", "#afafd7", "#afafff", "#afd700", "#afd75f", "#afd787", "#afd7af",
"#afd7d7", "#afd7ff", "#afff00", "#afff5f", "#afff87", "#afffaf", "#afffd7", "#afffff", "#d70000",
"#d7005f", "#d70087", "#d700af", "#d700d7", "#d700ff", "#d75f00", "#d75f5f", "#d75f87", "#d75faf",
"#d75fd7", "#d75fff", "#d78700", "#d7875f", "#d78787", "#d787af", "#d787d7", "#d787ff", "#d7af00",
"#d7af5f", "#d7af87", "#d7afaf", "#d7afd7", "#d7afff", "#d7d700", "#d7d75f", "#d7d787", "#d7d7af",
"#d7d7d7", "#d7d7ff", "#d7ff00", "#d7ff5f", "#d7ff87", "#d7ffaf", "#d7ffd7", "#d7ffff", "#ff0000",
"#ff005f", "#ff0087", "#ff00af", "#ff00d7", "#ff00ff", "#ff5f00", "#ff5f5f", "#ff5f87", "#ff5faf",
"#ff5fd7", "#ff5fff", "#ff8700", "#ff875f", "#ff8787", "#ff87af", "#ff87d7", "#ff87ff", "#ffaf00",
"#ffaf5f", "#ffaf87", "#ffafaf", "#ffafd7", "#ffafff", "#ffd700", "#ffd75f", "#ffd787", "#ffd7af",
"#ffd7d7", "#ffd7ff", "#ffff00", "#ffff5f", "#ffff87", "#ffffaf", "#ffffd7", "#ffffff", "#080808",
"#121212", "#1c1c1c", "#262626", "#303030", "#3a3a3a", "#444444", "#4e4e4e", "#585858", "#626262",
"#6c6c6c", "#767676", "#808080", "#8a8a8a", "#949494", "#9e9e9e", "#a8a8a8", "#b2b2b2", "#bcbcbc",
"#c6c6c6", "#d0d0d0", "#dadada", "#e4e4e4", "#eeeeee"]
class RichTextConsole(wx.richtext.RichTextCtrl):
"""
An advanced rich test console pannel supporting some Xterm control codes.
"""
def __init__(self, parent):
super().__init__(parent, -1, "", style=wx.TE_MULTILINE | wx.TE_READONLY)
self.esc = colored.style.ESC
self.end = colored.style.END
self.noop = lambda *args, **kwargs: None
self.actionsMap = dict()
# Supported font altering actions
self.actionsMap[colored.style.BOLD] = self.BeginBold
self.actionsMap[colored.style.RES_BOLD] = self.EndBold
self.actionsMap[colored.style.UNDERLINED] = self.BeginUnderline
self.actionsMap[colored.style.RES_UNDERLINED] = self.EndUnderline
self.actionsMap[colored.style.RESET] = self.EndAllStyles
# Actions for coloring text
for index, hex in enumerate(kColorList):
escSeq = '{}{}{}'.format(colored.fore.ESC, index, colored.fore.END)
wxcolor = wx.Colour(int(hex[1:3],16), int(hex[3:5],16), int(hex[5:],16), alpha=wx.ALPHA_OPAQUE)
# NB : we use a default parameter to force the evaluation of the binding
self.actionsMap[escSeq] = lambda bindedColor=wxcolor: self.BeginTextColour(bindedColor)
def AppendText(self, content):
"""
wx method overriden to capture the terminal control character and translate them into wx styles.
Complexity : o(len(content))
"""
unprocIndex = 0
while True:
# Invariant : unprocIndex is the starting index of the unprocessed part of the buffer
escPos = content.find(self.esc, unprocIndex)
if escPos == -1:
break
# Invariant : found an escape sequence starting at escPos
# NB : we flush all the characters before the escape sequence, if any
if content[unprocIndex:escPos]:
self.WriteText(content[unprocIndex:escPos])
endEsc = content.find(self.end, escPos)
if endEsc == -1:
unprocIndex = escPos + len(self.esc)
continue
# Invariant : end of sequence has been found
self.actionsMap.get(content[escPos:endEsc+1], self.noop)()
unprocIndex = endEsc + 1
# Invariant : unprocessed end of buffer is escape-free, ready to be printed
self.WriteText(content[unprocIndex:])

1
gooey/python_bindings/config_generator.py

@ -89,6 +89,7 @@ def create_from_parser(parser, source_path, **kwargs):
'terminal_font_family': kwargs.get('terminal_font_family', None),
'terminal_font_weight': kwargs.get('terminal_font_weight', None),
'terminal_font_size': kwargs.get('terminal_font_size', None),
'richtext_controls': kwargs.get('richtext_controls', False),
'error_color': kwargs.get('error_color', '#ea7878')
}

1
requirements.txt

@ -2,3 +2,4 @@ RXPY>=0.1.0
wxpython>=4.0.0b1
Pillow>=4.3.0
psutil>=5.4.2
colored>=1.3.93

3
setup.py

@ -10,7 +10,8 @@ version = '1.0.2'
deps = [
'Pillow>=4.3.0',
'psutil>=5.4.2'
'psutil>=5.4.2',
'colored>=1.3.93'
]
if sys.version[0] == '3':

Loading…
Cancel
Save