def __init__(self, *trees): from math import sqrt, ceil self._trees = trees self._top = Tk() self._top.title('NLTK') self._top.bind('<Control-x>', self.destroy) self._top.bind('<Control-q>', self.destroy) cf = self._cframe = CanvasFrame(self._top) self._top.bind('<Control-p>', self._cframe.print_to_file) # Size is variable. self._size = IntVar(self._top) self._size.set(12) bold = ('helvetica', -self._size.get(), 'bold') helv = ('helvetica', -self._size.get()) # Lay the trees out in a square. self._width = int(ceil(sqrt(len(trees)))) self._widgets = [] for i in range(len(trees)): widget = TreeWidget(cf.canvas(), trees[i], node_font=bold, leaf_color='#008040', node_color='#004080', roof_color='#004040', roof_fill='white', line_color='#004040', draggable=1, leaf_font=helv) widget.bind_click_trees(widget.toggle_collapsed) self._widgets.append(widget) cf.add_widget(widget, 0, 0) self._layout() self._cframe.pack(expand=1, fill='both') self._init_menubar()
def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = Font(family='helvetica', weight='bold', size=self._size.get()) self._font = Font(family='helvetica', size=self._size.get())
def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingShiftReduceParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Shift Reduce Parser Application') # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animating_lock = 0 self._animate = IntVar(self._top) self._animate.set(10) # = medium # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Initialize fonts. self._init_fonts(self._top) # Set up key bindings. self._init_bindings() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # A popup menu for reducing. self._reduce_menu = Menu(self._canvas, tearoff=0) # Reset the demo, and set the feedback frame to empty. self.reset() self._lastoper1['text'] = ''
def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingRecursiveDescentParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Recursive Descent Parser Application') # Set up key bindings. self._init_bindings() # Initialize the fonts. self._init_fonts(self._top) # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animation_frames = IntVar(self._top) self._animation_frames.set(5) self._animating_lock = 0 self._autostep = 0 # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # Initialize the parser. self._parser.initialize(self._sent) # Resize callback self._canvas.bind('<Configure>', self._configure)
def __init__(self, examples): # Set up the main window. self._top = Tk() self._top.title('DRT Glue Demo') # Set up key bindings. self._init_bindings() # Initialize the fonts.self._error = None self._init_fonts(self._top) self._examples = examples self._readingCache = [None for example in examples] # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Set the data to None self._curExample = -1 self._readings = [] self._drs = None self._drsWidget = None self._error = None self._init_glue() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_exampleListbox(self._top) self._init_readingListbox(self._top) self._init_canvas(self._top) # Resize callback self._canvas.bind('<Configure>', self._configure)
def __init__(self): GUITk.__init__(self) self.title(_("QEmu Log Viewer")) self.columnconfigure(0, weight = 1) self.rowconfigure(0, weight = 1) panes = AutoPanedWindow(self, orient = VERTICAL, sashrelief = RAISED) panes.grid(row = 0, column = 0, sticky = "NESW") fr_instructions = GUIFrame(panes) panes.add(fr_instructions) fr_instructions.rowconfigure(0, weight = 1) fr_instructions.columnconfigure(0, weight = 1) fr_instructions.columnconfigure(1, weight = 0) tv = InstructionsTreeview(fr_instructions) self.tv_instructions = tv tv.grid(row = 0, column = 0, sticky = "NESW") tv.bind("<<TreeviewSelect>>", self._on_instruction_selected, "+") vscroll = Scrollbar(fr_instructions) vscroll.grid(row = 0, column = 1, sticky = "NS") tv.config(yscrollcommand = vscroll.set) vscroll.config(command = tv.yview) # Showing trace message (CPU registers, etc.). self.panes_trace_text = panes_trace_text = AutoPanedWindow(panes, orient = HORIZONTAL, sashrelief = RAISED ) panes.add(panes_trace_text) self.rowconfigure(1, weight = 0) self.sb = sb = Statusbar(self) sb.grid(row = 1, column = 0, sticky = "EWS") self.var_inst_n = var = IntVar(self) sb.right(_("Instructions")) sb.right(var) self.qlog_trace_texts = []
class TreeView(object): def __init__(self, *trees): from math import sqrt, ceil self._trees = trees self._top = Tk() self._top.title('NLTK') self._top.bind('<Control-x>', self.destroy) self._top.bind('<Control-q>', self.destroy) cf = self._cframe = CanvasFrame(self._top) self._top.bind('<Control-p>', self._cframe.print_to_file) # Size is variable. self._size = IntVar(self._top) self._size.set(12) bold = ('helvetica', -self._size.get(), 'bold') helv = ('helvetica', -self._size.get()) # Lay the trees out in a square. self._width = int(ceil(sqrt(len(trees)))) self._widgets = [] for i in range(len(trees)): widget = TreeWidget(cf.canvas(), trees[i], node_font=bold, leaf_color='#008040', node_color='#004080', roof_color='#004040', roof_fill='white', line_color='#004040', draggable=1, leaf_font=helv) widget.bind_click_trees(widget.toggle_collapsed) self._widgets.append(widget) cf.add_widget(widget, 0, 0) self._layout() self._cframe.pack(expand=1, fill='both') self._init_menubar() def _layout(self): i = x = y = ymax = 0 width = self._width for i in range(len(self._widgets)): widget = self._widgets[i] (oldx, oldy) = widget.bbox()[:2] if i % width == 0: y = ymax x = 0 widget.move(x-oldx, y-oldy) x = widget.bbox()[2] + 10 ymax = max(ymax, widget.bbox()[3] + 10) def _init_menubar(self): menubar = Menu(self._top) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Print to Postscript', underline=0, command=self._cframe.print_to_file, accelerator='Ctrl-p') filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x') menubar.add_cascade(label='File', underline=0, menu=filemenu) zoommenu = Menu(menubar, tearoff=0) zoommenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) zoommenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) zoommenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) zoommenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=28, command=self.resize) zoommenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=50, command=self.resize) menubar.add_cascade(label='Zoom', underline=0, menu=zoommenu) self._top.config(menu=menubar) def resize(self, *e): bold = ('helvetica', -self._size.get(), 'bold') helv = ('helvetica', -self._size.get()) xspace = self._size.get() yspace = self._size.get() for widget in self._widgets: widget['node_font'] = bold widget['leaf_font'] = helv widget['xspace'] = xspace widget['yspace'] = yspace if self._size.get() < 20: widget['line_width'] = 1 elif self._size.get() < 30: widget['line_width'] = 2 else: widget['line_width'] = 3 self._layout() 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 init_gui(self): """init helper""" window = PanedWindow(self.root, orient="vertical") window.pack(side=TOP, fill=BOTH, expand=True) top_pane = Frame(window) window.add(top_pane) mid_pane = Frame(window) window.add(mid_pane) bottom_pane = Frame(window) window.add(bottom_pane) #setting up frames top_frame = Frame(top_pane) mid_frame = Frame(top_pane) history_frame = Frame(top_pane) radio_frame = Frame(mid_pane) rating_frame = Frame(mid_pane) res_frame = Frame(mid_pane) check_frame = Frame(bottom_pane) msg_frame = Frame(bottom_pane) btn_frame = Frame(bottom_pane) top_frame.pack(side=TOP, fill=X) mid_frame.pack(side=TOP, fill=X) history_frame.pack(side=TOP, fill=BOTH, expand=True) radio_frame.pack(side=TOP, fill=X) rating_frame.pack(side=TOP, fill=X) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=X) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #Message ListBox rightscrollbar = Scrollbar(msg_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.lb_messages = Listbox(msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.xview) #History ListBoxes rightscrollbar2 = Scrollbar(history_frame) rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) self.showhistory = Listbox(history_frame, yscrollcommand=rightscrollbar2.set, xscrollcommand=bottomscrollbar2.set, bg="white") self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) self.showhistory.bind('<Double-Button-1>', self.select_recent_file) self.set_history_window() #status bar self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) self.status.pack(side=BOTTOM, fill=X) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.pack(side=LEFT) Label(mid_frame, text='Recently Used:').pack(side=LEFT) Label(top_frame, text='Module or package').pack(side=LEFT) #file textbox self.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.pack(side=LEFT, expand=True, fill=X) #results box rightscrollbar = Scrollbar(res_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.results = Listbox(res_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white", font="Courier") self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) #buttons Button(top_frame, text='Open', command=self.file_open).pack(side=LEFT) Button(top_frame, text='Open Package', command=(lambda: self.file_open(package=True))).pack(side=LEFT) self.btnRun = Button(top_frame, text='Run', command=self.run_lint) self.btnRun.pack(side=LEFT) Button(btn_frame, text='Quit', command=self.quit).pack(side=BOTTOM) #radio buttons self.information_box = IntVar() self.convention_box = IntVar() self.refactor_box = IntVar() self.warning_box = IntVar() self.error_box = IntVar() self.fatal_box = IntVar() i = Checkbutton(check_frame, text="Information", fg=COLORS['(I)'], variable=self.information_box, command=self.refresh_msg_window) c = Checkbutton(check_frame, text="Convention", fg=COLORS['(C)'], variable=self.convention_box, command=self.refresh_msg_window) r = Checkbutton(check_frame, text="Refactor", fg=COLORS['(R)'], variable=self.refactor_box, command=self.refresh_msg_window) w = Checkbutton(check_frame, text="Warning", fg=COLORS['(W)'], variable=self.warning_box, command=self.refresh_msg_window) e = Checkbutton(check_frame, text="Error", fg=COLORS['(E)'], variable=self.error_box, command=self.refresh_msg_window) f = Checkbutton(check_frame, text="Fatal", fg=COLORS['(F)'], variable=self.fatal_box, command=self.refresh_msg_window) i.select() c.select() r.select() w.select() e.select() f.select() i.pack(side=LEFT) c.pack(side=LEFT) r.pack(side=LEFT) w.pack(side=LEFT) e.pack(side=LEFT) f.pack(side=LEFT) #check boxes self.box = StringVar() # XXX should be generated report = Radiobutton(radio_frame, text="Report", variable=self.box, value="Report", command=self.refresh_results_window) raw_met = Radiobutton(radio_frame, text="Raw metrics", variable=self.box, value="Raw metrics", command=self.refresh_results_window) dup = Radiobutton(radio_frame, text="Duplication", variable=self.box, value="Duplication", command=self.refresh_results_window) ext = Radiobutton(radio_frame, text="External dependencies", variable=self.box, value="External dependencies", command=self.refresh_results_window) stat = Radiobutton(radio_frame, text="Statistics by type", variable=self.box, value="Statistics by type", command=self.refresh_results_window) msg_cat = Radiobutton(radio_frame, text="Messages by category", variable=self.box, value="Messages by category", command=self.refresh_results_window) msg = Radiobutton(radio_frame, text="Messages", variable=self.box, value="Messages", command=self.refresh_results_window) source_file = Radiobutton(radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, sticky=W) #dictionary for check boxes and associated error term self.msg_type_dict = { 'I': lambda: self.information_box.get() == 1, 'C': lambda: self.convention_box.get() == 1, 'R': lambda: self.refactor_box.get() == 1, 'E': lambda: self.error_box.get() == 1, 'W': lambda: self.warning_box.get() == 1, 'F': lambda: self.fatal_box.get() == 1 } self.txt_module.focus_set()
class LintGui(object): """Build and control a window to interact with pylint""" def __init__(self, root=None): """init""" self.root = root or Tk() self.root.title('Pylint') #reporter self.reporter = None #message queue for output from reporter self.msg_queue = six.moves.queue.Queue() self.msgs = [] self.visible_msgs = [] self.filenames = [] self.rating = StringVar() self.tabs = {} self.report_stream = BasicStream(self) #gui objects self.lb_messages = None self.showhistory = None self.results = None self.btnRun = None self.information_box = None self.convention_box = None self.refactor_box = None self.warning_box = None self.error_box = None self.fatal_box = None self.txtModule = None self.status = None self.msg_type_dict = None self.init_gui() def init_gui(self): """init helper""" window = PanedWindow(self.root, orient="vertical") window.pack(side=TOP, fill=BOTH, expand=True) top_pane = Frame(window) window.add(top_pane) mid_pane = Frame(window) window.add(mid_pane) bottom_pane = Frame(window) window.add(bottom_pane) #setting up frames top_frame = Frame(top_pane) mid_frame = Frame(top_pane) history_frame = Frame(top_pane) radio_frame = Frame(mid_pane) rating_frame = Frame(mid_pane) res_frame = Frame(mid_pane) check_frame = Frame(bottom_pane) msg_frame = Frame(bottom_pane) btn_frame = Frame(bottom_pane) top_frame.pack(side=TOP, fill=X) mid_frame.pack(side=TOP, fill=X) history_frame.pack(side=TOP, fill=BOTH, expand=True) radio_frame.pack(side=TOP, fill=X) rating_frame.pack(side=TOP, fill=X) res_frame.pack(side=TOP, fill=BOTH, expand=True) check_frame.pack(side=TOP, fill=X) msg_frame.pack(side=TOP, fill=BOTH, expand=True) btn_frame.pack(side=TOP, fill=X) # Binding F5 application-wide to run lint self.root.bind('<F5>', self.run_lint) #Message ListBox rightscrollbar = Scrollbar(msg_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.lb_messages = Listbox(msg_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) bottomscrollbar.config(command=self.lb_messages.xview) #History ListBoxes rightscrollbar2 = Scrollbar(history_frame) rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) self.showhistory = Listbox(history_frame, yscrollcommand=rightscrollbar2.set, xscrollcommand=bottomscrollbar2.set, bg="white") self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) self.showhistory.bind('<Double-Button-1>', self.select_recent_file) self.set_history_window() #status bar self.status = Label(self.root, text="", bd=1, relief=SUNKEN, anchor=W) self.status.pack(side=BOTTOM, fill=X) #labelbl_ratingls lbl_rating_label = Label(rating_frame, text='Rating:') lbl_rating_label.pack(side=LEFT) lbl_rating = Label(rating_frame, textvariable=self.rating) lbl_rating.pack(side=LEFT) Label(mid_frame, text='Recently Used:').pack(side=LEFT) Label(top_frame, text='Module or package').pack(side=LEFT) #file textbox self.txt_module = Entry(top_frame, background='white') self.txt_module.bind('<Return>', self.run_lint) self.txt_module.pack(side=LEFT, expand=True, fill=X) #results box rightscrollbar = Scrollbar(res_frame) rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) self.results = Listbox(res_frame, yscrollcommand=rightscrollbar.set, xscrollcommand=bottomscrollbar.set, bg="white", font="Courier") self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) #buttons Button(top_frame, text='Open', command=self.file_open).pack(side=LEFT) Button(top_frame, text='Open Package', command=(lambda: self.file_open(package=True))).pack(side=LEFT) self.btnRun = Button(top_frame, text='Run', command=self.run_lint) self.btnRun.pack(side=LEFT) Button(btn_frame, text='Quit', command=self.quit).pack(side=BOTTOM) #radio buttons self.information_box = IntVar() self.convention_box = IntVar() self.refactor_box = IntVar() self.warning_box = IntVar() self.error_box = IntVar() self.fatal_box = IntVar() i = Checkbutton(check_frame, text="Information", fg=COLORS['(I)'], variable=self.information_box, command=self.refresh_msg_window) c = Checkbutton(check_frame, text="Convention", fg=COLORS['(C)'], variable=self.convention_box, command=self.refresh_msg_window) r = Checkbutton(check_frame, text="Refactor", fg=COLORS['(R)'], variable=self.refactor_box, command=self.refresh_msg_window) w = Checkbutton(check_frame, text="Warning", fg=COLORS['(W)'], variable=self.warning_box, command=self.refresh_msg_window) e = Checkbutton(check_frame, text="Error", fg=COLORS['(E)'], variable=self.error_box, command=self.refresh_msg_window) f = Checkbutton(check_frame, text="Fatal", fg=COLORS['(F)'], variable=self.fatal_box, command=self.refresh_msg_window) i.select() c.select() r.select() w.select() e.select() f.select() i.pack(side=LEFT) c.pack(side=LEFT) r.pack(side=LEFT) w.pack(side=LEFT) e.pack(side=LEFT) f.pack(side=LEFT) #check boxes self.box = StringVar() # XXX should be generated report = Radiobutton(radio_frame, text="Report", variable=self.box, value="Report", command=self.refresh_results_window) raw_met = Radiobutton(radio_frame, text="Raw metrics", variable=self.box, value="Raw metrics", command=self.refresh_results_window) dup = Radiobutton(radio_frame, text="Duplication", variable=self.box, value="Duplication", command=self.refresh_results_window) ext = Radiobutton(radio_frame, text="External dependencies", variable=self.box, value="External dependencies", command=self.refresh_results_window) stat = Radiobutton(radio_frame, text="Statistics by type", variable=self.box, value="Statistics by type", command=self.refresh_results_window) msg_cat = Radiobutton(radio_frame, text="Messages by category", variable=self.box, value="Messages by category", command=self.refresh_results_window) msg = Radiobutton(radio_frame, text="Messages", variable=self.box, value="Messages", command=self.refresh_results_window) source_file = Radiobutton(radio_frame, text="Source File", variable=self.box, value="Source File", command=self.refresh_results_window) report.select() report.grid(column=0, row=0, sticky=W) raw_met.grid(column=1, row=0, sticky=W) dup.grid(column=2, row=0, sticky=W) msg.grid(column=3, row=0, sticky=W) stat.grid(column=0, row=1, sticky=W) msg_cat.grid(column=1, row=1, sticky=W) ext.grid(column=2, row=1, sticky=W) source_file.grid(column=3, row=1, sticky=W) #dictionary for check boxes and associated error term self.msg_type_dict = { 'I': lambda: self.information_box.get() == 1, 'C': lambda: self.convention_box.get() == 1, 'R': lambda: self.refactor_box.get() == 1, 'E': lambda: self.error_box.get() == 1, 'W': lambda: self.warning_box.get() == 1, 'F': lambda: self.fatal_box.get() == 1 } self.txt_module.focus_set() def select_recent_file(self, event): # pylint: disable=unused-argument """adds the selected file in the history listbox to the Module box""" if not self.showhistory.size(): return selected = self.showhistory.curselection() item = self.showhistory.get(selected) #update module self.txt_module.delete(0, END) self.txt_module.insert(0, item) def refresh_msg_window(self): """refresh the message window with current output""" #clear the window self.lb_messages.delete(0, END) self.visible_msgs = [] for msg in self.msgs: if self.msg_type_dict.get(msg.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.itemconfigure(END, fg=fg_color) def refresh_results_window(self): """refresh the results window with current output""" #clear the window self.results.delete(0, END) try: for res in self.tabs[self.box.get()]: self.results.insert(END, res) except KeyError: pass def process_incoming(self): """process the incoming messages from running pylint""" while self.msg_queue.qsize(): try: msg = self.msg_queue.get(0) if msg == "DONE": self.report_stream.output_contents() return False #adding message to list of msgs self.msgs.append(msg) #displaying msg if message type is selected in check box if self.msg_type_dict.get(msg.C)(): self.visible_msgs.append(msg) msg_str = convert_to_string(msg) self.lb_messages.insert(END, msg_str) fg_color = COLORS.get(msg_str[:3], 'black') self.lb_messages.itemconfigure(END, fg=fg_color) except six.moves.queue.Empty: pass return True def periodic_call(self): """determine when to unlock the run button""" if self.process_incoming(): self.root.after(100, self.periodic_call) else: #enabling button so it can be run again self.btnRun.config(state=NORMAL) def mainloop(self): """launch the mainloop of the application""" self.root.mainloop() def quit(self, _=None): """quit the application""" self.root.quit() def halt(self): # pylint: disable=no-self-use """program halt placeholder""" return def file_open(self, package=False, _=None): """launch a file browser""" if not package: filename = askopenfilename(parent=self.root, filetypes=[('pythonfiles', '*.py'), ('allfiles', '*')], title='Select Module') else: filename = askdirectory(title="Select A Folder", mustexist=1) if filename == (): return self.txt_module.delete(0, END) self.txt_module.insert(0, filename) def update_filenames(self): """update the list of recent filenames""" filename = self.txt_module.get() if not filename: filename = os.getcwd() if filename + '\n' in self.filenames: index = self.filenames.index(filename + '\n') self.filenames.pop(index) #ensure only 10 most recent are stored if len(self.filenames) == 10: self.filenames.pop() self.filenames.insert(0, filename + '\n') def set_history_window(self): """update the history window with info from the history file""" #clear the window self.showhistory.delete(0, END) # keep the last 10 most recent files try: view_history = open(HOME + HISTORY, 'r') for hist in view_history.readlines(): if hist not in self.filenames: self.filenames.append(hist) self.showhistory.insert(END, hist.split('\n')[0]) view_history.close() except IOError: # do nothing since history file will be created later return def run_lint(self, _=None): """launches pylint""" self.update_filenames() self.root.configure(cursor='watch') self.reporter = GUIReporter(self, output=self.report_stream) module = self.txt_module.get() if not module: module = os.getcwd() #cleaning up msgs and windows self.msgs = [] self.visible_msgs = [] self.lb_messages.delete(0, END) self.tabs = {} self.results.delete(0, END) self.btnRun.config(state=DISABLED) #setting up a worker thread to run pylint worker = Thread(target=lint_thread, args=( module, self.reporter, self, )) self.periodic_call() worker.start() # Overwrite the .pylint-gui-history file with all the new recently added files # in order from filenames but only save last 10 files write_history = open(HOME + HISTORY, 'w') write_history.writelines(self.filenames) write_history.close() self.set_history_window() self.root.configure(cursor='') def show_sourcefile(self, event=None): # pylint: disable=unused-argument selected = self.lb_messages.curselection() if not selected: return msg = self.visible_msgs[int(selected[0])] scroll = msg.line - 3 if scroll < 0: scroll = 0 self.tabs["Source File"] = open(msg.path, "r").readlines() self.box.set("Source File") self.refresh_results_window() self.results.yview(scroll) self.results.select_set(msg.line - 1)
def __init__(self, root, *args, **kw): GUIDialog.__init__(self, master=root, *args, **kw) self.qom_type_var = root.qom_type_var self.title(_("Device Tree")) self.grid() self.columnconfigure(0, weight=1, minsize=300) self.columnconfigure(2, weight=1, minsize=100) self.rowconfigure(0, weight=1) geom = "+" + str(int(root.winfo_rootx())) \ + "+" + str(int(root.winfo_rooty())) self.geometry(geom) self.focus() self.device_tree = dt = VarTreeview(self, selectmode="browse") dt["columns"] = "Macros" dt.heading("#0", text=_("Devices")) dt.heading("Macros", text=_("Macros")) dt.bind("<ButtonPress-1>", self.on_b1_press_dt) dt.grid(row=0, column=0, sticky="NEWS") add_scrollbars_native(self, dt) column_fr = Frame(self, borderwidth=0) column_fr.grid(row=0, column=2, rowspan=2, sticky="SEWN") column_fr.columnconfigure(0, weight=1) column_fr.rowconfigure(0, weight=1) column_fr.rowconfigure(1, weight=1, minsize=100) fr_at = VarLabelFrame(column_fr, text=_("Architecture filter")) fr_at.grid(row=0, column=0, sticky="SEWN") self.fr_qt = VarLabelFrame(column_fr, text=_("Select QOM type")) self.fr_qt.grid(row=1, column=0, sticky="SEWN") self.add_button = VarButton(column_fr, text=_("Select"), command=self.on_select_qom_type) self.add_button.grid(row=2, column=0, sticky="EW") self.add_button.config(state="disabled") qtype_dt = self.qtype_dt = qvd_get( root.mach.project.build_path, version=root.mach.project.target_version).qvc.device_tree arch_buttons = Frame(fr_at, borderwidth=0) arch_buttons.pack(fill="x") arch_buttons.columnconfigure(0, weight=1, minsize=60) arch_buttons.columnconfigure(1, weight=1, minsize=60) arch_buttons.columnconfigure(2, weight=1, minsize=60) bt_all_arches = VarButton(arch_buttons, text=_("All"), command=self.select_arches) bt_all_arches.grid(row=0, column=0, sticky="EW") bt_none_arches = VarButton(arch_buttons, text=_("None"), command=self.deselect_arches) bt_none_arches.grid(row=0, column=1, sticky="EW") bt_invert_arches = VarButton(arch_buttons, text=_("Invert"), command=self.invert_arches) bt_invert_arches.grid(row=0, column=2, sticky="EW") if not qtype_dt.arches: bt_all_arches.config(state="disabled") bt_none_arches.config(state="disabled") bt_invert_arches.config(state="disabled") arch_selector_outer = Frame(fr_at, borderwidth=0) arch_selector_outer.pack(fill="both", anchor="w") arch_selector, scrolltag = add_scrollbars_with_tags( arch_selector_outer, GUIFrame) ac = self.arches_checkbox = [] for a in sorted(list(qtype_dt.arches)): v = IntVar() c = Checkbutton(arch_selector, text = a, variable = v, command = lambda arch = a, var = v: \ self.on_toggle_arch(arch, var) ) c.pack(expand=1, anchor="w") c.bindtags((scrolltag, ) + c.bindtags()) c.select() ac.append(c) # key: item # value: ItemDesc self.detached_items = {} self.all_items = {} self.disabled_arches = set() self.qom_create_tree("", qtype_dt.children)
class DrtGlueDemo(object): def __init__(self, examples): # Set up the main window. self._top = Tk() self._top.title('DRT Glue Demo') # Set up key bindings. self._init_bindings() # Initialize the fonts.self._error = None self._init_fonts(self._top) self._examples = examples self._readingCache = [None for example in examples] # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Set the data to None self._curExample = -1 self._readings = [] self._drs = None self._drsWidget = None self._error = None self._init_glue() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_exampleListbox(self._top) self._init_readingListbox(self._top) self._init_canvas(self._top) # Resize callback self._canvas.bind('<Configure>', self._configure) ######################################### ## Initialization Helpers ######################################### def _init_glue(self): tagger = RegexpTagger([ ('^(David|Mary|John)$', 'NNP'), ('^(walks|sees|eats|chases|believes|gives|sleeps|chases|persuades|tries|seems|leaves)$', 'VB'), ('^(go|order|vanish|find|approach)$', 'VB'), ('^(a)$', 'ex_quant'), ('^(every)$', 'univ_quant'), ('^(sandwich|man|dog|pizza|unicorn|cat|senator)$', 'NN'), ('^(big|gray|former)$', 'JJ'), ('^(him|himself)$', 'PRP') ]) depparser = MaltParser(tagger=tagger) self._glue = DrtGlue(depparser=depparser, remove_duplicates=False) def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = Font(family='helvetica', weight='bold', size=self._size.get()) self._font = Font(family='helvetica', size=self._size.get()) if self._size.get() < 0: big = self._size.get() - 2 else: big = self._size.get() + 2 self._bigfont = Font(family='helvetica', weight='bold', size=big) def _init_exampleListbox(self, parent): self._exampleFrame = listframe = Frame(parent) self._exampleFrame.pack(fill='both', side='left', padx=2) self._exampleList_label = Label(self._exampleFrame, font=self._boldfont, text='Examples') self._exampleList_label.pack() self._exampleList = Listbox(self._exampleFrame, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._exampleList.pack(side='right', fill='both', expand=1) for example in self._examples: self._exampleList.insert('end', (' %s' % example)) self._exampleList.config(height=min(len(self._examples), 25), width=40) # Add a scrollbar if there are more than 25 examples. if len(self._examples) > 25: listscroll = Scrollbar(self._exampleFrame, orient='vertical') self._exampleList.config(yscrollcommand=listscroll.set) listscroll.config(command=self._exampleList.yview) listscroll.pack(side='left', fill='y') # If they select a example, apply it. self._exampleList.bind('<<ListboxSelect>>', self._exampleList_select) def _init_readingListbox(self, parent): self._readingFrame = listframe = Frame(parent) self._readingFrame.pack(fill='both', side='left', padx=2) self._readingList_label = Label(self._readingFrame, font=self._boldfont, text='Readings') self._readingList_label.pack() self._readingList = Listbox(self._readingFrame, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0') self._readingList.pack(side='right', fill='both', expand=1) # Add a scrollbar if there are more than 25 examples. listscroll = Scrollbar(self._readingFrame, orient='vertical') self._readingList.config(yscrollcommand=listscroll.set) listscroll.config(command=self._readingList.yview) listscroll.pack(side='right', fill='y') self._populate_readingListbox() def _populate_readingListbox(self): # Populate the listbox with integers self._readingList.delete(0, 'end') for i in range(len(self._readings)): self._readingList.insert('end', (' %s' % (i + 1))) self._readingList.config(height=min(len(self._readings), 25), width=5) # If they select a example, apply it. self._readingList.bind('<<ListboxSelect>>', self._readingList_select) def _init_bindings(self): # Key bindings are a good thing. self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Escape>', self.destroy) self._top.bind('n', self.next) self._top.bind('<space>', self.next) self._top.bind('p', self.prev) self._top.bind('<BackSpace>', self.prev) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom', padx=3, pady=2) Button( buttonframe, text='Prev', background='#90c0d0', foreground='black', command=self.prev, ).pack(side='left') Button( buttonframe, text='Next', background='#90c0d0', foreground='black', command=self.next, ).pack(side='left') def _configure(self, event): self._autostep = 0 (x1, y1, x2, y2) = self._cframe.scrollregion() y2 = event.height - 6 self._canvas['scrollregion'] = '%d %d %d %d' % (x1, y1, x2, y2) self._redraw() def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background='white', #width=525, height=250, closeenough=10, border=2, relief='sunken') self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() # Initially, there's no tree or text self._tree = None self._textwidgets = [] self._textline = None def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='q') menubar.add_cascade(label='File', underline=0, menu=filemenu) actionmenu = Menu(menubar, tearoff=0) actionmenu.add_command(label='Next', underline=0, command=self.next, accelerator='n, Space') actionmenu.add_command(label='Previous', underline=0, command=self.prev, accelerator='p, Backspace') menubar.add_cascade(label='Action', underline=0, menu=actionmenu) optionmenu = Menu(menubar, tearoff=0) optionmenu.add_checkbutton(label='Remove Duplicates', underline=0, variable=self._glue.remove_duplicates, command=self._toggle_remove_duplicates, accelerator='r') menubar.add_cascade(label='Options', underline=0, menu=optionmenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_radiobutton(label='Tiny', variable=self._size, underline=0, value=10, command=self.resize) viewmenu.add_radiobutton(label='Small', variable=self._size, underline=0, value=12, command=self.resize) viewmenu.add_radiobutton(label='Medium', variable=self._size, underline=0, value=14, command=self.resize) viewmenu.add_radiobutton(label='Large', variable=self._size, underline=0, value=18, command=self.resize) viewmenu.add_radiobutton(label='Huge', variable=self._size, underline=0, value=24, command=self.resize) menubar.add_cascade(label='View', underline=0, menu=viewmenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) ######################################### ## Main draw procedure ######################################### def _redraw(self): canvas = self._canvas # Delete the old DRS, widgets, etc. if self._drsWidget is not None: self._drsWidget.clear() if self._drs: self._drsWidget = DrsWidget(self._canvas, self._drs) self._drsWidget.draw() if self._error: self._drsWidget = DrsWidget(self._canvas, self._error) self._drsWidget.draw() ######################################### ## Button Callbacks ######################################### def destroy(self, *e): self._autostep = 0 if self._top is None: return self._top.destroy() self._top = None def prev(self, *e): selection = self._readingList.curselection() readingListSize = self._readingList.size() # there are readings if readingListSize > 0: # if one reading is currently selected if len(selection) == 1: index = int(selection[0]) # if it's on (or before) the first item if index <= 0: self._select_previous_example() else: self._readingList_store_selection(index - 1) else: #select its first reading self._readingList_store_selection(readingListSize - 1) else: self._select_previous_example() def _select_previous_example(self): #if the current example is not the first example if self._curExample > 0: self._exampleList_store_selection(self._curExample - 1) else: #go to the last example self._exampleList_store_selection(len(self._examples) - 1) def next(self, *e): selection = self._readingList.curselection() readingListSize = self._readingList.size() # if there are readings if readingListSize > 0: # if one reading is currently selected if len(selection) == 1: index = int(selection[0]) # if it's on (or past) the last item if index >= (readingListSize - 1): self._select_next_example() else: self._readingList_store_selection(index + 1) else: #select its first reading self._readingList_store_selection(0) else: self._select_next_example() def _select_next_example(self): #if the current example is not the last example if self._curExample < len(self._examples) - 1: self._exampleList_store_selection(self._curExample + 1) else: #go to the first example self._exampleList_store_selection(0) def about(self, *e): ABOUT = ( "NLTK Discourse Representation Theory (DRT) Glue Semantics Demo\n" + "Written by Daniel H. Garrette") TITLE = 'About: NLTK DRT Glue Demo' try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def postscript(self, *e): self._autostep = 0 self._cframe.print_to_file() 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 resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) self._bigfont.configure(size=-(abs(size + 2))) self._redraw() def _toggle_remove_duplicates(self): self._glue.remove_duplicates = not self._glue.remove_duplicates self._exampleList.selection_clear(0, 'end') self._readings = [] self._populate_readingListbox() self._readingCache = [None for ex in self._examples] self._curExample = -1 self._error = None self._drs = None self._redraw() def _exampleList_select(self, event): selection = self._exampleList.curselection() if len(selection) != 1: return self._exampleList_store_selection(int(selection[0])) def _exampleList_store_selection(self, index): self._curExample = index example = self._examples[index] self._exampleList.selection_clear(0, 'end') if example: cache = self._readingCache[index] if cache: if isinstance(cache, list): self._readings = cache self._error = None else: self._readings = [] self._error = cache else: try: self._readings = self._glue.parse_to_meaning(example) self._error = None self._readingCache[index] = self._readings except Exception as e: self._readings = [] self._error = DrtVariableExpression( Variable('Error: ' + str(e))) self._readingCache[index] = self._error #add a star to the end of the example self._exampleList.delete(index) self._exampleList.insert(index, (' %s *' % example)) self._exampleList.config(height=min( len(self._examples), 25), width=40) self._populate_readingListbox() self._exampleList.selection_set(index) self._drs = None self._redraw() def _readingList_select(self, event): selection = self._readingList.curselection() if len(selection) != 1: return self._readingList_store_selection(int(selection[0])) def _readingList_store_selection(self, index): reading = self._readings[index] self._readingList.selection_clear(0, 'end') if reading: self._readingList.selection_set(index) self._drs = reading.simplify().normalize().resolve_anaphora() self._redraw()
class CanvasDnD(Canvas): unbind = unbind def __init__(self, master, id_priority_sort_function=lambda ids: ids, mesh_step=20, **kw): # override some defaults for arg, val in [("width", 100), ("height", 100), ("relief", RIDGE), ("background", "white"), ("borderwidth", 1)]: kw.setdefault(arg, val) Canvas.__init__(self, master, **kw) self.align = False self.mesh_step = IntVar(value=mesh_step) self._state = None self.off = None self.bind("<ButtonPress-1>", self.down, "+") self.bind("<ButtonRelease-1>", self.up, "+") self.bind("<ButtonPress-3>", self.b3down, "+") self.bind("<ButtonRelease-3>", self.b3up, "+") self.bind("<Motion>", self.motion, "+") self.id_priority_sort_function = id_priority_sort_function # backward compatibility properties @property def dragging(self): return self._state is dragging def down(self, event): x, y = event.widget.canvasx(event.x), event.widget.canvasy(event.y) touched = self.find_overlapping(x - 1, y - 1, x + 1, y + 1) touched = [t for t in touched if ("DnD" in self.gettags(t))] if not touched: return touched = self.id_priority_sort_function(touched) self.dnd_dragged = touched[0] offset = event.widget.coords(self.dnd_dragged) self.off = (x - offset[0], y - offset[1]) #print str((x,y)) + " - " + str(self.off) self._state = dragging self.event_generate('<<DnDDown>>') def motion(self, event): x, y = event.x, event.y if self._state is begin_drag_all: # if user moved mouse far enough then begin dragging of all ox, oy = self.off # Use Manchester metric to speed up the check dx, dy = abs(x - ox), abs(y - oy) if dx + dy > DRAG_GAP: self._state = dragging_all self.scan_mark(ox, oy) self.master.config(cursor="fleur") # Dragging of all items is just actually started self.event_generate("<<DnDAll>>") if self._state is dragging_all: self.scan_dragto(x, y, gain=1) self.scan_mark(x, y) self.event_generate("<<DnDAllMoved>>") return elif self._state is not dragging: return self.master.config(cursor="fleur") xy = self.canvasx(event.x), self.canvasy(event.y) points = self.coords(self.dnd_dragged) offset = self.off if self.align: new_pos = ( xy[0] - offset[0], xy[1] - offset[1], ) m = self.mesh_step.get() aligned_pos = (int(new_pos[0] / m) * m, int(new_pos[1] / m) * m) align_gain = (aligned_pos[0] - new_pos[0], aligned_pos[1] - new_pos[1]) else: align_gain = (0, 0) dxy = (xy[0] - (points[0] + offset[0]) + align_gain[0], xy[1] - (points[1] + offset[1]) + align_gain[1]) #print str(points) + " - " + str(self.off) tags = self.gettags(self.dnd_dragged) if "fixed_x" not in tags: for idx in xrange(0, len(points), 2): points[idx] = dxy[0] + points[idx] if "fixed_y" not in tags: for idx in xrange(1, len(points), 2): points[idx] = dxy[1] + points[idx] #print points self.coords(*([self.dnd_dragged] + points)) self.event_generate('<<DnDMoved>>') def up(self, event): if self._state is dragging: self.master.config(cursor="") self._state = None self.off = None self.event_generate('<<DnDUp>>') """ Right after event. Listeners should be able to get which id is not dragged now. """ del self.dnd_dragged def b3down(self, event): if self._state is not None: return # User already using mouse for something # prepare for dragging of all self.off = event.x, event.y self._state = begin_drag_all # Dragging all items sequence begun self.event_generate("<<DnDAllDown>>") def b3up(self, _): if self._state in (dragging_all, begin_drag_all): # reset dragging of all self.master.config(cursor="") # Dragging all items sequence finished self.event_generate("<<DnDAllUp>>") # Reset _state after the event. So, user may distinguish was a # dragging took place. self._state = None
def __init__(self, *args, **kwargs): TkToolWindow.__init__(self, *args, **kwargs) Observable.__init__(self) self.__serialmap = None # Temporarily self.inst = Inst() # End Temporarily #window = self.tk_object tooltab = Frame(self._tool_tabs) self._tool_tabs.add(tooltab, text='SPI') #tooltab.pack(expand='yes', fill='x') # Group OPEN open_group = Group(tooltab) open_group.name = 'Open Device' open_group.pack(side='left', fill='y', expand='yes') self.__dev_combo = dev_combo = Combobox(open_group, value=[], takefocus=1, stat='readonly', width=12) dev_combo.bind('<<ComboboxSelected>>', self._on_dev_change) self.__current_serialno = None dev_combo.pack(side='top') self.__is_opened = IntVar(0) self.__open_check = open_check = Checkbutton( open_group, text='Open', variable=self.__is_opened, command=self._on_open_click) open_check.pack(expand='yes', fill='y', side='top') # End Group Open # Group Parameters param_group = Group(tooltab) param_group.name = 'Parameters' param_group.pack(side='left') Button(param_group, text='Configure', command=self._on_param_change).pack(side='bottom') param_frame = Frame(param_group) param_frame.pack() self.__CPOL = CPOL = IntVar(0) self.__CPHA = CPHA = IntVar(0) Checkbutton(param_frame, text='CPOL', variable=CPOL).grid(row=0, column=0) Checkbutton(param_frame, text='CPHA', variable=CPHA).grid(row=1, column=0) self.__baud_combo = baud_combo = Combobox(param_frame, value=[], takefocus=1, stat='readonly', width=8) baud_combo.grid(row=0, column=1, columnspan=2) self.__read_timeout_str = r_timeout = StringVar() self.__write_timeout_str = w_timeout = StringVar() Entry(param_frame, textvariable=r_timeout, width=5).grid(row=1, column=1) Entry(param_frame, textvariable=w_timeout, width=5).grid(row=1, column=2) # End Group Parameters # Write Group write_group = Group(tooltab) write_group.name = 'Write' write_group.pack(side='left', fill='y', expand='yes') self.__writebuf = writebuf = StringVar() Entry(write_group, textvariable=writebuf).pack() Button(write_group, text='Write', command=self._on_write_click).pack() # End Write Group self._make_window_manager_tab() # To Do: a driver group for loading specified spi bus driver converter = USBSPIConverter() converter.add_observer(self) self.add_observer(converter)
class USBSPIWindow(TkToolWindow, Observable): '''A control panel for USB to SPI converter.''' def __init__(self, *args, **kwargs): TkToolWindow.__init__(self, *args, **kwargs) Observable.__init__(self) self.__serialmap = None # Temporarily self.inst = Inst() # End Temporarily #window = self.tk_object tooltab = Frame(self._tool_tabs) self._tool_tabs.add(tooltab, text='SPI') #tooltab.pack(expand='yes', fill='x') # Group OPEN open_group = Group(tooltab) open_group.name = 'Open Device' open_group.pack(side='left', fill='y', expand='yes') self.__dev_combo = dev_combo = Combobox(open_group, value=[], takefocus=1, stat='readonly', width=12) dev_combo.bind('<<ComboboxSelected>>', self._on_dev_change) self.__current_serialno = None dev_combo.pack(side='top') self.__is_opened = IntVar(0) self.__open_check = open_check = Checkbutton( open_group, text='Open', variable=self.__is_opened, command=self._on_open_click) open_check.pack(expand='yes', fill='y', side='top') # End Group Open # Group Parameters param_group = Group(tooltab) param_group.name = 'Parameters' param_group.pack(side='left') Button(param_group, text='Configure', command=self._on_param_change).pack(side='bottom') param_frame = Frame(param_group) param_frame.pack() self.__CPOL = CPOL = IntVar(0) self.__CPHA = CPHA = IntVar(0) Checkbutton(param_frame, text='CPOL', variable=CPOL).grid(row=0, column=0) Checkbutton(param_frame, text='CPHA', variable=CPHA).grid(row=1, column=0) self.__baud_combo = baud_combo = Combobox(param_frame, value=[], takefocus=1, stat='readonly', width=8) baud_combo.grid(row=0, column=1, columnspan=2) self.__read_timeout_str = r_timeout = StringVar() self.__write_timeout_str = w_timeout = StringVar() Entry(param_frame, textvariable=r_timeout, width=5).grid(row=1, column=1) Entry(param_frame, textvariable=w_timeout, width=5).grid(row=1, column=2) # End Group Parameters # Write Group write_group = Group(tooltab) write_group.name = 'Write' write_group.pack(side='left', fill='y', expand='yes') self.__writebuf = writebuf = StringVar() Entry(write_group, textvariable=writebuf).pack() Button(write_group, text='Write', command=self._on_write_click).pack() # End Write Group self._make_window_manager_tab() # To Do: a driver group for loading specified spi bus driver converter = USBSPIConverter() converter.add_observer(self) self.add_observer(converter) def _on_dev_change(self, event): # User selects another device via dev_combo. '''Called when user selects another device via dev_combo.''' dev_combo = self.__dev_combo self.__current_serialno = serialno = dev_combo.get() print(serialno) self.__is_opened.set(self.__serialmap[serialno].is_opened) print(self.__serialmap[serialno].is_opened) self.__baud_combo['values'] = self.__serialmap[serialno].baudrate_range def _on_open_click(self): open_or_close = self.__is_opened.get() serialno = self.__dev_combo.get() with code_printer(): if open_or_close: self.open_device(serialno) else: self.close_device(serialno) @WaveSynScriptAPI def open_device(self, serial_number): self.notify_observers( CommandSlot(command='open', args=(serial_number, True))) @WaveSynScriptAPI def close_device(self, serial_number): self.notify_observers( CommandSlot(command='open', args=(serial_number, False))) def _on_param_change(self): serialno = self.__dev_combo.get() baudrate = int(self.__baud_combo.get()) CPOL = self.__CPOL.get() CPHA = self.__CPHA.get() read_timeout = int(self.__read_timeout_str.get()) write_timeout = int(self.__write_timeout_str.get()) kwargs = {} kwargs['serial_number'] = serialno kwargs['is_master'] = True kwargs['baudrate'] = baudrate kwargs['CPHA'] = CPHA kwargs['CPOL'] = CPOL kwargs['read_timeout'] = read_timeout kwargs['write_timeout'] = write_timeout with code_printer(): self.configure_device(**kwargs) @WaveSynScriptAPI def configure_device(self, serial_number, is_master, baudrate, CPHA, CPOL, read_timeout, write_timeout): self.notify_observers( CommandSlot(command='config', args=(serial_number, is_master, baudrate, CPHA, CPOL, read_timeout, write_timeout))) def _on_write_click(self): serialno = self.__dev_combo.get() data = self.__writebuf.get() if len(data) % 2 != 0: data += '0' data_list = [ int(data[(k * 2):(k * 2 + 2)], base=16) for k in range(len(data) // 2) ] with code_printer(): self.write_bytes(serial_number=serialno, data=data_list) @WaveSynScriptAPI def write_bytes(self, serial_number, data): length = len(data) buf = (wintypes.BYTE * length)() for index, d in enumerate(data): if d > 255: raise ValueError('Value of bytes should less than 256.') buf[index] = d self.notify_observers( CommandSlot(command='write', args=(serial_number, buf))) def update( self, serialmap): # Notice: tk_object also has a method named "update". '''Called when the underlying USBSPI class catches an USB change event.''' # print(serialmap) dev_combo = self.__dev_combo current_text = dev_combo.get() try: current_dev = serialmap[current_text] current_index = current_dev.handle except KeyError: current_index = -1 dev_combo['values'] = list(iterkeys(serialmap)) if current_index == -1: # which means the current selected device has been plugged out. dev_combo.set('') else: dev_combo.current(current_index) dev_info = serialmap[current_text] self.__CPOL.set(dev_info.CPOL) self.__CPHA.set(dev_info.CPHA) self.__baud_combo.current( current_dev.baudrate_range.index(dev_info.baudrate)) self.__read_timeout_str.set(str(dev_info.read_timeout)) self.__write_timeout_str.set(str(dev_info.write_timeout)) self.__serialmap = serialmap @staticmethod def to_bytes(integer): if integer < 0: raise ValueError('Integer should be non-negative.') byte_list = [] while True: byte = integer & 0xFF byte_list.insert(0, byte) integer >>= 8 if integer == 0: break return byte_list
def get(self): h = IntVar.get(self) return ref_objects[h]
def __init__(self, project=None): GUITk.__init__(self, wait_msec=1) for signame in ["qvc_dirtied", "qvd_failed", "qvc_available"]: s = CoSignal() s.attach(self.signal_dispatcher) setattr(self, "sig_" + signame, s) self.title_suffix = _("Qemu device creator GUI") self.title_suffix.trace_variable("w", self.__on_title_suffix_write__) self.title_not_saved_asterisk = StringVar() self.title_not_saved_asterisk.trace_variable( "w", self.__on_title_suffix_write__) self.saved_operation = None self.var_title = StringVar() self.title(self.var_title) # Hot keys, accelerators self.hk = hotkeys = HotKey(self) hotkeys.add_bindings([ HotKeyBinding( self.invert_history_window, key_code=43, description=_("If editing history window is hidden then \ show it else hide it."), symbol="H"), HotKeyBinding(self.on_load, key_code=32, description=_("Load project from file."), symbol="O"), HotKeyBinding(self.on_new_project, key_code=57, description=_("Create new project."), symbol="N"), HotKeyBinding(self.on_add_description, key_code=40, description=_("Add description to the project"), symbol="D"), HotKeyBinding(self.on_set_qemu_build_path, key_code=56, description=_("Set Qemu build path for the project"), symbol="B"), HotKeyBinding( self.on_sel_tgt_qemu_version, key_code=28, description=_("Select target Qemu version for the project"), symbol="T"), HotKeyBinding(self.on_generate, key_code=42, description=_("Launch code generation"), symbol="G"), HotKeyBinding(self.on_delete, key_code=24, description=_("Shutdown the application."), symbol="Q"), HotKeyBinding(self.undo, key_code=52, description=_("Revert previous editing."), symbol="Z"), HotKeyBinding(self.redo, key_code=29, description=_("Make reverted editing again."), symbol="Y"), HotKeyBinding(self.on_save, key_code=39, description=_("Save project."), symbol="S"), HotKeyBinding(self.on_reload, key_code=27, description=_("Reload current project from file."), symbol="R") ]) # see `set_user_settings` self._user_settings = None # Menu bar menubar = VarMenu(self) self.filemenu = filemenu = VarMenu(menubar, tearoff=False) filemenu.add_command(label=_("Add description"), command=self.on_add_description, accelerator=hotkeys.get_keycode_string( self.on_add_description)) filemenu.add_command(label=_("Set Qemu build path"), command=self.on_set_qemu_build_path, accelerator=hotkeys.get_keycode_string( self.on_set_qemu_build_path)) filemenu.add_command(label=_("Select target Qemu version"), command=self.on_sel_tgt_qemu_version, accelerator=hotkeys.get_keycode_string( self.on_sel_tgt_qemu_version)) filemenu.add_command(label=_("Generate"), command=self.on_generate, accelerator=hotkeys.get_keycode_string( self.on_generate)) filemenu.add_separator() filemenu.add_command(label=_("New project"), command=self.on_new_project, accelerator=hotkeys.get_keycode_string( self.on_new_project)), filemenu.add_command(label=_("Save"), command=self.on_save, accelerator=hotkeys.get_keycode_string( self.on_save)), filemenu.add_command(label=_("Save project as..."), command=self.on_save_as) filemenu.add_command(label=_("Load"), command=self.on_load, accelerator=hotkeys.get_keycode_string( self.on_load)), self.reload_idx = filemenu.count filemenu.add_command(label=_("Reload"), command=self.on_reload, accelerator=hotkeys.get_keycode_string( self.on_reload)), self.recentmenu = recentmenu = VarMenu(filemenu, tearoff=False) filemenu.add_cascade( label=_("Recent projects"), menu=recentmenu, state=DISABLED # a user settings instance is required ) filemenu.add_separator() filemenu.add_command(label=_("Quit"), command=self.quit, accelerator=hotkeys.get_keycode_string( self.on_delete)) menubar.add_cascade(label=_("File"), menu=filemenu) self.editmenu = editmenu = VarMenu(menubar, tearoff=False) editmenu.add_command(label=_("Undo"), command=self.undo, accelerator=hotkeys.get_keycode_string(self.undo)) self.undo_idx = editmenu.count - 1 editmenu.add_command(label=_("Redo"), command=self.redo, accelerator=hotkeys.get_keycode_string(self.redo)) self.redo_idx = editmenu.count - 1 editmenu.add_separator() editmenu.add_command(label=_("Rebuild Cache"), command=self.rebuild_cache, accelerator=hotkeys.get_keycode_string( self.rebuild_cache)) editmenu.add_separator() v = self.var_history_window = BooleanVar() v.set(False) self.__on_var_history_window = v.trace_variable( "w", self.__on_var_history_window__) editmenu.add_checkbutton(label=_("Editing history window"), variable=v, accelerator=hotkeys.get_keycode_string( self.invert_history_window)) menubar.add_cascade(label=_("Edit"), menu=editmenu) self.optionsmenu = optionsmenu = VarMenu(menubar, tearoff=False) v = self.var_schedule_generation = BooleanVar() v.set(False) self.__on_var_schedule_generation = v.trace_variable( "w", self.__on_var_schedule_generation__) optionsmenu.add_checkbutton( label=_("Schedule generation after cache loading"), variable=v) v = self.var_gen_chunk_graphs = BooleanVar() v.set(False) self.__on_var_gen_chunk_graphs = v.trace_variable( "w", self.__on_var_gen_chunk_graphs__) optionsmenu.add_checkbutton(label=_("Generate chunk graphs"), variable=v) menubar.add_cascade(label=_("Options"), menu=optionsmenu) self.config(menu=menubar) # Widget layout self.grid() self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) # Status bar self.grid_rowconfigure(1, weight=0) self.sb = sb = Statusbar(self) sb.grid(row=1, column=0, sticky="NEWS") # Target Qemu version in the status bar self._target_qemu = Variable(None) # This complicated scheme is required because the status must also # be updated on language change. @as_variable(self._target_qemu, _("No target"), _("Target Qemu: %s")) def var_target_qemu(target, no_target, target_qemu): if target is None: return no_target else: return target_qemu % target sb.left(var_target_qemu) # QEMU build path displaying self.var_qemu_build_path = StringVar() sb.left(self.var_qemu_build_path) # Task counters in status bar self.var_tasks = vt = IntVar() self.var_callers = vc = IntVar() self.var_active_tasks = vat = IntVar() self.var_finished_tasks = vft = IntVar() sb.right(_("Background tasks: ")) sb.right(FormatVar(value="%u") % vt, fg="red") sb.right(FormatVar(value="%u") % vc, fg="orange") sb.right(FormatVar(value="%u") % vat) sb.right(FormatVar(value="%u") % vft, fg="grey") self.task_manager.watch_activated(self.__on_task_state_changed) self.task_manager.watch_finished(self.__on_task_state_changed) self.task_manager.watch_failed(self.__on_task_state_changed) self.task_manager.watch_removed(self.__on_task_state_changed) self.signal_dispatcher.watch_failed(self.__on_listener_failed) self.protocol("WM_DELETE_WINDOW", self.on_delete) self.set_project(GUIProject() if project is None else project) self.__update_title__() self.__check_saved_asterisk__() self.qsig_watch("qvc_available", self.__on_qvc_available)
for col in kw["columns"]: self.column(col, stretch = False) tv = TestTV(root) tv.grid(row = 0, column = 0, sticky = "NEWS") from six.moves.tkinter import ( BooleanVar, IntVar, DoubleVar ) sv = StringVar(value = "xxx...") bv = BooleanVar(value = True) iv = IntVar(value = 0) dv = DoubleVar(value = 1.0) tv.insert("", 0, values = [sv, bv, iv, dv]) tv.insert("", 1, values = [bv, iv, dv, sv]) tv.insert("", 2, values = [iv, dv, sv, bv]) tv.insert("", 3, values = [dv, sv, bv, iv]) def update(): s = sv.get() s = s[-1] + s[:-1] sv.set(s) bv.set(not bv.get()) iv.set(iv.get() + 1) dv.set(dv.get() + 0.1)
class CanvasDnD(GUIFrame): def __init__(self, master, id_priority_sort_function = lambda ids : ids, mesh_step = 20 ): GUIFrame.__init__ (self, master) self.canvas = Canvas (self, width = 100, # default width height = 100, # default height relief = RIDGE, background = "white", borderwidth = 1 ) self.canvas.pack(expand = 1, fill = BOTH) self.align = False self.mesh_step = IntVar(value = mesh_step) self.dragging = False self.off = None self.canvas.bind("<ButtonPress-1>", self.down, "+") self.canvas.bind("<ButtonRelease-1>", self.up, "+") self.canvas.bind("<Motion>", self.motion, "+") self.id_priority_sort_function = id_priority_sort_function def down(self, event): x, y = event.widget.canvasx(event.x), event.widget.canvasy(event.y) touched = self.canvas.find_overlapping(x - 1, y - 1, x + 1, y + 1) touched = [ t for t in touched if ("DnD" in self.canvas.gettags(t)) ] if not touched: return touched = self.id_priority_sort_function(touched) self.dnd_dragged = touched[0] offset = event.widget.coords(self.dnd_dragged) self.off = (x - offset[0], y - offset[1]) #print str((x,y)) + " - " + str(self.off) self.dragging = True self.event_generate('<<DnDDown>>') def motion(self, event): if not self.dragging: return self.master.config(cursor = "fleur") c = self.canvas xy = c.canvasx(event.x), c.canvasy(event.y) points = c.coords(self.dnd_dragged) offset = self.off if self.align: new_pos = ( xy[0] - offset[0], xy[1] - offset[1], ) m = self.mesh_step.get() aligned_pos = ( int(new_pos[0] / m) * m, int(new_pos[1] / m) * m ) align_gain = ( aligned_pos[0] - new_pos[0], aligned_pos[1] - new_pos[1] ) else: align_gain = (0, 0) dxy = ( xy[0] - (points[0] + offset[0]) + align_gain[0], xy[1] - (points[1] + offset[1]) + align_gain[1] ) #print str(points) + " - " + str(self.off) tags = c.gettags(self.dnd_dragged) if "fixed_x" not in tags: for idx in xrange(0, len(points), 2): points[idx] = dxy[0] + points[idx] if "fixed_y" not in tags: for idx in xrange(1, len(points), 2): points[idx] = dxy[1] + points[idx] #print points c.coords(*([self.dnd_dragged] + points)) self.event_generate('<<DnDMoved>>') def up(self, event): if self.dragging: self.master.config(cursor = "") self.dragging = False self.off = None self.event_generate('<<DnDUp>>') """ Right after event. Listeners should be able to get which id is not dragged now. """ del self.dnd_dragged
def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="Ctrl-q") menubar.add_cascade(label="File", underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton( label="20", variable=self._result_size, underline=0, value=20, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="50", variable=self._result_size, underline=0, value=50, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="100", variable=self._result_size, underline=0, value=100, command=self.set_result_size, ) rescntmenu.invoke(1) editmenu.add_cascade(label="Result Count", underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton( label="60 characters", variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len, ) cntxbfmenu.add_radiobutton( label="80 characters", variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len, ) cntxbfmenu.add_radiobutton( label="100 characters", variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len, ) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label="Before", underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton( label="70 characters", variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len, ) cntxafmenu.add_radiobutton( label="90 characters", variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len, ) cntxafmenu.add_radiobutton( label="110 characters", variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len, ) cntxafmenu.invoke(1) cntxmenu.add_cascade(label="After", underline=0, menu=cntxafmenu) editmenu.add_cascade(label="Context", underline=0, menu=cntxmenu) menubar.add_cascade(label="Edit", underline=0, menu=editmenu) self.top.config(menu=menubar)
class RecursiveDescentApp(object): """ A graphical tool for exploring the recursive descent parser. The tool displays the parser's tree and the remaining text, and allows the user to control the parser's operation. In particular, the user can expand subtrees on the frontier, match tokens on the frontier against the text, and backtrack. A "step" button simply steps through the parsing process, performing the operations that ``RecursiveDescentParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingRecursiveDescentParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Recursive Descent Parser Application') # Set up key bindings. self._init_bindings() # Initialize the fonts. self._init_fonts(self._top) # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animation_frames = IntVar(self._top) self._animation_frames.set(5) self._animating_lock = 0 self._autostep = 0 # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # Initialize the parser. self._parser.initialize(self._sent) # Resize callback self._canvas.bind('<Configure>', self._configure) ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = Font(family='helvetica', weight='bold', size=self._size.get()) self._font = Font(family='helvetica', size=self._size.get()) if self._size.get() < 0: big = self._size.get() - 2 else: big = self._size.get() + 2 self._bigfont = Font(family='helvetica', weight='bold', size=big) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label( self._prodframe, font=self._boldfont, text='Available Expansions' ) self._prodlist_label.pack() self._prodlist = Listbox( self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0', ) self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand=listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) def _init_bindings(self): # Key bindings are a good thing. self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Escape>', self.destroy) self._top.bind('e', self.expand) # self._top.bind('<Alt-e>', self.expand) # self._top.bind('<Control-e>', self.expand) self._top.bind('m', self.match) self._top.bind('<Alt-m>', self.match) self._top.bind('<Control-m>', self.match) self._top.bind('b', self.backtrack) self._top.bind('<Alt-b>', self.backtrack) self._top.bind('<Control-b>', self.backtrack) self._top.bind('<Control-z>', self.backtrack) self._top.bind('<BackSpace>', self.backtrack) self._top.bind('a', self.autostep) # self._top.bind('<Control-a>', self.autostep) self._top.bind('<Control-space>', self.autostep) self._top.bind('<Control-c>', self.cancel_autostep) self._top.bind('<space>', self.step) self._top.bind('<Delete>', self.reset) self._top.bind('<Control-p>', self.postscript) # self._top.bind('<h>', self.help) # self._top.bind('<Alt-h>', self.help) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) # self._top.bind('<g>', self.toggle_grammar) # self._top.bind('<Alt-g>', self.toggle_grammar) # self._top.bind('<Control-g>', self.toggle_grammar) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom', padx=3, pady=2) Button( buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step, ).pack(side='left') Button( buttonframe, text='Autostep', background='#90c0d0', foreground='black', command=self.autostep, ).pack(side='left') Button( buttonframe, text='Expand', underline=0, background='#90f090', foreground='black', command=self.expand, ).pack(side='left') Button( buttonframe, text='Match', underline=0, background='#90f090', foreground='black', command=self.match, ).pack(side='left') Button( buttonframe, text='Backtrack', underline=0, background='#f0a0a0', foreground='black', command=self.backtrack, ).pack(side='left') # Replace autostep... # self._autostep_button = Button(buttonframe, text='Autostep', # underline=0, command=self.autostep) # self._autostep_button.pack(side='left') def _configure(self, event): self._autostep = 0 (x1, y1, x2, y2) = self._cframe.scrollregion() y2 = event.height - 6 self._canvas['scrollregion'] = '%d %d %d %d' % (x1, y1, x2, y2) self._redraw() def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label( feedbackframe, text='Last Operation:', font=self._font ) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label( lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font ) self._lastoper2 = Label( lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font, ) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background='white', # width=525, height=250, closeenough=10, border=2, relief='sunken', ) self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() # Initially, there's no tree or text self._tree = None self._textwidgets = [] self._textline = None def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command( label='Reset Parser', underline=0, command=self.reset, accelerator='Del' ) filemenu.add_command( label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p', ) filemenu.add_command( label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x' ) menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command( label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g', ) editmenu.add_command( label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t', ) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command( label='Step', underline=1, command=self.step, accelerator='Space' ) rulemenu.add_separator() rulemenu.add_command( label='Match', underline=0, command=self.match, accelerator='Ctrl-m' ) rulemenu.add_command( label='Expand', underline=0, command=self.expand, accelerator='Ctrl-e' ) rulemenu.add_separator() rulemenu.add_command( label='Backtrack', underline=0, command=self.backtrack, accelerator='Ctrl-b' ) menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton( label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar, ) viewmenu.add_separator() viewmenu.add_radiobutton( label='Tiny', variable=self._size, underline=0, value=10, command=self.resize, ) viewmenu.add_radiobutton( label='Small', variable=self._size, underline=0, value=12, command=self.resize, ) viewmenu.add_radiobutton( label='Medium', variable=self._size, underline=0, value=14, command=self.resize, ) viewmenu.add_radiobutton( label='Large', variable=self._size, underline=0, value=18, command=self.resize, ) viewmenu.add_radiobutton( label='Huge', variable=self._size, underline=0, value=24, command=self.resize, ) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton( label="No Animation", underline=0, variable=self._animation_frames, value=0 ) animatemenu.add_radiobutton( label="Slow Animation", underline=0, variable=self._animation_frames, value=10, accelerator='-', ) animatemenu.add_radiobutton( label="Normal Animation", underline=0, variable=self._animation_frames, value=5, accelerator='=', ) animatemenu.add_radiobutton( label="Fast Animation", underline=0, variable=self._animation_frames, value=2, accelerator='+', ) menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command( label='Instructions', underline=0, command=self.help, accelerator='F1' ) menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) ######################################### ## Helper ######################################### def _get(self, widget, treeloc): for i in treeloc: widget = widget.subtrees()[i] if isinstance(widget, TreeSegmentWidget): widget = widget.label() return widget ######################################### ## Main draw procedure ######################################### def _redraw(self): canvas = self._canvas # Delete the old tree, widgets, etc. if self._tree is not None: self._cframe.destroy_widget(self._tree) for twidget in self._textwidgets: self._cframe.destroy_widget(twidget) if self._textline is not None: self._canvas.delete(self._textline) # Draw the tree. helv = ('helvetica', -self._size.get()) bold = ('helvetica', -self._size.get(), 'bold') attribs = { 'tree_color': '#000000', 'tree_width': 2, 'node_font': bold, 'leaf_font': helv, } tree = self._parser.tree() self._tree = tree_to_treesegment(canvas, tree, **attribs) self._cframe.add_widget(self._tree, 30, 5) # Draw the text. helv = ('helvetica', -self._size.get()) bottom = y = self._cframe.scrollregion()[3] self._textwidgets = [ TextWidget(canvas, word, font=self._font) for word in self._sent ] for twidget in self._textwidgets: self._cframe.add_widget(twidget, 0, 0) twidget.move(0, bottom - twidget.bbox()[3] - 5) y = min(y, twidget.bbox()[1]) # Draw a line over the text, to separate it from the tree. self._textline = canvas.create_line(-5000, y - 5, 5000, y - 5, dash='.') # Highlight appropriate nodes. self._highlight_nodes() self._highlight_prodlist() # Make sure the text lines up. self._position_text() def _redraw_quick(self): # This should be more-or-less sufficient after an animation. self._highlight_nodes() self._highlight_prodlist() self._position_text() def _highlight_nodes(self): # Highlight the list of nodes to be checked. bold = ('helvetica', -self._size.get(), 'bold') for treeloc in self._parser.frontier()[:1]: self._get(self._tree, treeloc)['color'] = '#20a050' self._get(self._tree, treeloc)['font'] = bold for treeloc in self._parser.frontier()[1:]: self._get(self._tree, treeloc)['color'] = '#008080' def _highlight_prodlist(self): # Highlight the productions that can be expanded. # Boy, too bad tkinter doesn't implement Listbox.itemconfig; # that would be pretty useful here. self._prodlist.delete(0, 'end') expandable = self._parser.expandable_productions() untried = self._parser.untried_expandable_productions() productions = self._productions for index in range(len(productions)): if productions[index] in expandable: if productions[index] in untried: self._prodlist.insert(index, ' %s' % productions[index]) else: self._prodlist.insert(index, ' %s (TRIED)' % productions[index]) self._prodlist.selection_set(index) else: self._prodlist.insert(index, ' %s' % productions[index]) def _position_text(self): # Line up the text widgets that are matched against the tree numwords = len(self._sent) num_matched = numwords - len(self._parser.remaining_text()) leaves = self._tree_leaves()[:num_matched] xmax = self._tree.bbox()[0] for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] widget['color'] = '#006040' leaf['color'] = '#006040' widget.move(leaf.bbox()[0] - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # Line up the text widgets that are not matched against the tree. for i in range(len(leaves), numwords): widget = self._textwidgets[i] widget['color'] = '#a0a0a0' widget.move(xmax - widget.bbox()[0], 0) xmax = widget.bbox()[2] + 10 # If we have a complete parse, make everything green :) if self._parser.currently_complete(): for twidget in self._textwidgets: twidget['color'] = '#00a000' # Move the matched leaves down to the text. for i in range(0, len(leaves)): widget = self._textwidgets[i] leaf = leaves[i] dy = widget.bbox()[1] - leaf.bbox()[3] - 10.0 dy = max(dy, leaf.parent().label().bbox()[3] - leaf.bbox()[3] + 10) leaf.move(0, dy) def _tree_leaves(self, tree=None): if tree is None: tree = self._tree if isinstance(tree, TreeSegmentWidget): leaves = [] for child in tree.subtrees(): leaves += self._tree_leaves(child) return leaves else: return [tree] ######################################### ## Button Callbacks ######################################### def destroy(self, *e): self._autostep = 0 if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._autostep = 0 self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset Application' self._lastoper2['text'] = '' self._redraw() def autostep(self, *e): if self._animation_frames.get() == 0: self._animation_frames.set(2) if self._autostep: self._autostep = 0 else: self._autostep = 1 self._step() def cancel_autostep(self, *e): # self._autostep_button['text'] = 'Autostep' self._autostep = 0 # Make sure to stop auto-stepping if we get any user input. def step(self, *e): self._autostep = 0 self._step() def match(self, *e): self._autostep = 0 self._match() def expand(self, *e): self._autostep = 0 self._expand() def backtrack(self, *e): self._autostep = 0 self._backtrack() def _step(self): if self._animating_lock: return # Try expanding, matching, and backtracking (in that order) if self._expand(): pass elif self._parser.untried_match() and self._match(): pass elif self._backtrack(): pass else: self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' self._autostep = 0 # Check if we just completed a parse. if self._parser.currently_complete(): self._autostep = 0 self._lastoper2['text'] += ' [COMPLETE PARSE]' def _expand(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.expand() if rv is not None: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = rv self._prodlist.selection_clear(0, 'end') index = self._productions.index(rv) self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) return True else: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = '(all expansions tried)' return False def _match(self, *e): if self._animating_lock: return old_frontier = self._parser.frontier() rv = self._parser.match() if rv is not None: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = rv self._animate_match(old_frontier[0]) return True else: self._lastoper1['text'] = 'Match:' self._lastoper2['text'] = '(failed)' return False def _backtrack(self, *e): if self._animating_lock: return if self._parser.backtrack(): elt = self._parser.tree() for i in self._parser.frontier()[0]: elt = elt[i] self._lastoper1['text'] = 'Backtrack' self._lastoper2['text'] = '' if isinstance(elt, Tree): self._animate_backtrack(self._parser.frontier()[0]) else: self._animate_match_backtrack(self._parser.frontier()[0]) return True else: self._autostep = 0 self._lastoper1['text'] = 'Finished' self._lastoper2['text'] = '' return False def about(self, *e): ABOUT = ( "NLTK Recursive Descent Parser Application\n" + "Written by Edward Loper" ) TITLE = 'About: Recursive Descent Parser Application' try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def help(self, *e): self._autostep = 0 # The default font's not very legible; try using 'fixed' instead. try: ShowText( self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75, font='fixed', ) except: ShowText( self._top, 'Help: Recursive Descent Parser Application', (__doc__ or '').strip(), width=75, ) def postscript(self, *e): self._autostep = 0 self._cframe.print_to_file() 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 resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) self._bigfont.configure(size=-(abs(size + 2))) self._redraw() ######################################### ## Expand Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack( fill='both', side='left', padx=2, after=self._feedbackframe ) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' # def toggle_grammar(self, *e): # self._show_grammar = not self._show_grammar # if self._show_grammar: # self._prodframe.pack(fill='both', expand='y', side='left', # after=self._feedbackframe) # self._lastoper1['text'] = 'Show Grammar' # else: # self._prodframe.pack_forget() # self._lastoper1['text'] = 'Hide Grammar' # self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) old_frontier = self._parser.frontier() production = self._parser.expand(self._productions[index]) if production: self._lastoper1['text'] = 'Expand:' self._lastoper2['text'] = production self._prodlist.selection_clear(0, 'end') self._prodlist.selection_set(index) self._animate_expand(old_frontier[0]) else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.expandable_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Animation ######################################### def _animate_expand(self, treeloc): oldwidget = self._get(self._tree, treeloc) oldtree = oldwidget.parent() top = not isinstance(oldtree.parent(), TreeSegmentWidget) tree = self._parser.tree() for i in treeloc: tree = tree[i] widget = tree_to_treesegment( self._canvas, tree, node_font=self._boldfont, leaf_color='white', tree_width=2, tree_color='white', node_color='white', leaf_font=self._font, ) widget.label()['color'] = '#20a050' (oldx, oldy) = oldtree.label().bbox()[:2] (newx, newy) = widget.label().bbox()[:2] widget.move(oldx - newx, oldy - newy) if top: self._cframe.add_widget(widget, 0, 5) widget.move(30 - widget.label().bbox()[0], 0) self._tree = widget else: oldtree.parent().replace_child(oldtree, widget) # Move the children over so they don't overlap. # Line the children up in a strange way. if widget.subtrees(): dx = ( oldx + widget.label().width() / 2 - widget.subtrees()[0].bbox()[0] / 2 - widget.subtrees()[0].bbox()[2] / 2 ) for subtree in widget.subtrees(): subtree.move(dx, 0) self._makeroom(widget) if top: self._cframe.destroy_widget(oldtree) else: oldtree.destroy() colors = [ 'gray%d' % (10 * int(10 * x / self._animation_frames.get())) for x in range(self._animation_frames.get(), 0, -1) ] # Move the text string down, if necessary. dy = widget.bbox()[3] + 30 - self._canvas.coords(self._textline)[1] if dy > 0: for twidget in self._textwidgets: twidget.move(0, dy) self._canvas.move(self._textline, 0, dy) self._animate_expand_frame(widget, colors) def _makeroom(self, treeseg): """ Make sure that no sibling tree bbox's overlap. """ parent = treeseg.parent() if not isinstance(parent, TreeSegmentWidget): return index = parent.subtrees().index(treeseg) # Handle siblings to the right rsiblings = parent.subtrees()[index + 1 :] if rsiblings: dx = treeseg.bbox()[2] - rsiblings[0].bbox()[0] + 10 for sibling in rsiblings: sibling.move(dx, 0) # Handle siblings to the left if index > 0: lsibling = parent.subtrees()[index - 1] dx = max(0, lsibling.bbox()[2] - treeseg.bbox()[0] + 10) treeseg.move(dx, 0) # Keep working up the tree. self._makeroom(parent) def _animate_expand_frame(self, widget, colors): if len(colors) > 0: self._animating_lock = 1 widget['color'] = colors[0] for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = colors[0] else: subtree['color'] = colors[0] self._top.after(50, self._animate_expand_frame, widget, colors[1:]) else: widget['color'] = 'black' for subtree in widget.subtrees(): if isinstance(subtree, TreeSegmentWidget): subtree.label()['color'] = 'black' else: subtree['color'] = 'black' self._redraw_quick() widget.label()['color'] = 'black' self._animating_lock = 0 if self._autostep: self._step() def _animate_backtrack(self, treeloc): # Flash red first, if we're animating. if self._animation_frames.get() == 0: colors = [] else: colors = ['#a00000', '#000000', '#a00000'] colors += [ 'gray%d' % (10 * int(10 * x / (self._animation_frames.get()))) for x in range(1, self._animation_frames.get() + 1) ] widgets = [self._get(self._tree, treeloc).parent()] for subtree in widgets[0].subtrees(): if isinstance(subtree, TreeSegmentWidget): widgets.append(subtree.label()) else: widgets.append(subtree) self._animate_backtrack_frame(widgets, colors) def _animate_backtrack_frame(self, widgets, colors): if len(colors) > 0: self._animating_lock = 1 for widget in widgets: widget['color'] = colors[0] self._top.after(50, self._animate_backtrack_frame, widgets, colors[1:]) else: for widget in widgets[0].subtrees(): widgets[0].remove_child(widget) widget.destroy() self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack(self, treeloc): widget = self._get(self._tree, treeloc) node = widget.parent().label() dy = (node.bbox()[3] - widget.bbox()[1] + 14) / max( 1, self._animation_frames.get() ) self._animate_match_backtrack_frame(self._animation_frames.get(), widget, dy) def _animate_match(self, treeloc): widget = self._get(self._tree, treeloc) dy = (self._textwidgets[0].bbox()[1] - widget.bbox()[3] - 10.0) / max( 1, self._animation_frames.get() ) self._animate_match_frame(self._animation_frames.get(), widget, dy) def _animate_match_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after(10, self._animate_match_frame, frame - 1, widget, dy) else: widget['color'] = '#006040' self._redraw_quick() self._animating_lock = 0 if self._autostep: self._step() def _animate_match_backtrack_frame(self, frame, widget, dy): if frame > 0: self._animating_lock = 1 widget.move(0, dy) self._top.after( 10, self._animate_match_backtrack_frame, frame - 1, widget, dy ) else: widget.parent().remove_child(widget) widget.destroy() self._animating_lock = 0 if self._autostep: self._step() def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sentence): self._sent = sentence.split() # [XX] use tagged? self.reset()
class CollocationsView: _BACKGROUND_COLOUR = "#FFF" # white def __init__(self): self.queue = q.Queue() self.model = CollocationsModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry("550x650+50+50") top.title("NLTK Collocations List") top.bind("<Control-q>", self.destroy) top.protocol("WM_DELETE_WINDOW", self.destroy) top.minsize(550, 650) def _init_widgets(self, parent): self.main_frame = Frame( parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill="both", expand=True) def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label( innerframe, justify=LEFT, text=" Corpus: ", background=self._BACKGROUND_COLOUR, padx=2, pady=1, border=0, ).pack(side="left") other_corpora = list(self.model.CORPORA.keys()).remove( self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om["borderwidth"] = 0 om["highlightthickness"] = 1 om.pack(side="left") innerframe.pack(side="top", fill="x", anchor="n") def _init_status(self, parent): self.status = Label( parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx=1, pady=0, ) self.status.pack(side="top", anchor="sw") def _init_menubar(self): self._result_size = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="Ctrl-q") menubar.add_cascade(label="File", underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton( label="20", variable=self._result_size, underline=0, value=20, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="50", variable=self._result_size, underline=0, value=50, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="100", variable=self._result_size, underline=0, value=100, command=self.set_result_size, ) rescntmenu.invoke(1) editmenu.add_cascade(label="Result Count", underline=0, menu=rescntmenu) menubar.add_cascade(label="Edit", underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient="horiz") self.results_box = Text( i1, font=Font(family="courier", size="16"), state="disabled", borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap="none", width="40", height="20", exportselection=1, ) self.results_box.pack(side="left", fill="both", expand=True) vscrollbar.pack(side="left", fill="y", anchor="e") vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side="left", fill="x", expand=True, anchor="w") hscrollbar.config(command=self.results_box.xview) # there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=" ", background=self._BACKGROUND_COLOUR).pack(side="left", anchor="e") i1.pack(side="top", fill="both", expand=True, anchor="n") i2.pack(side="bottom", fill="x", anchor="s") innerframe.pack(side="top", fill="both", expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button( innerframe, text="Previous", command=self.previous, width="10", borderwidth=1, highlightthickness=1, state="disabled", ) prev.pack(side="left", anchor="center") self.next = next = Button( innerframe, text="Next", command=self.__next__, width="10", borderwidth=1, highlightthickness=1, state="disabled", ) next.pack(side="right", anchor="center") innerframe.pack(side="top", fill="y") self.reset_current_page() def reset_current_page(self): self.current_page = -1 def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status["text"] = "Error in loading " + self.var.get() self.unfreeze_editable() self.clear_results_box() self.freeze_editable() self.reset_current_page() def handle_corpus_loaded(self, event): self.status["text"] = self.var.get() + " is loaded" self.unfreeze_editable() self.clear_results_box() self.reset_current_page() # self.next() collocations = self.model.next(self.current_page + 1) self.write_results(collocations) self.current_page += 1 def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def previous(self): self.freeze_editable() collocations = self.model.prev(self.current_page - 1) self.current_page = self.current_page - 1 self.clear_results_box() self.write_results(collocations) self.unfreeze_editable() def __next__(self): self.freeze_editable() collocations = self.model.next(self.current_page + 1) self.clear_results_box() self.write_results(collocations) self.current_page += 1 self.unfreeze_editable() def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status["text"] = "Loading " + selection + "..." self.freeze_editable() self.model.load_corpus(selection) def freeze_editable(self): self.prev["state"] = "disabled" self.next["state"] = "disabled" def clear_results_box(self): self.results_box["state"] = "normal" self.results_box.delete("1.0", END) self.results_box["state"] = "disabled" def fire_event(self, event): # Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when="tail") def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs) def unfreeze_editable(self): self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == -1 or self.current_page == 0: self.prev["state"] = "disabled" else: self.prev["state"] = "normal" if self.model.is_last_page(self.current_page): self.next["state"] = "disabled" else: self.next["state"] = "normal" def write_results(self, results): self.results_box["state"] = "normal" row = 1 for each in results: self.results_box.insert( str(row) + ".0", each[0] + " " + each[1] + "\n") row += 1 self.results_box["state"] = "disabled"
class CFGDemo(object): def __init__(self, grammar, text): self._grammar = grammar self._text = text # Set up the main window. self._top = Tk() self._top.title('Context Free Grammar Demo') # Base font size self._size = IntVar(self._top) self._size.set(12) # = medium # Set up the key bindings self._init_bindings(self._top) # Create the basic frames frame1 = Frame(self._top) frame1.pack(side='left', fill='y', expand=0) self._init_menubar(self._top) self._init_buttons(self._top) self._init_grammar(frame1) self._init_treelet(frame1) self._init_workspace(self._top) #////////////////////////////////////////////////// # Initialization #////////////////////////////////////////////////// def _init_bindings(self, top): top.bind('<Control-q>', self.destroy) def _init_menubar(self, parent): pass def _init_buttons(self, parent): pass def _init_grammar(self, parent): self._prodlist = ProductionList(parent, self._grammar, width=20) self._prodlist.pack(side='top', fill='both', expand=1) self._prodlist.focus() self._prodlist.add_callback('select', self._selectprod_cb) self._prodlist.add_callback('move', self._selectprod_cb) def _init_treelet(self, parent): self._treelet_canvas = Canvas(parent, background='white') self._treelet_canvas.pack(side='bottom', fill='x') self._treelet = None def _init_workspace(self, parent): self._workspace = CanvasFrame(parent, background='white') self._workspace.pack(side='right', fill='both', expand=1) self._tree = None self.reset_workspace() #////////////////////////////////////////////////// # Workspace #////////////////////////////////////////////////// def reset_workspace(self): c = self._workspace.canvas() fontsize = int(self._size.get()) node_font = ('helvetica', -(fontsize+4), 'bold') leaf_font = ('helvetica', -(fontsize+2)) # Remove the old tree if self._tree is not None: self._workspace.remove_widget(self._tree) # The root of the tree. start = self._grammar.start().symbol() rootnode = TextWidget(c, start, font=node_font, draggable=1) # The leaves of the tree. leaves = [] for word in self._text: leaves.append(TextWidget(c, word, font=leaf_font, draggable=1)) # Put it all together into one tree self._tree = TreeSegmentWidget(c, rootnode, leaves, color='white') # Add it to the workspace. self._workspace.add_widget(self._tree) # Move the leaves to the bottom of the workspace. for leaf in leaves: leaf.move(0,100) #self._nodes = {start:1} #self._leaves = dict([(l,1) for l in leaves]) def workspace_markprod(self, production): pass def _markproduction(self, prod, tree=None): if tree is None: tree = self._tree for i in range(len(tree.subtrees())-len(prod.rhs())): if tree['color', i] == 'white': self._markproduction for j, node in enumerate(prod.rhs()): widget = tree.subtrees()[i+j] if (isinstance(node, Nonterminal) and isinstance(widget, TreeSegmentWidget) and node.symbol == widget.label().text()): pass # matching nonterminal elif (isinstance(node, string_types) and isinstance(widget, TextWidget) and node == widget.text()): pass # matching nonterminal else: break else: # Everything matched! print('MATCH AT', i) #////////////////////////////////////////////////// # Grammar #////////////////////////////////////////////////// def _selectprod_cb(self, production): canvas = self._treelet_canvas self._prodlist.highlight(production) if self._treelet is not None: self._treelet.destroy() # Convert the production to a tree. rhs = production.rhs() for (i, elt) in enumerate(rhs): if isinstance(elt, Nonterminal): elt = Tree(elt) tree = Tree(production.lhs().symbol(), *rhs) # Draw the tree in the treelet area. fontsize = int(self._size.get()) node_font = ('helvetica', -(fontsize+4), 'bold') leaf_font = ('helvetica', -(fontsize+2)) self._treelet = tree_to_treesegment(canvas, tree, node_font=node_font, leaf_font=leaf_font) self._treelet['draggable'] = 1 # Center the treelet. (x1, y1, x2, y2) = self._treelet.bbox() w, h = int(canvas['width']), int(canvas['height']) self._treelet.move((w-x1-x2)/2, (h-y1-y2)/2) # Mark the places where we can add it to the workspace. self._markproduction(production) def destroy(self, *args): self._top.destroy() def mainloop(self, *args, **kwargs): self._top.mainloop(*args, **kwargs)
def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton(label='60 characters', variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='80 characters', variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='100 characters', variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label='Before', underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton(label='70 characters', variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='90 characters', variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='110 characters', variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len) cntxafmenu.invoke(1) cntxmenu.add_cascade(label='After', underline=0, menu=cntxafmenu) editmenu.add_cascade(label='Context', underline=0, menu=cntxmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar)
class CollocationsView: _BACKGROUND_COLOUR = '#FFF' # white def __init__(self): self.queue = q.Queue() self.model = CollocationsModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry('550x650+50+50') top.title('NLTK Collocations List') top.bind('<Control-q>', self.destroy) top.protocol('WM_DELETE_WINDOW', self.destroy) top.minsize(550, 650) def _init_widgets(self, parent): self.main_frame = Frame( parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill='both', expand=True) def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label(innerframe, justify=LEFT, text=' Corpus: ', background=self._BACKGROUND_COLOUR, padx=2, pady=1, border=0).pack(side='left') other_corpora = list(self.model.CORPORA.keys()).remove( self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om['borderwidth'] = 0 om['highlightthickness'] = 1 om.pack(side='left') innerframe.pack(side='top', fill='x', anchor='n') def _init_status(self, parent): self.status = Label(parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx=1, pady=0) self.status.pack(side='top', anchor='sw') def _init_menubar(self): self._result_size = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient='horiz') self.results_box = Text(i1, font=Font(family='courier', size='16'), state='disabled', borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap='none', width='40', height='20', exportselection=1) self.results_box.pack(side='left', fill='both', expand=True) vscrollbar.pack(side='left', fill='y', anchor='e') vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side='left', fill='x', expand=True, anchor='w') hscrollbar.config(command=self.results_box.xview) # there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=' ', background=self._BACKGROUND_COLOUR).pack(side='left', anchor='e') i1.pack(side='top', fill='both', expand=True, anchor='n') i2.pack(side='bottom', fill='x', anchor='s') innerframe.pack(side='top', fill='both', expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button(innerframe, text='Previous', command=self.previous, width='10', borderwidth=1, highlightthickness=1, state='disabled') prev.pack(side='left', anchor='center') self.next = next = Button(innerframe, text='Next', command=self.__next__, width='10', borderwidth=1, highlightthickness=1, state='disabled') next.pack(side='right', anchor='center') innerframe.pack(side='top', fill='y') self.reset_current_page() def reset_current_page(self): self.current_page = -1 def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status['text'] = 'Error in loading ' + self.var.get() self.unfreeze_editable() self.clear_results_box() self.freeze_editable() self.reset_current_page() def handle_corpus_loaded(self, event): self.status['text'] = self.var.get() + ' is loaded' self.unfreeze_editable() self.clear_results_box() self.reset_current_page() # self.next() collocations = self.model.next(self.current_page + 1) self.write_results(collocations) self.current_page += 1 def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def previous(self): self.freeze_editable() collocations = self.model.prev(self.current_page - 1) self.current_page = self.current_page - 1 self.clear_results_box() self.write_results(collocations) self.unfreeze_editable() def __next__(self): self.freeze_editable() collocations = self.model.next(self.current_page + 1) self.clear_results_box() self.write_results(collocations) self.current_page += 1 self.unfreeze_editable() def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status['text'] = 'Loading ' + selection + '...' self.freeze_editable() self.model.load_corpus(selection) def freeze_editable(self): self.prev['state'] = 'disabled' self.next['state'] = 'disabled' def clear_results_box(self): self.results_box['state'] = 'normal' self.results_box.delete("1.0", END) self.results_box['state'] = 'disabled' def fire_event(self, event): # Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when='tail') def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs) def unfreeze_editable(self): self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == -1 or self.current_page == 0: self.prev['state'] = 'disabled' else: self.prev['state'] = 'normal' if self.model.is_last_page(self.current_page): self.next['state'] = 'disabled' else: self.next['state'] = 'normal' def write_results(self, results): self.results_box['state'] = 'normal' row = 1 for each in results: self.results_box.insert( str(row) + '.0', each[0] + " " + each[1] + "\n") row += 1 self.results_box['state'] = 'disabled'
class ConcordanceSearchView(object): _BACKGROUND_COLOUR = "#FFF" # white # Colour of highlighted results _HIGHLIGHT_WORD_COLOUR = "#F00" # red _HIGHLIGHT_WORD_TAG = "HL_WRD_TAG" _HIGHLIGHT_LABEL_COLOUR = "#C0C0C0" # dark grey _HIGHLIGHT_LABEL_TAG = "HL_LBL_TAG" # Percentage of text left of the scrollbar position _FRACTION_LEFT_TEXT = 0.30 def __init__(self): self.queue = q.Queue() self.model = ConcordanceSearchModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry("950x680+50+50") top.title("NLTK Concordance Search") top.bind("<Control-q>", self.destroy) top.protocol("WM_DELETE_WINDOW", self.destroy) top.minsize(950, 680) def _init_widgets(self, parent): self.main_frame = Frame( parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_query_box(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill="both", expand=True) def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label="Exit", underline=1, command=self.destroy, accelerator="Ctrl-q") menubar.add_cascade(label="File", underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton( label="20", variable=self._result_size, underline=0, value=20, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="50", variable=self._result_size, underline=0, value=50, command=self.set_result_size, ) rescntmenu.add_radiobutton( label="100", variable=self._result_size, underline=0, value=100, command=self.set_result_size, ) rescntmenu.invoke(1) editmenu.add_cascade(label="Result Count", underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton( label="60 characters", variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len, ) cntxbfmenu.add_radiobutton( label="80 characters", variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len, ) cntxbfmenu.add_radiobutton( label="100 characters", variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len, ) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label="Before", underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton( label="70 characters", variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len, ) cntxafmenu.add_radiobutton( label="90 characters", variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len, ) cntxafmenu.add_radiobutton( label="110 characters", variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len, ) cntxafmenu.invoke(1) cntxmenu.add_cascade(label="After", underline=0, menu=cntxafmenu) editmenu.add_cascade(label="Context", underline=0, menu=cntxmenu) menubar.add_cascade(label="Edit", underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def set_cntx_af_len(self, **kwargs): self._char_after = self._cntx_af_len.get() def set_cntx_bf_len(self, **kwargs): self._char_before = self._cntx_bf_len.get() def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label( innerframe, justify=LEFT, text=" Corpus: ", background=self._BACKGROUND_COLOUR, padx=2, pady=1, border=0, ).pack(side="left") other_corpora = list(self.model.CORPORA.keys()).remove( self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om["borderwidth"] = 0 om["highlightthickness"] = 1 om.pack(side="left") innerframe.pack(side="top", fill="x", anchor="n") def _init_status(self, parent): self.status = Label( parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx=1, pady=0, ) self.status.pack(side="top", anchor="sw") def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side="left", fill="x", pady=25, anchor="center") self.search_button = Button( another, text="Search", command=self.search, borderwidth=1, highlightthickness=1, ) self.search_button.pack(side="left", fill="x", pady=25, anchor="center") self.query_box.bind("<KeyPress-Return>", self.search_enter_keypress_handler) another.pack() innerframe.pack(side="top", fill="x", anchor="n") def search_enter_keypress_handler(self, *event): self.search() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient="horiz") self.results_box = Text( i1, font=Font(family="courier", size="16"), state="disabled", borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap="none", width="40", height="20", exportselection=1, ) self.results_box.pack(side="left", fill="both", expand=True) self.results_box.tag_config(self._HIGHLIGHT_WORD_TAG, foreground=self._HIGHLIGHT_WORD_COLOUR) self.results_box.tag_config(self._HIGHLIGHT_LABEL_TAG, foreground=self._HIGHLIGHT_LABEL_COLOUR) vscrollbar.pack(side="left", fill="y", anchor="e") vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side="left", fill="x", expand=True, anchor="w") hscrollbar.config(command=self.results_box.xview) # there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=" ", background=self._BACKGROUND_COLOUR).pack(side="left", anchor="e") i1.pack(side="top", fill="both", expand=True, anchor="n") i2.pack(side="bottom", fill="x", anchor="s") innerframe.pack(side="top", fill="both", expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button( innerframe, text="Previous", command=self.previous, width="10", borderwidth=1, highlightthickness=1, state="disabled", ) prev.pack(side="left", anchor="center") self.next = next = Button( innerframe, text="Next", command=self.__next__, width="10", borderwidth=1, highlightthickness=1, state="disabled", ) next.pack(side="right", anchor="center") innerframe.pack(side="top", fill="y") self.current_page = 0 def previous(self): self.clear_results_box() self.freeze_editable() self.model.prev(self.current_page - 1) def __next__(self): self.clear_results_box() self.freeze_editable() self.model.next(self.current_page + 1) def about(self, *e): ABOUT = "NLTK Concordance Search Demo\n" TITLE = "About: NLTK Concordance Search Demo" try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE, parent=self.main_frame).show() except: ShowText(self.top, TITLE, ABOUT) def _bind_event_handlers(self): self.top.bind(CORPUS_LOADED_EVENT, self.handle_corpus_loaded) self.top.bind(SEARCH_TERMINATED_EVENT, self.handle_search_terminated) self.top.bind(SEARCH_ERROR_EVENT, self.handle_search_error) self.top.bind(ERROR_LOADING_CORPUS_EVENT, self.handle_error_loading_corpus) def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == SEARCH_TERMINATED_EVENT: self.handle_search_terminated(event) elif event == SEARCH_ERROR_EVENT: self.handle_search_error(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status["text"] = "Error in loading " + self.var.get() self.unfreeze_editable() self.clear_all() self.freeze_editable() def handle_corpus_loaded(self, event): self.status["text"] = self.var.get() + " is loaded" self.unfreeze_editable() self.clear_all() self.query_box.focus_set() def handle_search_terminated(self, event): # todo: refactor the model such that it is less state sensitive results = self.model.get_results() self.write_results(results) self.status["text"] = "" if len(results) == 0: self.status["text"] = "No results found for " + self.model.query else: self.current_page = self.model.last_requested_page self.unfreeze_editable() self.results_box.xview_moveto(self._FRACTION_LEFT_TEXT) def handle_search_error(self, event): self.status["text"] = "Error in query " + self.model.query self.unfreeze_editable() def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status["text"] = "Loading " + selection + "..." self.freeze_editable() self.model.load_corpus(selection) def search(self): self.current_page = 0 self.clear_results_box() self.model.reset_results() query = self.query_box.get() if len(query.strip()) == 0: return self.status["text"] = "Searching for " + query self.freeze_editable() self.model.search(query, self.current_page + 1) def write_results(self, results): self.results_box["state"] = "normal" row = 1 for each in results: sent, pos1, pos2 = each[0].strip(), each[1], each[2] if len(sent) != 0: if pos1 < self._char_before: sent, pos1, pos2 = self.pad(sent, pos1, pos2) sentence = sent[pos1 - self._char_before:pos1 + self._char_after] if not row == len(results): sentence += "\n" self.results_box.insert(str(row) + ".0", sentence) word_markers, label_markers = self.words_and_labels( sent, pos1, pos2) for marker in word_markers: self.results_box.tag_add( self._HIGHLIGHT_WORD_TAG, str(row) + "." + str(marker[0]), str(row) + "." + str(marker[1]), ) for marker in label_markers: self.results_box.tag_add( self._HIGHLIGHT_LABEL_TAG, str(row) + "." + str(marker[0]), str(row) + "." + str(marker[1]), ) row += 1 self.results_box["state"] = "disabled" def words_and_labels(self, sentence, pos1, pos2): search_exp = sentence[pos1:pos2] words, labels = [], [] labeled_words = search_exp.split(" ") index = 0 for each in labeled_words: if each == "": index += 1 else: word, label = each.split("/") words.append((self._char_before + index, self._char_before + index + len(word))) index += len(word) + 1 labels.append((self._char_before + index, self._char_before + index + len(label))) index += len(label) index += 1 return words, labels def pad(self, sent, hstart, hend): if hstart >= self._char_before: return sent, hstart, hend d = self._char_before - hstart sent = "".join([" "] * d) + sent return sent, hstart + d, hend + d def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def clear_all(self): self.query_box.delete(0, END) self.model.reset_query() self.clear_results_box() def clear_results_box(self): self.results_box["state"] = "normal" self.results_box.delete("1.0", END) self.results_box["state"] = "disabled" def freeze_editable(self): self.query_box["state"] = "disabled" self.search_button["state"] = "disabled" self.prev["state"] = "disabled" self.next["state"] = "disabled" def unfreeze_editable(self): self.query_box["state"] = "normal" self.search_button["state"] = "normal" self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == 0 or self.current_page == 1: self.prev["state"] = "disabled" else: self.prev["state"] = "normal" if self.model.has_more_pages(self.current_page): self.next["state"] = "normal" else: self.next["state"] = "disabled" def fire_event(self, event): # Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when="tail") def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs)
class ShiftReduceApp(object): """ A graphical tool for exploring the shift-reduce parser. The tool displays the parser's stack and the remaining text, and allows the user to control the parser's operation. In particular, the user can shift tokens onto the stack, and can perform reductions on the top elements of the stack. A "step" button simply steps through the parsing process, performing the operations that ``nltk.parse.ShiftReduceParser`` would use. """ def __init__(self, grammar, sent, trace=0): self._sent = sent self._parser = SteppingShiftReduceParser(grammar, trace) # Set up the main window. self._top = Tk() self._top.title('Shift Reduce Parser Application') # Animations. animating_lock is a lock to prevent the demo # from performing new operations while it's animating. self._animating_lock = 0 self._animate = IntVar(self._top) self._animate.set(10) # = medium # The user can hide the grammar. self._show_grammar = IntVar(self._top) self._show_grammar.set(1) # Initialize fonts. self._init_fonts(self._top) # Set up key bindings. self._init_bindings() # Create the basic frames. self._init_menubar(self._top) self._init_buttons(self._top) self._init_feedback(self._top) self._init_grammar(self._top) self._init_canvas(self._top) # A popup menu for reducing. self._reduce_menu = Menu(self._canvas, tearoff=0) # Reset the demo, and set the feedback frame to empty. self.reset() self._lastoper1['text'] = '' ######################################### ## Initialization Helpers ######################################### def _init_fonts(self, root): # See: <http://www.astro.washington.edu/owen/ROTKFolklore.html> self._sysfont = Font(font=Button()["font"]) root.option_add("*Font", self._sysfont) # TWhat's our font size (default=same as sysfont) self._size = IntVar(root) self._size.set(self._sysfont.cget('size')) self._boldfont = Font(family='helvetica', weight='bold', size=self._size.get()) self._font = Font(family='helvetica', size=self._size.get()) def _init_grammar(self, parent): # Grammar view. self._prodframe = listframe = Frame(parent) self._prodframe.pack(fill='both', side='left', padx=2) self._prodlist_label = Label( self._prodframe, font=self._boldfont, text='Available Reductions' ) self._prodlist_label.pack() self._prodlist = Listbox( self._prodframe, selectmode='single', relief='groove', background='white', foreground='#909090', font=self._font, selectforeground='#004040', selectbackground='#c0f0c0', ) self._prodlist.pack(side='right', fill='both', expand=1) self._productions = list(self._parser.grammar().productions()) for production in self._productions: self._prodlist.insert('end', (' %s' % production)) self._prodlist.config(height=min(len(self._productions), 25)) # Add a scrollbar if there are more than 25 productions. if 1: # len(self._productions) > 25: listscroll = Scrollbar(self._prodframe, orient='vertical') self._prodlist.config(yscrollcommand=listscroll.set) listscroll.config(command=self._prodlist.yview) listscroll.pack(side='left', fill='y') # If they select a production, apply it. self._prodlist.bind('<<ListboxSelect>>', self._prodlist_select) # When they hover over a production, highlight it. self._hover = -1 self._prodlist.bind('<Motion>', self._highlight_hover) self._prodlist.bind('<Leave>', self._clear_hover) def _init_bindings(self): # Quit self._top.bind('<Control-q>', self.destroy) self._top.bind('<Control-x>', self.destroy) self._top.bind('<Alt-q>', self.destroy) self._top.bind('<Alt-x>', self.destroy) # Ops (step, shift, reduce, undo) self._top.bind('<space>', self.step) self._top.bind('<s>', self.shift) self._top.bind('<Alt-s>', self.shift) self._top.bind('<Control-s>', self.shift) self._top.bind('<r>', self.reduce) self._top.bind('<Alt-r>', self.reduce) self._top.bind('<Control-r>', self.reduce) self._top.bind('<Delete>', self.reset) self._top.bind('<u>', self.undo) self._top.bind('<Alt-u>', self.undo) self._top.bind('<Control-u>', self.undo) self._top.bind('<Control-z>', self.undo) self._top.bind('<BackSpace>', self.undo) # Misc self._top.bind('<Control-p>', self.postscript) self._top.bind('<Control-h>', self.help) self._top.bind('<F1>', self.help) self._top.bind('<Control-g>', self.edit_grammar) self._top.bind('<Control-t>', self.edit_sentence) # Animation speed control self._top.bind('-', lambda e, a=self._animate: a.set(20)) self._top.bind('=', lambda e, a=self._animate: a.set(10)) self._top.bind('+', lambda e, a=self._animate: a.set(4)) def _init_buttons(self, parent): # Set up the frames. self._buttonframe = buttonframe = Frame(parent) buttonframe.pack(fill='none', side='bottom') Button( buttonframe, text='Step', background='#90c0d0', foreground='black', command=self.step, ).pack(side='left') Button( buttonframe, text='Shift', underline=0, background='#90f090', foreground='black', command=self.shift, ).pack(side='left') Button( buttonframe, text='Reduce', underline=0, background='#90f090', foreground='black', command=self.reduce, ).pack(side='left') Button( buttonframe, text='Undo', underline=0, background='#f0a0a0', foreground='black', command=self.undo, ).pack(side='left') def _init_menubar(self, parent): menubar = Menu(parent) filemenu = Menu(menubar, tearoff=0) filemenu.add_command( label='Reset Parser', underline=0, command=self.reset, accelerator='Del' ) filemenu.add_command( label='Print to Postscript', underline=0, command=self.postscript, accelerator='Ctrl-p', ) filemenu.add_command( label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-x' ) menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) editmenu.add_command( label='Edit Grammar', underline=5, command=self.edit_grammar, accelerator='Ctrl-g', ) editmenu.add_command( label='Edit Text', underline=5, command=self.edit_sentence, accelerator='Ctrl-t', ) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) rulemenu = Menu(menubar, tearoff=0) rulemenu.add_command( label='Step', underline=1, command=self.step, accelerator='Space' ) rulemenu.add_separator() rulemenu.add_command( label='Shift', underline=0, command=self.shift, accelerator='Ctrl-s' ) rulemenu.add_command( label='Reduce', underline=0, command=self.reduce, accelerator='Ctrl-r' ) rulemenu.add_separator() rulemenu.add_command( label='Undo', underline=0, command=self.undo, accelerator='Ctrl-u' ) menubar.add_cascade(label='Apply', underline=0, menu=rulemenu) viewmenu = Menu(menubar, tearoff=0) viewmenu.add_checkbutton( label="Show Grammar", underline=0, variable=self._show_grammar, command=self._toggle_grammar, ) viewmenu.add_separator() viewmenu.add_radiobutton( label='Tiny', variable=self._size, underline=0, value=10, command=self.resize, ) viewmenu.add_radiobutton( label='Small', variable=self._size, underline=0, value=12, command=self.resize, ) viewmenu.add_radiobutton( label='Medium', variable=self._size, underline=0, value=14, command=self.resize, ) viewmenu.add_radiobutton( label='Large', variable=self._size, underline=0, value=18, command=self.resize, ) viewmenu.add_radiobutton( label='Huge', variable=self._size, underline=0, value=24, command=self.resize, ) menubar.add_cascade(label='View', underline=0, menu=viewmenu) animatemenu = Menu(menubar, tearoff=0) animatemenu.add_radiobutton( label="No Animation", underline=0, variable=self._animate, value=0 ) animatemenu.add_radiobutton( label="Slow Animation", underline=0, variable=self._animate, value=20, accelerator='-', ) animatemenu.add_radiobutton( label="Normal Animation", underline=0, variable=self._animate, value=10, accelerator='=', ) animatemenu.add_radiobutton( label="Fast Animation", underline=0, variable=self._animate, value=4, accelerator='+', ) menubar.add_cascade(label="Animate", underline=1, menu=animatemenu) helpmenu = Menu(menubar, tearoff=0) helpmenu.add_command(label='About', underline=0, command=self.about) helpmenu.add_command( label='Instructions', underline=0, command=self.help, accelerator='F1' ) menubar.add_cascade(label='Help', underline=0, menu=helpmenu) parent.config(menu=menubar) def _init_feedback(self, parent): self._feedbackframe = feedbackframe = Frame(parent) feedbackframe.pack(fill='x', side='bottom', padx=3, pady=3) self._lastoper_label = Label( feedbackframe, text='Last Operation:', font=self._font ) self._lastoper_label.pack(side='left') lastoperframe = Frame(feedbackframe, relief='sunken', border=1) lastoperframe.pack(fill='x', side='right', expand=1, padx=5) self._lastoper1 = Label( lastoperframe, foreground='#007070', background='#f0f0f0', font=self._font ) self._lastoper2 = Label( lastoperframe, anchor='w', width=30, foreground='#004040', background='#f0f0f0', font=self._font, ) self._lastoper1.pack(side='left') self._lastoper2.pack(side='left', fill='x', expand=1) def _init_canvas(self, parent): self._cframe = CanvasFrame( parent, background='white', width=525, closeenough=10, border=2, relief='sunken', ) self._cframe.pack(expand=1, fill='both', side='top', pady=2) canvas = self._canvas = self._cframe.canvas() self._stackwidgets = [] self._rtextwidgets = [] self._titlebar = canvas.create_rectangle( 0, 0, 0, 0, fill='#c0f0f0', outline='black' ) self._exprline = canvas.create_line(0, 0, 0, 0, dash='.') self._stacktop = canvas.create_line(0, 0, 0, 0, fill='#408080') size = self._size.get() + 4 self._stacklabel = TextWidget( canvas, 'Stack', color='#004040', font=self._boldfont ) self._rtextlabel = TextWidget( canvas, 'Remaining Text', color='#004040', font=self._boldfont ) self._cframe.add_widget(self._stacklabel) self._cframe.add_widget(self._rtextlabel) ######################################### ## Main draw procedure ######################################### def _redraw(self): scrollregion = self._canvas['scrollregion'].split() (cx1, cy1, cx2, cy2) = [int(c) for c in scrollregion] # Delete the old stack & rtext widgets. for stackwidget in self._stackwidgets: self._cframe.destroy_widget(stackwidget) self._stackwidgets = [] for rtextwidget in self._rtextwidgets: self._cframe.destroy_widget(rtextwidget) self._rtextwidgets = [] # Position the titlebar & exprline (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 self._canvas.coords(self._titlebar, -5000, 0, 5000, y - 4) self._canvas.coords(self._exprline, 0, y * 2 - 10, 5000, y * 2 - 10) # Position the titlebar labels.. (x1, y1, x2, y2) = self._stacklabel.bbox() self._stacklabel.move(5 - x1, 3 - y1) (x1, y1, x2, y2) = self._rtextlabel.bbox() self._rtextlabel.move(cx2 - x2 - 5, 3 - y1) # Draw the stack. stackx = 5 for tok in self._parser.stack(): if isinstance(tok, Tree): attribs = { 'tree_color': '#4080a0', 'tree_width': 2, 'node_font': self._boldfont, 'node_color': '#006060', 'leaf_color': '#006060', 'leaf_font': self._font, } widget = tree_to_treesegment(self._canvas, tok, **attribs) widget.label()['color'] = '#000000' else: widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) widget.bind_click(self._popup_reduce) self._stackwidgets.append(widget) self._cframe.add_widget(widget, stackx, y) stackx = widget.bbox()[2] + 10 # Draw the remaining text. rtextwidth = 0 for tok in self._parser.remaining_text(): widget = TextWidget(self._canvas, tok, color='#000000', font=self._font) self._rtextwidgets.append(widget) self._cframe.add_widget(widget, rtextwidth, y) rtextwidth = widget.bbox()[2] + 4 # Allow enough room to shift the next token (for animations) if len(self._rtextwidgets) > 0: stackx += self._rtextwidgets[0].width() # Move the remaining text to the correct location (keep it # right-justified, when possible); and move the remaining text # label, if necessary. stackx = max(stackx, self._stacklabel.width() + 25) rlabelwidth = self._rtextlabel.width() + 10 if stackx >= cx2 - max(rtextwidth, rlabelwidth): cx2 = stackx + max(rtextwidth, rlabelwidth) for rtextwidget in self._rtextwidgets: rtextwidget.move(4 + cx2 - rtextwidth, 0) self._rtextlabel.move(cx2 - self._rtextlabel.bbox()[2] - 5, 0) midx = (stackx + cx2 - max(rtextwidth, rlabelwidth)) / 2 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) (x1, y1, x2, y2) = self._stacklabel.bbox() # Set up binding to allow them to shift a token by dragging it. if len(self._rtextwidgets) > 0: def drag_shift(widget, midx=midx, self=self): if widget.bbox()[0] < midx: self.shift() else: self._redraw() self._rtextwidgets[0].bind_drag(drag_shift) self._rtextwidgets[0].bind_click(self.shift) # Draw the stack top. self._highlight_productions() def _draw_stack_top(self, widget): # hack.. midx = widget.bbox()[2] + 50 self._canvas.coords(self._stacktop, midx, 0, midx, 5000) def _highlight_productions(self): # Highlight the productions that can be reduced. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) ######################################### ## Button Callbacks ######################################### def destroy(self, *e): if self._top is None: return self._top.destroy() self._top = None def reset(self, *e): self._parser.initialize(self._sent) self._lastoper1['text'] = 'Reset App' self._lastoper2['text'] = '' self._redraw() def step(self, *e): if self.reduce(): return True elif self.shift(): return True else: if list(self._parser.parses()): self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Success' else: self._lastoper1['text'] = 'Finished:' self._lastoper2['text'] = 'Failure' def shift(self, *e): if self._animating_lock: return if self._parser.shift(): tok = self._parser.stack()[-1] self._lastoper1['text'] = 'Shift:' self._lastoper2['text'] = '%r' % tok if self._animate.get(): self._animate_shift() else: self._redraw() return True return False def reduce(self, *e): if self._animating_lock: return production = self._parser.reduce() if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() return production def undo(self, *e): if self._animating_lock: return if self._parser.undo(): self._redraw() def postscript(self, *e): self._cframe.print_to_file() 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) ######################################### ## Menubar callbacks ######################################### def resize(self, size=None): if size is not None: self._size.set(size) size = self._size.get() self._font.configure(size=-(abs(size))) self._boldfont.configure(size=-(abs(size))) self._sysfont.configure(size=-(abs(size))) # self._stacklabel['font'] = ('helvetica', -size-4, 'bold') # self._rtextlabel['font'] = ('helvetica', -size-4, 'bold') # self._lastoper_label['font'] = ('helvetica', -size) # self._lastoper1['font'] = ('helvetica', -size) # self._lastoper2['font'] = ('helvetica', -size) # self._prodlist['font'] = ('helvetica', -size) # self._prodlist_label['font'] = ('helvetica', -size-2, 'bold') self._redraw() def help(self, *e): # The default font's not very legible; try using 'fixed' instead. try: ShowText( self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75, font='fixed', ) except: ShowText( self._top, 'Help: Shift-Reduce Parser Application', (__doc__ or '').strip(), width=75, ) def about(self, *e): ABOUT = "NLTK Shift-Reduce Parser Application\n" + "Written by Edward Loper" TITLE = 'About: Shift-Reduce Parser Application' try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE).show() except: ShowText(self._top, TITLE, ABOUT) def edit_grammar(self, *e): CFGEditor(self._top, self._parser.grammar(), self.set_grammar) def set_grammar(self, grammar): self._parser.set_grammar(grammar) self._productions = list(grammar.productions()) self._prodlist.delete(0, 'end') for production in self._productions: self._prodlist.insert('end', (' %s' % production)) def edit_sentence(self, *e): sentence = " ".join(self._sent) title = 'Edit Text' instr = 'Enter a new sentence to parse.' EntryDialog(self._top, sentence, instr, self.set_sentence, title) def set_sentence(self, sent): self._sent = sent.split() # [XX] use tagged? self.reset() ######################################### ## Reduce Production Selection ######################################### def _toggle_grammar(self, *e): if self._show_grammar.get(): self._prodframe.pack( fill='both', side='left', padx=2, after=self._feedbackframe ) self._lastoper1['text'] = 'Show Grammar' else: self._prodframe.pack_forget() self._lastoper1['text'] = 'Hide Grammar' self._lastoper2['text'] = '' def _prodlist_select(self, event): selection = self._prodlist.curselection() if len(selection) != 1: return index = int(selection[0]) production = self._parser.reduce(self._productions[index]) if production: self._lastoper1['text'] = 'Reduce:' self._lastoper2['text'] = '%s' % production if self._animate.get(): self._animate_reduce() else: self._redraw() else: # Reset the production selections. self._prodlist.selection_clear(0, 'end') for prod in self._parser.reducible_productions(): index = self._productions.index(prod) self._prodlist.selection_set(index) def _popup_reduce(self, widget): # Remove old commands. productions = self._parser.reducible_productions() if len(productions) == 0: return self._reduce_menu.delete(0, 'end') for production in productions: self._reduce_menu.add_command(label=str(production), command=self.reduce) self._reduce_menu.post( self._canvas.winfo_pointerx(), self._canvas.winfo_pointery() ) ######################################### ## Animations ######################################### def _animate_shift(self): # What widget are we shifting? widget = self._rtextwidgets[0] # Where are we shifting from & to? right = widget.bbox()[0] if len(self._stackwidgets) == 0: left = 5 else: left = self._stackwidgets[-1].bbox()[2] + 10 # Start animating. dt = self._animate.get() dx = (left - right) * 1.0 / dt self._animate_shift_frame(dt, widget, dx) def _animate_shift_frame(self, frame, widget, dx): if frame > 0: self._animating_lock = 1 widget.move(dx, 0) self._top.after(10, self._animate_shift_frame, frame - 1, widget, dx) else: # but: stacktop?? # Shift the widget to the stack. del self._rtextwidgets[0] self._stackwidgets.append(widget) self._animating_lock = 0 # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() def _animate_reduce(self): # What widgets are we shifting? numwidgets = len(self._parser.stack()[-1]) # number of children widgets = self._stackwidgets[-numwidgets:] # How far are we moving? if isinstance(widgets[0], TreeSegmentWidget): ydist = 15 + widgets[0].label().height() else: ydist = 15 + widgets[0].height() # Start animating. dt = self._animate.get() dy = ydist * 2.0 / dt self._animate_reduce_frame(dt / 2, widgets, dy) def _animate_reduce_frame(self, frame, widgets, dy): if frame > 0: self._animating_lock = 1 for widget in widgets: widget.move(0, dy) self._top.after(10, self._animate_reduce_frame, frame - 1, widgets, dy) else: del self._stackwidgets[-len(widgets) :] for widget in widgets: self._cframe.remove_widget(widget) tok = self._parser.stack()[-1] if not isinstance(tok, Tree): raise ValueError() label = TextWidget( self._canvas, str(tok.label()), color='#006060', font=self._boldfont ) widget = TreeSegmentWidget(self._canvas, label, widgets, width=2) (x1, y1, x2, y2) = self._stacklabel.bbox() y = y2 - y1 + 10 if not self._stackwidgets: x = 5 else: x = self._stackwidgets[-1].bbox()[2] + 10 self._cframe.add_widget(widget, x, y) self._stackwidgets.append(widget) # Display the available productions. self._draw_stack_top(widget) self._highlight_productions() # # Delete the old widgets.. # del self._stackwidgets[-len(widgets):] # for widget in widgets: # self._cframe.destroy_widget(widget) # # # Make a new one. # tok = self._parser.stack()[-1] # if isinstance(tok, Tree): # attribs = {'tree_color': '#4080a0', 'tree_width': 2, # 'node_font': bold, 'node_color': '#006060', # 'leaf_color': '#006060', 'leaf_font':self._font} # widget = tree_to_treesegment(self._canvas, tok.type(), # **attribs) # widget.node()['color'] = '#000000' # else: # widget = TextWidget(self._canvas, tok.type(), # color='#000000', font=self._font) # widget.bind_click(self._popup_reduce) # (x1, y1, x2, y2) = self._stacklabel.bbox() # y = y2-y1+10 # if not self._stackwidgets: x = 5 # else: x = self._stackwidgets[-1].bbox()[2] + 10 # self._cframe.add_widget(widget, x, y) # self._stackwidgets.append(widget) # self._redraw() self._animating_lock = 0 ######################################### ## Hovering. ######################################### def _highlight_hover(self, event): # What production are we hovering over? index = self._prodlist.nearest(event.y) if self._hover == index: return # Clear any previous hover highlighting. self._clear_hover() # If the production corresponds to an available reduction, # highlight the stack. selection = [int(s) for s in self._prodlist.curselection()] if index in selection: rhslen = len(self._productions[index].rhs()) for stackwidget in self._stackwidgets[-rhslen:]: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = '#00a000' else: stackwidget['color'] = '#00a000' # Remember what production we're hovering over. self._hover = index def _clear_hover(self, *event): # Clear any previous hover highlighting. if self._hover == -1: return self._hover = -1 for stackwidget in self._stackwidgets: if isinstance(stackwidget, TreeSegmentWidget): stackwidget.label()['color'] = 'black' else: stackwidget['color'] = 'black'
class ShipPanel(Frame): ''' Panel that keeps track of your ships as they get placed onto the board. ''' ########### geometry ########## WIDTH = 150 ############################### ########### states ############ UNPLACED = 0 PLACED = 1 SUNK = 2 # <-- should be unused ############################### ########### colors ############ UNPLACED_COLOR = "black" PLACED_COLOR = "forest green" SUNK_COLOR = "red" #<-- should be unused ############################### def __init__(self, master): '''Create a new ship panel. <master> is the parent TKinter element.''' Frame.__init__(self, master) self._create_ui() #self.reset() def _create_ui(self): '''Create the UI for this panel.''' self._ship_var = IntVar() self.ship_buttons = {} for i, ship in enumerate(Ship.SHORT_NAMES): b = Radiobutton(self, text=Ship.NAMES[ship].title(), value=i, variable=self._ship_var, indicatoron=False) b.pack(anchor=W, pady=10) b.grid(sticky=N + S + E + W) # and a sort-of experimental feature... b.ship_state = self.UNPLACED # save it self.ship_buttons[ship] = b def reset(self): '''Return this panel to its starting state.''' self.unselect_ship() for ship in Ship.SIZES.keys(): self.set_state(ship, self.UNPLACED) @staticmethod def get_state_color(state): '''Return the color based on the state.''' return { ShipPanel.UNPLACED: ShipPanel.UNPLACED_COLOR, ShipPanel.PLACED: ShipPanel.PLACED_COLOR, ShipPanel.SUNK: ShipPanel.SUNK_COLOR }[state] def redraw(self, model): '''Redraw the entire panel based on the model. <model> is the ship grid.''' for ship_name in model.get_ship_placement().keys(): self.set_placed(ship_name) def click(self, ship): '''Click given button.''' self.ship_buttons[ship].invoke() def set_state(self, ship, state): '''Change the state of the given ship.''' self.ship_buttons[ship].ship_state = state self.ship_buttons[ship].config(foreground=self.get_state_color(state)) def set_placed(self, ship): '''Set the ship as placed.''' self.set_state(ship, self.PLACED) def set_sunk(self, ship): '''Set the ship as sunk.''' self.set_state(ship, self.SUNK) def unselect_ship(self): '''Unselect all ships.''' self._ship_var.set(len(Ship.SHIPS) + 1) def get_current_ship(self): '''Return the ship currently selected.''' if self._ship_var.get() > len(Ship.SHIPS): return None else: return Ship.SHORT_NAMES[self._ship_var.get()]
class ConcordanceSearchView(object): _BACKGROUND_COLOUR = '#FFF' #white #Colour of highlighted results _HIGHLIGHT_WORD_COLOUR = '#F00' #red _HIGHLIGHT_WORD_TAG = 'HL_WRD_TAG' _HIGHLIGHT_LABEL_COLOUR = '#C0C0C0' # dark grey _HIGHLIGHT_LABEL_TAG = 'HL_LBL_TAG' #Percentage of text left of the scrollbar position _FRACTION_LEFT_TEXT = 0.30 def __init__(self): self.queue = q.Queue() self.model = ConcordanceSearchModel(self.queue) self.top = Tk() self._init_top(self.top) self._init_menubar() self._init_widgets(self.top) self.load_corpus(self.model.DEFAULT_CORPUS) self.after = self.top.after(POLL_INTERVAL, self._poll) def _init_top(self, top): top.geometry('950x680+50+50') top.title('NLTK Concordance Search') top.bind('<Control-q>', self.destroy) top.protocol('WM_DELETE_WINDOW', self.destroy) top.minsize(950, 680) def _init_widgets(self, parent): self.main_frame = Frame( parent, dict(background=self._BACKGROUND_COLOUR, padx=1, pady=1, border=1)) self._init_corpus_select(self.main_frame) self._init_query_box(self.main_frame) self._init_results_box(self.main_frame) self._init_paging(self.main_frame) self._init_status(self.main_frame) self.main_frame.pack(fill='both', expand=True) def _init_menubar(self): self._result_size = IntVar(self.top) self._cntx_bf_len = IntVar(self.top) self._cntx_af_len = IntVar(self.top) menubar = Menu(self.top) filemenu = Menu(menubar, tearoff=0, borderwidth=0) filemenu.add_command(label='Exit', underline=1, command=self.destroy, accelerator='Ctrl-q') menubar.add_cascade(label='File', underline=0, menu=filemenu) editmenu = Menu(menubar, tearoff=0) rescntmenu = Menu(editmenu, tearoff=0) rescntmenu.add_radiobutton(label='20', variable=self._result_size, underline=0, value=20, command=self.set_result_size) rescntmenu.add_radiobutton(label='50', variable=self._result_size, underline=0, value=50, command=self.set_result_size) rescntmenu.add_radiobutton(label='100', variable=self._result_size, underline=0, value=100, command=self.set_result_size) rescntmenu.invoke(1) editmenu.add_cascade(label='Result Count', underline=0, menu=rescntmenu) cntxmenu = Menu(editmenu, tearoff=0) cntxbfmenu = Menu(cntxmenu, tearoff=0) cntxbfmenu.add_radiobutton(label='60 characters', variable=self._cntx_bf_len, underline=0, value=60, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='80 characters', variable=self._cntx_bf_len, underline=0, value=80, command=self.set_cntx_bf_len) cntxbfmenu.add_radiobutton(label='100 characters', variable=self._cntx_bf_len, underline=0, value=100, command=self.set_cntx_bf_len) cntxbfmenu.invoke(1) cntxmenu.add_cascade(label='Before', underline=0, menu=cntxbfmenu) cntxafmenu = Menu(cntxmenu, tearoff=0) cntxafmenu.add_radiobutton(label='70 characters', variable=self._cntx_af_len, underline=0, value=70, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='90 characters', variable=self._cntx_af_len, underline=0, value=90, command=self.set_cntx_af_len) cntxafmenu.add_radiobutton(label='110 characters', variable=self._cntx_af_len, underline=0, value=110, command=self.set_cntx_af_len) cntxafmenu.invoke(1) cntxmenu.add_cascade(label='After', underline=0, menu=cntxafmenu) editmenu.add_cascade(label='Context', underline=0, menu=cntxmenu) menubar.add_cascade(label='Edit', underline=0, menu=editmenu) self.top.config(menu=menubar) def set_result_size(self, **kwargs): self.model.result_count = self._result_size.get() def set_cntx_af_len(self, **kwargs): self._char_after = self._cntx_af_len.get() def set_cntx_bf_len(self, **kwargs): self._char_before = self._cntx_bf_len.get() def _init_corpus_select(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.var = StringVar(innerframe) self.var.set(self.model.DEFAULT_CORPUS) Label(innerframe, justify=LEFT, text=' Corpus: ', background=self._BACKGROUND_COLOUR, padx=2, pady=1, border=0).pack(side='left') other_corpora = list(self.model.CORPORA.keys()).remove( self.model.DEFAULT_CORPUS) om = OptionMenu(innerframe, self.var, self.model.DEFAULT_CORPUS, command=self.corpus_selected, *self.model.non_default_corpora()) om['borderwidth'] = 0 om['highlightthickness'] = 1 om.pack(side='left') innerframe.pack(side='top', fill='x', anchor='n') def _init_status(self, parent): self.status = Label(parent, justify=LEFT, relief=SUNKEN, background=self._BACKGROUND_COLOUR, border=0, padx=1, pady=0) self.status.pack(side='top', anchor='sw') def _init_query_box(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) another = Frame(innerframe, background=self._BACKGROUND_COLOUR) self.query_box = Entry(another, width=60) self.query_box.pack(side='left', fill='x', pady=25, anchor='center') self.search_button = Button(another, text='Search', command=self.search, borderwidth=1, highlightthickness=1) self.search_button.pack(side='left', fill='x', pady=25, anchor='center') self.query_box.bind('<KeyPress-Return>', self.search_enter_keypress_handler) another.pack() innerframe.pack(side='top', fill='x', anchor='n') def search_enter_keypress_handler(self, *event): self.search() def _init_results_box(self, parent): innerframe = Frame(parent) i1 = Frame(innerframe) i2 = Frame(innerframe) vscrollbar = Scrollbar(i1, borderwidth=1) hscrollbar = Scrollbar(i2, borderwidth=1, orient='horiz') self.results_box = Text(i1, font=Font(family='courier', size='16'), state='disabled', borderwidth=1, yscrollcommand=vscrollbar.set, xscrollcommand=hscrollbar.set, wrap='none', width='40', height='20', exportselection=1) self.results_box.pack(side='left', fill='both', expand=True) self.results_box.tag_config(self._HIGHLIGHT_WORD_TAG, foreground=self._HIGHLIGHT_WORD_COLOUR) self.results_box.tag_config(self._HIGHLIGHT_LABEL_TAG, foreground=self._HIGHLIGHT_LABEL_COLOUR) vscrollbar.pack(side='left', fill='y', anchor='e') vscrollbar.config(command=self.results_box.yview) hscrollbar.pack(side='left', fill='x', expand=True, anchor='w') hscrollbar.config(command=self.results_box.xview) #there is no other way of avoiding the overlap of scrollbars while using pack layout manager!!! Label(i2, text=' ', background=self._BACKGROUND_COLOUR).pack(side='left', anchor='e') i1.pack(side='top', fill='both', expand=True, anchor='n') i2.pack(side='bottom', fill='x', anchor='s') innerframe.pack(side='top', fill='both', expand=True) def _init_paging(self, parent): innerframe = Frame(parent, background=self._BACKGROUND_COLOUR) self.prev = prev = Button(innerframe, text='Previous', command=self.previous, width='10', borderwidth=1, highlightthickness=1, state='disabled') prev.pack(side='left', anchor='center') self.next = next = Button(innerframe, text='Next', command=self.__next__, width='10', borderwidth=1, highlightthickness=1, state='disabled') next.pack(side='right', anchor='center') innerframe.pack(side='top', fill='y') self.current_page = 0 def previous(self): self.clear_results_box() self.freeze_editable() self.model.prev(self.current_page - 1) def __next__(self): self.clear_results_box() self.freeze_editable() self.model.next(self.current_page + 1) def about(self, *e): ABOUT = ("NLTK Concordance Search Demo\n") TITLE = 'About: NLTK Concordance Search Demo' try: from six.moves.tkinter_messagebox import Message Message(message=ABOUT, title=TITLE, parent=self.main_frame).show() except: ShowText(self.top, TITLE, ABOUT) def _bind_event_handlers(self): self.top.bind(CORPUS_LOADED_EVENT, self.handle_corpus_loaded) self.top.bind(SEARCH_TERMINATED_EVENT, self.handle_search_terminated) self.top.bind(SEARCH_ERROR_EVENT, self.handle_search_error) self.top.bind(ERROR_LOADING_CORPUS_EVENT, self.handle_error_loading_corpus) def _poll(self): try: event = self.queue.get(block=False) except q.Empty: pass else: if event == CORPUS_LOADED_EVENT: self.handle_corpus_loaded(event) elif event == SEARCH_TERMINATED_EVENT: self.handle_search_terminated(event) elif event == SEARCH_ERROR_EVENT: self.handle_search_error(event) elif event == ERROR_LOADING_CORPUS_EVENT: self.handle_error_loading_corpus(event) self.after = self.top.after(POLL_INTERVAL, self._poll) def handle_error_loading_corpus(self, event): self.status['text'] = 'Error in loading ' + self.var.get() self.unfreeze_editable() self.clear_all() self.freeze_editable() def handle_corpus_loaded(self, event): self.status['text'] = self.var.get() + ' is loaded' self.unfreeze_editable() self.clear_all() self.query_box.focus_set() def handle_search_terminated(self, event): #todo: refactor the model such that it is less state sensitive results = self.model.get_results() self.write_results(results) self.status['text'] = '' if len(results) == 0: self.status['text'] = 'No results found for ' + self.model.query else: self.current_page = self.model.last_requested_page self.unfreeze_editable() self.results_box.xview_moveto(self._FRACTION_LEFT_TEXT) def handle_search_error(self, event): self.status['text'] = 'Error in query ' + self.model.query self.unfreeze_editable() def corpus_selected(self, *args): new_selection = self.var.get() self.load_corpus(new_selection) def load_corpus(self, selection): if self.model.selected_corpus != selection: self.status['text'] = 'Loading ' + selection + '...' self.freeze_editable() self.model.load_corpus(selection) def search(self): self.current_page = 0 self.clear_results_box() self.model.reset_results() query = self.query_box.get() if (len(query.strip()) == 0): return self.status['text'] = 'Searching for ' + query self.freeze_editable() self.model.search( query, self.current_page + 1, ) def write_results(self, results): self.results_box['state'] = 'normal' row = 1 for each in results: sent, pos1, pos2 = each[0].strip(), each[1], each[2] if len(sent) != 0: if (pos1 < self._char_before): sent, pos1, pos2 = self.pad(sent, pos1, pos2) sentence = sent[pos1 - self._char_before:pos1 + self._char_after] if not row == len(results): sentence += '\n' self.results_box.insert(str(row) + '.0', sentence) word_markers, label_markers = self.words_and_labels( sent, pos1, pos2) for marker in word_markers: self.results_box.tag_add(self._HIGHLIGHT_WORD_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) for marker in label_markers: self.results_box.tag_add(self._HIGHLIGHT_LABEL_TAG, str(row) + '.' + str(marker[0]), str(row) + '.' + str(marker[1])) row += 1 self.results_box['state'] = 'disabled' def words_and_labels(self, sentence, pos1, pos2): search_exp = sentence[pos1:pos2] words, labels = [], [] labeled_words = search_exp.split(' ') index = 0 for each in labeled_words: if each == '': index += 1 else: word, label = each.split('/') words.append((self._char_before + index, self._char_before + index + len(word))) index += len(word) + 1 labels.append((self._char_before + index, self._char_before + index + len(label))) index += len(label) index += 1 return words, labels def pad(self, sent, hstart, hend): if hstart >= self._char_before: return sent, hstart, hend d = self._char_before - hstart sent = ''.join([' '] * d) + sent return sent, hstart + d, hend + d def destroy(self, *e): if self.top is None: return self.top.after_cancel(self.after) self.top.destroy() self.top = None def clear_all(self): self.query_box.delete(0, END) self.model.reset_query() self.clear_results_box() def clear_results_box(self): self.results_box['state'] = 'normal' self.results_box.delete("1.0", END) self.results_box['state'] = 'disabled' def freeze_editable(self): self.query_box['state'] = 'disabled' self.search_button['state'] = 'disabled' self.prev['state'] = 'disabled' self.next['state'] = 'disabled' def unfreeze_editable(self): self.query_box['state'] = 'normal' self.search_button['state'] = 'normal' self.set_paging_button_states() def set_paging_button_states(self): if self.current_page == 0 or self.current_page == 1: self.prev['state'] = 'disabled' else: self.prev['state'] = 'normal' if self.model.has_more_pages(self.current_page): self.next['state'] = 'normal' else: self.next['state'] = 'disabled' def fire_event(self, event): #Firing an event so that rendering of widgets happen in the mainloop thread self.top.event_generate(event, when='tail') def mainloop(self, *args, **kwargs): if in_idle(): return self.top.mainloop(*args, **kwargs)
def __init__(self, project=None): GUITk.__init__(self, wait_msec=1) for signame in ["qvc_dirtied", "qvd_failed", "qvc_available"]: s = CoSignal() s.attach(self.signal_dispatcher) setattr(self, "sig_" + signame, s) self.title_suffix = _("Qemu device creator GUI") self.title_suffix.trace_variable("w", self.__on_title_suffix_write__) self.title_not_saved_asterisk = StringVar() self.title_not_saved_asterisk.trace_variable( "w", self.__on_title_suffix_write__) self.saved_operation = None self.var_title = StringVar() self.title(self.var_title) # Hot keys, accelerators self.hk = hotkeys = HotKey(self) hotkeys.add_bindings([ HotKeyBinding( self.invert_history_window, key_code=43, # H description=_("If editing history window is hidden then \ show it else hide it.")), HotKeyBinding( self.on_load, key_code=32, # O description=_("Load project from file.")), HotKeyBinding( self.on_new_project, key_code=57, # N description=_("Create new project.")), HotKeyBinding( self.on_add_description, key_code=40, # D description=_("Add description to the project")), HotKeyBinding( self.on_set_qemu_build_path, key_code=56, # B description=_("Set Qemu build path for the project")), HotKeyBinding( self.on_generate, key_code=42, # G description=_("Launch code generation")), HotKeyBinding( self.on_delete, key_code=24, # Q description=_("Shutdown the application.")), HotKeyBinding( self.undo, key_code=52, # Z description=_("Revert previous editing.")), HotKeyBinding( self.redo, key_code=29, # Y description=_("Make reverted editing again.")), HotKeyBinding( self.on_save, key_code=39, # S description=_("Save project.")), HotKeyBinding( self.rebuild_cache, key_code=27, # R description=_("Rebuild Cache.")) ]) hotkeys.add_key_symbols({ 27: "R", 43: "H", 32: "O", 57: "N", 40: "D", 56: "B", 42: "G", 24: "Q", 52: "Z", 29: "Y", 39: "S" }) # Menu bar menubar = VarMenu(self) filemenu = VarMenu(menubar, tearoff=False) filemenu.add_command(label=_("Add description"), command=self.on_add_description, accelerator=hotkeys.get_keycode_string( self.on_add_description)) filemenu.add_command(label=_("Set Qemu build path"), command=self.on_set_qemu_build_path, accelerator=hotkeys.get_keycode_string( self.on_set_qemu_build_path)) filemenu.add_command(label=_("Generate"), command=self.on_generate, accelerator=hotkeys.get_keycode_string( self.on_generate)) filemenu.add_separator() filemenu.add_command(label=_("New project"), command=self.on_new_project, accelerator=hotkeys.get_keycode_string( self.on_new_project)), filemenu.add_command(label=_("Save"), command=self.on_save, accelerator=hotkeys.get_keycode_string( self.on_save)), filemenu.add_command(label=_("Save project as..."), command=self.on_save_as) filemenu.add_command(label=_("Load"), command=self.on_load, accelerator=hotkeys.get_keycode_string( self.on_load)), filemenu.add_separator() filemenu.add_command(label=_("Quit"), command=self.quit, accelerator=hotkeys.get_keycode_string( self.on_delete)) menubar.add_cascade(label=_("File"), menu=filemenu) self.editmenu = editmenu = VarMenu(menubar, tearoff=False) editmenu.add_command(label=_("Undo"), command=self.undo, accelerator=hotkeys.get_keycode_string(self.undo)) self.undo_idx = editmenu.count - 1 editmenu.add_command(label=_("Redo"), command=self.redo, accelerator=hotkeys.get_keycode_string(self.redo)) self.redo_idx = editmenu.count - 1 editmenu.add_separator() editmenu.add_command(label=_("Rebuild Cache"), command=self.rebuild_cache, accelerator=hotkeys.get_keycode_string( self.rebuild_cache)) editmenu.add_separator() v = self.var_history_window = BooleanVar() v.set(False) self.__on_var_history_window = v.trace_variable( "w", self.__on_var_history_window__) editmenu.add_checkbutton(label=_("Editing history window"), variable=v, accelerator=hotkeys.get_keycode_string( self.invert_history_window)) menubar.add_cascade(label=_("Edit"), menu=editmenu) self.config(menu=menubar) # Widget layout self.grid() self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(0, weight=1) # Status bar self.grid_rowconfigure(1, weight=0) self.sb = sb = Statusbar(self) sb.grid(row=1, column=0, sticky="NEWS") # QEMU build path displaying self.var_qemu_build_path = StringVar() sb.left(self.var_qemu_build_path) # Task counters in status bar self.var_tasks = vt = IntVar() self.var_callers = vc = IntVar() self.var_active_tasks = vat = IntVar() self.var_finished_tasks = vft = IntVar() sb.right(_("Background tasks: ")) sb.right(FormatVar(value="%u") % vt, fg="red") sb.right(FormatVar(value="%u") % vc, fg="orange") sb.right(FormatVar(value="%u") % vat) sb.right(FormatVar(value="%u") % vft, fg="grey") self.task_manager.watch_activated(self.__on_task_state_changed) self.task_manager.watch_finished(self.__on_task_state_changed) self.task_manager.watch_failed(self.__on_task_state_changed) self.task_manager.watch_removed(self.__on_task_state_changed) self.protocol("WM_DELETE_WINDOW", self.on_delete) self.set_project(GUIProject() if project is None else project) self.__update_title__() self.__check_saved_asterisk__()