Exemplo n.º 1
0
 def paste_and_take(self):
     if self._clipboardStack.has_any():
         action1 = self.delete_selection(False)
         action2 = self._model.execute_insert_at_caret(self._clipboardStack.pop())
         actions = [a for a in [action1, action2] if a is not None]
         if actions:
             UndoManager.get_instance().push(JumboEditAction(actions))
Exemplo n.º 2
0
    def init_toolbar(self):
        toolbar = Frame(self.master)

        undo = Button(toolbar, text="Undo", command=self.undo, state=DISABLED)
        undo.pack(side=LEFT, padx=2, pady=2)
        UndoManager.get_instance().attach_undo_observer(
            type("UndoManagerStackObserver3", (UndoManagerStackObserver, object),
                 {"stack_empty": lambda _, e: undo.config(state=DISABLED if e else NORMAL)})())

        redo = Button(toolbar, text="Redo", command=self.redo, state=DISABLED)
        redo.pack(side=LEFT, padx=2, pady=2)
        UndoManager.get_instance().attach_redo_observer(
            type("UndoManagerStackObserver4", (UndoManagerStackObserver, object),
                 {"stack_empty": lambda _, e: redo.config(state=DISABLED if e else NORMAL)})())

        copy = Button(toolbar, text="Copy", command=self.copy, state=DISABLED)
        copy.pack(side=LEFT, padx=2, pady=2)
        self._model.attach_selection_observer(
            type("SelectionObserverCopyTool", (SelectionObserver, object),
                 {"update_selection": lambda _, e: copy.config(state=DISABLED if not e else NORMAL)})())

        cut = Button(toolbar, text="Cut", command=self.cut, state=DISABLED)
        cut.pack(side=LEFT, padx=2, pady=2)
        self._model.attach_selection_observer(
            type("SelectionObserverCutTool", (SelectionObserver, object),
                 {"update_selection": lambda _, e: cut.config(state=DISABLED if not e else NORMAL)})())

        paste = Button(toolbar, text="Paste", command=self.cut, state=DISABLED)
        paste.pack(side=LEFT, padx=2, pady=2)
        self._clipboardStack.attach_clipboard_observer(
            type("ClipboardObserverPasteTool", (ClipboardObserver, object),
                 {"update_clipboard": lambda _, e: paste.config(state=DISABLED if not e else NORMAL)})())

        toolbar.pack(side=TOP, fill=X)
Exemplo n.º 3
0
    def delete_selection(self, push_action=True) -> EditAction:
        if self._model.get_selection_range().is_empty():
            return
        sel_left = self._model.get_selection_range().get_left()
        self._model.move_caret_to(sel_left)

        action = self._model.execute_delete_range(self._model.get_selection_range().clone())
        if push_action and action is not None:
            UndoManager.get_instance().push(action)
        self._model.set_selection_range(LocationRange(sel_left.get(), sel_left.get()))
        return action
Exemplo n.º 4
0
    def init_menubar(self):
        menubar = Menu(self.master)
        self.master.config(menu=menubar)

        file_menu = Menu(menubar)
        file_menu.add_command(label="Open", underline=0, command=self.open_file)
        file_menu.add_command(label="Save", underline=0, command=self.save_file)
        file_menu.add_command(label="Exit", underline=0, command=self.on_exit)
        menubar.add_cascade(label="File", underline=0, menu=file_menu)

        edit_menu = Menu(menubar)
        edit_menu.add_command(label="Undo", command=self.undo, state=DISABLED)
        UndoManager.get_instance().attach_undo_observer(
            type("UndoManagerStackObserver1", (UndoManagerStackObserver, object),
                 {"stack_empty": lambda _, e: edit_menu.entryconfig(1, state=DISABLED if e else NORMAL)})())

        edit_menu.add_command(label="Redo", command=self.redo, state=DISABLED)
        UndoManager.get_instance().attach_redo_observer(
            type("UndoManagerStackObserver2", (UndoManagerStackObserver, object),
                 {"stack_empty": lambda _, e: edit_menu.entryconfig(2, state=DISABLED if e else NORMAL)})())

        edit_menu.add_command(label="Cut", command=self.cut, state=DISABLED)
        self._model.attach_selection_observer(
            type("SelectionObserverCut", (SelectionObserver, object),
                 {"update_selection": lambda _, e: edit_menu.entryconfig(3, state=DISABLED if not e else NORMAL)})())

        edit_menu.add_command(label="Copy", command=self.copy, state=DISABLED)
        self._model.attach_selection_observer(
            type("SelectionObserverCopy", (SelectionObserver, object),
                 {"update_selection": lambda _, e: edit_menu.entryconfig(4, state=DISABLED if not e else NORMAL)})())

        edit_menu.add_command(label="Paste", command=self.paste, state=DISABLED)
        self._clipboardStack.attach_clipboard_observer(
            type("ClipboardObserverPaste", (ClipboardObserver, object),
                 {"update_clipboard": lambda _, e: edit_menu.entryconfig(5, state=DISABLED if not e else NORMAL)})())

        edit_menu.add_command(label="Paste and Take", command=self.paste_and_take)
        self._clipboardStack.attach_clipboard_observer(
            type("ClipboardObserverPasteAndTake", (ClipboardObserver, object),
                 {"update_clipboard": lambda _, e: edit_menu.entryconfig(6, state=DISABLED if not e else NORMAL)})())

        edit_menu.add_command(label="Delete selection", command=self.delete_selection, state=DISABLED)
        self._model.attach_selection_observer(
            type("SelectionObserverDelete", (SelectionObserver, object),
                 {"update_selection": lambda _, e: edit_menu.entryconfig(7, state=DISABLED if not e else NORMAL)})())

        edit_menu.add_command(label="Clear document", command=self.clear_document)
        menubar.add_cascade(label="Edit", underline=0, menu=edit_menu)

        move_menu = Menu(menubar)
        move_menu.add_command(label="Caret to document start", command=self.caret_to_start)
        move_menu.add_command(label="Caret to document end", command=self.caret_to_end)
        menubar.add_cascade(label="Move", underline=0, menu=move_menu)

        plugins_menu = Menu(menubar)
        for plugin in self._plugins:
            plugins_menu.add_command(
                label=plugin.get_name(),
                command=lambda p=plugin: p.execute(self._model, UndoManager.get_instance(), self._clipboardStack))

        menubar.add_cascade(label="Plugins", underline=0, menu=plugins_menu)
Exemplo n.º 5
0
 def paste(self):
     if self._clipboardStack.has_any():
         self.delete_selection()
         action = self._model.execute_insert_at_caret(self._clipboardStack.peek())
         if action is not None:
             UndoManager.get_instance().push(action)
Exemplo n.º 6
0
 def redo(self):
     um = UndoManager.get_instance()
     if not um.is_redo_empty():
         um.redo()
Exemplo n.º 7
0
 def undo(self):
     um = UndoManager.get_instance()
     if not um.is_undo_empty():
         um.undo()
Exemplo n.º 8
0
    def on_key_pressed(self, e):
        if self._other_dialog_open:
            return
        keysym = e.keysym
        char = e.char

        # https://stackoverflow.com/questions/19861689/check-if-modifier-key-is-pressed-in-tkinter
        ctrl = (e.state & 0x4) != 0
        alt = (e.state & 0x8) != 0 or (e.state & 0x80) != 0
        shift = (e.state & 0x1) != 0
        self._selecting_active = shift

        # print(e.keysym, e.char, e.keycode, e.char.isprintable(), "%x" % e.state, ctrl, shift, alt)

        if keysym == "Left":
            self._display_caret = True
            caret_before = self._model.get_caret_location().get()
            self._model.move_caret_left()
            self.update_selection(caret_before == self._model.get_selection_range().get_end().get())
        elif keysym == "Right":
            self._display_caret = True
            caret_before = self._model.get_caret_location().get()
            self._model.move_caret_right()
            self.update_selection(caret_before == self._model.get_selection_range().get_end().get())
        elif keysym == "Up":
            self._display_caret = True
            caret_before = self._model.get_caret_location().get()
            self._model.move_caret_up()
            self.update_selection(caret_before == self._model.get_selection_range().get_end().get())
        elif keysym == "Down":
            self._display_caret = True
            caret_before = self._model.get_caret_location().get()
            self._model.move_caret_down()
            self.update_selection(caret_before == self._model.get_selection_range().get_end().get())
        elif keysym == "BackSpace":
            self._display_caret = True
            if self._model.get_selection_range().is_empty():
                action = self._model.execute_delete_before()
                if action is not None:
                    UndoManager.get_instance().push(action)
            else:
                self.delete_selection()
        elif keysym == "Delete":
            self._display_caret = True
            if self._model.get_selection_range().is_empty():
                action = self._model.execute_delete_after()
                if action is not None:
                    UndoManager.get_instance().push(action)
            else:
                self.delete_selection()
        elif keysym == "Return":
            # TODO what if None
            action1 = self.delete_selection(False)
            action2 = self._model.execute_insert_at_caret("\n")
            actions = [a for a in [action1, action2] if a is not None]
            if actions:
                UndoManager.get_instance().push(JumboEditAction(actions))
        elif keysym == "Escape":
            self._display_caret = True
            self.master.destroy()
        elif ctrl and keysym.lower() == "c":
            self.copy()
        elif ctrl and keysym.lower() == "x":
            self.cut()
        elif ctrl and keysym.lower() == "v":
            if shift:
                self.paste_and_take()
            else:
                self.paste()
        elif ctrl and keysym.lower() == "y":
            self.redo()
        elif ctrl and keysym.lower() == "z":
            self.undo()
        elif len(char) and char.isprintable():
            # TODO should LocationRange be immutable? Or how should I pass it around?
            action1 = self.delete_selection(False)
            action2 = self._model.execute_insert_at_caret(char)
            self._model.reset_selection()
            actions = [a for a in [action1, action2] if a is not None]
            if actions:
                UndoManager.get_instance().push(JumboEditAction(actions))