示例#1
0
class Facade(Frame):
    """This is a Frame that contains group info, group order, apex and prime
    graph.
    """
    def __init__(self, parent, group, show_graph=True, graph_class=None, **kw):
        """
        Parameters:
            show_graph: whether to create and show graph instantly or provide a button to do that lately
            graph_factory: callable accepting one argument - the Group instance and returning Graph instance. Note that
                __str__ method of the callable is used in the UI.
        """
        Frame.__init__(self, parent, **kw)
        self._group = group
        #        self._show_apex = True
        self._show_graph = show_graph
        self._graph_class = graph_class
        self._init_variables()
        self._init_menu()
        self._init_components()

    @property
    def group(self):
        return self._group

    @property
    def apex_list_container(self):
        return self._apex_container

    @property
    def graph_canvas(self):
        return self._graph_canvas

    def _show_graph_canvas(self):
        self._show_graph_button.forget()
        # TODO: add different layouts and other options
        graph_class = self._graph_class
        self.graph = graph_class(self._group)
        self._graph_canvas = GraphCanvas(self._right_pane, SpringLayout(self.graph), caption=str(graph_class))
        self._graph_canvas.pack(expand=True, fill='both')

        self._graph_canvas.vertex_label_mode = self.getvar(
            name=self.winfo_name() + ".vertexlabelposition")

        self._iterations_plugin = IterationsPlugin()
        self._iterations_plugin.apply(self._graph_canvas)

        self.update_layout()

    def _init_components(self):
        self._panes = PanedWindow(self, orient='horizontal', sashrelief='raised')
        self._panes.pack(expand=True, fill='both')

        self._left_pane = Frame(self._panes, padx=2, pady=2)
        self._right_pane = Frame(self._panes)
        self._panes.add(self._left_pane, width=250)
        self._panes.add(self._right_pane)

        # group name
        group_name_pane = LabelFrame(self._left_pane, text="Group", padx=10, pady=5)
        group_name_pane.pack(fill='x')

        self._group_name = GroupNameLabel(group_name_pane, self._group)
        self._group_name.pack(expand=True, fill='both')

        # group order
        group_order_pane = LabelFrame(self._left_pane, text="Order", padx=10, pady=5)
        group_order_pane.pack(fill='x')

        self._group_order = IntegerContainer(group_order_pane, integer=self._group.order())
        self._group_order.pack(expand=True, fill='both')

        # apex
        self._apex_pane = LabelFrame(self._left_pane, text="Apex", padx=10, pady=5)
        self._apex_pane.pack(expand=True, fill='both')

        self._apex_container = ApexListContainer(self._apex_pane, apex=self._group.apex())
        self._apex_container.pack(expand=True, fill='both')

        # graph controls
        cocliques_frame = LabelFrame(self._left_pane, text="Cocliques", padx=10, pady=5)
        cocliques_frame.pack(fill='x')

        self._cocliques_button = Button(cocliques_frame, text="Calculate", command=self._show_cocliques)
        self._cocliques_button.pack(anchor='nw')

        self._cocliques_container = ListContainer(cocliques_frame)
        self._cocliques_list = Listbox(self._cocliques_container)
        self._cocliques_container.set_listbox(self._cocliques_list)

        # Button(graph_controls, text='Group equivalent vertices').pack(anchor='nw')

        # this is a button that show up instead of graph canvas if we uncheck 'Show graph' checkbox.
        self._show_graph_button = Button(self._right_pane, text='Show graph',
                                         command=self._show_graph_canvas)
        self._graph_canvas = None
        if self._show_graph:
            self._show_graph_canvas()
        else:
            self._show_graph_button.pack()

    def _init_variables(self):
        def set_default_var(self, name):
            """Sets widget-specific var with same value as root.
            """
            default_var = self.getvar(name)
            local_var_name = self.winfo_name() + "." + name
            self.setvar(local_var_name, default_var)
            return local_var_name

        local_name = set_default_var(self, "vertexlabelposition")
        tools.trace_variable(self, local_name, "w",
                             self._change_vertex_label_position)

    def _change_vertex_label_position(self, name, *arg):
        # override default value
        self.setvar("vertexlabelposition", self.getvar(name))
        if self._graph_canvas is not None:
            self._graph_canvas.vertex_label_mode = self.getvar(name)

    def _init_menu(self):
        """Init menu bar content.
        """
        toplevel = self.winfo_toplevel()
        if toplevel['menu']:
            self._menu = self.nametowidget(name=toplevel['menu'])
        else:
            self._menu = Menu(toplevel)
            toplevel['menu'] = self._menu

        graph_options = Menu(self._menu, tearoff=0)
        self._menu.add_cascade(label="Graph", menu=graph_options)
        self._menu_index = self._menu.index("end")

        vertex_label_position_menu = Menu(graph_options, tearoff=0)
        graph_options.add_cascade(label="Label position", menu=vertex_label_position_menu)

        menu_var = self.winfo_name() + ".vertexlabelposition"
        vertex_label_position_menu.add_radiobutton(variable=menu_var, label="Auto", value="auto")
        vertex_label_position_menu.add_radiobutton(variable=menu_var, label="Center", value="center")

        graph_options.add_command(label="Save graph...", command=self.call_graph_save_dialog)

        self.bind("<Destroy>", self.__destroy_menu)

    #noinspection PyUnusedLocal
    def __destroy_menu(self, event):
        try:
            self._menu.delete(self._menu_index)
        except TclError:
            pass

    def _show_cocliques(self):
        cocliques = self.graph.max_cocliques()

        def select_coclique(*_):
            index = next(iter(self._cocliques_list.curselection()), None)
            if index is not None:
                selected = cocliques[int(index)]
                pick_state = self._graph_canvas.picked_vertex_state
                pick_state.clear()
                for value in selected:
                    pick_state.pick(self._graph_canvas.get_vertex(value))

        self._cocliques_list.insert(0, *[', '.join(map(str, coclique)) for coclique in cocliques])
        self._cocliques_list.bind("<Double-Button-1>", select_coclique)

        self._cocliques_button.forget()
        self._cocliques_container.pack(expand=True, fill='both')

    def call_graph_save_dialog(self):
        file_name = tkFileDialog.asksaveasfilename(defaultextension='.ps',
                                                   filetypes=[('PostScript', '.ps')], parent=self.winfo_toplevel(),
                                                   title="Save graph as image")
        if file_name:
            with codecs.open(file_name, 'w', encoding='utf-8') as f:
                f.write(self._graph_canvas.postscript())

    def update_layout(self):
        try:
            self._iterations_plugin.iterate(50)
        except AttributeError:
            pass
示例#2
0
class Facade(Frame):
    """This is a Frame that contains group info, group order, apex and prime
    graph.
    """
    def __init__(self, parent, group, show_graph=True, graph_class=None, **kw):
        """
        Parameters:
            show_graph: whether to create and show graph instantly or provide a button to do that lately
            graph_factory: callable accepting one argument - the Group instance and returning Graph instance. Note that
                __str__ method of the callable is used in the UI.
        """
        Frame.__init__(self, parent, **kw)
        self._group = group
        #        self._show_apex = True
        self._show_graph = show_graph
        self._graph_class = graph_class
        # self._init_variables()  # TODO: fix vertex label automatic positioning
        self._init_menu()
        self._init_components()

    @property
    def group(self):
        return self._group

    @property
    def apex_list_container(self):
        return self._apex_container

    @property
    def graph_canvas(self):
        return self._graph_canvas

    def _show_graph_canvas(self):
        self._show_graph_button.forget()
        # TODO: add different layouts and other options
        graph_class = self._graph_class
        self.graph = graph_class(self._group)
        self._graph_canvas = GraphCanvas(self._right_pane, SpringLayout(self.graph), caption=str(graph_class))
        self._graph_canvas.pack(expand=True, fill='both')

        self._graph_canvas.vertex_label_mode = self.getvar(
            name=self.winfo_name() + ".vertexlabelposition")

        self._iterations_plugin = IterationsPlugin()
        self._iterations_plugin.apply(self._graph_canvas)

        self.update_layout()

    def _init_components(self):
        self._panes = PanedWindow(self, orient='horizontal', sashrelief='raised')
        self._panes.pack(expand=True, fill='both')

        self._left_pane = Frame(self._panes, padx=2, pady=2)
        self._right_pane = Frame(self._panes)
        self._panes.add(self._left_pane, width=250)
        self._panes.add(self._right_pane)

        # group name
        group_name_pane = LabelFrame(self._left_pane, text="Group", padx=10, pady=5)
        group_name_pane.pack(fill='x')

        self._group_name = GroupNameLabel(group_name_pane, self._group)
        self._group_name.pack(expand=True, fill='both')

        # group order
        group_order_pane = LabelFrame(self._left_pane, text="Order", padx=10, pady=5)
        group_order_pane.pack(fill='x')

        self._group_order = IntegerContainer(group_order_pane, integer=self._group.order())
        self._group_order.pack(expand=True, fill='both')

        # apex
        self._apex_pane = LabelFrame(self._left_pane, text="Apex", padx=10, pady=5)
        self._apex_pane.pack(expand=True, fill='both')

        self._apex_container = ApexListContainer(self._apex_pane, apex=self._group.apex())
        self._apex_container.pack(expand=True, fill='both')

        # graph controls
        cocliques_frame = LabelFrame(self._left_pane, text="Cocliques", padx=10, pady=5)
        cocliques_frame.pack(fill='x')

        self._cocliques_button = Button(cocliques_frame, text="Calculate", command=self._show_cocliques)
        self._cocliques_button.pack(anchor='nw')

        self._cocliques_container = ListContainer(cocliques_frame)
        self._cocliques_list = Listbox(self._cocliques_container)
        self._cocliques_container.set_listbox(self._cocliques_list)

        # Button(graph_controls, text='Group equivalent vertices').pack(anchor='nw')

        # this is a button that show up instead of graph canvas if we uncheck 'Show graph' checkbox.
        self._show_graph_button = Button(self._right_pane, text='Show graph',
                                         command=self._show_graph_canvas)
        self._graph_canvas = None
        if self._show_graph:
            self._show_graph_canvas()
        else:
            self._show_graph_button.pack()

    def _init_variables(self):
        def set_default_var(name):
            """Sets widget-specific var with same value as root.
            """
            default_var = self.getvar(name)
            local_var_name = self.winfo_name() + "." + name
            self.setvar(local_var_name, default_var)
            return local_var_name

        local_name = set_default_var("vertexlabelposition")
        tools.trace_variable(self, local_name, "w",
                             self._change_vertex_label_position)

    def _change_vertex_label_position(self, name, *arg):
        # override default value
        self.setvar("vertexlabelposition", self.getvar(name))
        if self._graph_canvas is not None:
            self._graph_canvas.vertex_label_mode = self.getvar(name)

    def _init_menu(self):
        """Init menu bar content.
        """
        toplevel = self.winfo_toplevel()
        if toplevel['menu']:
            self._menu = self.nametowidget(name=toplevel['menu'])
        else:
            self._menu = Menu(toplevel)
            toplevel['menu'] = self._menu

        graph_options = Menu(self._menu, tearoff=0)
        self._menu.add_cascade(label="Graph", menu=graph_options)
        self._menu_index = self._menu.index("end")

        vertex_label_position_menu = Menu(graph_options, tearoff=0)
        graph_options.add_cascade(label="Label position", menu=vertex_label_position_menu)

        menu_var = self.winfo_name() + ".vertexlabelposition"
        vertex_label_position_menu.add_radiobutton(variable=menu_var, label="Auto", value="auto")
        vertex_label_position_menu.add_radiobutton(variable=menu_var, label="Center", value="center")

        graph_options.add_command(label="Save graph...", command=self.call_graph_save_dialog)

        self.bind("<Destroy>", self.__destroy_menu)

    #noinspection PyUnusedLocal
    def __destroy_menu(self, event):
        try:
            self._menu.delete(self._menu_index)
        except TclError:
            pass

    def _show_cocliques(self):
        cocliques = self.graph.max_cocliques()

        def select_coclique(*_):
            index = next(iter(self._cocliques_list.curselection()), None)
            if index is not None:
                selected = cocliques[int(index)]
                pick_state = self._graph_canvas.picked_vertex_state
                pick_state.clear()
                for value in selected:
                    pick_state.pick(self._graph_canvas.get_vertex(value))

        self._cocliques_list.insert(0, *[', '.join(map(str, coclique)) for coclique in cocliques])
        self._cocliques_list.bind("<Double-Button-1>", select_coclique)

        self._cocliques_button.forget()
        self._cocliques_container.pack(expand=True, fill='both')

    def call_graph_save_dialog(self):
        file_name = filedialog.asksaveasfilename(defaultextension='.ps',
                                                   filetypes=[('PostScript', '.ps')], parent=self.winfo_toplevel(),
                                                   title="Save graph as image")
        if file_name:
            with codecs.open(file_name, 'w', encoding='utf-8') as f:
                f.write(self._graph_canvas.postscript())

    def update_layout(self):
        try:
            self._iterations_plugin.iterate(50)
        except AttributeError:
            pass
示例#3
0
class Facade(Frame):
    """This is a Frame that contains group info, group order, apex and prime
    graph.
    """

    def __init__(self, parent, group, show_graph=True, **kw):
        Frame.__init__(self, parent, **kw)
        self._group = group
        #        self._show_apex = True
        self._show_graph = show_graph
        self._init_variables()
        self._init_menu()
        self._init_components()


    @property
    def group(self):
        return self._group

    @property
    def apex_list_container(self):
        return self._apex_container

    @property
    def graph_canvas(self):
        return self._graph_canvas

    def _show_graph_canvas(self):
        self._show_graph_button.forget()
        # TODO: add different layouts and other options
        graph = self._group.prime_graph()
        self._graph_canvas = GraphCanvas(self._right_pane, SpringLayout(graph))
        self._graph_canvas.pack(expand=True, fill='both')

        self._graph_canvas.vertex_label_mode = self.getvar(
            name=self.winfo_name() + ".vertexlabelposition")

        self._iterations_plugin = IterationsPlugin()
        self._iterations_plugin.apply(self._graph_canvas)

        self.update_layout()

    def _init_components(self):
        self._panes = PanedWindow(self, orient='horizontal',
            sashrelief='raised')
        self._panes.pack(expand=True, fill='both')

        self._left_pane = Frame(self._panes, padx=2, pady=2)
        self._right_pane = Frame(self._panes)
        self._panes.add(self._left_pane, width=500)
        self._panes.add(self._right_pane)

        # group name
        group_name_pane = LabelFrame(self._left_pane, text="Group")
        group_name_pane.pack(fill='x')

        self._group_name = GroupNameLabel(group_name_pane, self._group)
        self._group_name.pack(expand=True, fill='both')

        # group order
        group_order_pane = LabelFrame(self._left_pane, text="Order")
        group_order_pane.pack(fill='x')

        self._group_order = IntegerContainer(group_order_pane,
            integer=self._group.order())
        self._group_order.pack(expand=True, fill='both')

        # apex
        self._apex_pane = LabelFrame(self._left_pane, text="Apex")
        self._apex_pane.pack(expand=True, fill='both')

        self._apex_container = ApexListContainer(self._apex_pane,
            apex=self._group.apex())
        self._apex_container.pack(expand=True, fill='both')

        self._show_graph_button = Button(self._right_pane, text='Show graph',
            command=self._show_graph_canvas)
        self._graph_canvas = None
        if self._show_graph:
            self._show_graph_canvas()
        else:
            self._show_graph_button.pack()

    def _init_variables(self):
        def set_default_var(self, name):
            """Sets widget-specific var with same value as root.
            """
            default_var = self.getvar(name)
            local_var_name = self.winfo_name() + "." + name
            self.setvar(local_var_name, default_var)
            return local_var_name

        local_name = set_default_var(self, "vertexlabelposition")
        tools.trace_variable(self, local_name, "w",
            self._change_vertex_label_position)

    def _change_vertex_label_position(self, name, *arg):
        # override default value
        self.setvar("vertexlabelposition", self.getvar(name))
        if self._graph_canvas is not None:
            self._graph_canvas.vertex_label_mode = self.getvar(name)


    def _init_menu(self):
        toplevel = self.winfo_toplevel()
        if toplevel['menu']:
            self._menu = self.nametowidget(name=toplevel['menu'])
        else:
            self._menu = Menu(toplevel)
            toplevel['menu'] = self._menu

        graph_options = Menu(self._menu, tearoff=0)
        self._menu.add_cascade(label="Graph", menu=graph_options)
        self._menu_index = self._menu.index("end")

        vertex_label_position = Menu(graph_options, tearoff=0)
        graph_options.add_cascade(label="Label position",
            menu=vertex_label_position)

        vertexlabelposition_var = self.winfo_name() + ".vertexlabelposition"
        vertex_label_position.add_radiobutton(label="Auto", value="auto",
            variable=vertexlabelposition_var)
        vertex_label_position.add_radiobutton(label="Center", value="center",
            variable=vertexlabelposition_var)

        graph_options.add_command(label="Save graph...",
            command=self.call_graph_save_dialog)

        self.bind("<Destroy>", self.__destroy_menu)

    #noinspection PyUnusedLocal
    def __destroy_menu(self, event):
        try:
            self._menu.delete(self._menu_index)
        except TclError:
            pass

    def call_graph_save_dialog(self):
        file_name = tkFileDialog.asksaveasfilename(defaultextension='.ps',
            filetypes=[('PostScript', '.ps')], parent=self.winfo_toplevel(),
            title="Save graph as image")
        if file_name:
            with codecs.open(file_name, 'w', encoding='utf-8') as file:
                file.write(self._graph_canvas.postscript())


    def update_layout(self):
        try:
            self._iterations_plugin.iterate(50)
        except AttributeError:
            pass