Viewer.py
changeset 586 9aa96a36cf33
parent 585 bd8c7a033b17
child 599 4bb7b132e15d
--- a/Viewer.py	Mon Nov 07 10:55:17 2011 +0100
+++ b/Viewer.py	Tue Nov 08 21:59:22 2011 +0100
@@ -37,6 +37,7 @@
 
 from dialogs import *
 from graphics import *
+from controls import EditorPanel
 
 SCROLLBAR_UNIT = 10
 WINDOW_BORDER = 10
@@ -264,7 +265,7 @@
                         self.ParentWindow.RefreshBuffer()
                         self.ParentWindow.RefreshScrollBars()
                         self.ParentWindow.RefreshVisibleElements()
-                        self.ParentWindow.ParentWindow.RefreshVariablePanel(tagname)
+                        self.ParentWindow.RefreshVariablePanel()
                         self.ParentWindow.Refresh(False)
             elif values[1] == "location":
                 if len(values) > 2 and pou_type == "program":
@@ -282,7 +283,7 @@
                             var_type = LOCATIONDATATYPES.get(values[0][2], ["BOOL"])[0]
                         if not var_name.upper() in [name.upper() for name in self.ParentWindow.Controler.GetEditedElementVariables(tagname, self.ParentWindow.Debug)]:
                             self.ParentWindow.Controler.AddEditedElementPouVar(tagname, var_type, var_name, values[0], values[4])
-                        self.ParentWindow.ParentWindow.RefreshVariablePanel(tagname)
+                        self.ParentWindow.RefreshVariablePanel()
                         self.ParentWindow.AddVariableBlock(x, y, scaling, var_class, var_name, var_type)
             elif values[3] == tagname:
                 if values[1] == "Output":
@@ -340,7 +341,7 @@
 manipulating graphic elements
 """
 
-class Viewer(wx.ScrolledWindow, DebugViewer):
+class Viewer(EditorPanel, DebugViewer):
     
     if wx.VERSION < (2, 6, 0):
         def Bind(self, event, function, id = None):
@@ -446,16 +447,24 @@
         self._init_coll_AlignmentMenu_Items(self.AlignmentMenu)
         self._init_coll_ContextualMenu_Items(self.ContextualMenu)
     
+    def _init_Editor(self, prnt):
+        self.Editor = wx.ScrolledWindow(prnt, name="Viewer", 
+            pos=wx.Point(0, 0), size=wx.Size(0, 0), 
+            style=wx.HSCROLL | wx.VSCROLL | wx.ALWAYS_SHOW_SB)
+    
     # Create a new Viewer
     def __init__(self, parent, tagname, window, controler, debug = False, instancepath = ""):
-        wx.ScrolledWindow.__init__(self, parent, pos=wx.Point(0, 0), size=wx.Size(0, 0), 
-            style=wx.HSCROLL | wx.VSCROLL | wx.ALWAYS_SHOW_SB)
+        self.VARIABLE_PANEL_TYPE = controler.GetPouType(tagname.split("::")[1])
+        
+        EditorPanel.__init__(self, parent, tagname, window, controler)
         DebugViewer.__init__(self, controler, debug)
+        
         self._init_menus()
+        
         # Adding a rubberband to Viewer
-        self.rubberBand = RubberBand(drawingSurface=self)
-        self.SetBackgroundColour(wx.Colour(255,255,255))
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+        self.rubberBand = RubberBand(viewer=self)
+        self.Editor.SetBackgroundColour(wx.Colour(255,255,255))
+        self.Editor.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.ResetView()
         self.Scaling = None
         self.DrawGrid = True
@@ -482,16 +491,13 @@
         self.SavedMode = False
         self.CurrentLanguage = "FBD"
         
-        self.ParentWindow = window
-        self.Controler = controler
-        
         if not self.Debug:
-            self.SetDropTarget(ViewerDropTarget(self))
+            self.Editor.SetDropTarget(ViewerDropTarget(self))
         
         self.NewDataRefreshRect = None
         self.NewDataRefreshRect_lock = Lock()
         
-        dc = wx.ClientDC(self)
+        dc = wx.ClientDC(self.Editor)
         font = wx.Font(faces["size"], wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["mono"])
         dc.SetFont(font)
         width, height = dc.GetTextExtent("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
@@ -504,7 +510,8 @@
         self.MiniTextDC = wx.MemoryDC()
         self.MiniTextDC.SetFont(wx.Font(faces["size"] * 0.75, wx.SWISS, wx.NORMAL, wx.NORMAL, faceName = faces["helv"]))
         
-        self.SetScale(len(ZOOM_FACTORS) / 2)
+        self.CurrentScale = None
+        self.SetScale(len(ZOOM_FACTORS) / 2, False)
         
         self.RefreshHighlightsTimer = wx.Timer(self, -1)
         self.Bind(wx.EVT_TIMER, self.OnRefreshHighlightsTimer, self.RefreshHighlightsTimer)
@@ -512,21 +519,21 @@
         self.ResetView()
         
         # Link Viewer event to corresponding methods
-        self.Bind(wx.EVT_PAINT, self.OnPaint)
-        self.Bind(wx.EVT_LEFT_DOWN, self.OnViewerLeftDown)
-        self.Bind(wx.EVT_LEFT_UP, self.OnViewerLeftUp)
-        self.Bind(wx.EVT_LEFT_DCLICK, self.OnViewerLeftDClick)
-        self.Bind(wx.EVT_RIGHT_DOWN, self.OnViewerRightDown)
-        self.Bind(wx.EVT_RIGHT_UP, self.OnViewerRightUp)
-        self.Bind(wx.EVT_MIDDLE_DOWN, self.OnViewerMiddleDown)
-        self.Bind(wx.EVT_MIDDLE_UP, self.OnViewerMiddleUp)
-        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveViewer)
-        self.Bind(wx.EVT_MOTION, self.OnViewerMotion)
-        self.Bind(wx.EVT_CHAR, self.OnChar)
-        self.Bind(wx.EVT_SCROLLWIN, self.OnScrollWindow)
-        self.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.OnScrollStop)
-        self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheelWindow)
-        self.Bind(wx.EVT_SIZE, self.OnMoveWindow)
+        self.Editor.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Editor.Bind(wx.EVT_LEFT_DOWN, self.OnViewerLeftDown)
+        self.Editor.Bind(wx.EVT_LEFT_UP, self.OnViewerLeftUp)
+        self.Editor.Bind(wx.EVT_LEFT_DCLICK, self.OnViewerLeftDClick)
+        self.Editor.Bind(wx.EVT_RIGHT_DOWN, self.OnViewerRightDown)
+        self.Editor.Bind(wx.EVT_RIGHT_UP, self.OnViewerRightUp)
+        self.Editor.Bind(wx.EVT_MIDDLE_DOWN, self.OnViewerMiddleDown)
+        self.Editor.Bind(wx.EVT_MIDDLE_UP, self.OnViewerMiddleUp)
+        self.Editor.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeaveViewer)
+        self.Editor.Bind(wx.EVT_MOTION, self.OnViewerMotion)
+        self.Editor.Bind(wx.EVT_CHAR, self.OnChar)
+        self.Editor.Bind(wx.EVT_SCROLLWIN, self.OnScrollWindow)
+        self.Editor.Bind(wx.EVT_SCROLLWIN_THUMBRELEASE, self.OnScrollStop)
+        self.Editor.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheelWindow)
+        self.Editor.Bind(wx.EVT_SIZE, self.OnMoveWindow)
     
     def __del__(self):
         DebugViewer.__del__(self)
@@ -537,32 +544,32 @@
             global CURSORS
             if self.CurrentCursor != cursor:
                 self.CurrentCursor = cursor
-                self.SetCursor(CURSORS[cursor])
+                self.Editor.SetCursor(CURSORS[cursor])
     
     def GetScrolledRect(self, rect):
-        rect.x, rect.y = self.CalcScrolledPosition(int(rect.x * self.ViewScale[0]), 
+        rect.x, rect.y = self.Editor.CalcScrolledPosition(int(rect.x * self.ViewScale[0]), 
                                                    int(rect.y * self.ViewScale[1]))
         rect.width = int(rect.width * self.ViewScale[0]) + 2
         rect.height = int(rect.height * self.ViewScale[1]) + 2
         return rect
     
+    def GetTitle(self):
+        if self.Debug:
+            if len(self.InstancePath) > 15:
+                return "..." + self.InstancePath[-12:]
+            return self.InstancePath
+        return EditorPanel.GetTitle(self)
+    
     def GetScaling(self):
         return self.Scaling
     
-    def SetTagName(self, tagname):
-        self.TagName = tagname
-        
-    def GetTagName(self):
-        return self.TagName
-    
     def GetInstancePath(self):
         return self.InstancePath
     
     def IsViewing(self, tagname):
         if self.Debug:
             return self.InstancePath == tagname
-        else:
-            return self.TagName == tagname
+        return EditorPanel.IsViewing(self, tagname)
     
     # Returns a new id
     def GetNewId(self):
@@ -575,28 +582,81 @@
         self.Flush()
         self.ResetView()
     
-    def SetScale(self, scale_number, refresh=True):
-        self.CurrentScale = max(0, min(scale_number, len(ZOOM_FACTORS) - 1))
-        self.ViewScale = (ZOOM_FACTORS[self.CurrentScale], ZOOM_FACTORS[self.CurrentScale])
-        self.RefreshScaling(refresh)
-
+    def SetScale(self, scale_number, refresh=True, mouse_event=None):
+        new_scale = max(0, min(scale_number, len(ZOOM_FACTORS) - 1))
+        if self.CurrentScale != new_scale:
+            if refresh:
+                dc = self.GetLogicalDC()
+            self.CurrentScale = new_scale
+            self.ViewScale = (ZOOM_FACTORS[self.CurrentScale], ZOOM_FACTORS[self.CurrentScale])
+            if refresh:
+                self.Editor.Freeze()
+                if mouse_event is None:
+                    client_size = self.Editor.GetClientSize()
+                    mouse_pos = wx.Point(client_size[0] / 2, client_size[1] / 2)
+                    mouse_event = wx.MouseEvent(wx.EVT_MOUSEWHEEL.typeId)
+                    mouse_event.m_x = mouse_pos.x
+                    mouse_event.m_y = mouse_pos.y
+                else:
+                    mouse_pos = mouse_event.GetPosition()
+                pos = mouse_event.GetLogicalPosition(dc)
+                xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
+                ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
+                scrollx = max(0, round(pos.x * self.ViewScale[0] - mouse_pos.x) / SCROLLBAR_UNIT)
+                scrolly = max(0, round(pos.y * self.ViewScale[1] - mouse_pos.y) / SCROLLBAR_UNIT)
+                if scrollx > xmax or scrolly > ymax:
+                    self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
+                    self.Scroll(scrollx, scrolly)
+                else:
+                    self.Scroll(scrollx, scrolly)
+                    self.RefreshScrollBars()
+                self.RefreshScaling(refresh)
+                self.Editor.Thaw()
+    
     def GetScale(self):
         return self.CurrentScale
 
     def GetLogicalDC(self, buffered=False):
         if buffered:
-            bitmap = wx.EmptyBitmap(*self.GetClientSize())
+            bitmap = wx.EmptyBitmap(*self.Editor.GetClientSize())
             dc = wx.MemoryDC(bitmap)
         else:
-            dc = wx.ClientDC(self)
+            dc = wx.ClientDC(self.Editor)
         dc.SetFont(self.GetFont())
         if wx.VERSION >= (2, 6, 0):
-            self.DoPrepareDC(dc)
+            self.Editor.DoPrepareDC(dc)
         else:
-            self.PrepareDC(dc)
+            self.Editor.PrepareDC(dc)
         dc.SetUserScale(self.ViewScale[0], self.ViewScale[1])
         return dc
-
+    
+    def RefreshRect(self, rect, eraseBackground=True):
+        self.Editor.RefreshRect(rect, eraseBackground)
+    
+    def Scroll(self, x, y):
+        self.Editor.Scroll(x, y)
+    
+    def GetScrollPos(self, orientation):
+        return self.Editor.GetScrollPos(orientation)
+    
+    def GetScrollRange(self, orientation):
+        return self.Editor.GetScrollRange(orientation)
+    
+    def GetScrollThumb(self, orientation):
+        return self.Editor.GetScrollThumb(orientation)
+    
+    def CalcUnscrolledPosition(self, x, y):
+        return self.Editor.CalcUnscrolledPosition(x, y)
+    
+    def GetViewStart(self):
+        return self.Editor.GetViewStart()
+    
+    def GetTextExtent(self, text):
+        return self.Editor.GetTextExtent(text)
+    
+    def GetFont(self):
+        return self.Editor.GetFont()
+    
     def GetMiniTextExtent(self, text):
         return self.MiniTextDC.GetTextExtent(text)
     
@@ -656,12 +716,12 @@
         return None
     
     def RefreshVisibleElements(self, xp = None, yp = None):
-        x, y = self.CalcUnscrolledPosition(0, 0)
+        x, y = self.Editor.CalcUnscrolledPosition(0, 0)
         if xp is not None:
-            x = xp * self.GetScrollPixelsPerUnit()[0]
+            x = xp * self.Editor.GetScrollPixelsPerUnit()[0]
         if yp is not None:
-            y = yp * self.GetScrollPixelsPerUnit()[1]
-        width, height = self.GetClientSize()
+            y = yp * self.Editor.GetScrollPixelsPerUnit()[1]
+        width, height = self.Editor.GetClientSize()
         screen = wx.Rect(int(x / self.ViewScale[0]), int(y / self.ViewScale[1]),
                          int(width / self.ViewScale[0]), int(height / self.ViewScale[1]))
         for comment in self.Comments.itervalues():
@@ -732,7 +792,7 @@
     def SetMode(self, mode):
         if self.Mode != mode or mode == MODE_SELECTION:    
             if self.Mode == MODE_MOTION:
-                wx.CallAfter(self.SetCursor, wx.NullCursor)
+                wx.CallAfter(self.Editor.SetCursor, wx.NullCursor)
             self.Mode = mode
             self.SavedMode = False
         else:
@@ -742,7 +802,7 @@
             self.SelectedElement.SetSelected(False)
             self.SelectedElement = None
         if self.Mode == MODE_MOTION:
-            wx.CallAfter(self.SetCursor, wx.StockCursor(wx.CURSOR_HAND))
+            wx.CallAfter(self.Editor.SetCursor, wx.StockCursor(wx.CURSOR_HAND))
             self.SavedMode = True
         
     # Return current drawing mode
@@ -755,7 +815,29 @@
         self.ParentWindow.RefreshTitle()
         self.ParentWindow.RefreshFileMenu()
         self.ParentWindow.RefreshEditMenu()
-
+    
+    def GetBufferState(self):
+        if not self.Debug:
+            return self.Controler.GetBufferState()
+        return False, False
+    
+    def Undo(self):
+        if not self.Debug:
+            self.Controler.LoadPrevious()
+            self.ParentWindow.CloseTabsWithoutModel()
+            self.ParentWindow.RefreshEditor()
+            
+    def Redo(self):
+        if not self.Debug:
+            self.Controler.LoadNext()
+            self.ParentWindow.CloseTabsWithoutModel()
+            self.ParentWindow.RefreshEditor()
+    
+    def HasNoModel(self):
+        if not self.Debug:
+            return self.Controler.GetEditedElement(self.TagName) is None
+        return False
+    
     # Refresh the current scaling
     def RefreshScaling(self, refresh=True):
         properties = self.Controler.GetProjectProperties(self.Debug)
@@ -767,7 +849,7 @@
                 height = max(2, int(scaling[1] * self.ViewScale[1]))
                 bitmap = wx.EmptyBitmap(width, height)
                 dc = wx.MemoryDC(bitmap)
-                dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+                dc.SetBackground(wx.Brush(self.Editor.GetBackgroundColour()))
                 dc.Clear()
                 dc.SetPen(MiterPen(wx.Colour(180, 180, 180)))
                 dc.DrawPoint(0, 0)
@@ -810,11 +892,10 @@
         else:
             DebugViewer.RefreshNewData(self)
         
-    def ResetBuffer(self):
-        pass
-
     # Refresh Viewer elements
-    def RefreshView(self, selection=None):
+    def RefreshView(self, variablepanel=True, selection=None):
+        EditorPanel.RefreshView(self, variablepanel)
+        
         self.Inhibit(True)
         self.current_id = 0
         # Start by reseting Viewer
@@ -890,7 +971,7 @@
     
     def RefreshScrollBars(self, width_incr=0, height_incr=0):
         xstart, ystart = self.GetViewStart()
-        window_size = self.GetClientSize()
+        window_size = self.Editor.GetClientSize()
         maxx, maxy = self.GetMaxSize()
         maxx = max(maxx + WINDOW_BORDER, (xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[0])
         maxy = max(maxy + WINDOW_BORDER, (ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[1])
@@ -900,7 +981,7 @@
             maxy = max(maxy, extent.y + extent.height)
         maxx = int(maxx * self.ViewScale[0])
         maxy = int(maxy * self.ViewScale[1])
-        self.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
+        self.Editor.SetScrollbars(SCROLLBAR_UNIT, SCROLLBAR_UNIT, 
             round(maxx / SCROLLBAR_UNIT) + width_incr, round(maxy / SCROLLBAR_UNIT) + height_incr, 
             xstart, ystart, True)
     
@@ -1119,7 +1200,7 @@
                 menu.Enable(new_id, True)
             else:
                 menu.Enable(new_id, False)
-            self.PopupMenu(menu)
+            self.Editor.PopupMenu(menu)
 
     def PopupBlockMenu(self, connector = None):
         if connector is not None and connector.IsCompatible("BOOL"):
@@ -1149,7 +1230,7 @@
                 self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS3, True)
             else:
                 self.ContextualMenu.Check(ID_VIEWERCONTEXTUALMENUITEMS0, True)
-        self.PopupMenu(self.ContextualMenu)
+        self.Editor.PopupMenu(self.ContextualMenu)
     
     def PopupWireMenu(self, delete=True):
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
@@ -1163,7 +1244,7 @@
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
-        self.PopupMenu(self.ContextualMenu)
+        self.Editor.PopupMenu(self.ContextualMenu)
     
     def PopupDivergenceMenu(self, connector):
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
@@ -1177,7 +1258,7 @@
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
-        self.PopupMenu(self.ContextualMenu)
+        self.Editor.PopupMenu(self.ContextualMenu)
     
     def PopupGroupMenu(self):
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
@@ -1191,7 +1272,7 @@
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, True)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, True)
-        self.PopupMenu(self.ContextualMenu)
+        self.Editor.PopupMenu(self.ContextualMenu)
     
     def PopupDefaultMenu(self, block = True):
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS0, False)
@@ -1205,7 +1286,7 @@
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS14, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS16, False)
         self.ContextualMenu.Enable(ID_VIEWERCONTEXTUALMENUITEMS17, block)
-        self.PopupMenu(self.ContextualMenu)
+        self.Editor.PopupMenu(self.ContextualMenu)
 
 #-------------------------------------------------------------------------------
 #                            Menu items functions
@@ -1319,7 +1400,7 @@
             dc = self.GetLogicalDC()
             pos = event.GetLogicalPosition(dc)
             if event.ShiftDown() and not event.ControlDown() and self.SelectedElement is not None:
-                element = self.FindElement(pos, True)
+                element = self.FindElement(event, True)
                 if element is not None:
                     if isinstance(self.SelectedElement, Graphic_Group):
                         self.SelectedElement.SetSelected(False)
@@ -1570,7 +1651,7 @@
         else:
             if not event.Dragging():
                 if self.Debug:
-                    tooltip_pos = self.ClientToScreen(event.GetPosition())
+                    tooltip_pos = self.Editor.ClientToScreen(event.GetPosition())
                     tooltip_pos.x += 10
                     tooltip_pos.y += 10
                 highlighted = self.FindElement(event) 
@@ -1613,7 +1694,7 @@
                             self.HighlightedElement.SetHighlighted(False)
                             self.HighlightedElement = None
                         data = wx.TextDataObject(str((iec_path, "debug")))
-                        dragSource = wx.DropSource(self)
+                        dragSource = wx.DropSource(self.Editor)
                         dragSource.SetData(data)
                         dragSource.DoDragDrop()
             self.UpdateScrollPos(event)
@@ -1635,7 +1716,7 @@
         if (event.Dragging() and self.SelectedElement is not None) or self.rubberBand.IsShown():
             position = event.GetPosition()
             move_window = wx.Point()
-            window_size = self.GetClientSize()
+            window_size = self.Editor.GetClientSize()
             xstart, ystart = self.GetViewStart()
             if position.x < SCROLL_ZONE and xstart > 0:
                 move_window.x = -1
@@ -1648,7 +1729,7 @@
             if move_window.x != 0 or move_window.y != 0:
                 self.RefreshVisibleElements(xp = xstart + move_window.x, yp = ystart + move_window.y)
                 self.Scroll(xstart + move_window.x, ystart + move_window.y)
-            self.RefreshScrollBars()
+                self.RefreshScrollBars(move_window.x, move_window.y)
 
 #-------------------------------------------------------------------------------
 #                          Keyboard event functions
@@ -1733,17 +1814,23 @@
             if self.IsBlock(self.SelectedElement) or self.IsComment(self.SelectedElement):
                 block = self.CopyBlock(self.SelectedElement, wx.Point(*self.SelectedElement.GetPosition()))
                 event = wx.MouseEvent()
-                event.m_x, event.m_y = self.ScreenToClient(wx.GetMousePosition())
+                event.m_x, event.m_y = self.Editor.ScreenToClient(wx.GetMousePosition())
                 dc = self.GetLogicalDC()
                 self.SelectedElement.OnLeftUp(event, dc, self.Scaling)
                 self.SelectedElement.SetSelected(False)
                 block.OnLeftDown(event, dc, self.Scaling)
                 self.SelectedElement = block
                 self.SelectedElement.SetSelected(True)
-                self.ParentWindow.RefreshVariablePanel(self.TagName)
+                self.RefreshVariablePanel()
                 self.RefreshVisibleElements()
             else:
                 event.Skip()
+        elif keycode == ord("+"):
+            self.SetScale(self.CurrentScale + 1)
+            self.ParentWindow.RefreshDisplayMenu()
+        elif keycode == ord("-"):
+            self.SetScale(self.CurrentScale - 1)
+            self.ParentWindow.RefreshDisplayMenu()
         else:
             event.Skip()
 
@@ -1803,7 +1890,7 @@
             self.RefreshBuffer()
             self.RefreshScrollBars()
             self.RefreshVisibleElements()
-            self.ParentWindow.RefreshVariablePanel(self.TagName)
+            self.RefreshVariablePanel()
             self.ParentWindow.RefreshInstancesTree()
             block.Refresh()
         dialog.Destroy()
@@ -2114,7 +2201,7 @@
             self.RefreshBuffer()
             self.RefreshScrollBars()
             self.RefreshVisibleElements()
-            self.ParentWindow.RefreshVariablePanel(self.TagName)
+            self.RefreshVariablePanel()
             self.ParentWindow.RefreshInstancesTree()
             if old_values["executionOrder"] != new_values["executionOrder"]:
                 self.RefreshView()
@@ -2527,7 +2614,7 @@
         self.Controler.RemoveEditedElementInstance(self.TagName, block.GetId())
         for element in elements:
             element.RefreshModel()
-        wx.CallAfter(self.ParentWindow.RefreshVariablePanel, self.TagName)
+        wx.CallAfter(self.RefreshVariablePanel)
         wx.CallAfter(self.ParentWindow.RefreshInstancesTree)
         
     def DeleteVariable(self, variable):
@@ -2665,7 +2752,7 @@
             self.SelectedElement = None
             self.RefreshBuffer()
             self.RefreshScrollBars()
-            self.ParentWindow.RefreshVariablePanel(self.TagName)
+            self.RefreshVariablePanel()
             self.ParentWindow.RefreshInstancesTree()
             self.RefreshRect(self.GetScrolledRect(rect), False)
         
@@ -2678,8 +2765,8 @@
     def Paste(self):
         if not self.Debug:
             element = self.ParentWindow.GetCopyBuffer()
-            mouse_pos = self.ScreenToClient(wx.GetMousePosition())
-            middle = wx.Rect(0, 0, *self.GetClientSize()).InsideXY(mouse_pos.x, mouse_pos.y)
+            mouse_pos = self.Editor.ScreenToClient(wx.GetMousePosition())
+            middle = wx.Rect(0, 0, *self.Editor.GetClientSize()).InsideXY(mouse_pos.x, mouse_pos.y)
             if middle:
                 x, y = self.CalcUnscrolledPosition(mouse_pos.x, mouse_pos.y)
             else:
@@ -2688,11 +2775,11 @@
             result = self.Controler.PasteEditedElementInstances(self.TagName, element, new_pos, middle, self.Debug)
             if not isinstance(result, (StringType, UnicodeType)):
                 self.RefreshBuffer()
-                self.RefreshView(result)
-                self.ParentWindow.RefreshVariablePanel(self.TagName)
+                self.RefreshView(selection=result)
+                self.RefreshVariablePanel()
                 self.ParentWindow.RefreshInstancesTree()
             else:
-                message = wx.MessageDialog(self, result, "Error", wx.OK|wx.ICON_ERROR)
+                message = wx.MessageDialog(self.Editor, result, "Error", wx.OK|wx.ICON_ERROR)
                 message.ShowModal()
                 message.Destroy()
 
@@ -2819,38 +2906,22 @@
             rotation = event.GetWheelRotation() / event.GetWheelDelta()
             if event.ShiftDown():
                 x, y = self.GetViewStart()
-                xp = max(0, min(x - rotation * 3, self.GetVirtualSize()[0] / self.GetScrollPixelsPerUnit()[0]))
+                xp = max(0, min(x - rotation * 3, self.Editor.GetVirtualSize()[0] / self.Editor.GetScrollPixelsPerUnit()[0]))
                 self.RefreshVisibleElements(xp = xp)
                 self.Scroll(xp, y)
             elif event.ControlDown():
                 dc = self.GetLogicalDC()
-                self.Freeze()
-                pos = event.GetLogicalPosition(dc)
-                mouse_pos = event.GetPosition()
-                self.SetScale(self.CurrentScale + rotation, False)
-                xmax = self.GetScrollRange(wx.HORIZONTAL) - self.GetScrollThumb(wx.HORIZONTAL)
-                ymax = self.GetScrollRange(wx.VERTICAL) - self.GetScrollThumb(wx.VERTICAL)
-                scrollx = max(0, round(pos.x * self.ViewScale[0] - mouse_pos.x) / SCROLLBAR_UNIT)
-                scrolly = max(0, round(pos.y * self.ViewScale[1] - mouse_pos.y) / SCROLLBAR_UNIT)
-                if scrollx > xmax or scrolly > ymax:
-                    self.RefreshScrollBars(max(0, scrollx - xmax), max(0, scrolly - ymax))
-                    self.Scroll(scrollx, scrolly)
-                else:
-                    self.Scroll(scrollx, scrolly)
-                    self.RefreshScrollBars()
-                self.RefreshVisibleElements()
-                self.Refresh()
-                self.Thaw()
+                self.SetScale(self.CurrentScale + rotation, mouse_event = event)
                 self.ParentWindow.RefreshDisplayMenu()
             else:
                 x, y = self.GetViewStart()
-                yp = max(0, min(y - rotation * 3, self.GetVirtualSize()[1] / self.GetScrollPixelsPerUnit()[1]))
+                yp = max(0, min(y - rotation * 3, self.Editor.GetVirtualSize()[1] / self.Editor.GetScrollPixelsPerUnit()[1]))
                 self.RefreshVisibleElements(yp = yp)
                 self.Scroll(x, yp)
         
     def OnMoveWindow(self, event):
         if not USE_AUI:
-            self.GetBestSize()
+            self.Editor.GetBestSize()
         self.RefreshScrollBars()
         self.RefreshVisibleElements()
         event.Skip()
@@ -2863,22 +2934,22 @@
             else:
                 dc.SetFont(self.GetFont())
         else:
-            dc.SetBackground(wx.Brush(self.GetBackgroundColour()))
+            dc.SetBackground(wx.Brush(self.Editor.GetBackgroundColour()))
             dc.Clear()
             dc.BeginDrawing()
         if self.Scaling is not None and self.DrawGrid and not printing:
             dc.SetPen(wx.TRANSPARENT_PEN)
             dc.SetBrush(self.GridBrush)
             xstart, ystart = self.GetViewStart()
-            window_size = self.GetClientSize()
-            width, height = self.GetVirtualSize()
+            window_size = self.Editor.GetClientSize()
+            width, height = self.Editor.GetVirtualSize()
             width = int(max(width, xstart * SCROLLBAR_UNIT + window_size[0]) / self.ViewScale[0])
             height = int(max(height, ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[1])
             dc.DrawRectangle(1, 1, width, height)
         if self.PageSize is not None and not printing:
             dc.SetPen(self.PagePen)
             xstart, ystart = self.GetViewStart()
-            window_size = self.GetClientSize()
+            window_size = self.Editor.GetClientSize()
             for x in xrange(self.PageSize[0] - (xstart * SCROLLBAR_UNIT) % self.PageSize[0], int(window_size[0] / self.ViewScale[0]), self.PageSize[0]):
                 dc.DrawLine(xstart * SCROLLBAR_UNIT + x + 1, int(ystart * SCROLLBAR_UNIT / self.ViewScale[0]), 
                             xstart * SCROLLBAR_UNIT + x + 1, int((ystart * SCROLLBAR_UNIT + window_size[1]) / self.ViewScale[0]))
@@ -2916,7 +2987,7 @@
     def OnPaint(self, event):
         dc = self.GetLogicalDC(True)
         self.DoDrawing(dc)
-        wx.BufferedPaintDC(self, dc.GetAsBitmap())
+        wx.BufferedPaintDC(self.Editor, dc.GetAsBitmap())
         if self.Debug:
             DebugViewer.RefreshNewData(self)
         event.Skip()