From b3d64d5f67a698f636fb15e120c00da1de3e260a Mon Sep 17 00:00:00 2001 From: Cheryl Sabella Date: Fri, 1 Jun 2018 21:45:54 -0400 Subject: [PATCH] bpo-33679: IDLE: Re-enable color configuration for code context (GH-7199) The difference from before is that the settings are now on the Highlights tab instead of the Extensions tab and only change one theme at a time instead of all themes. The default for light themes is black on light gray, as before. The default for the IDLE Dark theme is white on dark gray, which better fits the dark theme. When one starts IDLE from a console and loads a custom theme without definitions for 'context', one will see a warning message on the console. To stop the warning, go to Options => Configure IDLE => Highlights, select the custom theme if not selected already, select 'Code Context', and select foreground and background colors. (cherry picked from commit de6516264e793be991f692fdd892707afb9104a7) Co-authored-by: Cheryl Sabella --- Lib/idlelib/codecontext.py | 28 +++++++------- Lib/idlelib/config-highlight.def | 6 +++ Lib/idlelib/config.py | 2 + Lib/idlelib/configdialog.py | 28 +++++++------- Lib/idlelib/idle_test/test_codecontext.py | 38 +++++++++++++++---- .../2018-05-29-07-14-37.bpo-33679.MgX_Ui.rst | 12 ++++++ 6 files changed, 79 insertions(+), 35 deletions(-) create mode 100644 Misc/NEWS.d/next/IDLE/2018-05-29-07-14-37.bpo-33679.MgX_Ui.rst diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py index b061f3b2fe8eb9..78edf12263a681 100644 --- a/Lib/idlelib/codecontext.py +++ b/Lib/idlelib/codecontext.py @@ -20,7 +20,7 @@ BLOCKOPENERS = {"class", "def", "elif", "else", "except", "finally", "for", "if", "try", "while", "with", "async"} UPDATEINTERVAL = 100 # millisec -FONTUPDATEINTERVAL = 1000 # millisec +CONFIGUPDATEINTERVAL = 1000 # millisec def get_spaces_firstword(codeline, c=re.compile(r"^(\s*)(\w*)")): @@ -45,9 +45,6 @@ def get_line_info(codeline): class CodeContext: "Display block context above the edit window." - bgcolor = "LightGray" - fgcolor = "Black" - def __init__(self, editwin): """Initialize settings for context block. @@ -69,22 +66,20 @@ def __init__(self, editwin): self.editwin = editwin self.text = editwin.text self.textfont = self.text["font"] + self.contextcolors = CodeContext.colors self.label = None self.topvisible = 1 self.info = [(0, -1, "", False)] # Start two update cycles, one for context lines, one for font changes. self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) - self.t2 = self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) + self.t2 = self.text.after(CONFIGUPDATEINTERVAL, self.config_timer_event) @classmethod def reload(cls): "Load class variables from config." cls.context_depth = idleConf.GetOption("extensions", "CodeContext", "maxlines", type="int", default=15) -## cls.bgcolor = idleConf.GetOption("extensions", "CodeContext", -## "bgcolor", type="str", default="LightGray") -## cls.fgcolor = idleConf.GetOption("extensions", "CodeContext", -## "fgcolor", type="str", default="Black") + cls.colors = idleConf.GetHighlight(idleConf.CurrentTheme(), 'context') def __del__(self): "Cancel scheduled events." @@ -118,7 +113,8 @@ def toggle_code_context_event(self, event=None): self.label = tkinter.Label( self.editwin.top, text="", anchor=W, justify=LEFT, font=self.textfont, - bg=self.bgcolor, fg=self.fgcolor, + bg=self.contextcolors['background'], + fg=self.contextcolors['foreground'], width=1, # Don't request more than we get. padx=padx, border=border, relief=SUNKEN) # Pack the label widget before and above the text_frame widget, @@ -202,13 +198,17 @@ def timer_event(self): self.update_code_context() self.t1 = self.text.after(UPDATEINTERVAL, self.timer_event) - def font_timer_event(self): - "Event on editor text widget triggered every FONTUPDATEINTERVAL ms." + def config_timer_event(self): + "Event on editor text widget triggered every CONFIGUPDATEINTERVAL ms." newtextfont = self.text["font"] - if self.label and newtextfont != self.textfont: + if (self.label and (newtextfont != self.textfont or + CodeContext.colors != self.contextcolors)): self.textfont = newtextfont + self.contextcolors = CodeContext.colors self.label["font"] = self.textfont - self.t2 = self.text.after(FONTUPDATEINTERVAL, self.font_timer_event) + self.label['background'] = self.contextcolors['background'] + self.label['foreground'] = self.contextcolors['foreground'] + self.t2 = self.text.after(CONFIGUPDATEINTERVAL, self.config_timer_event) CodeContext.reload() diff --git a/Lib/idlelib/config-highlight.def b/Lib/idlelib/config-highlight.def index 4146e28c4eda1f..aaa2b57a7f6d85 100644 --- a/Lib/idlelib/config-highlight.def +++ b/Lib/idlelib/config-highlight.def @@ -31,6 +31,8 @@ stderr-foreground= red stderr-background= #ffffff console-foreground= #770000 console-background= #ffffff +context-foreground= #000000 +context-background= lightgray [IDLE New] normal-foreground= #000000 @@ -62,6 +64,8 @@ stderr-foreground= red stderr-background= #ffffff console-foreground= #770000 console-background= #ffffff +context-foreground= #000000 +context-background= lightgray [IDLE Dark] comment-foreground = #dd0000 @@ -91,3 +95,5 @@ stdout-background = #002240 hit-foreground = #002240 comment-background = #002240 break-foreground = #FFFFFF +context-foreground= #ffffff +context-background= #454545 diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index c3e57bc692d801..94b20832091691 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -360,6 +360,8 @@ def GetThemeDict(self, type, themeName): 'stderr-background':'#ffffff', 'console-foreground':'#000000', 'console-background':'#ffffff', + 'context-foreground':'#000000', + 'context-background':'#ffffff', } for element in theme: if not cfgParser.has_option(themeName, element): diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 28ad4586394137..7df69d5c4d64f8 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -799,19 +799,20 @@ def create_page_highlight(self): """ self.theme_elements = { 'Normal Text': ('normal', '00'), - 'Python Keywords': ('keyword', '01'), - 'Python Definitions': ('definition', '02'), - 'Python Builtins': ('builtin', '03'), - 'Python Comments': ('comment', '04'), - 'Python Strings': ('string', '05'), - 'Selected Text': ('hilite', '06'), - 'Found Text': ('hit', '07'), - 'Cursor': ('cursor', '08'), - 'Editor Breakpoint': ('break', '09'), - 'Shell Normal Text': ('console', '10'), - 'Shell Error Text': ('error', '11'), - 'Shell Stdout Text': ('stdout', '12'), - 'Shell Stderr Text': ('stderr', '13'), + 'Code Context': ('context', '01'), + 'Python Keywords': ('keyword', '02'), + 'Python Definitions': ('definition', '03'), + 'Python Builtins': ('builtin', '04'), + 'Python Comments': ('comment', '05'), + 'Python Strings': ('string', '06'), + 'Selected Text': ('hilite', '07'), + 'Found Text': ('hit', '08'), + 'Cursor': ('cursor', '09'), + 'Editor Breakpoint': ('break', '10'), + 'Shell Normal Text': ('console', '11'), + 'Shell Error Text': ('error', '12'), + 'Shell Stdout Text': ('stdout', '13'), + 'Shell Stderr Text': ('stderr', '14'), } self.builtin_name = tracers.add( StringVar(self), self.var_changed_builtin_name) @@ -842,6 +843,7 @@ def create_page_highlight(self): ('\n', 'normal'), ('#you can click here', 'comment'), ('\n', 'normal'), ('#to choose items', 'comment'), ('\n', 'normal'), + ('code context section', 'context'), ('\n\n', 'normal'), ('def', 'keyword'), (' ', 'normal'), ('func', 'definition'), ('(param):\n ', 'normal'), ('"""string"""', 'string'), ('\n var0 = ', 'normal'), diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py index 4c775eee6b5fd1..d446090b0820c1 100644 --- a/Lib/idlelib/idle_test/test_codecontext.py +++ b/Lib/idlelib/idle_test/test_codecontext.py @@ -110,6 +110,8 @@ def test_del(self): def test_reload(self): codecontext.CodeContext.reload() + self.assertEqual(self.cc.colors, {'background': 'lightgray', + 'foreground': '#000000'}) self.assertEqual(self.cc.context_depth, 15) def test_toggle_code_context_event(self): @@ -125,8 +127,8 @@ def test_toggle_code_context_event(self): eq(toggle(), 'break') self.assertIsNotNone(cc.label) eq(cc.label['font'], cc.textfont) - eq(cc.label['fg'], cc.fgcolor) - eq(cc.label['bg'], cc.bgcolor) + eq(cc.label['fg'], cc.colors['foreground']) + eq(cc.label['bg'], cc.colors['background']) eq(cc.label['text'], '') # Toggle off. @@ -275,11 +277,13 @@ def test_timer_event(self, mock_update): self.cc.timer_event() mock_update.assert_called() - def test_font_timer_event(self): + def test_config_timer_event(self): eq = self.assertEqual cc = self.cc save_font = cc.text['font'] + save_colors = codecontext.CodeContext.colors test_font = 'FakeFont' + test_colors = {'background': '#222222', 'foreground': '#ffff00'} # Ensure code context is not active. if cc.label: @@ -287,24 +291,42 @@ def test_font_timer_event(self): # Nothing updates on inactive code context. cc.text['font'] = test_font - cc.font_timer_event() + codecontext.CodeContext.colors = test_colors + cc.config_timer_event() eq(cc.textfont, save_font) + eq(cc.contextcolors, save_colors) - # Activate code context, but no change to font. + # Activate code context, but no change to font or color. cc.toggle_code_context_event() cc.text['font'] = save_font - cc.font_timer_event() + codecontext.CodeContext.colors = save_colors + cc.config_timer_event() eq(cc.textfont, save_font) + eq(cc.contextcolors, save_colors) eq(cc.label['font'], save_font) + eq(cc.label['background'], save_colors['background']) + eq(cc.label['foreground'], save_colors['foreground']) # Active code context, change font. cc.text['font'] = test_font - cc.font_timer_event() + cc.config_timer_event() eq(cc.textfont, test_font) + eq(cc.contextcolors, save_colors) eq(cc.label['font'], test_font) + eq(cc.label['background'], save_colors['background']) + eq(cc.label['foreground'], save_colors['foreground']) + # Active code context, change color. cc.text['font'] = save_font - cc.font_timer_event() + codecontext.CodeContext.colors = test_colors + cc.config_timer_event() + eq(cc.textfont, save_font) + eq(cc.contextcolors, test_colors) + eq(cc.label['font'], save_font) + eq(cc.label['background'], test_colors['background']) + eq(cc.label['foreground'], test_colors['foreground']) + codecontext.CodeContext.colors = save_colors + cc.config_timer_event() class HelperFunctionText(unittest.TestCase): diff --git a/Misc/NEWS.d/next/IDLE/2018-05-29-07-14-37.bpo-33679.MgX_Ui.rst b/Misc/NEWS.d/next/IDLE/2018-05-29-07-14-37.bpo-33679.MgX_Ui.rst new file mode 100644 index 00000000000000..43d78b023f66af --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2018-05-29-07-14-37.bpo-33679.MgX_Ui.rst @@ -0,0 +1,12 @@ +IDLE: Re-enable color configuration for Code Context. +The difference from before is that the settings are now on the +Highlights tab instead of the Extensions tab and only change one theme +at a time instead of all themes. The default for light themes is black +on light gray, as before. The default for the IDLE Dark theme is white +on dark gray, which better fits the dark theme. + +When one starts IDLE from a console and loads a custom theme without +definitions for 'context', one will see a warning message on the console. +To stop the warning, go to Options => Configure IDLE => Highlights, +select the custom theme if not selected already, select 'Code Context', +and select foreground and background colors.