class FrameDialog(tk.Toplevel, FrameVisualizer): def __init__(self, master, frame_info): tk.Toplevel.__init__(self, master) self.transient(master) if misc_utils.running_on_windows(): self.wm_attributes('-toolwindow', 1) # TODO: take size from prefs editor_notebook = get_workbench().get_editor_notebook() if master.winfo_toplevel() == get_workbench(): position_reference = editor_notebook else: # align to previous frame position_reference = master.winfo_toplevel() self.geometry("{}x{}+{}+{}".format(editor_notebook.winfo_width(), editor_notebook.winfo_height()-20, position_reference.winfo_rootx(), position_reference.winfo_rooty())) self.protocol("WM_DELETE_WINDOW", self._on_close) self._init_layout_widgets(master, frame_info) FrameVisualizer.__init__(self, self._text_frame, frame_info) self._load_code(frame_info) self._text_frame.text.focus() def _init_layout_widgets(self, master, frame_info): self.main_frame= ttk.Frame(self) # just a backgroud behind padding of main_pw, without this OS X leaves white border self.main_frame.grid(sticky=tk.NSEW) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_pw = ui_utils.AutomaticPanedWindow(self.main_frame, orient=tk.VERTICAL) self.main_pw.grid(sticky=tk.NSEW, padx=10, pady=10) self.main_frame.rowconfigure(0, weight=1) self.main_frame.columnconfigure(0, weight=1) self._code_book = ttk.Notebook(self.main_pw) self._text_frame = CodeView(self._code_book, first_line_number=frame_info.firstlineno, font=get_workbench().get_font("EditorFont")) self._code_book.add(self._text_frame, text="Source") self.main_pw.add(self._code_book, minsize=100) def _load_code(self, frame_info): self._text_frame.set_content(frame_info.source) def _update_this_frame(self, msg, frame_info): FrameVisualizer._update_this_frame(self, msg, frame_info) def _on_close(self): showinfo("Can't close yet", 'Use "Stop" command if you want to cancel debugging') def close(self): FrameVisualizer.close(self) self.destroy()
def _init_layout_widgets(self, master, frame_info): self.main_frame= ttk.Frame(self) # just a backgroud behind padding of main_pw, without this OS X leaves white border self.main_frame.grid(sticky=tk.NSEW) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_pw = ui_utils.AutomaticPanedWindow(self.main_frame, orient=tk.VERTICAL) self.main_pw.grid(sticky=tk.NSEW, padx=10, pady=10) self.main_frame.rowconfigure(0, weight=1) self.main_frame.columnconfigure(0, weight=1) self._code_book = ttk.Notebook(self.main_pw) self._text_frame = CodeView(self._code_book, first_line_number=frame_info.firstlineno, font=get_workbench().get_font("EditorFont")) self._code_book.add(self._text_frame, text="Source") self.main_pw.add(self._code_book, minsize=100)
def _init_layout_widgets(self, master, msg): self.main_frame= ttk.Frame(self) # just a backgroud behind padding of main_pw, without this OS X leaves white border self.main_frame.grid(sticky=tk.NSEW) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_pw = ui_utils.AutomaticPanedWindow(self.main_frame, orient=tk.VERTICAL) self.main_pw.grid(sticky=tk.NSEW, padx=10, pady=10) self.main_frame.rowconfigure(0, weight=1) self.main_frame.columnconfigure(0, weight=1) self._code_book = ttk.Notebook(self.main_pw) self._code_view = CodeView(self._code_book, first_line_no=msg.firstlineno) self._code_book.add(self._code_view) self._code_view.enter_execution_mode() #self._code_book.rowconfigure(1, weight=1) #self._code_book.columnconfigure(0, weight=1) self._locals_book = ttk.Notebook(self.main_pw) self._locals_frame = LocalsFrame(self._locals_book) self._locals_book.add(self._locals_frame, text="Local variables") self.main_pw.add(self._code_book, minsize=130) self.main_pw.add(self._locals_book, minsize=75)
def _create_widgets(self): bg = "#ffff99" banner_frame = tk.Frame(self, background=bg) banner_frame.grid(row=0, column=0, sticky="nsew") banner_frame.rowconfigure(0, weight=1) banner_frame.columnconfigure(0, weight=1) banner_text = tk.Label( banner_frame, text=_("These\nare\ninstructions asdfa afs fa sfasdf"), background=bg, justify="left", ) banner_text.grid(column=0, row=0, pady=10, padx=10, sticky="nsew") main_frame = ttk.Frame(self) main_frame.grid(row=1, column=0, sticky=tk.NSEW, padx=15, pady=15) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_command_text = CodeView(main_frame, height=5) self.main_command_text.grid(column=0, row=1, sticky="nsew") # main_command_text["relief"] = "groove" main_frame.rowconfigure(1, weight=1) main_frame.columnconfigure(0, weight=1) button_frame = ttk.Frame(main_frame) button_frame.grid(row=2, column=0, sticky="nsew") run_button = ttk.Button(button_frame, text=_("Save and execute"), command=self._save_exec) run_button.grid(row=0, column=1, sticky="nsew") ok_button = ttk.Button(button_frame, text=_("Save"), command=self._save) ok_button.grid(row=0, column=2, sticky="nsew") cancel_button = ttk.Button(button_frame, text=_("Cancel"), command=self._cancel) cancel_button.grid(row=0, column=3, sticky="nsew") button_frame.columnconfigure(0, weight=1)
def __init__(self, master, filename=None): ttk.Frame.__init__(self, master) assert isinstance(master, EditorNotebook) # parent of codeview will be workbench so that it can be maximized self._code_view = CodeView(get_workbench(), propose_remove_line_numbers=True, font=get_workbench().get_font("EditorFont")) get_workbench().event_generate("EditorTextCreated", editor=self, text_widget=self.get_text_widget()) self._code_view.grid(row=0, column=0, sticky=tk.NSEW, in_=self) self._code_view.home_widget = self # don't forget home self.maximizable_widget = self._code_view self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self._filename = None self.file_encoding = None if filename is not None: self._load_file(filename) self._code_view.text.edit_modified(False) self._code_view.text.bind("<<Modified>>", lambda e: master.update_editor_title(self), True) self._code_view.text.bind("<Control-Tab>", self._control_tab, True) get_workbench().bind("AfterKnownMagicCommand", self._listen_for_execute, True) get_workbench().bind("ToplevelResult", self._listen_for_toplevel_result, True) self.update_appearance()
def __init__(self, master, workbench, filename=None): self._workbench = workbench ttk.Frame.__init__(self, master) assert isinstance(master, EditorNotebook) self._code_view = CodeView(self, workbench, propose_remove_line_numbers=True) self._code_view.grid(sticky=tk.NSEW) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self._stepper = None self._filename = None self.file_encoding = None if filename is not None: self._load_file(filename) self._code_view.text.edit_modified(False) self._code_view.text.bind("<<Modified>>", lambda _: self.event_generate(EDITOR_STATE_CHANGE), "+")
class ShellMacroDialog(tk.Toplevel): def __init__(self, master): tk.Toplevel.__init__(self, master) self.title(_("Configure shell macro")) if misc_utils.running_on_mac_os(): self.configure(background="systemSheetBackground") self.transient(master) self.grab_set() # to make it active # self.grab_release() # to allow eg. copy something from the editor self._create_widgets() self.bind("<Escape>", self._on_close, True) self.protocol("WM_DELETE_WINDOW", self._on_close) self.main_command_text.focus_set() def _create_widgets(self): bg = "#ffff99" banner_frame = tk.Frame(self, background=bg) banner_frame.grid(row=0, column=0, sticky="nsew") banner_frame.rowconfigure(0, weight=1) banner_frame.columnconfigure(0, weight=1) banner_text = tk.Label( banner_frame, text=_("These\nare\ninstructions asdfa afs fa sfasdf"), background=bg, justify="left", ) banner_text.grid(column=0, row=0, pady=10, padx=10, sticky="nsew") main_frame = ttk.Frame(self) main_frame.grid(row=1, column=0, sticky=tk.NSEW, padx=15, pady=15) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_command_text = CodeView(main_frame, height=5) self.main_command_text.grid(column=0, row=1, sticky="nsew") # main_command_text["relief"] = "groove" main_frame.rowconfigure(1, weight=1) main_frame.columnconfigure(0, weight=1) button_frame = ttk.Frame(main_frame) button_frame.grid(row=2, column=0, sticky="nsew") run_button = ttk.Button(button_frame, text=_("Save and execute"), command=self._save_exec) run_button.grid(row=0, column=1, sticky="nsew") ok_button = ttk.Button(button_frame, text=_("Save"), command=self._save) ok_button.grid(row=0, column=2, sticky="nsew") cancel_button = ttk.Button(button_frame, text=_("Cancel"), command=self._cancel) cancel_button.grid(row=0, column=3, sticky="nsew") button_frame.columnconfigure(0, weight=1) def _on_close(self, event=None): self.destroy() def _save_exec(self, event=None): self._save(event) execute_macro() def _save(self, event=None): source = self.main_command_text.text.get("1.0", "end") get_workbench().set_option("run.shell_macro_main", repr(source)) self.destroy() def _cancel(self, event=None): self.destroy()
class Editor(ttk.Frame): def __init__(self, master, filename=None): ttk.Frame.__init__(self, master) assert isinstance(master, EditorNotebook) # parent of codeview will be workbench so that it can be maximized self._code_view = CodeView(get_workbench(), propose_remove_line_numbers=True, font=get_workbench().get_font("EditorFont")) get_workbench().event_generate("EditorTextCreated", editor=self, text_widget=self.get_text_widget()) self._code_view.grid(row=0, column=0, sticky=tk.NSEW, in_=self) self._code_view.home_widget = self # don't forget home self.maximizable_widget = self._code_view self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self._filename = None self.file_encoding = None if filename is not None: self._load_file(filename) self._code_view.text.edit_modified(False) self._code_view.text.bind("<<Modified>>", lambda e: master.update_editor_title(self), True) self._code_view.text.bind("<Control-Tab>", self._control_tab, True) get_workbench().bind("AfterKnownMagicCommand", self._listen_for_execute, True) get_workbench().bind("ToplevelResult", self._listen_for_toplevel_result, True) self.update_appearance() def get_text_widget(self): return self._code_view.text def get_code_view(self): # TODO: try to get rid of this return self._code_view def get_filename(self, try_hard=False): if self._filename is None and try_hard: self.save_file() return self._filename def _load_file(self, filename): source, self.file_encoding = misc_utils.read_python_file( filename) # TODO: support also text files self._filename = filename get_workbench().event_generate("Open", editor=self, filename=filename) self._code_view.set_content(source) self._code_view.focus_set() self.master.remember_recent_file(filename) def is_modified(self): return self._code_view.text.edit_modified() def save_file_enabled(self): return self.is_modified() or not self.get_filename() def save_file(self, ask_filename=False): if self._filename is not None and not ask_filename: filename = self._filename get_workbench().event_generate("Save", editor=self, filename=filename) else: # http://tkinter.unpythonic.net/wiki/tkFileDialog filename = asksaveasfilename( filetypes=_dialog_filetypes, defaultextension=".py", initialdir=get_workbench().get_option("run.working_directory")) if filename in [ "", (), None ]: # Different tkinter versions may return different values return None # Seems that in some Python versions defaultextension # acts funny if filename.lower().endswith(".py.py"): filename = filename[:-3] get_workbench().event_generate("SaveAs", editor=self, filename=filename) content = self._code_view.get_content() encoding = self.file_encoding or "UTF-8" f = open( filename, mode="wb", ) f.write(content.encode(encoding)) f.close() self._filename = filename self.master.remember_recent_file(filename) self._code_view.text.edit_modified(False) return self._filename def show(self): self.master.select(self) def update_appearance(self): self._code_view.set_line_numbers( get_workbench().get_option("view.show_line_numbers")) self._code_view.set_line_length_margin( get_workbench().get_option("view.recommended_line_length")) self._code_view.text.event_generate("<<UpdateAppearance>>") def _listen_for_execute(self, event): command, args = parse_shell_command(event.cmd_line) if command.lower() in ["run", "debug"]: if len(args) == 0: return filename = args[0] self_filename = self.get_filename() if self_filename is not None and os.path.basename( self_filename) == filename: # Not that command has only basename # so this solution may make more editors read-only than necessary self._code_view.text.set_read_only(True) def _listen_for_toplevel_result(self, event): self._code_view.text.set_read_only(False) def _control_tab(self, event): if event.state & 1: # shift was pressed direction = -1 else: direction = 1 self.master.select_next_prev_editor(direction) return "break" def _shift_control_tab(self, event): self.master.select_next_prev_editor(-1) return "break" def select_range(self, text_range): self._code_view.select_range(text_range) def focus_set(self): self._code_view.focus_set() def is_focused(self): return self.focus_displayof() == self._code_view.text def destroy(self): get_workbench().unbind("AfterKnownMagicCommand", self._listen_for_execute) get_workbench().unbind("ToplevelResult", self._listen_for_toplevel_result) ttk.Frame.destroy(self)
class FunctionDialog(tk.Toplevel): def __init__(self, master, msg, title): tk.Toplevel.__init__(self, master) self._frame_id = msg.frame_id self.title(title) self.transient(master) if misc_utils.running_on_windows(): self.wm_attributes('-toolwindow', 1) # TODO: take size from prefs self.geometry("{}x{}+{}+{}".format(master.winfo_width(), master.winfo_height(), master.winfo_toplevel().winfo_rootx(), master.winfo_toplevel().winfo_rooty())) self.protocol("WM_DELETE_WINDOW", self._on_close) self._init_layout_widgets(master, msg) self._load_function(msg) self._stepper = StatementStepper(msg.frame_id, self, self._workbench, self._code_view) self._code_view.text.focus() def get_frame_id(self): return self._frame_id def _init_layout_widgets(self, master, msg): self.main_frame= ttk.Frame(self) # just a backgroud behind padding of main_pw, without this OS X leaves white border self.main_frame.grid(sticky=tk.NSEW) self.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.main_pw = ui_utils.AutomaticPanedWindow(self.main_frame, orient=tk.VERTICAL) self.main_pw.grid(sticky=tk.NSEW, padx=10, pady=10) self.main_frame.rowconfigure(0, weight=1) self.main_frame.columnconfigure(0, weight=1) self._code_book = ttk.Notebook(self.main_pw) self._code_view = CodeView(self._code_book, first_line_no=msg.firstlineno) self._code_book.add(self._code_view) self._code_view.enter_execution_mode() #self._code_book.rowconfigure(1, weight=1) #self._code_book.columnconfigure(0, weight=1) self._locals_book = ttk.Notebook(self.main_pw) self._locals_frame = LocalsFrame(self._locals_book) self._locals_book.add(self._locals_frame, text="Local variables") self.main_pw.add(self._code_book, minsize=130) self.main_pw.add(self._locals_book, minsize=75) def _load_function(self, msg): self._code_view.set_content(msg.source) if hasattr(msg, "function"): function_label = msg.function.repr else: function_label = msg.code_name self._code_book.tab(self._code_view, text=function_label) #self._locals_frame.handle_vm_message(msg) def handle_vm_message(self, msg): self._stepper.handle_vm_message(msg) if hasattr(msg, "stack"): frame = list(filter(lambda f: f.id == self._frame_id, msg.stack))[0] self._locals_frame.update_variables(frame.locals) else: self._locals_frame.update_variables(None) def _on_close(self): showinfo("Can't close yet", "Step until the end of this function to close it")
class Editor(ttk.Frame): """ Text editor and visual part of module stepper """ def __init__(self, master, workbench, filename=None): self._workbench = workbench ttk.Frame.__init__(self, master) assert isinstance(master, EditorNotebook) self._code_view = CodeView(self, workbench, propose_remove_line_numbers=True) self._code_view.grid(sticky=tk.NSEW) self.columnconfigure(0, weight=1) self.rowconfigure(0, weight=1) self._stepper = None self._filename = None self.file_encoding = None if filename is not None: self._load_file(filename) self._code_view.text.edit_modified(False) self._code_view.text.bind("<<Modified>>", lambda _: self.event_generate(EDITOR_STATE_CHANGE), "+") def get_filename(self, try_hard=False): if self._filename is None and try_hard: self._cmd_save_file() return self._filename def _load_file(self, filename): source, self.file_encoding = misc_utils.read_python_file(filename) # TODO: support also text files self._filename = filename self._code_view.modified_since_last_save = False self._workbench.event_generate("Open", editor=self, filename=filename) self._code_view.set_content(source) self._code_view.focus_set() def is_modified(self): return self._code_view.modified_since_last_save def save_file_enabled(self): return self.is_modified() or not self.get_filename() def save_file(self): if self._filename is not None: filename = self._filename self._workbench.event_generate("Save", editor=self) else: # http://tkinter.unpythonic.net/wiki/tkFileDialog filename = asksaveasfilename ( filetypes = _dialog_filetypes, defaultextension = ".py", initialdir = self._workbench.get_option("run.working_directory") ) if filename == "": return None self._workbench.event_generate("SaveAs", editor=self, filename=filename) content = self._code_view.get_content() encoding = self.file_encoding or "UTF-8" f = open(filename, mode="wb", ) f.write(content.encode(encoding)) f.close() self._code_view.modified_since_last_save = False self._filename = filename self._code_view.text.edit_modified(False) self.event_generate(EDITOR_STATE_CHANGE) return self._filename def change_font_size(self, delta): self._code_view.change_font_size(delta) def show(self): self.master.select(self) def handle_vm_message(self, msg): assert isinstance(msg, DebuggerResponse) if self.is_modified(): raise RuntimeError ("Can't show debug info in modified editor") """ # actually this check is not sound, as this_frame.source is not guaranteed # to be saved at code compilation time if frame.source != self._code_view.get_content(): print("Editor content>" + self._code_view.get_content() + "<") print("frame.source>" + frame.source + "<") raise RuntimeError ("Editor content doesn't match module source. Did you change it after starting the program?") """ if self._stepper is None: self._stepper = StatementStepper(msg.frame_id, self, self._workbench, self._code_view) self._stepper.handle_vm_message(msg) def select_range(self, text_range): self._code_view.select_range(text_range) def enter_execution_mode(self): self._code_view.enter_execution_mode() def clear_debug_view(self): if self._stepper is not None: self._stepper.clear_debug_view() def exit_execution_mode(self): self.clear_debug_view() self._code_view.exit_execution_mode() self._stepper = None def get_frame_id(self): if self._stepper is None: return None else: return self._stepper.frame_id def focus_set(self): self._code_view.focus_set() def is_focused(self): return self.focus_displayof() == self._code_view.text