Repository: psychopy/psychopy

Issue:
Borders being drawn around coder notebooks
Borders are being drawn around coder notebooks still. However, it the borders go away when moving tabs around. I think the problem here is that we are applying the theme after creating the tabs, so they don't update to fill the space until you force the notebook to do a full redraw.

![Capture](https://user-images.githubusercontent.com/5150568/87711622-86822a80-c775-11ea-9780-1c4ba61df4cd.PNG)

Changing theme after closing one frame causes a crash
I think this is because the IconCache tries to set the icon of buttons wich no longer exist


Discussion:

Resolving patch:
diff --git a/psychopy/app/coder/coder.py b/psychopy/app/coder/coder.py
--- a/psychopy/app/coder/coder.py
+++ b/psychopy/app/coder/coder.py
@@ -997,6 +997,9 @@ def DoFindNext(self, findData, findDlg=None):
                 start = 0
                 loc = textstring.find(findstring, start)
 
+        # Adjust for offset
+        loc += 2
+
         # was it still not found?
         if loc == -1:
             dlg = dialogs.MessageDialog(self, message=_translate(
@@ -1013,8 +1016,8 @@ def DoFindNext(self, findData, findDlg=None):
             if loc == -1:
                 wx.CallAfter(findDlg.SetFocus)
                 return
-            else:
-                findDlg.Close()
+            # else:
+            #     findDlg.Close()
 
 
 class CoderFrame(wx.Frame, ThemeMixin):
@@ -1149,7 +1152,7 @@ def __init__(self, parent, ID, title, files=(), app=None):
         self.Bind(wx.EVT_DROP_FILES, self.filesDropped)
         self.Bind(wx.EVT_FIND, self.OnFindNext)
         self.Bind(wx.EVT_FIND_NEXT, self.OnFindNext)
-        self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
+        #self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
         self.Bind(wx.EVT_END_PROCESS, self.onProcessEnded)
 
         # take files from arguments and append the previously opened files
@@ -1160,7 +1163,7 @@ def __init__(self, parent, ID, title, files=(), app=None):
                 self.setCurrentDoc(filename, keepHidden=True)
 
         # Create shelf notebook
-        self.shelf = aui.AuiNotebook(self.pnlMain, wx.ID_ANY, size=wx.Size(600, 600), style=wx.BORDER_NONE)
+        self.shelf = aui.AuiNotebook(self.pnlMain, wx.ID_ANY, size=wx.Size(600, 600), agwStyle=aui.AUI_NB_CLOSE_ON_ALL_TABS)
         #self.shelf.SetArtProvider(PsychopyTabArt())
         # Create shell
         self._useShell = None
@@ -1184,6 +1187,9 @@ def __init__(self, parent, ID, title, files=(), app=None):
             # Add shell to output pane
             self.shell.SetName("PythonShell")
             self.shelf.AddPage(self.shell, _translate('Shell'))
+            # Hide close button
+            for i in range(self.shelf.GetPageCount()):
+                self.shelf.SetCloseButton(i, False)
         # Add shelf panel
         self.paneManager.AddPane(self.shelf,
                                  aui.AuiPaneInfo().
@@ -1923,12 +1929,12 @@ def OnFindNext(self, event):
             self.OnFindOpen(event)
             return
         self.currentDoc.DoFindNext(self.findData, self.findDlg)
-        if self.findDlg is not None:
-            self.OnFindClose(None)
+        # if self.findDlg is not None:
+        #     self.OnFindClose(None)
 
-    def OnFindClose(self, event):
-        self.findDlg.Destroy()
-        self.findDlg = None
+    # def OnFindClose(self, event):
+    #     self.findDlg.Destroy()
+    #     self.findDlg = None
 
     def OnFileHistory(self, evt=None):
         # get the file based on the menu ID
@@ -2229,8 +2235,9 @@ def fileSave(self, event=None, filename=None, doc=None):
         If the ``filename`` is ``None`` then the ``doc``'s current filename
         is used or a dlg is presented to get a new filename.
         """
-        if self.currentDoc.AutoCompActive():
-            self.currentDoc.AutoCompCancel()
+        if hasattr(self.currentDoc, 'AutoCompActive'):
+            if self.currentDoc.AutoCompActive():
+                self.currentDoc.AutoCompCancel()
 
         if doc is None:
             doc = self.currentDoc
diff --git a/psychopy/app/coder/fileBrowser.py b/psychopy/app/coder/fileBrowser.py
--- a/psychopy/app/coder/fileBrowser.py
+++ b/psychopy/app/coder/fileBrowser.py
@@ -183,6 +183,9 @@ def _applyAppTheme(self, target=None):
         self.toolBar.SetBackgroundColour(cs['tab_bg'])
         self.toolBar.SetForegroundColour(cs['text'])
         self.makeFileImgIcons()
+        ThemeMixin._applyAppTheme(self.coder, self.txtAddr)
+        self.lblDir.SetForegroundColour(ThemeMixin.codeColors['base']['fg'])
+
 
     def makeFileImgIcons(self):
 
diff --git a/psychopy/app/themes/_themes.py b/psychopy/app/themes/_themes.py
--- a/psychopy/app/themes/_themes.py
+++ b/psychopy/app/themes/_themes.py
@@ -255,6 +255,11 @@ def applyToRichText(target):
                     ln) + 1  # +1 as \n is not included in character count
             target.SetStyle(0, i, _style)
 
+        def applyToTextCtrl(target):
+            base = ThemeMixin.codeColors['base']
+            target.SetForegroundColour(base['fg'])
+            target.SetBackgroundColour(base['bg'])
+
         # Define dict linking object types to subfunctions
         handlers = {
             wx.Frame: applyToFrame,
@@ -264,7 +269,8 @@ def applyToRichText(target):
             wx.richtext.RichTextCtrl: applyToRichText,
             wx.py.shell.Shell: applyToCodeEditor,
             wx.ToolBar: applyToToolbar,
-            wx.StatusBar: applyToStatusBar
+            wx.StatusBar: applyToStatusBar,
+            wx.TextCtrl: applyToTextCtrl
         }
 
         # If no target supplied, default to using self
@@ -335,10 +341,12 @@ def applyToRichText(target):
                 # except AttributeError:
                 #     pass
 
-        if hasattr(self, 'Refresh'):
-            self.Refresh()
-        if hasattr(self, 'Update'):
-            self.Update()
+        if hasattr(target, 'Refresh'):
+            target.Refresh()
+        if hasattr(target, 'Update'):
+            target.Update()
+        if hasattr(target, '_mgr'):
+            target._mgr.Update()
 
     @property
     def lexkw(self):
@@ -835,17 +843,17 @@ def getComponentBitmap(self, name, size=None):
     def setTheme(self, theme):
         if theme.icons != IconCache._lastIcons:
             for thisBtn in IconCache._buttons:
-                newBmp = self.getBitmap(name=thisBtn['name'],
-                                        size=thisBtn['size'],
-                                        theme=theme.icons,
-                                        emblem=thisBtn['emblem'])
-
-                thisBtn['btn'].SetBitmap(newBmp)
-                thisBtn['btn'].SetBitmapCurrent(newBmp)
-                thisBtn['btn'].SetBitmapPressed(newBmp)
-                thisBtn['btn'].SetBitmapFocus(newBmp)
-                thisBtn['btn'].SetBitmapDisabled(newBmp)
-                thisBtn['btn'].SetBitmapPosition(wx.TOP)
+                if thisBtn['btn']:  # Check that button hasn't been deleted
+                    newBmp = self.getBitmap(name=thisBtn['name'],
+                                            size=thisBtn['size'],
+                                            theme=theme.icons,
+                                            emblem=thisBtn['emblem'])
+                    thisBtn['btn'].SetBitmap(newBmp)
+                    thisBtn['btn'].SetBitmapCurrent(newBmp)
+                    thisBtn['btn'].SetBitmapPressed(newBmp)
+                    thisBtn['btn'].SetBitmapFocus(newBmp)
+                    thisBtn['btn'].SetBitmapDisabled(newBmp)
+                    thisBtn['btn'].SetBitmapPosition(wx.TOP)
         IconCache._lastIcons = theme.icons
         if theme.appColors['frame_bg'] != IconCache._lastBGColor:
             for thisBtn in IconCache._buttons:


Test patch: