• Facebook
  • Twitter
  • Reddit
  • StumbleUpon
  • Digg
  • email

# -*- coding: cp1252 -*-
import wx
import math
 
import wx.lib.dragscroller
 
from config import *
 
from blocks import *
from block import *
 
 
sortedlibsourcesclasses = libsourcesclasses.keys()
sortedlibsourcesclasses.sort()
 
sortedliblinearclasses = liblinearclasses.keys()
sortedliblinearclasses.sort()
 
sortedlibnonlinearclasses = libnonlinearclasses.keys()
sortedlibnonlinearclasses.sort()
 
# Consideraciones para crear el menu
# 'name':'-' agrega un separador al menu
# Adentro de 'subMenus' el item '-' agrega un separador al submenu
 
# requisito:
# - El texto que aparece en el menu debe coincidir con alguna clave del 
# diccionario classes
# - En el diccionario classes las claves 'InputBlock' y 'OutputBlock' se usan
# despues para identificar al bloque. 
menu1 = { 1: {'name':"Sources",   'subMenus':sortedlibsourcesclasses},
          2: {'name':"Measures",  'subMenus':['Scope',]},
          3: {'name':"Linear",    'subMenus':sortedliblinearclasses},
          4: {'name':"NonLinear", 'subMenus':sortedlibnonlinearclasses},
          5: {'name':"Subsystem", 'subMenus':['Subsystem','-','InputBlock','OutputBlock']}}
 
 
classes = {'Scope':Scope,
           'Subsystem':Subsystem,
           'InputBlock':InputBlock,         
           'OutputBlock':OutputBlock}       
 
classes.update(liblinearclasses)
classes.update(libsourcesclasses)
classes.update(libnonlinearclasses)
 
 
# Submenu properties
 
subMenuProps = ['Show Port Number',
                'Show Block Name',
                'Show Port Name']
 
 
 
 
 
 
class drawPanelClass(wx.Panel):
    """
    """
    # ==================
    # == Constructors ==
    # ==================
 
    def __init__(self, parent, id=-1, mainSystem = None, treeCtrl = None, clipboard = None):
        """
        """
        # Setup the main drawing area.
 
        wx.Panel.__init__(self, parent, id)
 
        sizer = wx.FlexGridSizer(2,2,0,0)
        self.canvas = wx.Window(self, -1)
        self.sb_vert = wx.ScrollBar(self, -1, style=wx.SB_VERTICAL)
        self.sb_vert.SetScrollbar(0,pageHeight,100,pageHeight)
        self.sb_hor = wx.ScrollBar(self, -1, style=wx.SB_HORIZONTAL)
        self.sb_hor.SetScrollbar(0,pageWidth,100,pageWidth)
 
        sizer.Add(self.canvas, 1, wx.EXPAND)
        sizer.Add(self.sb_vert, 0, wx.EXPAND)
        sizer.Add(self.sb_hor, 0, wx.EXPAND)
        sizer.Add((0,0))
 
        sizer.AddGrowableRow(0, 1)
        sizer.AddGrowableCol(0, 1)
 
        self.sb_vert.Show(False)
        self.sb_hor.Show(False)
 
        self.SetSizer(sizer)
        self.Fit()
 
        self.border = (1,1)
 
        self.SetBackgroundColour("white")
 
 
        # scrollbar variables
        self.origin = (0,0)
        self._sb_ignore = False
        self._adjustingSB = False
        self._sb_xfullrange = 0
        self._sb_yfullrange = 0
        self._sb_xunit = 0
        self._sb_yunit = 0
 
 
 
        # Create some mouse events for zooming
        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.onMouseLeftDown)
        self.canvas.Bind(wx.EVT_LEFT_UP, self.onMouseLeftUp)
        self.canvas.Bind(wx.EVT_MOTION, self.onMouseMotion)
        self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.onDoubleClickEvent)
        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
        self.canvas.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)        
 
        self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.onWheel)
 
        self.canvas.Bind(wx.EVT_PAINT, self.onPaint)
        self.canvas.Bind(wx.EVT_CHAR, self.onKeyEvent)
 
        self.canvas.Bind(wx.EVT_KEY_UP, self.onKeyUp)        
 
        self.canvas.Bind(wx.EVT_SET_FOCUS, self.onSetFocus)
        self.canvas.Bind(wx.EVT_KILL_FOCUS, self.onKillFocus)
 
        self.canvas.Bind(wx.EVT_MOUSEWHEEL, self.onWheel)
 
 
##        self.SetBackgroundColour(wx.WHITE)
##        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
##
##        self.EnableScrolling(True, True)
##        self.SetScrollbars(5, 5, pageWidth / 5, pageHeight / 5)
 
##        self.scroller = wx.lib.dragscroller.DragScroller(self)
 
##        self.Bind(wx.EVT_MOTION, self.onMouseMotion)
##        self.Bind(wx.EVT_LEFT_DOWN, self.onMouseLeftDown)
##        self.Bind(wx.EVT_LEFT_UP, self.onMouseLeftUp)        
##        self.Bind(wx.EVT_MOUSEWHEEL, self.onWheel)
##        self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
##        self.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)
##        self.Bind(wx.EVT_LEFT_DCLICK, self.onDoubleClickEvent)
##        self.Bind(wx.EVT_PAINT, self.onPaint)
##        self.Bind(wx.EVT_CHAR, self.onKeyEvent)
##        self.Bind(wx.EVT_KEY_UP, self.onKeyUp)        
 
        self._Buffer = wx.EmptyBitmap(pageWidth, pageHeight)
 
        self.mainSystem = mainSystem
 
        self.clipboard = clipboard
 
        self.scaleZoom = 1
        self.dragMode = drag_NONE
 
        self.makeMenu()
 
 
        self.updatePanel(self)
 
 
 
        # scrollbar events
        self.Bind(wx.EVT_SCROLL_THUMBTRACK, self.OnScroll)
        self.Bind(wx.EVT_SCROLL_PAGEUP, self.OnScroll)
        self.Bind(wx.EVT_SCROLL_PAGEDOWN, self.OnScroll)
        self.Bind(wx.EVT_SCROLL_LINEUP, self.OnScroll)
        self.Bind(wx.EVT_SCROLL_LINEDOWN, self.OnScroll)
 
        self.canvas.Bind(wx.EVT_SIZE, self.OnSize)
        self.OnSize(None)
 
 
 
    # ================
    # == Properties ==
    # ================
 
    def setScaleZoom(self, scale):
        """
        """
        self.scaleZoom = scale
 
    def getScaleZoom(self):
        """
        """
        return self.scaleZoom
 
    def setMainSystem(self,MainSystem):
        """
        """
        self.mainSystem = MainSystem
 
    def getMainSystem(self):
        """
        """
        return self.MainSystem
 
 
 
    # =====================
    # == Mouse's Methods ==
    # =====================
 
    def onSetFocus(self, evt):
        """
        """
        pass
##        print 'set Focus on DrawPanel'
 
 
    def onKillFocus(self, evt):
        """
        """
        pass
##        print 'kill Focus on DrawPanel'    
 
    def updatePanel(self, source):
        """
        """
        self.systemToDraw = self.mainSystem.getCurrentlyViewedSystem()
 
##        self.SetScrollbars(5, 5, self.systemToDraw.sheet.getSheetSize().width / 5, self.systemToDraw.sheet.getSheetSize().height / 5)
 
        self.draw()
 
 
    def OnScroll(self, evt):
        if not self._adjustingSB:
            self._sb_ignore = True
            sbpos = evt.GetPosition()
 
            if evt.GetOrientation() == wx.VERTICAL:
                self.ScrollUp(self.origin[1] + sbpos)
 
            if evt.GetOrientation() == wx.HORIZONTAL:
                self.ScrollRight(self.origin[0] + sbpos)        
 
 
    def ScrollRight(self, units):
        self.origin = (self.origin[0] - units, self.origin[1])
        self.draw()
 
 
    def ScrollUp(self, units):
        self.origin = (self.origin[0], self.origin[1] - units)
        self.draw()
 
 
    def onMouseLeftDown(self, event):
        """
        """
 
        self.canvas.SetFocus()
 
        mousePt = self._getEventCoordinates(event) 
        obj, handle = self.systemToDraw.getObjectAndSelectionHandleAt(mousePt)
 
 
##        self.systemToDraw.getInAt(mousePt)
##        self.systemToDraw.getOutAt(mousePt)
 
 
        dc = wx.ClientDC(self.canvas)
        dc.SetDeviceOrigin(self.origin[0],self.origin[1])
##        self.PrepareDC(dc)
 
        scale = self.getScaleZoom()
        dc.SetUserScale(scale,scale) 
 
        if (obj != None) and (handle != handle_NONE):
            # The user clicked on an object's selection handle.  Let the
            # user resize the clicked-on object.
 
            if len(self.systemToDraw.getSelection()) != 1: return
 
            self.dragMode     = drag_RESIZE
            self.firstTimeRESIZE = True            
            self.resizeObj    = obj
 
            pos  = obj.getPosition()
            size = obj.getSize()
            topLeft  = wx.Point(pos.x, pos.y)
            topRight = wx.Point(pos.x + size.width, pos.y)
            botLeft  = wx.Point(pos.x, pos.y + size.height)
            botRight = wx.Point(pos.x + size.width, pos.y + size.height)
 
            if handle == handle_TOP_LEFT:
                self.resizeAnchor  = botRight
                self.resizeFloater = topLeft
            elif handle == handle_TOP_RIGHT:
                self.resizeAnchor  = botLeft
                self.resizeFloater = topRight
            elif handle == handle_BOTTOM_LEFT:
                self.resizeAnchor  = topRight
                self.resizeFloater = botLeft
            elif handle == handle_BOTTOM_RIGHT:
                self.resizeAnchor  = topLeft
                self.resizeFloater = botRight
 
            self.curPt = mousePt
            self.resizeOffsetX = self.resizeFloater.x - mousePt.x
            self.resizeOffsetY = self.resizeFloater.y - mousePt.y
            endPt = wx.Point(self.curPt.x + self.resizeOffsetX,
                            self.curPt.y + self.resizeOffsetY)
 
            self.drawObjectOutline(dc, 0, 0)
 
        elif self.systemToDraw.getObjectAt(mousePt) != None and self.systemToDraw.getOutAt(mousePt) != None:
            self.startPtForConnection = mousePt
            self.connectPt = mousePt
            self.selectedOutput = self.systemToDraw.getOutAt(mousePt)     ## (Objeto, puerto)
            self.dragMode = drag_CONNECT            
 
        elif self.systemToDraw.getObjectAt(mousePt) != None and self.systemToDraw.getInAt(mousePt) != None:
            self.selectedInput = self.systemToDraw.getInAt(mousePt)     ## (Objeto, puerto)
            self.dragMode = drag_DECONNECT            
 
        elif self.systemToDraw.getObjectAt(mousePt) != None:
 
            # The user clicked on an object to select it.  If the user
            # drags, he/she will move the object.
 
            if self.systemToDraw.getObjectAt(mousePt) not in self.systemToDraw.getSelection():
                if event.ControlDown():
                    self.systemToDraw.select(self.systemToDraw.getObjectAt(mousePt),add=True)
                else:
                    self.systemToDraw.select(self.systemToDraw.getObjectAt(mousePt),add=False)
            else:
                if event.ControlDown():
                    self.systemToDraw.getSelection().remove(self.getObjectAt(mousePt))
 
            self.mainSystem.setParamListeners(param = paramSelectingChange)
            self.mainSystem.callListeners(self)
 
            self.dragMode = drag_MOVE
            self.firstTimeMOVE = True
            self.moveOrigin = mousePt
            self.curPt      = mousePt
 
            self.drawObjectOutline(dc, 0, 0)
 
        elif self.systemToDraw.getBezierAt(mousePt)[0] != None:
            # Se presiono sobre un punto de control de bezier estando este visible
 
            self.dragMode = drag_PTSBEZIER
            self.bezierObj, self.bezierInOut, self.bezierPort = self.systemToDraw.getBezierAt(mousePt)
 
            self.bezierPointStartEdit = mousePt
 
            # Almacena la posicion de la entrada o salida para calcular despues 
            # la distancia al nuevo punto de control de bezier
            if self.bezierInOut is 'IN':
                self.bezierPoint = self.bezierObj.getInputPosition(self.bezierPort)
            else:
                self.bezierPoint = self.bezierObj.getOutputPosition(self.bezierPort)
 
        else:
 
            # The user is dragging out a selection rect or new object.
            self.dragOrigin = mousePt
            self.curPt      = mousePt
            self.SetCursor(wx.CROSS_CURSOR)
##            self.CaptureMouse()
            self.dragMode = drag_DRAG
 
##        self.Scroll(originX,originY)
 
 
    def onMouseLeftUp(self, event):
        """
        """
 
##        originX, originY = self.GetViewStart()
 
        mousePt = self._getEventCoordinates(event)
 
 
        dc = wx.ClientDC(self.canvas)
        dc.SetDeviceOrigin(self.origin[0],self.origin[1])
##        self.PrepareDC(dc)
 
        scale = self.getScaleZoom()
        dc.SetUserScale(scale,scale) 
 
 
        if self.dragMode == drag_RESIZE:
 
            # We're resizing an object.
            # Erase last visual feedback.
            endPt = wx.Point(self.curPt.x + self.resizeOffsetX,
                            self.curPt.y + self.resizeOffsetY)
 
 
            resizePt = wx.Point(mousePt.x + self.resizeOffsetX,
                               mousePt.y + self.resizeOffsetY)
 
            if (self.resizeFloater.x != resizePt.x) or \
               (self.resizeFloater.y != resizePt.y):
 
                self.systemToDraw.resizeObject(self.resizeObj, self.resizeAnchor, resizePt)
 
                self.mainSystem.setParamListeners(param = paramGraphicChange)
                self.mainSystem.callListeners(self)
            else:
                self.Refresh() # Clean up after empty resize.
            self.dirty     = True
 
        elif self.dragMode == drag_MOVE:
 
            # We're moving a selected object.
            # Erase last visual feedback.
            self.drawObjectOutline(dc ,self.curPt.x - self.moveOrigin.x,
                                    self.curPt.y - self.moveOrigin.y)
            if (self.moveOrigin.x != mousePt.x) or \
               (self.moveOrigin.y != mousePt.y):
                self.systemToDraw.moveObjects(mousePt.x - self.moveOrigin.x,
                                 mousePt.y - self.moveOrigin.y)
 
                self.mainSystem.setParamListeners(param = paramGraphicChange)
                self.mainSystem.callListeners(self)
            else:
                self.Refresh() # Clean up after empty drag.
            self.dirty     = True
 
        elif self.dragMode == drag_DRAG:
 
            # We're dragging out a new object or selection rect.
 
            # Erase last visual feedback.
##            self.ReleaseMouse()
            self.SetCursor(wx.STANDARD_CURSOR)
            # Perform the appropriate action for the current tool.
 
            x1 = min(self.dragOrigin.x, self.curPt.x)
            y1 = min(self.dragOrigin.y, self.curPt.y)
            x2 = max(self.dragOrigin.x, self.curPt.x)
            y2 = max(self.dragOrigin.y, self.curPt.y)
 
            startX = x1
            startY = y1
            width  = x2 - x1
            height = y2 - y1
 
            self.dirty     = True
            self.systemToDraw.selectByRectangle(x1, y1, x2-x1, y2-y1)
 
            self.mainSystem.setParamListeners(param = paramSelectingChange)
            self.mainSystem.callListeners(self)
 
        elif self.dragMode == drag_CONNECT:
 
            if self.systemToDraw.getInAt(mousePt) != None:
                self.selectedInput = self.systemToDraw.getInAt(mousePt)                
                self.systemToDraw.connectBlocks(self.selectedInput[0],self.selectedInput[1],self.selectedOutput[0],self.selectedOutput[1]) 
                self.output = None
 
            self.dirty     = True
            self.mainSystem.setParamListeners(param = paramConnectingChange)
            self.mainSystem.callListeners(self)
 
        elif self.dragMode == drag_DECONNECT:
 
            self.selectedInput[0].desconnect(self.selectedInput[1]) 
 
            self.dirty     = True
            self.mainSystem.setParamListeners(param = paramConnectingChange)
            self.mainSystem.callListeners(self)
 
        elif self.dragMode == drag_PTSBEZIER:
            self.dirty     = True
 
            distance = int(abs((self.bezierPoint.x-mousePt.x) +1j* (self.bezierPoint.y-mousePt.y)))
            if self.bezierInOut == 'IN':
                self.bezierObj.setInputParameter(self.bezierPort,'distCtrlPtBezier',distance)
            else:
                self.bezierObj.setOutputParameter(self.bezierPort,'distCtrlPtBezier',distance)
 
            self.mainSystem.setParamListeners(param = paramGraphicChange)
            self.mainSystem.callListeners(self)
 
 
        self.dragMode = drag_NONE # We've finished with this mouse event.
 
##        self.draw()
##        self.Scroll(originX,originY)
 
    def onMouseMotion(self, event):
        """
        """
 
##        originX, originY = self.GetViewStart()
 
        mousePt = self._getEventCoordinates(event)
 
        dc = wx.ClientDC(self.canvas)
        dc.SetDeviceOrigin(self.origin[0],self.origin[1])
##        self.PrepareDC(dc)
 
        scale = self.getScaleZoom()
        dc.SetUserScale(scale,scale) 
 
        if self.dragMode == drag_RESIZE:
            # We're resizing an object.
 
            self.drawLittleCircle(dc, centre = self.curPt,
                                colourBrush =wx.BLUE_BRUSH)
 
            dashedLine   = True
 
            if (self.curPt.x != mousePt.x) or (self.curPt.y != mousePt.y):
                # Erase previous visual feedback.
                endPt = wx.Point(self.curPt.x + self.resizeOffsetX,
                                self.curPt.y + self.resizeOffsetY)
                self.drawVisualFeedback( dc,self.resizeAnchor, endPt, dashedLine)
                self.curPt = mousePt
                # Draw new visual feedback.
                endPt = wx.Point(self.curPt.x + self.resizeOffsetX,
                                self.curPt.y + self.resizeOffsetY)
                self.drawVisualFeedback(dc,self.resizeAnchor, endPt, dashedLine)
            self.dirty     = True
 
 
            self.drawLittleCircle(dc, centre = self.curPt,
                                colourBrush =wx.BLUE_BRUSH)
 
            # dibujo los bloques transparentes la primera vez
            # Luega de que se da el leftDown
            if self.firstTimeRESIZE:
                self.firstTimeRESIZE = False
                self.drawTransparentSelectedBlocks(dc)                
 
 
        elif self.dragMode == drag_MOVE:
             # We're moving a selected object.
 
            if (self.curPt.x != mousePt.x) or (self.curPt.y != mousePt.y):
                # Erase previous visual feedback.
                self.drawObjectOutline(dc,self.curPt.x - self.moveOrigin.x,
                                        self.curPt.y - self.moveOrigin.y)
                self.curPt = mousePt
                # Draw new visual feedback.
                self.drawObjectOutline(dc,self.curPt.x - self.moveOrigin.x,
                                        self.curPt.y - self.moveOrigin.y)
 
 
            # dibujo los bloques transparentes la primera vez
            # Luega de que se da el leftDown
            if self.firstTimeMOVE:
                self.firstTimeMOVE = False
                self.drawTransparentSelectedBlocks(dc)
 
            self.dirty     = True
 
        elif self.dragMode == drag_DRAG:
 
             # We're dragging out a new object or selection rect.
            if ((self.curPt.x != mousePt.x) or (self.curPt.y != mousePt.y)):
                # Erase previous visual feedback.
                self.drawVisualFeedbackSelection(dc ,self.dragOrigin, self.curPt)
                self.curPt = mousePt
                # Draw new visual feedback.
                self.drawVisualFeedbackSelection(dc,self.dragOrigin, self.curPt)
            self.dirty     = True
 
        elif self.dragMode == drag_CONNECT:
 
            self.drawLittleCircle(dc, centre = self.connectPt,
                                colourBrush =wx.RED_BRUSH)
 
            dashedLine   = True
            # Erase previous visual feedback.
            self.drawVisualFeedbackLineConnection( dc,self.startPtForConnection, self.connectPt, dashedLine)
            self.connectPt = mousePt
            # Draw new visual feedback.
            self.drawVisualFeedbackLineConnection( dc,self.startPtForConnection, self.connectPt, dashedLine)
 
            self.drawLittleCircle(dc, centre = self.connectPt,
                                colourBrush =wx.RED_BRUSH)
 
            self.dirty     = True
 
        elif self.dragMode == drag_PTSBEZIER:
 
            self.drawLittleCircle(dc, centre = self.bezierPointStartEdit, radio = 4,
                                    colourBrush =wx.CYAN_BRUSH)
 
            self.dirty     = True
            # Erase previous visual feedback.
            self.drawVisualFeedbackLineBezierControl(dc, self.bezierPoint, self.bezierPointStartEdit)
            self.bezierPointStartEdit = mousePt
            # Draw new visual feedback.
            self.drawVisualFeedbackLineBezierControl(dc, self.bezierPoint, self.bezierPointStartEdit)
 
            self.drawLittleCircle(dc, centre = self.bezierPointStartEdit, radio = 4,
                                    colourBrush =wx.CYAN_BRUSH)
 
##        self.Scroll(originX,originY)
 
    def onWheel(self, event):
        """
        """
##        pass
        self.SetFocus()
        if event.ControlDown():
            self._zoom(delta=event.GetWheelRotation())
 
        self.dirty     = True
 
    def OnMouseRightDown(self, event):
        """
        """
 
 
        if event.ControlDown():
##            self.scroller.Start(event.GetPosition())
            pass
        else:
 
##            originX, originY = self.GetViewStart()                  
 
            mousePt = self._getEventCoordinates(event)
            obj = self.systemToDraw.getObjectAt(mousePt)
 
            if obj == None:
                self.systemToDraw.deselectAll()
                self.mainSystem.setParamListeners(param = paramSelectingChange)
                self.mainSystem.callListeners(self)
 
                self.SetFocus()
 
##            self.Scroll(originX,originY)
 
 
    def OnMouseRightUp(self, event):
        """
        """
 
 
##        self.scroller.Stop()
        if not event.ControlDown():
##            originX, originY = self.GetViewStart()    
 
            mousePt = self._getEventCoordinates(event)
            obj = self.systemToDraw.getObjectAt(mousePt)
 
            if obj == None:           
 
                self.popupMenuXY = mousePt
##                menu = self.PopupMenuXY(self.menu, mousePt.x,mousePt.y)
##              Para tener en cuenta el zoom
 
##                self.Scroll(originX,originY)
                menu = self.PopupMenuXY(self.menu, event.GetX(),event.GetY())
 
                self.systemToDraw.deselectAll()
 
                self.mainSystem.setParamListeners(param = paramSelectingChange)
                self.mainSystem.callListeners(self)
 
##                self.Scroll(originX,originY)
 
                event.Skip()
            else:
                self.systemToDraw.select(obj,add = False)
                self.mainSystem.setParamListeners(param = paramSelectingChange)
                self.mainSystem.callListeners(self)
 
 
 
                menu = wx.Menu()
                menu.Append(menu_DUPLICATE, "Duplicate")
                menu.AppendSeparator()
                menu.Append(menu_DELETE,    "Delete")
                menu.AppendSeparator()
                menu.Append(menu_CONFIG,   "Configuration...")
                menu.AppendSeparator()
                menu.Append(menu_ENTER,   "Enter Subsystem...")
 
                menu.AppendSeparator()
 
                subMenu = wx.Menu()
 
                # Show Number Port
                item = subMenu.Append(menu_PORTNUMBERCHECK,subMenuProps[0],kind=wx.ITEM_CHECK)
                self.Bind(wx.EVT_MENU, self.onMenuProps, item)
                self.Bind(wx.EVT_UPDATE_UI, self.onCheckNumberPort, item)
 
                # Show Name
                item = subMenu.Append(menu_NAMECHECK,subMenuProps[1],kind=wx.ITEM_CHECK)
                self.Bind(wx.EVT_MENU, self.onMenuProps, item)
                self.Bind(wx.EVT_UPDATE_UI, self.onCheckName, item)
 
                # Show Port Name
                item = subMenu.Append(menu_PORTNAMECHECK,subMenuProps[2],kind=wx.ITEM_CHECK)
                self.Bind(wx.EVT_MENU, self.onMenuProps, item)
                self.Bind(wx.EVT_UPDATE_UI, self.onCheckPortName, item) 
 
                if obj.inlet == {}:
                    subMenu.Enable(menu_PORTNAMECHECK,False)
                else:
                    subMenu.Enable(menu_PORTNAMECHECK,True)
 
                menu.AppendMenu(menu_PROPS,"Visualization properties",subMenu)
 
                itemLock = menu.Append(menu_ANCHOR,"Lock to grid",kind=wx.ITEM_CHECK)
                self.Bind(wx.EVT_MENU, self.onMenuProps, itemLock)
                self.Bind(wx.EVT_UPDATE_UI, self.onCheckAnchor, itemLock) 
 
 
                menu.AppendSeparator()
                # Submenu Sent to...
                subMenuSentTo = wx.Menu()
 
                item = subMenuSentTo.Append(menu_SENTTOBACK,'Back')
                self.Bind(wx.EVT_MENU, self.onSentToBack, item)
 
                item = subMenuSentTo.Append(menu_SENTTOFRONT,'Front')
                self.Bind(wx.EVT_MENU, self.onSentToFront, item)
 
                menu.AppendMenu(menu_SENTTO,"Sent to",subMenuSentTo)
 
 
                if obj.isASubsystemBlock():
                    menu.Enable(menu_ENTER, True)
                else:
                    menu.Enable(menu_ENTER, False)
 
                self.Bind(wx.EVT_MENU, self.doDuplicate, id=menu_DUPLICATE)
                self.Bind(wx.EVT_MENU, self.doDelete, id=menu_DELETE)
                self.Bind(wx.EVT_MENU, self.doConfiguration, id=menu_CONFIG)
                self.Bind(wx.EVT_MENU, self.doEnterSubsystem, id=menu_ENTER)
 
                self.menuObj = menu
 
                self.dirty     = True
                self.mainSystem.setParamListeners(param = paramSystemChange)
                self.mainSystem.callListeners(self)
 
                # Show the pop-up menu.
 
##                self.Scroll(originX,originY)
 
                point = wx.Point(event.GetX(),event.GetY())
                self.PopupMenu(self.menuObj, point)
                self.menuObj.Destroy()
 
##                self.Scroll(originX,originY)
 
 
    def onCheckAnchor(self,event):
        """
        """
        if self.systemToDraw.stateAnchor():
            event.Check(True)
        else: event.Check(False)
 
    def onCheckNumberPort(self,event):
        """
        """
        if self.systemToDraw.stateNumberPorts():
            event.Check(True)
        else: event.Check(False)
 
    def onCheckName(self,event):
        """
        """
        if self.systemToDraw.stateName():
            event.Check(True)
        else: event.Check(False)
 
    def onCheckPortName(self,event):
        """
        """
        if self.systemToDraw.statePortName():
            event.Check(True)
        else: event.Check(False)
 
    def onMenuProps(self,event):
        item = self.menuObj.FindItemById(event.GetId())
        text = item.GetText()
        if text == subMenuProps[0]:
            self.systemToDraw.showNumberPorts(not(self.systemToDraw.stateNumberPorts()))
        elif text == subMenuProps[1]:
            self.systemToDraw.showNameBlock(not(self.systemToDraw.stateName()))
        elif text == subMenuProps[2]:
            self.systemToDraw.showPortName(not(self.systemToDraw.statePortName()))
        elif text == 'Lock to grid':
            self.systemToDraw.anchorObject(not(self.systemToDraw.stateAnchor()))
 
 
        self.mainSystem.setParamListeners(param = paramSystemChange)
        self.mainSystem.callListeners(self)
 
    def onSentToFront(self, event):
        """
        """
        self.systemToDraw.sentSelectionToFront()
        self.mainSystem.setParamListeners(param = paramGraphicChange)
        self.mainSystem.callListeners(self)
 
 
    def onSentToBack(self, event):
        """
        """
 
        self.systemToDraw.sentSelectionToBack()
        self.mainSystem.setParamListeners(param = paramGraphicChange)
        self.mainSystem.callListeners(self)
 
    def onDoubleClickEvent(self, event):
        """ Respond to a double-click within our drawing panel.
        """
        mousePt = self._getEventCoordinates(event)
        obj = self.systemToDraw.getObjectAt(mousePt)
 
        if len(self.systemToDraw.getSelection())>1: return
        elif obj == None: return
 
 
        self.systemToDraw.select(obj,add = False)
 
        if obj.isASubsystemBlock():
            self.dirty     = True
            self.mainSystem.setCurrentlyViewedSystem(obj)
            self.mainSystem.setParamListeners(param = paramSystemChange)
            self.mainSystem.callListeners(self)   
        else:
            flag = True                 # /Se modifico para poder validar las entradas de menu...
            while flag:
                flag = False
                ed = obj.editMenu(self)
                if ed is None: pass
                else:
                    val = ed.doEnter()
                    if val: break
                    else: flag = True   # /Fin
 
            self.dirty     = True
            self.mainSystem.setParamListeners(param = paramSystemChange)
            self.mainSystem.callListeners(self)
 
    def onPaint(self, event):
        """
        """
 
        #dc = wx.PaintDC(self)
 
##        dc = wx.BufferedPaintDC(self.canvas)
##        dc.Clear()
##        self.PrepareDC(dc)
##        
##
##        scale = self.getScaleZoom()
##        dc.SetUserScale(scale,scale) 
##
##        dc.BeginDrawing()
##
##        self.systemToDraw.drawSystem(dc)
##
##        dc.EndDrawing()
        dc = wx.BufferedPaintDC(self.canvas, self._Buffer)
 
##        dc.Clear()
##        self.draw(dc)
 
    def draw(self, dc=None):
 
        if dc is None:
            dc = wx.MemoryDC(self._Buffer)
 
        dc.BeginDrawing()
 
        dc.Clear()
        dc.SetDeviceOrigin(self.origin[0],self.origin[1])
        scale = self.getScaleZoom()
        dc.SetUserScale(scale,scale)
 
        self.systemToDraw.drawSystem(dc)
 
        dc.EndDrawing()
 
        dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer)
        self._adjustScrollbars()
 
    def OnSize(self,event):        
 
        self.resizeBuffer()
 
 
    def onKeyUp(self, event):
        """ Se detectan las combinaciones de teclas
        """
##        originX, originY = self.GetViewStart()
        if event.GetModifiers() == wx.MOD_CONTROL:
            if event.GetKeyCode() == ord('R') or event.GetKeyCode() == ord('r'):
                self.systemToDraw.rotateObjects()
                self.dirty     = True
                self.mainSystem.setParamListeners(param = paramGraphicChange)
                self.mainSystem.callListeners(self)
 
            if event.GetKeyCode() == ord('F') or event.GetKeyCode() == ord('f'):
                self.systemToDraw.flipHObjects()
                self.dirty     = True
                self.mainSystem.setParamListeners(param = paramGraphicChange)
                self.mainSystem.callListeners(self)
 
        if event.GetModifiers() == wx.MOD_CONTROL | wx.MOD_SHIFT:
            if event.GetKeyCode() == ord('F') or event.GetKeyCode() == ord('f'):
                self.systemToDraw.flipVObjects()
                self.dirty     = True
                self.mainSystem.setParamListeners(param = paramGraphicChange)
                self.mainSystem.callListeners(self)
 
##        self.Scroll(originX,originY)
 
    def onKeyEvent(self, event):
        """ Respond to a keypress event.
 
            We make the arrow keys move the selected object(s) by one pixel in
            the given direction.
        """
##        originX, originY = self.GetViewStart()
        if event.GetKeyCode() == wx.WXK_UP:
            self.dirty     = True
            self.systemToDraw.moveObjectsByKeyboard(0, -1)            
            self.mainSystem.setParamListeners(param = paramGraphicChange)
 
        elif event.GetKeyCode() == wx.WXK_DOWN:
            self.dirty     = True
            self.systemToDraw.moveObjectsByKeyboard(0, 1)
            self.mainSystem.setParamListeners(param = paramGraphicChange)
 
        elif event.GetKeyCode() == wx.WXK_LEFT:
            self.dirty     = True
            self.systemToDraw.moveObjectsByKeyboard(-1, 0)
            self.mainSystem.setParamListeners(param = paramGraphicChange)
 
        elif event.GetKeyCode() == wx.WXK_RIGHT:
            self.dirty     = True
            self.systemToDraw.moveObjectsByKeyboard(1, 0)
            self.mainSystem.setParamListeners(param = paramGraphicChange)
 
        elif event.GetKeyCode() == wx.WXK_DELETE:
            self.dirty     = True
            self.systemToDraw.deleteSelection()
            self.mainSystem.setParamListeners(param = paramSystemChange)
 
        elif event.GetKeyCode() == wx.WXK_F5:
            # edicion de puntos de control de las lineas de bezier
            self.systemToDraw.editBezier= not self.systemToDraw.editBezier
            self.mainSystem.setParamListeners(param = paramGraphicChange)
 
            self.dirty = True        
 
        elif event.GetKeyCode() == wx.WXK_F6:
            pass
 
        elif event.GetKeyCode() == wx.WXK_F7:
            pass
        elif event.GetKeyCode() == wx.WXK_F8:
            self.dirty     = True
            self.systemToDraw.lockObjectsToGrid()
            self.mainSystem.setParamListeners(param = paramGraphicChange)
 
        elif event.GetKeyCode() == wx.WXK_F9:
            pass
 
        elif event.GetKeyCode() == wx.WXK_F10:
            pass
 
##        elif event.GetKeyCode() == wx.WXK_TAB:
##            self.systemToDraw.IterSelection()
##            self.mainSystem.setParamListeners(param = paramSelectingChange)
 
        elif event.GetKeyCode() == wx.WXK_F11:
            self.dirty     = True
            self._zoom(scale = 2)
            self.mainSystem.setParamListeners(param = paramZoomChange)
##        else:
 
##        event.Skip()
 
        self.mainSystem.callListeners(self)
##        self.Scroll(originX,originY)
 
    def drawObjectOutline(self, dc, offsetX, offsetY):
        """ draw the out line of the currently selected object(s)
        """
##        dc.BeginDrawing()
        #dc.SetPen(wx.BLACK_DASHED_PEN)
        dc.SetPen(wx.Pen(wx.LIGHT_GREY,1,wx.DOT))
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)
 
        for obj in self.systemToDraw.getSelection():
            position = obj.getPosition()
            size     = obj.getSize()
            dc.DrawRectangle(position.x + offsetX, position.y + offsetY,
                             size.width, size.height)
 
##        dc.EndDrawing()
 
 
 
    def drawVisualFeedback(self, dc, startPt, endPt, dashedLine):
        """ Draw visual feedback for a drawing operation.
 
            if 'dashedLine' is True, the feedback is drawn as a dashed rather
            than a solid line.
 
            Note that the feedback is drawn by *inverting* the window's
            contents, so calling _drawVisualFeedback twice in succession will
            restore the window's contents back to what they were previously.
        """
##        dc.BeginDrawing()
        if dashedLine:
            #dc.SetPen(wx.BLACK_DASHED_PEN)
            dc.SetPen(wx.Pen(wx.LIGHT_GREY,1,wx.DOT))
        else:
            dc.SetPen(wx.BLACK_PEN)
 
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)
 
        dc.DrawRectangle(startPt.x, startPt.y,
                         endPt.x - startPt.x,
                         endPt.y - startPt.y)
 
##        dc.EndDrawing()
 
    def drawTransparentSelectedBlocks(self,dc):
        """ Dibuja un rectangulo medio transparente sobre los bloques seleccionados
        """
 
        try:
            dc1 = wx.GCDC(dc)
        except:
            dc1 = dc
 
 
        dc1.BeginDrawing()
        r, g, b = ( 35, 142,  35)
        penclr   = wx.Colour(r, g, b, wx.ALPHA_OPAQUE)
        brushclr = wx.Colour(r, g, b, 20)   # half transparent
        dc1.SetPen(wx.Pen(penclr))
        dc1.SetBrush(wx.Brush(brushclr))
 
        for obj in self.systemToDraw.getSelection():
            position = obj.getPosition()
            size     = obj.getSize()
            rect = wx.Rect(1,1, size.width-1, size.height-1)
            rect.SetPosition(position)
            dc1.DrawRoundedRectangleRect(rect, 2)
 
        dc1.EndDrawing()
 
    def drawLittleCircle(self, dc, centre, radio = 3, colourBrush = wx.BLUE_BRUSH, colourPen = wx.BLACK_PEN):
        """
        """
##        dc.BeginDrawing()
        dc.SetLogicalFunction(wx.EQUIV)
        dc.SetPen(colourPen)
        dc.SetBrush(colourBrush)
        dc.DrawEllipse(centre.x-radio, centre.y-radio, radio*2, radio*2)
##        dc.EndDrawing()
 
 
    def drawVisualFeedbackSelection(self, dc, startPt, endPt):
        """ Draw visual feedback for a drawing operation.
 
            Note that the feedback is drawn by *inverting* the window's
            contents, so calling _drawVisualFeedback twice in succession will
            restore the window's contents back to what they were previously.
        """
##        dc.BeginDrawing()
 
        dc.SetPen(wx.Pen(wx.LIGHT_GREY,1,wx.DOT))
 
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)
 
        dc.DrawRectangle(startPt.x, startPt.y,
                         endPt.x - startPt.x,
                         endPt.y - startPt.y)
 
##        dc.EndDrawing()
 
 
    def drawVisualFeedbackLineConnection(self, dc, startPt, endPt, dashedLine):
        """ Dibuja la realimentacion de la linea de coneccion
        """
##        dc.BeginDrawing()
        if dashedLine:
            dc.SetPen(wx.Pen(wx.LIGHT_GREY,1,wx.DOT))
        else:
            dc.SetPen(wx.BLACK_PEN)
 
 
 
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)
 
        dc.DrawLine(startPt.x, startPt.y,
                         endPt.x, endPt.y)
 
##        dc.EndDrawing()
 
    def drawVisualFeedbackLineBezierControl(self, dc, startPt, endPt):
        """ Dibuja la realimentacion de la linea de control de bezier
        """
##        dc.BeginDrawing()
 
        dc.SetPen(wx.Pen(wx.LIGHT_GREY,1,wx.DOT))            
 
        dc.SetBrush(wx.TRANSPARENT_BRUSH)
        dc.SetLogicalFunction(wx.INVERT)
 
        dc.DrawLine(startPt.x, startPt.y,
                         endPt.x, endPt.y)
 
##        dc.EndDrawing()
 
 
    # =====================
    # == Private Methods ==
    # =====================
 
    def _getEventCoordinates(self, event):
        """ Return the coordinates associated with the given mouse event.
 
            The coordinates have to be adj# Se modifico para poder validar las entradas de menu...usted to allow for the current scroll
            position.
        """
 
        scale = self.getScaleZoom()    
##        originX, originY = self.GetViewStart()
##        unitX, unitY = self.GetScrollPixelsPerUnit()        
        originX, originY = self.origin
        unitX, unitY = (1.0,1.0)
        return wx.Point((event.GetX() - (originX * unitX)) / scale,
                       (event.GetY() - (originY * unitY)) / scale)
 
    def _zoom(self,scale = None, delta = None):
        """
        """
 
        scales = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5]
 
        if delta != None:
            oldScale = self.getScaleZoom()
            if oldScale not in scales:
                a = [x for x in scales if x > oldScale]
                b = [x for x in scales if x < oldScale]
                if len(a) > 0:
                    oldScale = a[0]
                else:
                    oldScale = b[-1]
 
            indexOldScale = scales.index(oldScale)
            scale = oldScale
            if delta < 0:
                if indexOldScale > 0:
                    scale = scales[indexOldScale - 1]
            else:
                if indexOldScale < len(scales)-1:
                    scale = scales[indexOldScale + 1]                
        else:
            if scale not in scales:
                a = [x for x in scales if x > scale]
                b = [x for x in scales if x < scale]
                if len(a) > 0:
                    scale = a[0]
                else:
                    scale = b[-1]
 
        self.setScaleZoom(scale)
 
        self.resizeBuffer()
 
    def resizeBuffer(self):
 
        sheetSize = self.mainSystem.getCurrentlyViewedSystem().sheet.getSheetSize()
        clientSize = self.canvas.GetClientSize()
        scale = self.getScaleZoom()
 
 
        a=-max(min(-self.origin[0],sheetSize.width * scale-clientSize.width),0)
        b=-max(min(-self.origin[1],sheetSize.height * scale-clientSize.height),0)
        self.origin = (a,b)
 
 
        # Limpia el buffer
        dc = wx.ClientDC(self.canvas)
        dc.BeginDrawing()
        dc.Clear()
        dc.EndDrawing()
 
        self.canvas.SetBackgroundColour(wx.WHITE)
 
        self._Buffer = wx.EmptyBitmap(scale * self.systemToDraw.sheet.getSheetSize().width, scale * self.systemToDraw.sheet.getSheetSize().height)
 
        # Dibuja el contenido
        self.draw()        
 
    def makeMenu(self):
        """Make a menu that can be popped up later"""
        menu = wx.Menu()
        subMenus = []
        for k in range(1,len(menu1)+1):
            menuk = menu1[k]
            if menuk['name']== "-":
                menu.AppendSeparator()
            else:
                if menuk.has_key('subMenus'):
                    subMenu = wx.Menu()
                    for s in menuk['subMenus']:
                        if s == "-":
                            subMenu.AppendSeparator()
                        else:
                            item = subMenu.Append(-1,s)
                            self.Bind(wx.EVT_MENU, self.OnPopupItemSelected,item)
 
                    menu.AppendMenu(k,menuk['name'],subMenu)
                else:
                    #menu.AppendSeparator()
                    item = menu.Append(k,menuk['name'])                
                    self.Bind(wx.EVT_MENU, self.OnPopupItemSelected,item)                
 
        self.menu = menu
 
    def OnPopupItemSelected(self, event):
        item = self.menu.FindItemById(event.GetId())
        text = item.GetText()
 
        if classes.has_key(text): # se eligio un bloque de una clase definida
            mousePt = self.popupMenuXY
 
            # Para que no dé error al intentar insertar un InputBlock y/o OutputBlock en mainSystem...
            if (text == 'InputBlock' or text =='OutputBlock') and self.mainSystem.getCurrentlyViewedSystem().isAMainSystem():
                error_dlg = wx.MessageDialog(self,"This block should be inserted into a Subsystem block","Error...",
                                             style = wx.OK | wx.ICON_EXCLAMATION  )
                error_dlg.ShowModal()
                return
 
 
 
            action = self.createObj(mousePt.x,mousePt.y,60,60,text,lockedToGrid=True)
            self.dirty     = True
            self.mainSystem.setParamListeners(param = paramSystemChange)
            self.mainSystem.callListeners(self)
        else: # se eligio un item que no tiene asociada una clase
            pass
 
        event.Skip()
 
 
    def doEnterSubsystem(self,event):
        """
        """
        if len(self.systemToDraw.getSelection())>1: return
        for obj in self.systemToDraw.getSelection():
            if obj.isASubsystemBlock():
                self.mainSystem.setCurrentlyViewedSystem(obj)
 
        self.dirty     = True
        self.mainSystem.setParamListeners(param = paramSelectingChange)
        self.mainSystem.callListeners(self)   
 
 
    def doConfiguration(self, event):
        """ Respond to a double-click within our drawing panel.
        """
 
        if len(self.systemToDraw.getSelection())>1: return
        for obj in self.systemToDraw.getSelection():
            pos = obj.getPosition()
##            obj.editMenu(self)
            flag = True                 #/Se modifico para poder validar las entradas de menu...
            while flag:
                flag = False
                ed = obj.editMenu(self)
                if ed is None: pass
                else:
                    val = ed.doEnter()
                    if val: break
                    else: flag = True   #/Fin
 
        self.dirty     = True
        self.mainSystem.setParamListeners(param = paramSystemChange)
        self.mainSystem.callListeners(self)
 
 
    def doDelete(self, event):
        """ Respond to the "Delete" menu command.
        """
 
        self.systemToDraw.deleteSelection()
        self.dirty     = True
        self.mainSystem.setParamListeners(param = paramSystemChange)
        self.mainSystem.callListeners(self)
 
 
    def doDuplicate(self, event):
        """ Respond to the "Duplicate" menu command.
        """
 
        self.systemToDraw.duplicateSelection()
        self.dirty     = True
        self.mainSystem.setParamListeners(param = paramSystemChange)
        self.mainSystem.callListeners(self)
 
 
    def createObj(self, x, y, width, height, text, lockedToGrid):
        """ Create a new rectangle object at the given position and size.
        """
        rel = 0.1
 
        point = wx.Point(x,y)
        sizePt = wx.Size(width, height)
 
        parameters ={'name':classes[text].defaultName, 'showName':True, 'upperName':False, 'rotation':rot0,
                 'position':wx.Point(point.x,point.y),'size':sizePt, 'offX': rel*width,
                 'offY': rel*height, 'lockedToGrid':lockedToGrid}
        obj = classes[text](**parameters)
        self.systemToDraw.insertObj(obj, classes[text].defaultName)
        self.dirty     = True
        return obj
 
 
    def _adjustScrollbars(self):
        if self._sb_ignore:
            self._sb_ignore = False
            return
 
        self._adjustingSB = True
        needScrollbars = False
 
        scale = self.getScaleZoom()
 
        sheetSize = self.mainSystem.getCurrentlyViewedSystem().sheet.getSheetSize()
        clientSize = self.canvas.GetClientSize()
 
        # horizontal scrollbar
 
        pos = self.sb_hor.GetThumbPosition()
        self.sb_hor.SetScrollbar(pos, clientSize.width, sheetSize.width * scale, clientSize.width)
        needScrollbars = needScrollbars or (sheetSize.width * scale >= clientSize.width)
 
        pos = self.sb_vert.GetThumbPosition()
        self.sb_vert.SetScrollbar(pos, clientSize.height, sheetSize.height * scale, clientSize.height)
        needScrollbars = needScrollbars or (sheetSize.height * scale >= clientSize.height)
 
        self.SetShowScrollbars(needScrollbars)
        self._adjustingSB = False
 
 
    def SetShowScrollbars(self, value):
        """Set True to show scrollbars"""
        if value not in [True,False]:
            raise TypeError, "Value should be True or False"
        if value == self.GetShowScrollbars():
            return
        self.sb_vert.Show(value)
        self.sb_hor.Show(value)
        wx.CallAfter(self.Layout)
 
    def GetShowScrollbars(self):
        """Set True to show scrollbars"""
        return self.sb_vert.IsShown()