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 <cheryl.sabella@gmail.com>
diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py
index b061f3b..78edf12 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 @@
 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 @@
         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 @@
             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 @@
             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()