class SimulationCanvas( object ): """A canvas where blocks can be dragged around and connected up""" size = ( width, height ) = ( 550, 300 ) def __init__( self, frame ): # Create the canvas self.canvas = Canvas( frame, width=self.width, height=self.height, relief=RIDGE, background=colours["background"], borderwidth=1 ) # Add event handlers for dragable items self.canvas.tag_bind ( "DRAG", "<ButtonPress-1>", self.mouse_down ) #self.canvas.tag_bind ("DRAG", "<ButtonRelease-1>", self.mouse_release) self.canvas.tag_bind ( "DRAG", "<Enter>", self.enter ) self.canvas.tag_bind ( "DRAG", "<Leave>", self.leave ) self.canvas.pack( side=TOP ) # Some default locations self.PREVIEW_WIDTH = 80 self.PREVIEW_LOCATION = ( self.PREVIEW_X, self.PREVIEW_Y ) = ( 15, 30 ) # Draw a "preview" area self.canvas.create_line( self.PREVIEW_WIDTH, 0, self.PREVIEW_WIDTH, self.height, dash=True ) # A dict indexed by unique ID of elements in the canvas. self.blocks = {} def preview_actor( self, codefile ): """ Display a preview of an actor or compisite actor in the canvas, it will be dragable into desired position """ logging.debug( "Creating a preview of %(name)s on simulation canvas." % {'name':codefile.name} ) logging.debug( "Deleting any existing items still tagged 'preview'" ) self.canvas.delete( "preview" ) block = CanvasBlock( self.canvas, codefile, *self.PREVIEW_LOCATION ) self.blocks[block.id] = block def mouse_down( self, event ): logging.debug( "The mouse was pressed at (%d, %d)" % ( event.x, event.y ) ) logging.debug( "The mouse went down on a block. Binding mouse release..." ) selected = self.canvas.gettags( "current" ) logging.debug( "Currently selected items tags are %s" % selected.__repr__() ) self.selected_name = [tag for tag in selected if tag.startswith( "name:" ) ][0][5:] self.selected_id = [tag for tag in selected if tag.startswith( "id:" ) ][0][3:] self.selected_type = [tag for tag in selected if tag.startswith( "type:" ) ][0][5:] logging.debug( "Block selected was %s with id:%s" % ( self.selected_name, self.selected_id ) ) #self.canvas.addtag( 'Selected', 'withtag', self.selected_id ) logging.debug( "Current blocks are: %s" % self.blocks ) #self.blocks[block_id].set_colour( colours['selected'] ) if self.selected_type == "block" or self.selected_type == "text": self.blocks[self.selected_id].select(event.x, event.y) self.canvas.bind( "<ButtonRelease-1>", self.block_move_mouse_release ) elif self.selected_type.startswith("input") or self.selected_type.startswith("output"): self.blocks[self.selected_id].select_port(self.selected_type) self.canvas.bind( "<ButtonRelease-1>", self.port_connect_mouse_release ) else: logging.info("Tried to select %s" % self.selected_type) def block_move_mouse_release( self, event ): logging.debug( "The mouse was released at (%d, %d)" % ( event.x, event.y ) ) self.canvas.bind( "<ButtonRelease-1>", lambda e: None ) if event.x >= 0 and event.x <= self.canvas.winfo_width() \ and event.y >= 0 and event.y <= self.canvas.winfo_height(): logging.debug( "Valid move inside canvas. Relocating block." ) self.blocks[self.selected_id].move_to(event.x, event.y) if event.x >= self.PREVIEW_WIDTH: if self.blocks[self.selected_id].is_preview(): logging.info( "Moved out of preview zone, adding new component to model" ) #TODO HERE - add to model compiler or what ever... self.blocks[self.selected_id].unselect() else: self.blocks[self.selected_id].preview() else: logging.info( "Invalid move." ) def port_connect_mouse_release( self, event ): logging.debug( "The mouse was released at (%d, %d)" % ( event.x, event.y ) ) self.canvas.bind( "<ButtonRelease-1>", lambda e: None ) if event.x >= 0 and event.x <= self.canvas.winfo_width() \ and event.y >= 0 and event.y <= self.canvas.winfo_height(): logging.debug( "Valid location inside canvas." ) event.widget.itemconfigure( "Selected", fill="#000000" ) event.widget.itemconfigure( "type:text", fill="#000000" ) #block = self.canvas.gettags("Selected") #logging.debug("Block moved was made up of these components: %s" % block.__repr__()) self.canvas.dtag( "Selected", "Selected" ) else: logging.info( "Invalid wiring." ) def enter( self, event ): logging.debug( "Enter" ) def leave( self, event ): logging.debug( "Leaving" )
class histogramWidget: BACKGROUND = "#222222" EDGE_HISTOGRAM_COLOR = "#999999" NODE_HISTOGRAM_COLOR = "#555555" TOOLTIP_COLOR="#FFFF55" PADDING = 8 CENTER_WIDTH = 1 CENTER_COLOR = "#444444" ZERO_GAP = 1 UPDATE_WIDTH = 9 UPDATE_COLOR = "#FFFFFF" HANDLE_WIDTH = 5 HANDLE_COLOR = "#FFFFFF" HANDLE_LENGTH = (HEIGHT-2*PADDING) TICK_COLOR = "#FFFFFF" TICK_WIDTH = 10 TICK_FACTOR = 2 LOG_BASE = 10.0 def __init__(self, parent, x, y, width, height, data, logScale=False, callback=None): self.canvas = Canvas(parent,background=histogramWidget.BACKGROUND, highlightbackground=histogramWidget.BACKGROUND,width=width,height=height) self.canvas.place(x=x,y=y,width=width,height=height,bordermode="inside") self.logScale = logScale self.callback = callback self.edgeBars = [] self.nodeBars = [] self.binValues = [] self.numBins = len(data) - 1 self.currentBin = self.numBins # start the slider at the highest bin edgeRange = 0.0 nodeRange = 0.0 for values in data.itervalues(): if values[0] > edgeRange: edgeRange = values[0] if values[1] > nodeRange: nodeRange = values[1] edgeRange = float(edgeRange) # ensure that it will yield floats when used in calculations... nodeRange = float(nodeRange) if logScale: edgeRange = math.log(edgeRange,histogramWidget.LOG_BASE) nodeRange = math.log(nodeRange,histogramWidget.LOG_BASE) # calculate the center line - but don't draw it yet self.center_x = histogramWidget.PADDING if self.logScale: self.center_x += histogramWidget.TICK_WIDTH+histogramWidget.PADDING self.center_y = height/2 self.center_x2 = width-histogramWidget.PADDING self.center_y2 = self.center_y + histogramWidget.CENTER_WIDTH # draw the histograms with background-colored baseline rectangles (these allow tooltips to work on very short bars with little area) self.bar_interval = float(self.center_x2 - self.center_x) / (self.numBins+1) bar_x = self.center_x edge_y2 = self.center_y-histogramWidget.PADDING edge_space = edge_y2-histogramWidget.PADDING node_y = self.center_y2+histogramWidget.PADDING node_space = (height-node_y)-histogramWidget.PADDING thresholds = sorted(data.iterkeys()) for threshold in thresholds: self.binValues.append(threshold) edgeWeight = data[threshold][0] nodeWeight = data[threshold][1] if logScale: if edgeWeight > 0: edgeWeight = math.log(edgeWeight,histogramWidget.LOG_BASE) else: edgeWeight = 0 if nodeWeight > 0: nodeWeight = math.log(nodeWeight,histogramWidget.LOG_BASE) else: nodeWeight = 0 bar_x2 = bar_x + self.bar_interval edge_y = histogramWidget.PADDING + int(edge_space*(1.0-edgeWeight/edgeRange)) edge = self.canvas.create_rectangle(bar_x,edge_y,bar_x2,edge_y2,fill=histogramWidget.EDGE_HISTOGRAM_COLOR,width=0) baseline = self.canvas.create_rectangle(bar_x,edge_y2+histogramWidget.ZERO_GAP,bar_x2,edge_y2+histogramWidget.PADDING,fill=histogramWidget.BACKGROUND,width=0) self.canvas.addtag_withtag("Threshold: %f" % threshold,edge) self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],edge) self.canvas.tag_bind(edge,"<Enter>",self.updateToolTip) self.canvas.tag_bind(edge,"<Leave>",self.updateToolTip) self.edgeBars.append(edge) self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline) self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],baseline) self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip) self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip) node_y2 = node_y + int(node_space*(nodeWeight/nodeRange)) node = self.canvas.create_rectangle(bar_x,node_y,bar_x2,node_y2,fill=histogramWidget.NODE_HISTOGRAM_COLOR,width=0) baseline = self.canvas.create_rectangle(bar_x,node_y-histogramWidget.PADDING,bar_x2,node_y-histogramWidget.ZERO_GAP,fill=histogramWidget.BACKGROUND,width=0) self.canvas.addtag_withtag("Threshold: %f" % threshold,node) self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],node) self.canvas.tag_bind(node,"<Enter>",self.updateToolTip) self.canvas.tag_bind(node,"<Leave>",self.updateToolTip) self.nodeBars.append(node) self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline) self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],baseline) self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip) self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip) bar_x = bar_x2 # now draw the center line self.centerLine = self.canvas.create_rectangle(self.center_x,self.center_y,self.center_x2,self.center_y2,fill=histogramWidget.CENTER_COLOR,width=0) # draw the tick marks if logarithmic if self.logScale: tick_x = histogramWidget.PADDING tick_x2 = histogramWidget.PADDING+histogramWidget.TICK_WIDTH start_y = edge_y2 end_y = histogramWidget.PADDING dist = start_y-end_y while dist > 1: dist /= histogramWidget.TICK_FACTOR self.canvas.create_rectangle(tick_x,end_y+dist-1,tick_x2,end_y+dist,fill=histogramWidget.TICK_COLOR,width=0) start_y = node_y end_y = height-histogramWidget.PADDING dist = end_y-start_y while dist > 1: dist /= histogramWidget.TICK_FACTOR self.canvas.create_rectangle(tick_x,end_y-dist,tick_x2,end_y-dist+1,fill=histogramWidget.TICK_COLOR,width=0) # draw the update bar bar_x = self.currentBin*self.bar_interval + self.center_x bar_x2 = self.center_x2 bar_y = self.center_y-histogramWidget.UPDATE_WIDTH/2 bar_y2 = bar_y+histogramWidget.UPDATE_WIDTH self.updateBar = self.canvas.create_rectangle(bar_x,bar_y,bar_x2,bar_y2,fill=histogramWidget.UPDATE_COLOR,width=0) # draw the handle handle_x = self.currentBin*self.bar_interval-histogramWidget.HANDLE_WIDTH/2+self.center_x handle_x2 = handle_x+histogramWidget.HANDLE_WIDTH handle_y = self.center_y-histogramWidget.HANDLE_LENGTH/2 handle_y2 = handle_y+histogramWidget.HANDLE_LENGTH self.handleBar = self.canvas.create_rectangle(handle_x,handle_y,handle_x2,handle_y2,fill=histogramWidget.HANDLE_COLOR,width=0) self.canvas.tag_bind(self.handleBar, "<Button-1>",self.adjustHandle) self.canvas.tag_bind(self.handleBar, "<B1-Motion>",self.adjustHandle) self.canvas.tag_bind(self.handleBar, "<ButtonRelease-1>",self.adjustHandle) parent.bind("<Left>",lambda e: self.nudgeHandle(e,-1)) parent.bind("<Right>",lambda e: self.nudgeHandle(e,1)) # init the tooltip as nothing self.toolTipBox = self.canvas.create_rectangle(0,0,0,0,state="hidden",fill=histogramWidget.TOOLTIP_COLOR,width=0) self.toolTip = self.canvas.create_text(0,0,state="hidden",anchor="nw") self.canvas.bind("<Enter>",self.updateToolTip) self.canvas.bind("<Leave>",self.updateToolTip) def adjustHandle(self, event): newBin = int(self.numBins*(event.x-self.center_x)/float(self.center_x2-self.center_x)+0.5) if newBin == self.currentBin or newBin < 0 or newBin > self.numBins: return self.canvas.move(self.handleBar,(newBin-self.currentBin)*self.bar_interval,0) self.currentBin = newBin if self.callback != None: self.callback(self.binValues[newBin]) def nudgeHandle(self, event, distance): temp = self.currentBin+distance if temp < 0 or temp > self.numBins: return self.canvas.move(self.handleBar,distance*self.bar_interval,0) self.currentBin += distance if self.callback != None: self.callback(self.binValues[self.currentBin]) def update(self, currentBins): currentBar = self.canvas.coords(self.updateBar) self.canvas.coords(self.updateBar,currentBins*self.bar_interval+self.center_x,currentBar[1],currentBar[2],currentBar[3]) def updateToolTip(self, event): allTags = self.canvas.gettags(self.canvas.find_overlapping(event.x,event.y,event.x+1,event.y+1)) if len(allTags) == 0: self.canvas.itemconfig(self.toolTipBox,state="hidden") self.canvas.itemconfig(self.toolTip,state="hidden") return outText = "" for t in allTags: if t == "current": continue outText += t + "\n" outText = outText[:-1] # strip the last return self.canvas.coords(self.toolTip,event.x+20,event.y) self.canvas.itemconfig(self.toolTip,state="normal",text=outText,anchor="nw") # correct if our tooltip is off screen textBounds = self.canvas.bbox(self.toolTip) if textBounds[2] >= WIDTH-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="ne") self.canvas.coords(self.toolTip,event.x-20,event.y) if textBounds[3] >= HEIGHT-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="se") elif textBounds[3] >= HEIGHT-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="sw") # draw the box behind it self.canvas.coords(self.toolTipBox,self.canvas.bbox(self.toolTip)) self.canvas.itemconfig(self.toolTipBox, state="normal")
class MainCanvas(object): """ The shapefile displaying device based on TKinter Canvas Attributes ---------- shapes : array The spatial units bbox : array The bounding box: minX, minY, maxX, maxY shp_type : integer The shape types: SHP_TYPE_POINT,SHP_TYPE_LINE,SHP_TYPE_POLYGON root : Tk The Tk Object attributeName : string The attribute name datalist : array The attribute data """ def __init__(self,shapes,bbox,shp_type,root,attributeName,datalist): self.shapes = shapes self.bbox = bbox self.shp_type = shp_type self.root = root self.attributeName = attributeName self.datalist = datalist self.__createCanvas() def __createCanvas(self): """ Create the canvas and draw all the spatial objects """ self.canvasRoot = Toplevel() self.canvasRoot.title(self.attributeName) self.canvasRoot.lower(belowThis = self.root) self.mainCanvas = Canvas(self.canvasRoot, bg = 'black', width = canvasWidth+margin_x, height = canvasHeight+margin_y, scrollregion=('-50c','-50c',"50c","50c")) #Change by Sagar for Full Screen self.canvasRoot.state('zoomed') self.canvasRoot.geometry=("1000x900+0+0") #Change End self.__drawShape() self.mainCanvas.pack() def __drawShape(self): """ Draw all the spatial objects on the canvas """ minX, minY, maxX, maxY = self.bbox[0],self.bbox[1],self.bbox[2],self.bbox[3] # calculate ratios of visualization ratiox = canvasWidth/(maxX-minX) ratioy = canvasHeight/(maxY-minY) # take the smaller ratio of window size to geographic distance ratio = ratiox if ratio>ratioy: ratio = ratioy if self.shp_type == SHP_TYPE_POINT: self.__drawPoints(minX, minY, maxX, maxY, ratio) elif self.shp_type == SHP_TYPE_LINE: self.__drawPolylines(minX, minY, maxX, maxY, ratio) elif self.shp_type == SHP_TYPE_POLYGON: self.__drawPolygons(minX, minY, maxX, maxY, ratio) def __drawPoints(self,minX, minY, maxX, maxY,ratio): """ Draw points on the canvas """ tag_count = 0 # loop through each point for point in self.shapes: #define an empty xylist for holding converted coordinates x = int((point.x-minX)*ratio)+margin_x/2 y = int((maxY-point.y)*ratio)+margin_y/2 _point = self.mainCanvas.create_oval(x-2, y-2, x+2, y+2,outline=point.color, fill=point.color, width=2, tags = self.datalist[tag_count]) self.mainCanvas.tag_bind( _point, '<ButtonPress-1>', self.__showAttriInfo) tag_count += 1 def __drawPolylines(self,minX, minY, maxX, maxY,ratio): """ Draw polylines on the canvas """ tag_count = 0 # loop through each polyline for polyline in self.shapes: #define an empty xylist for holding converted coordinates xylist = [] # loops through each point and calculate the window coordinates, put in xylist for j in range(len(polyline.x)): pointx = int((polyline.x[j]-minX)*ratio)+margin_x/2 pointy = int((maxY-polyline.y[j])*ratio)+margin_y/2 xylist.append(pointx) xylist.append(pointy) # loop through each part of the polyline for k in range(polyline.partsNum): #get the end sequence number of points in the part if (k==polyline.partsNum-1): endPointIndex = len(polyline.x) else: endPointIndex = polyline.partsIndex[k+1] # define a temporary list for holding the part coordinates tempXYlist = [] #take out points' coordinates for the part and add to the temporary list for m in range(polyline.partsIndex[k], endPointIndex): tempXYlist.append(xylist[m*2]) tempXYlist.append(xylist[m*2+1]) # create the line _line = self.mainCanvas.create_line(tempXYlist,fill=polyline.color, tags = self.datalist[tag_count]) self.mainCanvas.tag_bind( _line, '<ButtonPress-1>', self.__showAttriInfo) tag_count += 1 def __drawPolygons(self,minX, minY, maxX, maxY,ratio): """ Draw polygons on the canvas """ tag_count = 0 for polygon in self.shapes: #define an empty xylist for holding converted coordinates xylist = [] # loops through each point and calculate the window coordinates, put in xylist for point in polygon.points: pointx = int((point.x -minX)*ratio) + +margin_x/0.5 pointy = int((maxY- point.y)*ratio) + +margin_y/5 xylist.append(pointx) xylist.append(pointy) ## print xylist """ polyline.partsIndex is a tuple data type holding the starting points for each part. For example, if the polyline.partsIndex of a polyline equals to (0, 4, 9), and the total points, which is calcuate by len(polyline.points) equals to 13. This means that the polyline has three parts, and the each part would have the points as follows. part 1: p0,p1,p2,p3 part 2: p4,p5,p6,p7,p8 part 3: p9,p10,p11,p12 The xylist would be: xylist = [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4....x12, y12] where xylist[0] = x0 xylist[1] = y0 xylist[2] = x1 xylist[3] = y1 ..... To draw the first part of polyline, we want to get tempXYlist as tempXYlist = [x0, y0, x1, y1, x2, y2, x3, y3] At this time, m is in range(0,4) xylist[m*2] would be is x0(when m=0), x1(when m=1), x2(when m=2), x3(when m=3) xylist[m*2+1] would be is y0(when m=0), y1(when m=1), y2(when m=2), y3(when m=3) """ for k in range(polygon.partsNum): #get the end sequence number of points in the part if (k==polygon.partsNum-1): endPointIndex = len(polygon.points) else: endPointIndex = polygon.partsIndex[k+1] #Define a temporary list for holding the part coordinates tempXYlist = [] tempXlist = [] tempYlist = [] #take out points' coordinates for the part and add to the temporary list for m in range(polygon.partsIndex[k], endPointIndex): tempXYlist.append(xylist[m*2]) tempXYlist.append(xylist[m*2+1]) tempXlist.append (xylist[m*2]) tempYlist.append (xylist[m*2+1]) xMax = max(tempXlist) xMin = min(tempXlist) yMax = max(tempYlist) yMin = min(tempYlist) if xMax == xMin: xMin = xMax - 1 if yMax == yMin: yMin = yMax - 1 tempVar = False #while not tempVar: xPoint = rd.randrange(xMin,xMax) yPoint = rd.randrange(yMin,yMax) tempVar = point_inside_polygon(xPoint,yPoint,tempXYlist) startIndex = polygon.partsIndex[k] #start index for our positive polygon. tempPoints = polygon.points[startIndex: endPointIndex]#we get our temppoints to help use create our polygon using positive data newPolygon = Polygon(tempPoints) #here we create our polygons using positve data area = newPolygon.getArea() # Calculate the area #Sagar Jha center added to calculate centroid of polygon center = newPolygon.getCentroid() xCenter = int((center.x -minX)*ratio) + +margin_x/0.5 yCenter = int((maxY- center.y)*ratio) + +margin_y/5 if area > 0: _polygon = self.mainCanvas.create_polygon(tempXYlist,activefill="blue",fill=polygon.color,outline="blue",tags = self.datalist[tag_count])#creating our polygon outline #print k,_polygon #Michigan Special Condition according to its 2 parts if tag_count == 48: if k==4: _oval = self.mainCanvas.create_oval(xCenter, yCenter,xCenter +5,yCenter+ 5, outline="red",fill="green", width=2,tags = center) dict1[_oval]=[center.x,center.y] else: if k==0: #print "Tag Count: ",tag_count," ",self.mainCanvas.gettags(_polygon)[0] _oval = self.mainCanvas.create_oval(xCenter, yCenter,xCenter +5,yCenter+ 5, outline="red",fill="green", width=2,tags = center) dict1[_oval]=[center.x,center.y] #_oval1 = self.mainCanvas.create_oval(xPoint, yPoint,xPoint +5,yPoint+ 5, outline="red",fill="green", width=2) else: # If it is a hole, fill with the same color as the canvas background color _polygon = self.mainCanvas.create_polygon(tempXYlist,fill="black",outline="black", tags = self.datalist[tag_count]) #self.mainCanvas.tag_bind( _polygon, '<ButtonPress-1>', self.__showAttriInfo) #self.mainCanvas.tag_bind( _oval, '<ButtonPress-1>', self.__showAttriInfo) tag_count += 1 def __showAttriInfo(self,event): """ Show attribute information of clicked unit """ widget_id=event.widget.find_closest(event.x, event.y) if widget_id[0] in dict1.keys(): print widget_id[0], dict1[widget_id[0]][0],dict1[widget_id[0]][1] else: print "click!!!!", widget_id print self.attributeName+" is: "+self.mainCanvas.gettags(widget_id)[0]
class MainCanvas(object): """ The shapefile displaying device based on TKinter Canvas Attributes ---------- shapes : array The spatial units bbox : array The bounding box: minX, minY, maxX, maxY shp_type : integer The shape types: SHP_TYPE_POINT,SHP_TYPE_LINE,SHP_TYPE_POLYGON root : Tk The Tk Object attributeName : string The attribute name datalist : array The attribute data """ def __init__(self, shapes, bbox, shp_type, root, attributeName, datalist): self.shapes = shapes self.bbox = bbox self.shp_type = shp_type self.root = root self.attributeName = attributeName self.datalist = datalist self.__createCanvas() def __createCanvas(self): """ Create the canvas and draw all the spatial objects """ self.canvasRoot = Toplevel() self.canvasRoot.title(self.attributeName) self.canvasRoot.lower(belowThis=self.root) self.mainCanvas = Canvas(self.canvasRoot, bg='black', width=canvasWidth + margin_x, height=canvasHeight + margin_y, scrollregion=('-50c', '-50c', "50c", "50c")) #Change by Sagar for Full Screen self.canvasRoot.state('zoomed') self.canvasRoot.geometry = ("1000x900+0+0") #Change End self.__drawShape() self.mainCanvas.pack() def __drawShape(self): """ Draw all the spatial objects on the canvas """ minX, minY, maxX, maxY = self.bbox[0], self.bbox[1], self.bbox[ 2], self.bbox[3] # calculate ratios of visualization ratiox = canvasWidth / (maxX - minX) ratioy = canvasHeight / (maxY - minY) # take the smaller ratio of window size to geographic distance ratio = ratiox if ratio > ratioy: ratio = ratioy if self.shp_type == SHP_TYPE_POINT: self.__drawPoints(minX, minY, maxX, maxY, ratio) elif self.shp_type == SHP_TYPE_LINE: self.__drawPolylines(minX, minY, maxX, maxY, ratio) elif self.shp_type == SHP_TYPE_POLYGON: self.__drawPolygons(minX, minY, maxX, maxY, ratio) def __drawPoints(self, minX, minY, maxX, maxY, ratio): """ Draw points on the canvas """ tag_count = 0 # loop through each point for point in self.shapes: #define an empty xylist for holding converted coordinates x = int((point.x - minX) * ratio) + margin_x / 2 y = int((maxY - point.y) * ratio) + margin_y / 2 _point = self.mainCanvas.create_oval(x - 2, y - 2, x + 2, y + 2, outline=point.color, fill=point.color, width=2, tags=self.datalist[tag_count]) self.mainCanvas.tag_bind(_point, '<ButtonPress-1>', self.__showAttriInfo) tag_count += 1 def __drawPolylines(self, minX, minY, maxX, maxY, ratio): """ Draw polylines on the canvas """ tag_count = 0 # loop through each polyline for polyline in self.shapes: #define an empty xylist for holding converted coordinates xylist = [] # loops through each point and calculate the window coordinates, put in xylist for j in range(len(polyline.x)): pointx = int((polyline.x[j] - minX) * ratio) + margin_x / 2 pointy = int((maxY - polyline.y[j]) * ratio) + margin_y / 2 xylist.append(pointx) xylist.append(pointy) # loop through each part of the polyline for k in range(polyline.partsNum): #get the end sequence number of points in the part if (k == polyline.partsNum - 1): endPointIndex = len(polyline.x) else: endPointIndex = polyline.partsIndex[k + 1] # define a temporary list for holding the part coordinates tempXYlist = [] #take out points' coordinates for the part and add to the temporary list for m in range(polyline.partsIndex[k], endPointIndex): tempXYlist.append(xylist[m * 2]) tempXYlist.append(xylist[m * 2 + 1]) # create the line _line = self.mainCanvas.create_line( tempXYlist, fill=polyline.color, tags=self.datalist[tag_count]) self.mainCanvas.tag_bind(_line, '<ButtonPress-1>', self.__showAttriInfo) tag_count += 1 def __drawPolygons(self, minX, minY, maxX, maxY, ratio): """ Draw polygons on the canvas """ tag_count = 0 for polygon in self.shapes: #define an empty xylist for holding converted coordinates xylist = [] # loops through each point and calculate the window coordinates, put in xylist for point in polygon.points: pointx = int((point.x - minX) * ratio) + +margin_x / 0.5 pointy = int((maxY - point.y) * ratio) + +margin_y / 5 xylist.append(pointx) xylist.append(pointy) ## print xylist """ polyline.partsIndex is a tuple data type holding the starting points for each part. For example, if the polyline.partsIndex of a polyline equals to (0, 4, 9), and the total points, which is calcuate by len(polyline.points) equals to 13. This means that the polyline has three parts, and the each part would have the points as follows. part 1: p0,p1,p2,p3 part 2: p4,p5,p6,p7,p8 part 3: p9,p10,p11,p12 The xylist would be: xylist = [x0, y0, x1, y1, x2, y2, x3, y3, x4, y4....x12, y12] where xylist[0] = x0 xylist[1] = y0 xylist[2] = x1 xylist[3] = y1 ..... To draw the first part of polyline, we want to get tempXYlist as tempXYlist = [x0, y0, x1, y1, x2, y2, x3, y3] At this time, m is in range(0,4) xylist[m*2] would be is x0(when m=0), x1(when m=1), x2(when m=2), x3(when m=3) xylist[m*2+1] would be is y0(when m=0), y1(when m=1), y2(when m=2), y3(when m=3) """ for k in range(polygon.partsNum): #get the end sequence number of points in the part if (k == polygon.partsNum - 1): endPointIndex = len(polygon.points) else: endPointIndex = polygon.partsIndex[k + 1] #Define a temporary list for holding the part coordinates tempXYlist = [] tempXlist = [] tempYlist = [] #take out points' coordinates for the part and add to the temporary list for m in range(polygon.partsIndex[k], endPointIndex): tempXYlist.append(xylist[m * 2]) tempXYlist.append(xylist[m * 2 + 1]) tempXlist.append(xylist[m * 2]) tempYlist.append(xylist[m * 2 + 1]) xMax = max(tempXlist) xMin = min(tempXlist) yMax = max(tempYlist) yMin = min(tempYlist) if xMax == xMin: xMin = xMax - 1 if yMax == yMin: yMin = yMax - 1 tempVar = False #while not tempVar: xPoint = rd.randrange(xMin, xMax) yPoint = rd.randrange(yMin, yMax) tempVar = point_inside_polygon(xPoint, yPoint, tempXYlist) startIndex = polygon.partsIndex[ k] #start index for our positive polygon. tempPoints = polygon.points[ startIndex: endPointIndex] #we get our temppoints to help use create our polygon using positive data newPolygon = Polygon( tempPoints ) #here we create our polygons using positve data area = newPolygon.getArea() # Calculate the area #Sagar Jha center added to calculate centroid of polygon center = newPolygon.getCentroid() xCenter = int((center.x - minX) * ratio) + +margin_x / 0.5 yCenter = int((maxY - center.y) * ratio) + +margin_y / 5 if area > 0: _polygon = self.mainCanvas.create_polygon( tempXYlist, activefill="blue", fill=polygon.color, outline="blue", tags=self.datalist[tag_count] ) #creating our polygon outline #print k,_polygon #Michigan Special Condition according to its 2 parts if tag_count == 48: if k == 4: _oval = self.mainCanvas.create_oval(xCenter, yCenter, xCenter + 5, yCenter + 5, outline="red", fill="green", width=2, tags=center) dict1[_oval] = [center.x, center.y] else: if k == 0: #print "Tag Count: ",tag_count," ",self.mainCanvas.gettags(_polygon)[0] _oval = self.mainCanvas.create_oval(xCenter, yCenter, xCenter + 5, yCenter + 5, outline="red", fill="green", width=2, tags=center) dict1[_oval] = [center.x, center.y] #_oval1 = self.mainCanvas.create_oval(xPoint, yPoint,xPoint +5,yPoint+ 5, outline="red",fill="green", width=2) else: # If it is a hole, fill with the same color as the canvas background color _polygon = self.mainCanvas.create_polygon( tempXYlist, fill="black", outline="black", tags=self.datalist[tag_count]) #self.mainCanvas.tag_bind( _polygon, '<ButtonPress-1>', self.__showAttriInfo) #self.mainCanvas.tag_bind( _oval, '<ButtonPress-1>', self.__showAttriInfo) tag_count += 1 def __showAttriInfo(self, event): """ Show attribute information of clicked unit """ widget_id = event.widget.find_closest(event.x, event.y) if widget_id[0] in dict1.keys(): print widget_id[0], dict1[widget_id[0]][0], dict1[widget_id[0]][1] else: print "click!!!!", widget_id print self.attributeName + " is: " + self.mainCanvas.gettags( widget_id)[0]
class SimulationCanvas(object): """A canvas where blocks can be dragged around and connected up""" size = (width, height) = (550, 300) def __init__(self, frame): # Create the canvas self.canvas = Canvas(frame, width=self.width, height=self.height, relief=RIDGE, background=colours["background"], borderwidth=1) # Add event handlers for dragable items self.canvas.tag_bind("DRAG", "<ButtonPress-1>", self.mouse_down) #self.canvas.tag_bind ("DRAG", "<ButtonRelease-1>", self.mouse_release) self.canvas.tag_bind("DRAG", "<Enter>", self.enter) self.canvas.tag_bind("DRAG", "<Leave>", self.leave) self.canvas.pack(side=TOP) # Some default locations self.PREVIEW_WIDTH = 80 self.PREVIEW_LOCATION = (self.PREVIEW_X, self.PREVIEW_Y) = (15, 30) # Draw a "preview" area self.canvas.create_line(self.PREVIEW_WIDTH, 0, self.PREVIEW_WIDTH, self.height, dash=True) # A dict indexed by unique ID of elements in the canvas. self.blocks = {} def preview_actor(self, codefile): """ Display a preview of an actor or compisite actor in the canvas, it will be dragable into desired position """ logging.debug("Creating a preview of %(name)s on simulation canvas." % {'name': codefile.name}) logging.debug("Deleting any existing items still tagged 'preview'") self.canvas.delete("preview") block = CanvasBlock(self.canvas, codefile, *self.PREVIEW_LOCATION) self.blocks[block.id] = block def mouse_down(self, event): logging.debug("The mouse was pressed at (%d, %d)" % (event.x, event.y)) logging.debug( "The mouse went down on a block. Binding mouse release...") selected = self.canvas.gettags("current") logging.debug("Currently selected items tags are %s" % selected.__repr__()) self.selected_name = [ tag for tag in selected if tag.startswith("name:") ][0][5:] self.selected_id = [tag for tag in selected if tag.startswith("id:")][0][3:] self.selected_type = [ tag for tag in selected if tag.startswith("type:") ][0][5:] logging.debug("Block selected was %s with id:%s" % (self.selected_name, self.selected_id)) #self.canvas.addtag( 'Selected', 'withtag', self.selected_id ) logging.debug("Current blocks are: %s" % self.blocks) #self.blocks[block_id].set_colour( colours['selected'] ) if self.selected_type == "block" or self.selected_type == "text": self.blocks[self.selected_id].select(event.x, event.y) self.canvas.bind("<ButtonRelease-1>", self.block_move_mouse_release) elif self.selected_type.startswith( "input") or self.selected_type.startswith("output"): self.blocks[self.selected_id].select_port(self.selected_type) self.canvas.bind("<ButtonRelease-1>", self.port_connect_mouse_release) else: logging.info("Tried to select %s" % self.selected_type) def block_move_mouse_release(self, event): logging.debug("The mouse was released at (%d, %d)" % (event.x, event.y)) self.canvas.bind("<ButtonRelease-1>", lambda e: None) if event.x >= 0 and event.x <= self.canvas.winfo_width() \ and event.y >= 0 and event.y <= self.canvas.winfo_height(): logging.debug("Valid move inside canvas. Relocating block.") self.blocks[self.selected_id].move_to(event.x, event.y) if event.x >= self.PREVIEW_WIDTH: if self.blocks[self.selected_id].is_preview(): logging.info( "Moved out of preview zone, adding new component to model" ) #TODO HERE - add to model compiler or what ever... self.blocks[self.selected_id].unselect() else: self.blocks[self.selected_id].preview() else: logging.info("Invalid move.") def port_connect_mouse_release(self, event): logging.debug("The mouse was released at (%d, %d)" % (event.x, event.y)) self.canvas.bind("<ButtonRelease-1>", lambda e: None) if event.x >= 0 and event.x <= self.canvas.winfo_width() \ and event.y >= 0 and event.y <= self.canvas.winfo_height(): logging.debug("Valid location inside canvas.") event.widget.itemconfigure("Selected", fill="#000000") event.widget.itemconfigure("type:text", fill="#000000") #block = self.canvas.gettags("Selected") #logging.debug("Block moved was made up of these components: %s" % block.__repr__()) self.canvas.dtag("Selected", "Selected") else: logging.info("Invalid wiring.") def enter(self, event): logging.debug("Enter") def leave(self, event): logging.debug("Leaving")