Beispiel #1
0
class TAGTreeSetView(object):
    """
    A window that displays a TAG Tree set. TAG Tree Set
    contains a group of TAG trees, when clicking the tree
    name on the tree list, the tree will be displayed on
    the canvas.

    """
    def __init__(self, tagtrees, parent=None):
        self._trees = tagtrees

        if parent is None:
            self._top = Tk()
            self._top.title('NLTK')
            self._top.bind('<Control-p>', lambda e: self.print_to_file())
            self._top.bind('<Control-x>', self.destroy)
            self._top.bind('<Control-q>', self.destroy)
            self._top.geometry("1400x800")
        else:
            self._top = parent[0]

        frame = Frame(self._top)

        v = StringVar()
        self.w = Label(frame, text='Regexp:')
        self._e = Entry(frame, textvariable=v)
        self._e.bind("<Return>", self.return_pressed)
        self._show_fs = True
        self._show_fs_button = Button(frame, text="Hide Features",
                                      command=self.show_fs)
        self._sfs_button = Button(frame, text="Add Start Features",
                                  command=self.start_feat)
        self.highlight_button = Button(frame, text="Highlight",
                                       command=self.highlight)
        self.remove_button = Button(frame, text="Remove",
                                    command=self.remove)
        self.keep_button = Button(frame, text="Keep",
                                  command=self.keep)
        self._sfs_button.pack(side=LEFT)
        self._show_fs_button.pack(side=LEFT)
        self.w.pack(side=LEFT)
        self._e.pack(expand=1, fill='both', side = LEFT)
        self.highlight_button.pack(side=RIGHT)
        self.keep_button.pack(side=RIGHT)
        self.remove_button.pack(side=RIGHT)
        

        statframe = Frame(self._top)
        self.notfl = Label(statframe, text='Tree Framilies:')
        self.notf = StringVar()
        self.nott = StringVar()
        self.tfcl = Label(statframe, textvariable=self.notf)
        self.nottl = Label(statframe, text='Trees:')
        self.tcl = Label(statframe, textvariable=self.nott)

        self.notf.set(str(self._trees.tree_family_count()))
        self.nott.set(str(self._trees.tree_count()))

        statframe.pack(side = BOTTOM, fill='both')
        self.notfl.pack(side = LEFT)
        self.tfcl.pack(side = LEFT)
        self.nottl.pack(side = LEFT)
        self.tcl.pack(side = LEFT)

        frame.pack(side = BOTTOM, fill='both')

        self._frame = Frame(self._top)
        self._frame.pack(fill='both', side = LEFT)
        
        self.cols = ('fullpath', 'type') 
        self._add_fs = True
        self._tagview = ttk.Treeview(self._frame, columns=self.cols,
                            displaycolumns='',
                            yscrollcommand=lambda f, l:autoscroll(vsb, f, l),
                            xscrollcommand=lambda f, l:autoscroll(hsb, f, l))
        ysb = ttk.Scrollbar(self._frame, orient=VERTICAL, 
                            command=self._tagview.yview)
        xsb = ttk.Scrollbar(self._frame, orient=HORIZONTAL,
                            command=self._tagview.xview)
        self._tagview['yscroll'] = ysb.set
        self._tagview['xscroll'] = xsb.set
        if parent:
            self._tagview.bind('<<TreeviewSelect>>', parent[1])
        else:
            self._tagview.bind('<<TreeviewSelect>>', self.display)
        self.populate_tree('', self._trees)
        self._tagview.configure(xscrollcommand=xsb.set,
                                yscrollcommand=ysb.set)
        ysb.pack(fill='y', side='right')
        xsb.pack(fill='x', side='bottom')

        self._tagview.heading('#0', text='Trees', anchor=W)
        self._tagview.column('#0', stretch=1, width=220)

        self._tagview.pack(expand=1, fill='both')
        self._tw = TAGTreeView(None, parent=self._top)
        self._tw.pack(expand=1, fill='both', side = LEFT)
        self.sfs_tree ={}

    def return_pressed(self, event):
        """
        Short-cut for pressing return to show feature structures
        """
        words = self._e.get().split()
        if len(words) == 0:
            self._show_fs = False
            self.show_fs()
        return

    def start_feat(self):
        """
        Add or Remove start feature structure of TAG tree set
        """
        if self._trees.start_fs is None:
            raise TypeError("Should set start feature for TAG Trees First")
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)
        if isinstance(tree, type(self._trees)):
            return
        if not tree.start_feat:
            self._sfs_button['text'] = 'Delete Start Features'
            self.add_start_fs(tree, self._trees.start_fs)
            tree.start_feat = True
        else:
            self._sfs_button['text'] = 'Add Start Features'
            self.del_start_fs(tree)
            tree.start_feat = False
        self._add_fs = not self._add_fs

    def add_start_fs(self, tree, start_fs):
        """
        Add start feature structure.
        :param tree: display tree
        :type: TAGTree
        :param start_fs: start feature structure
        :type: FeatStruct
        """
        root = tree.get_node_name() + '.t'
        all_fs = tree.get_all_fs()
        self._old_sfs = copy.deepcopy(all_fs[root])
        for i in start_fs:
            all_fs[root][i] = start_fs[i]
        tree.set_all_fs(all_fs)
        self._tw.redraw(self._show_fs, tree)

    def del_start_fs(self, tree):
        """
        Remove start feature structure.
        :param tree: display tree
        :type: TAGTree
        """
        root = tree.get_node_name() + '.t'
        all_fs = tree.get_all_fs()
        all_fs[root] = self._old_sfs
        tree.set_all_fs(all_fs)
        self._old_sfs = None
        self._tw.redraw(self._show_fs, tree)
    
    def pack(self):
        """
        Pack the canvas frame of ``TAGTreeView``.
        """
        self._tagview.pack(expand=1, fill='both')
        self._frame.pack(fill='both', side = LEFT)
        self._tw.pack(expand=1, fill='both', side = LEFT)

    def focus(self):
        """
        Get selected TAGTree
        :return: selected treeview
        :rtype: TAGTree
        """
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                if not isinstance(tree, type(self._trees)):
                    if tree._lex:
                        tree[subpath] = tree[subpath].copy(True)

                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)

        if not isinstance(tree, type(self._trees)):
            if tree._lex:
                tree.lexicalize()
                tree._lex = False
            return (tree, subpath)

    def display(self, event=None):
        """
        Display the tag tree on the canvas when the tree
        is selected.
        """
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                if not isinstance(tree, type(self._trees)):
                    if tree._lex:
                        tree[subpath] = tree[subpath].copy(True)

                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)

        if not isinstance(tree, type(self._trees)):
            if tree.start_feat:
                self._sfs_button['text'] = 'Delete Start Features'
            else:
                self._sfs_button['text'] = 'Add Start Features'
            if tree._lex:
                tree.lexicalize()
                tree._lex = False
                self._tw.redraw(self._show_fs, tree)
            else:
                self._tw.redraw(self._show_fs, tree)

    def populate_tree(self, parent, trees):
        """
        Popluate the trees on the treeview.
        """
        if not trees:
            return
        for t in sorted(trees.keys()):
            node = parent
            parent_path = self._tagview.set(parent, "fullpath")
            path = parent_path + '/' + t
            if ord(t[0]) < 10:
                f_chr = self.greek(t[0])
            else:
                f_chr = t[0]
            if isinstance(trees[t], type(trees)):
                node = self._tagview.insert(parent, END, text=f_chr+t[1:],
                                      values=[path, 'directory'])
                self.populate_tree(node, trees[t])
            else:
                self._tagview.insert(parent, END, text=f_chr+t[1:],
                                      values=[path, 'file'])
    
    def clear(self):
        """
        Empty the treeview and TAG tree set.
        """
        self._sfs_button['text'] = 'Add Start Features'
        self._add_fs = True
        x = self._tagview.get_children()
        for item in x: 
            self._tagview.delete(item)
        self._trees = TAGTreeSet()

    def update(self, trees):
        """
        Update the window when the change the TAG tree set.
        """
        self._tw.clear()
        self._trees = trees
        self.populate_tree('', trees)
        self.notf.set(str(self._trees.tree_family_count()))
        self.nott.set(str(self._trees.tree_count()))

    def greek(self, ascii):
        """
        Translate ASCII to greek letter
        """    
        i = ord(u'\u03af') + ord(ascii)
        return chr(i)

    def destroy(self, *e):
        if self._top is None: return
        self._top.destroy()
        self._top = None

    def mainloop(self, *args, **kwargs):
        """
        Enter the Tkinter mainloop.  This function must be called if
        this demo is created from a non-interactive program (e.g.
        from a secript); otherwise, the demo will close as soon as
        the script completes.
        """
        if in_idle(): return
        self._top.mainloop(*args, **kwargs)

    def show_fs(self):
        """
        Display or hide the feature structure on the canvas.
        """
        if self._show_fs:
            self._show_fs_button['text'] = 'Show Feature'
        else:
            self._show_fs_button['text'] = 'Hide Feature'
        self._e.delete(0, END)
        self._show_fs = not self._show_fs
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)
        if not isinstance(tree, type(self._trees)):
            self._tw.redraw(self._show_fs, tree)

    def keep(self):
        """
        Display the feature structures which match the
        input regular expression.
        """
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)
        if not isinstance(tree, type(self._trees)):
            self._tw.redraw(self._show_fs, tree, keep=True, reg=self._e.get())
        self._show_fs_button['text'] = 'Show ALL Features'
        self._show_fs = False
        #return

    def highlight(self):
        """
        Remove the feature structures which match the
        input regular expression from the canvas.
        """
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)
        if not isinstance(tree, type(self._trees)):
            self._tw.redraw(self._show_fs, tree, 
                            highlight=True, reg=self._e.get())

    def remove(self):
        """
        Highlight the feature structures which match 
        the input regular expression.
        """
        node = self._tagview.focus()
        path = self._tagview.set(node, "fullpath").split('/')
        tree = self._trees
        for subpath in path[1:]:
            if subpath in tree:
                tree = tree[subpath]
            else:
                raise TypeError("%s: tree does not match"
                             % type(self).__name__)
        if not isinstance(tree, type(self._trees)):
            self._tw.redraw(self._show_fs, tree, 
                            remove=True, reg=self._e.get())
        self._show_fs_button['text'] = 'Show ALL Features'
        self._show_fs = False