示例#1
0
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