コード例 #1
0
ファイル: code.py プロジェクト: aivarannamaa/thonny
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")
コード例 #2
0
ファイル: code.py プロジェクト: aivarannamaa/thonny
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