Example #1
0
 def SetTree(self, tree, filename):
     self.layout = CircleLayout(tree)
     self.layout.get_text_size = get_text_size
     self.layout.run()
     self.renderer.layout = self.layout
     self.filename = filename
     self.dirty = False
     
     self.show_bounding_circles = False
     self.auto_relayout = True
     self.scroll_x = 0
     self.scroll_y = 0
     self.zoom = 1.0
     
     self.selected_node = None
     
     self.ReLayout()
Example #2
0
canvas.pack()

# Create one node

rootNode = Node("root")
rootNode.x = 300
rootNode.y = 200
rootNode.width = 50
rootNode.height = 50
rootNode.color = "black"
graph.add(rootNode)

for i in range(1, 10):
    toNode = Node(str(i))
    toNode.x = random.randint(10, 500)
    toNode.y = random.randint(10, 300)
    toNode.color = "white"
    toNode.textColor = "red"
    graph.add(toNode)
    link = Link(rootNode, toNode, "Link-" + str(i))
    link.color = 'green'
    graph.add(link)

circleLayout = CircleLayout(120)
circleLayout.doLayout(graph.nodes, rootNode)

graph.render()


win.mainloop()
Example #3
0
class LayoutPanel(wx.Panel):
    def __init__(self, 
                 parent=None, ID=-1
                 ):

        wx.Panel.__init__(self, parent, size=(1,1), style=wx.WANTS_CHARS)
        
        self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseScroll)
        self.Bind(wx.EVT_MOTION, self.OnMouseMove)
        self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
        self.Bind(wx.EVT_LEFT_DCLICK, self.OnMouseLeftDoubleClick)

        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)

        self.Bind(wx.EVT_ERASE_BACKGROUND, lambda evt: None)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, lambda e: self.Refresh())
        
        self.drag_pos = None
        
        self.renderer = WxLayoutRenderer()
        self.editor = TreeEditor(self)

    def SetTree(self, tree, filename):
        self.layout = CircleLayout(tree)
        self.layout.get_text_size = get_text_size
        self.layout.run()
        self.renderer.layout = self.layout
        self.filename = filename
        self.dirty = False
        
        self.show_bounding_circles = False
        self.auto_relayout = True
        self.scroll_x = 0
        self.scroll_y = 0
        self.zoom = 1.0
        
        self.selected_node = None
        
        self.ReLayout()
    
    def OnMouseScroll(self, evt):
        if evt.CmdDown():
            r = 1.125**(evt.GetWheelRotation()/120.0)
            self.zoom *= r
            self.scroll_x *= r
            self.scroll_y *= r
            self.Refresh()

    def OnMouseMove(self, evt):
        if not evt.Dragging():
            self.drag_pos = None
        else:
            self.CaptureMouse()
            if not self.drag_pos:
                self.drag_pos = evt.GetPosition()
                self.start_x,self.start_y = self.scroll_x,self.scroll_y
            else:
                displacement = evt.GetPosition() - self.drag_pos
                self.scroll_x = self.start_x + displacement.x
                self.scroll_y = self.start_y + displacement.y
                self.Refresh()
            self.ReleaseMouse()

    def OnMouseLeftUp(self, evt):
        if self.drag_pos is not None:
            self.drag_pos = None
            return
        
        x,y = evt.GetPositionTuple()
        x,y = self.renderer.screen_to_coord(x, y)
        n = self.layout.find_node(x,y)
        self.SelectNode(n)

    def OnMouseLeftDoubleClick(self, evt):
        self.OnMouseLeftUp(evt)
        self.OnEditNode(evt)

    def OnKeyDown(self, evt):
        if evt.CmdDown():
            if evt.GetKeyCode() == wx.WXK_HOME:
                self.SelectNode(self.layout.root)
            elif evt.GetKeyCode() in [wx.WXK_LEFT, wx.WXK_RIGHT]:
                self.MoveNode(evt.GetKeyCode())
            else:
                evt.Skip()
            return

        if evt.GetKeyCode() in [wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT, wx.WXK_RIGHT]:
            self.MoveSelection(evt.GetKeyCode())
        elif evt.GetKeyCode() == wx.WXK_F9:
            self.ReLayout()
        elif evt.GetKeyCode() == wx.WXK_BACK and self.selected_node is not None:
            self.selected_node = self.selected_node.parent  
            self.ReLayout()
        elif evt.GetKeyCode() == ord('B'):
            self.show_bounding_circles = not self.show_bounding_circles
            self.Refresh()
        elif evt.GetKeyCode() == ord('P'):
            self.Pivot()
        elif evt.GetKeyCode() == ord('R'):
            self.SetRoot()
        else:
            evt.Skip()
        
    def OnPaint(self, evt):
        s = self.GetSize()
        dc = wx.MemoryDC()
        dc.SelectObject(wx.EmptyBitmap(s.x, s.y))
        
        dc.SetBrush(wx.WHITE_BRUSH)
        dc.Clear()

        gc = wx.GraphicsContext.Create(dc)
        
        self.renderer.zoom = self.zoom
        self.renderer.scroll_x = self.scroll_x
        self.renderer.scroll_y = self.scroll_y
        self.renderer.selected_node = self.selected_node
        self.renderer.show_bounding  = self.show_bounding_circles
        self.renderer.gc = gc
        self.renderer.dc = dc
        self.renderer.render()
        
        dc2 = wx.PaintDC(self)
        dc2.Blit(0,0,s.x,s.y,dc,0,0)
        del dc2
    
    def MoveSelection(self, key_code):
        if self.selected_node is None:
            return
        
        node = self.selected_node
        all_neighbours = []
        if node.parent is not None:
            all_neighbours.append(node.parent)
        all_neighbours.extend(node.children)
        if node.parent is not None:
            all_neighbours.extend([c for c in node.parent.children if c != node])
        
        relevant_neighbours = []
        x,y = self.layout.positions[node]
        for n in all_neighbours:
            nx,ny = self.layout.positions[n]
            dx = nx - x
            dy = ny - y
            if ((-dx > abs(dy) and key_code == wx.WXK_LEFT)
                    or (dx > abs(dy) and key_code == wx.WXK_RIGHT)
                    or (-dy > abs(dx) and key_code == wx.WXK_UP)
                    or (dy > abs(dx) and key_code == wx.WXK_DOWN)):
                relevant_neighbours.append(n)
        
        if len(relevant_neighbours) > 0:
            new_node = relevant_neighbours[0]
            self.SelectNode(new_node)

    def SelectNode(self, node):
        if node != self.selected_node:
            self.selected_node = node
            self.Refresh()

    def Pivot(self):
        if self.selected_node is None or self.selected_node.parent is None:
            return
        mutation = tree_editor.PivotMutation(self.layout, self.selected_node)
        self.selected_node = mutation.parent
        self.editor.perform(mutation)
        self.dirty = True

    def SetRoot(self):
        if self.selected_node is None or self.selected_node.parent is None:
            return
        
        mutation = tree_editor.SetRootMutation(self.layout, self.selected_node)
        self.selected_node = mutation.old_root
        self.editor.perform(mutation)
        self.dirty = True

    def MoveNode(self, key_code):
        if self.selected_node is None or self.selected_node.parent is None:
            return
        if key_code == wx.WXK_LEFT and self.selected_node != self.selected_node.parent.children[0]:
            direction = -1
        elif key_code == wx.WXK_RIGHT and self.selected_node != self.selected_node.parent.children[-1]:
            direction = 1
        else:
            return
        mutation = tree_editor.MoveMutation(self.layout, self.selected_node, direction)
        self.editor.perform(mutation)
        self.dirty = True

    def OnZoomAll(self, evt):
        diameter = self.layout.root.bounding_radius*2
        self.scroll_x,self.scroll_y = 0,0
        self.zoom = min(self.renderer.width, self.renderer.height)/float(diameter)
        self.Refresh()

    def OnUndo(self, evt):
        self.editor.undo()
    
    def OnRedo(self, evt):
        self.editor.redo()
    
    def OnCopy(self, evt):
        if self.selected_node is None:
            return
        target = self.selected_node
        
        node_text = tree.to_string(target)

        clipdata = wx.TextDataObject()
        clipdata.SetText(node_text)
        wx.TheClipboard.Open()
        wx.TheClipboard.SetData(clipdata)
        wx.TheClipboard.Close()
    
    def OnCut(self, evt):
        if self.selected_node is None:
            return
        
        self.OnCopy(evt)
        self.OnDeleteNode(evt)

    def OnPaste(self, evt):
        target = self.selected_node
        if not target:
            target = self.layout.root
        
        if wx.TheClipboard.IsOpened():
            return
    
        do = wx.TextDataObject()
        wx.TheClipboard.Open()
        success = wx.TheClipboard.GetData(do)
        wx.TheClipboard.Close()
        if not success:
            return
        
        node = tree.from_string(do.GetText())
        
        mutation = tree_editor.InsertMutation(self.layout, target, node)
        self.editor.perform(mutation)
        self.dirty = True
    
    def OnDeleteNode(self, evt):
        if self.selected_node is not None and self.selected_node != self.layout.root:
            mutation = tree_editor.DeleteMutation(self.layout, self.selected_node)
            self.selected_node = None
            self.editor.perform(mutation)
            self.dirty = True

    def OnEditNode(self, evt):
        if self.selected_node is None:
            return
            
        #new_text = wx.GetTextFromUser("Edit node content", "Edit node", self.selected_node.content.replace('\n', ' '))
        dlg = EditNodeDialog(self.selected_node.content, self.selected_node.properties, self.GetParent())
        dlg.Show()
        val = dlg.ShowModal()
        new_text = dlg.GetNewContent()
        new_props = dlg.GetNewProperties()
        dlg.Destroy()
        
        if val != wx.ID_OK:
            return
        
        if len(new_text) == 0:
            return
        
        points = justify.get_points(new_text)
        all_js = justify.justify_text(points, 2)
        j = all_js[0][1]
        new_text = justify.render_text(new_text, j)
        
        mutation = tree_editor.EditMutation(self.layout, self.selected_node, new_text, new_props)
        self.editor.perform(mutation)
        self.dirty = True

    def OnAddNode(self, evt):
        if self.selected_node is None:
            return
        
        new_text = wx.GetTextFromUser("Enter new node content", "New node", '')
        if len(new_text) == 0:
            return
            
        points = justify.get_points(new_text)
        all_js = justify.justify_text(points, 2)
        j = all_js[0][1]
        new_text = justify.render_text(new_text, j)
        
        n = tree.Node(new_text)
        mutation = tree_editor.InsertMutation(self.layout, self.selected_node, n)
        self.editor.perform(mutation)
        self.dirty = True
        
        wx.PostEvent(self, evt)

    def ReLayout(self):
        self.layout.run()
        self.Refresh()