Fixed bug with margin cursor in StyledTextCtrl on Windows
authorLaurent Bessard
Mon, 06 May 2013 10:28:47 +0200
changeset 1091 5f612651d227
parent 1090 f4d08cea7774
child 1092 e91f2c8d6f51
Fixed bug with margin cursor in StyledTextCtrl on Windows
Beremiz.py
c_ext/CFileEditor.py
controls/CustomStyledTextCtrl.py
editors/TextViewer.py
py_ext/PythonEditor.py
--- a/Beremiz.py	Fri May 03 11:10:15 2013 +0200
+++ b/Beremiz.py	Mon May 06 10:28:47 2013 +0200
@@ -147,6 +147,7 @@
 from util.MiniTextControler import MiniTextControler
 from util.ProcessLogger import ProcessLogger
 from controls.LogViewer import LogViewer
+from controls.CustomStyledTextCtrl import CustomStyledTextCtrl
 
 from PLCControler import LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY, ITEM_PROJECT, ITEM_RESOURCE
 from ProjectController import ProjectController, MATIEC_ERROR_MODEL, ITEM_CONFNODE
@@ -255,18 +256,18 @@
                 if style != self.black_white:
                     self.output.StartStyling(self.output.GetLength(), 0xff)
                 
-                # Temporary deactivate read only mode on StyledTextCtrl for adding text
-                # It seems that text modifications, even programmatically, are disabled
-                # in StyledTextCtrl when read only is active 
+                # Temporary deactivate read only mode on StyledTextCtrl for
+                # adding text. It seems that text modifications, even 
+                # programmatically, are disabled in StyledTextCtrl when read
+                # only is active 
                 self.output.SetReadOnly(False)
-                self.output.AddText(s)
+                self.output.AppendText(s)
                 self.output.SetReadOnly(True)
                 
                 if style != self.black_white:
                     self.output.SetStyling(len(s), style)
             self.stack = []
             self.lock.release()
-            self.output.ScrollToLine(self.output.GetLineCount())
             self.output.Thaw()
             self.LastRefreshTime = gettime()
             try:
@@ -289,9 +290,9 @@
         wx.GetApp().Yield()
 
     def flush(self):
-        # Temporary deactivate read only mode on StyledTextCtrl for clearing text
-        # It seems that text modifications, even programmatically, are disabled
-        # in StyledTextCtrl when read only is active 
+        # Temporary deactivate read only mode on StyledTextCtrl for clearing
+        # text. It seems that text modifications, even programmatically, are
+        # disabled in StyledTextCtrl when read only is active 
         self.output.SetReadOnly(False)
         self.output.SetText("")
         self.output.SetReadOnly(True)
@@ -412,7 +413,7 @@
         
         self.SetAcceleratorTable(wx.AcceleratorTable(accels))
         
-        self.LogConsole = wx.stc.StyledTextCtrl(id=ID_BEREMIZLOGCONSOLE,
+        self.LogConsole = CustomStyledTextCtrl(id=ID_BEREMIZLOGCONSOLE,
                   name='LogConsole', parent=self.BottomNoteBook, pos=wx.Point(0, 0),
                   size=wx.Size(0, 0))
         self.LogConsole.Bind(wx.EVT_SET_FOCUS, self.OnLogConsoleFocusChanged)
--- a/c_ext/CFileEditor.py	Fri May 03 11:10:15 2013 +0200
+++ b/c_ext/CFileEditor.py	Mon May 06 10:28:47 2013 +0200
@@ -8,7 +8,7 @@
 from controls import CustomGrid, CustomTable
 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor, SCROLLBAR_UNIT
 from util.BitmapLibrary import GetBitmap
-from editors.TextViewer import GetCursorPos, faces
+from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos
 
 def AppendMenu(parent, help, id, kind, text):
     if wx.VERSION >= (2, 6, 0):
@@ -30,12 +30,12 @@
     "typedef", "typeid", "typename", "union", "unsigned", "using", "virtual", 
     "void", "volatile", "wchar_t", "while"]
 
-class CppEditor(stc.StyledTextCtrl):
+class CppEditor(CustomStyledTextCtrl):
 
     fold_symbols = 3
     
     def __init__(self, parent, name, window, controler):
-        stc.StyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
+        CustomStyledTextCtrl.__init__(self, parent, ID_CPPEDITOR, wx.DefaultPosition, 
                  wx.Size(-1, 300), 0)
 
         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/controls/CustomStyledTextCtrl.py	Mon May 06 10:28:47 2013 +0200
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import wx
+import wx.stc
+
+if wx.Platform == '__WXMSW__':
+    faces = { 'times': 'Times New Roman',
+              'mono' : 'Courier New',
+              'helv' : 'Arial',
+              'other': 'Comic Sans MS',
+              'size' : 10,
+             }
+else:
+    faces = { 'times': 'Times',
+              'mono' : 'Courier',
+              'helv' : 'Helvetica',
+              'other': 'new century schoolbook',
+              'size' : 12,
+             }
+
+def GetCursorPos(old, new):
+    if old == "":
+        return 0
+    old_length = len(old)
+    new_length = len(new)
+    common_length = min(old_length, new_length)
+    i = 0
+    for i in xrange(common_length):
+        if old[i] != new[i]:
+            break
+    if old_length < new_length:
+        if common_length > 0 and old[i] != new[i]:
+            return i + new_length - old_length
+        else:
+            return i + new_length - old_length + 1
+    elif old_length > new_length or i < min(old_length, new_length) - 1:
+        if common_length > 0 and old[i] != new[i]:
+            return i
+        else:
+            return i + 1
+    else:
+        return None
+
+class CustomStyledTextCtrl(wx.stc.StyledTextCtrl):
+    
+    def __init__(self, *args, **kwargs):
+        wx.stc.StyledTextCtrl(self, *args, **kwargs)
+        
+        self.Bind(wx.EVT_MOTION, self.OnMotion)
+        
+    def OnMotion(self, event):
+        if wx.Platform == '__WXMSW__':
+            if not event.Dragging():
+                x, y = event.GetPosition()
+                margin_width = reduce(
+                        lambda x, y: x + y,
+                        [self.LogConsole.GetMarginWidth(i)
+                         for i in xrange(3)],
+                        0)
+                if x <= margin_width:
+                    self.LogConsole.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
+                else:
+                    self.LogConsole.SetCursor(wx.StockCursor(wx.CURSOR_IBEAM))
+        else:
+            event.Skip()
+
+    def AppendText(self, text):
+        last_position = self.GetLength()
+        current_selection = self.GetSelection()
+        self.GotoPos(last_position)
+        self.AddText(text)
+        if current_selection[0] != last_position:
+            self.SetSelection(*current_selection)
+        else:
+            self.ScrollToLine(self.GetLineCount())
--- a/editors/TextViewer.py	Fri May 03 11:10:15 2013 +0200
+++ b/editors/TextViewer.py	Mon May 06 10:28:47 2013 +0200
@@ -31,6 +31,7 @@
 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
 from plcopen.structures import ST_BLOCK_START_KEYWORDS, ST_BLOCK_END_KEYWORDS, IEC_BLOCK_START_KEYWORDS, IEC_BLOCK_END_KEYWORDS, LOCATIONDATATYPES
 from EditorPanel import EditorPanel
+from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos
 
 #-------------------------------------------------------------------------------
 #                         Textual programs Viewer class
@@ -52,20 +53,6 @@
 [ID_TEXTVIEWER, ID_TEXTVIEWERTEXTCTRL,
 ] = [wx.NewId() for _init_ctrls in range(2)]
 
-if wx.Platform == '__WXMSW__':
-    faces = { 'times': 'Times New Roman',
-              'mono' : 'Courier New',
-              'helv' : 'Arial',
-              'other': 'Comic Sans MS',
-              'size' : 10,
-             }
-else:
-    faces = { 'times': 'Times',
-              'mono' : 'Courier',
-              'helv' : 'Helvetica',
-              'other': 'new century schoolbook',
-              'size' : 12,
-             }
 re_texts = {}
 re_texts["letter"] = "[A-Za-z]"
 re_texts["digit"] = "[0-9]"
@@ -79,29 +66,6 @@
     SEARCH_RESULT_HIGHLIGHT: STC_PLC_SEARCH_RESULT,
 }
 
-def GetCursorPos(old, new):
-    if old == "":
-        return 0
-    old_length = len(old)
-    new_length = len(new)
-    common_length = min(old_length, new_length)
-    i = 0
-    for i in xrange(common_length):
-        if old[i] != new[i]:
-            break
-    if old_length < new_length:
-        if common_length > 0 and old[i] != new[i]:
-            return i + new_length - old_length
-        else:
-            return i + new_length - old_length + 1
-    elif old_length > new_length or i < min(old_length, new_length) - 1:
-        if common_length > 0 and old[i] != new[i]:
-            return i
-        else:
-            return i + 1
-    else:
-        return None
-
 def LineStartswith(line, symbols):
     return reduce(lambda x, y: x or y, map(lambda x: line.startswith(x), symbols), False)
 
@@ -117,7 +81,7 @@
                 event(self, function)
     
     def _init_Editor(self, prnt):
-        self.Editor = wx.stc.StyledTextCtrl(id=ID_TEXTVIEWERTEXTCTRL, 
+        self.Editor = CustomStyledTextCtrl(id=ID_TEXTVIEWERTEXTCTRL, 
                 parent=prnt, name="TextViewer", size=wx.Size(0, 0), style=0)
         self.Editor.ParentWindow = self
         
--- a/py_ext/PythonEditor.py	Fri May 03 11:10:15 2013 +0200
+++ b/py_ext/PythonEditor.py	Mon May 06 10:28:47 2013 +0200
@@ -8,7 +8,7 @@
 from plcopen.plcopen import TestTextElement
 from graphics.GraphicCommons import ERROR_HIGHLIGHT, SEARCH_RESULT_HIGHLIGHT, REFRESH_HIGHLIGHT_PERIOD
 from editors.ConfTreeNodeEditor import ConfTreeNodeEditor
-from editors.TextViewer import GetCursorPos, faces
+from controls.CustomStyledTextCtrl import CustomStyledTextCtrl, faces, GetCursorPos
 
 [STC_PYTHON_ERROR, STC_PYTHON_SEARCH_RESULT] = range(15, 17)
 
@@ -27,7 +27,7 @@
         (_("Python code"), "_create_PythonCodeEditor")]
     
     def _create_PythonCodeEditor(self, prnt):
-        self.PythonCodeEditor = stc.StyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
+        self.PythonCodeEditor = CustomStyledTextCtrl(id=ID_PYTHONEDITOR, parent=prnt,
                  name="TextViewer", pos=wx.DefaultPosition, 
                  size=wx.DefaultSize, style=0)
         self.PythonCodeEditor.ParentWindow = self