コード例 #1
0
class Editor(Component):
    def __init__(self, page, cid):
        super().__init__(page, cid)
        self._box = None
        self._strvar_title = tk.StringVar()
        self._text_widget = None

    @property
    def parts(self):
        """Dictionary that contains parts of this component.
        Exposed parts are: "text_widget" and "strvar_title"
        """
        return self._parts

    def build(self,
              title=None,
              text=None,
              readonly=False,
              width=45,
              height=10,
              new_col=True,
              side=tk.BOTTOM,
              anchor="nw",
              padx=5,
              pady=5,
              expand=False,
              fill=None):
        # get new box
        self._box = self._page.new_box(new_col, side, anchor, padx, pady,
                                       expand, fill)
        # set title
        if title:
            self._strvar_title.set(title)
            title_label = tk.Label(self._box, textvariable=self._strvar_title)
            title_label.pack(anchor="nw")
        self._parts["strvar_title"] = self._strvar_title
        # create text widget
        from tkinter.scrolledtext import ScrolledText
        self._text_widget = ScrolledText(self._box, width=width, height=height)
        self._text_widget.pack(fill=fill, expand=expand)
        self._parts["text"] = self._text_widget
        # fill text widget
        if text is not None:
            self._text_widget.insert("1.0", text)
        if readonly:
            self._text_widget.config(state=tk.DISABLED)

    def read(self):
        if self._text_widget:
            return self._text_widget.get("1.0", tk.END)
        return None

    def update(self, title=None, text=None, readonly=None):
        if title is not None:
            self._strvar_title.set(title)
        if text is not None:
            readonly_cache = self._text_widget.cget("state")
            readonly_cache = True if readonly_cache == tk.DISABLED else False
            if readonly_cache:
                self._text_widget.config(state=tk.NORMAL)
            self._text_widget.delete("1.0", tk.END)
            self._text_widget.insert("1.0", text)
            if readonly_cache:
                self._text_widget.config(state=tk.DISABLED)
        if readonly is not None:
            state = tk.DISABLED if readonly else tk.NORMAL
            self._text_widget.config(state=state)

    def _gen_info(self):
        Info = namedtuple("Info", ("page", "cid", "component"))
        info = Info(self._page, self._cid, self)
        return info
コード例 #2
0
class EditorTab(tk.Frame):
    def __init__(self, master, filepath: str, new_file=False):
        tk.Frame.__init__(self, master)
        self.new_file = new_file
        self.filepath = filepath
        self.filename = get_filename(filepath) if not new_file else filepath
        self.master = master
        self.modified = False
        self.text_editor = ScrolledText(self,
                                        font=("", 15),
                                        undo=True,
                                        maxundo=-1,
                                        wrap="none")
        self.text_editor.config(highlightthickness=0, bd=0)
        self.text_editor.grid(row=0, column=1, sticky=tk.NSEW)
        self.scrollbar_x = tk.Scrollbar(self,
                                        orient=tk.HORIZONTAL,
                                        command=self.text_editor.xview)
        self.scrollbar_x.grid(row=1, column=0, columnspan=2, stick=tk.EW)
        self.text_editor.configure(xscrollcommand=self.scrollbar_x.set)
        self.line_nb_canvas = tk.Canvas(self,
                                        bg=self.text_editor.cget("bg"),
                                        bd=0,
                                        highlightthickness=0)
        self.line_nb_canvas.grid_propagate(False)
        self.line_nb_canvas.grid(row=0, column=0, sticky=tk.NS)
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=1)
        self.default_file_content = str()

    @property
    def id(self) -> str:
        return str(self)

    def get(self) -> str:
        return self.text_editor.get("1.0", "end-1c")

    @property
    def lines(self):
        return self.get().splitlines()

    def update_lines(self):
        self.line_nb_canvas.delete("all")
        font = self.text_editor.cget("font")
        i = 1
        y = 0
        while self.text_editor.compare(f"{i}.0", "<", tk.END):
            dline = self.text_editor.dlineinfo(f"{i}.0")
            if dline:
                y = dline[1]
            else:
                y = -20
            self.line_nb_canvas.create_text(1,
                                            y,
                                            anchor="ne",
                                            text=str(i),
                                            font=font,
                                            fill=Color(175, 175, 175).hex)
            i += 1
        all_boxes = [
            self.line_nb_canvas.bbox(item)
            for item in self.line_nb_canvas.find_all()
        ]
        max_width = (min(box[2] - box[0] for box in all_boxes)) * 4
        self.line_nb_canvas.configure(width=max_width + 20)
        for item in self.line_nb_canvas.find_all():
            self.line_nb_canvas.move(item, max_width, 0)

    def get_filename_from_champion_name(self) -> (str, None):
        content = self.lines
        for line in content:
            if line.startswith(".name"):
                first_quote = line.find('"')
                if first_quote == -1:
                    break
                second_quote = line.find('"', first_quote + 1)
                if second_quote == -1:
                    break
                name = line[first_quote + 1:second_quote]
                if len(name) == 0:
                    break
                return name.replace(" ", "_").lower() + ".s"
        return None

    def open(self) -> bool:
        if not os.path.isfile(self.filepath):
            showwarning("An error occurs...", f"Can't open '{self.filepath}'")
            return False
        with open(self.filepath, "r") as file:
            self.default_file_content = file.read()
            self.text_editor.insert("1.0", self.default_file_content)
            self.text_editor.edit_reset()
            self.text_editor.edit_modified(False)
        self.set_modified_status(False, on_opening=True)
        return True

    def save(self) -> bool:
        if self.new_file:
            return self.master.save_file_as()
        self.default_file_content = self.text_editor.get("1.0", "end-1c")
        with open(self.filepath, "w") as file:
            file.write(self.default_file_content)
        self.set_modified_status(False)
        self.text_editor.edit_modified(False)
        return True

    def save_as(self, filepath: str) -> bool:
        self.master.files_opened[filepath] = self.master.files_opened[
            self.filepath]
        self.master.files_opened.pop(self.filepath)
        self.filepath = filepath
        self.filename = get_filename(filepath)
        self.new_file = False
        return self.save()

    def close(self) -> bool:
        if self.modified:
            save_file = askyesnocancel(
                f"{self.filename} - Modifications not saved",
                "This file was modified and was not saved.\nDo you want to save this file ?"
            )
            if save_file is None:
                return False
            if save_file and not self.save():
                return False
        self.master.forget(self.id)
        self.master.files_opened.pop(self.filepath)
        return True

    def undo(self) -> None:
        try:
            self.text_editor.edit_undo()
        except tk.TclError:
            pass

    def redo(self) -> None:
        try:
            self.text_editor.edit_redo()
        except tk.TclError:
            pass

    def copy_to_clipboard(self, remove_from_editor=False) -> bool:
        try:
            txt = self.text_editor.get("sel.first", "sel.last")
            self.clipboard_clear()
            self.clipboard_append(txt)
            if remove_from_editor:
                self.text_editor.delete("sel.first", "sel.last")
        except tk.TclError:
            return False
        return True

    def paste_from_clipboard(self) -> None:
        try:
            self.text_editor.get("sel.first", "sel.last")
        except tk.TclError:
            pass
        else:
            self.text_editor.mark_set("insert", "sel.first")
            self.text_editor.delete("sel.first", "sel.last")
        self.text_editor.insert("insert", self.clipboard_get())

    def check_file_status(self) -> None:
        actual = self.text_editor.get("1.0", "end-1c")
        if self.text_editor.edit_modified():
            self.text_editor.edit_separator()
            self.text_editor.edit_modified(False)
        self.set_modified_status(actual != self.default_file_content)

    def set_modified_status(self, status: bool, on_opening=False) -> None:
        self.modified = status
        if not on_opening:
            if self.modified and not self.new_file:
                self.master.tab(self.id, text=self.filename + " - Modified")
            else:
                self.master.tab(self.id, text=self.filename)

    def add(self) -> None:
        self.master.add(self, text=self.filename)

    def select(self) -> None:
        self.master.select(self.id)
        self.text_editor.focus_set()

    def set_template(self, name: str, comment: str, author: str) -> None:
        content = [
            line for line in self.lines
            if not line.startswith(".name") and not line.startswith(".comment")
        ]
        header = [
            "#", "# {name} champion for CoreWar".format(name=name), "#",
            "# By {author}".format(author=author), "#",
            "# {date}".format(date=date.today().strftime("%c")), "#", ""
            ".name \"{name}\"".format(name=name),
            ".comment \"{comment}\"".format(comment=comment), ""
        ]
        content = header + content
        self.text_editor.delete("1.0", "end")
        self.text_editor.insert("1.0", "\n".join(content))

    def insert_command(self, cmd: str) -> None:
        insert = self.text_editor.index(tk.INSERT).split(".")
        end_of_line = insert[0] + "." + tk.END
        self.text_editor.insert(end_of_line, "\n" + cmd)
コード例 #3
0
class Application(tkinter.Tk):
    def __init__(self):
        """Initialize widgets, methods."""

        tkinter.Tk.__init__(self)
        self.grid()

        fontoptions = families(self)
        font = Font(family="Verdana", size=10)

        menubar = tkinter.Menu(self)
        fileMenu = tkinter.Menu(menubar, tearoff=0)
        editMenu = tkinter.Menu(menubar, tearoff=0)
        fsubmenu = tkinter.Menu(editMenu, tearoff=0)
        ssubmenu = tkinter.Menu(editMenu, tearoff=0)

        # adds fonts to the font submenu and associates lambda functions
        for option in fontoptions:
            fsubmenu.add_command(label=option, command = lambda: font.configure(family=option))
        # adds values to the size submenu and associates lambda functions
        for value in range(1,31):
            ssubmenu.add_command(label=str(value), command = lambda: font.configure(size=value))

        # adds commands to the menus
        menubar.add_cascade(label="File",underline=0, menu=fileMenu)
        menubar.add_cascade(label="Edit",underline=0, menu=editMenu)
        fileMenu.add_command(label="New", underline=1,command=self.new, accelerator="Ctrl+N")
        fileMenu.add_command(label="Open", command=self.open, accelerator="Ctrl+O")
        fileMenu.add_command(label="Save", command=self.save, accelerator="Ctrl+S")
        fileMenu.add_command(label="Exit", underline=1,command=exit, accelerator="Ctrl+Q")                      
        editMenu.add_command(label="Copy", command=self.copy, accelerator="Ctrl+C")
        editMenu.add_command(label="Cut", command=self.cut, accelerator="Ctrl+X")
        editMenu.add_command(label="Paste", command=self.paste, accelerator="Ctrl+V")
        editMenu.add_cascade(label="Font", underline=0, menu=fsubmenu)
        editMenu.add_cascade(label="Size", underline=0, menu=ssubmenu)
        editMenu.add_command(label="Color", command=self.color)
        editMenu.add_command(label="Bold", command=self.bold, accelerator="Ctrl+B")
        editMenu.add_command(label="Italic", command=self.italic, accelerator="Ctrl+I")
        editMenu.add_command(label="Underline", command=self.underline, accelerator="Ctrl+U")
        editMenu.add_command(label="Overstrike", command=self.overstrike, accelerator="Ctrl+T")
        editMenu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z")
        editMenu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y")
        self.config(menu=menubar)


        self.bind_all("<Control-n>", self.new)
        self.bind_all("<Control-o>", self.open)
        self.bind_all("<Control-s>", self.save)
        self.bind_all("<Control-q>", self.exit)
        self.bind_all("<Control-b>", self.bold)
        self.bind_all("<Control-i>", self.italic)
        self.bind_all("<Control-u>", self.underline)
        self.bind_all("<Control-T>", self.overstrike)
        self.bind_all("<Control-z>", self.undo)
        self.bind_all("<Control-y>", self.redo)

        self.text = ScrolledText(self, state='normal', height=80, wrap='word', font = font, pady=2, padx=3, undo=True)
        self.text.grid(column=0, row=0, sticky='NSEW')

        # Frame configuration
        self.grid_columnconfigure(0, weight=1)
        self.resizable(True, True)



    def new(self, *args):
        """Creates a new window."""
        app = Application()
        app.title('Python Text Editor')
        app.option_add('*tearOff', False)
        app.mainloop()

    def color(self):
        """Changes selected text color."""
        try:
            (rgb, hx) = tkinter.colorchooser.askcolor()
            self.text.tag_add('color', 'sel.first', 'sel.last')
            self.text.tag_configure('color', foreground=hx)
        except TclError:
            pass

    def bold(self, *args):
        """Toggles bold for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "bold" in current_tags:
                self.text.tag_remove("bold", "sel.first", "sel.last")
            else:
                self.text.tag_add("bold", "sel.first", "sel.last")
                bold_font = Font(self.text, self.text.cget("font"))
                bold_font.configure(weight="bold")
                self.text.tag_configure("bold", font=bold_font)
        except TclError:
            pass

    def italic(self, *args):
        """Toggles italic for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "italic" in current_tags:
                self.text.tag_remove("italic", "sel.first", "sel.last")
            else:
                self.text.tag_add("italic", "sel.first", "sel.last")
                italic_font = Font(self.text, self.text.cget("font"))
                italic_font.configure(slant="italic")
                self.text.tag_configure("italic", font=italic_font)
        except TclError:
            pass

    def underline(self, *args):
        """Toggles underline for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "underline" in current_tags:
                self.text.tag_remove("underline", "sel.first", "sel.last")
            else:
                self.text.tag_add("underline", "sel.first", "sel.last")
                underline_font = Font(self.text, self.text.cget("font"))
                underline_font.configure(underline=1)
                self.text.tag_configure("underline", font=underline_font)
        except TclError:
            pass

    def overstrike(self, *args):
        """Toggles overstrike for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "overstrike" in current_tags:
                self.text.tag_remove("overstrike", "sel.first", "sel.last")
            else:
                self.text.tag_add("overstrike", "sel.first", "sel.last")
                overstrike_font = Font(self.text, self.text.cget("font"))
                overstrike_font.configure(overstrike=1)
                self.text.tag_configure("overstrike", font=overstrike_font)
        except TclError:
            pass

    def undo(self, *args):
        """Undo function"""
        try:
            self.text.edit_undo()
        except TclError:
            pass

    def redo(self, *args):
        """Redo function"""
        try:
            self.text.edit_redo()
        except TclError:
            pass

    def copy(self, *args):
        """Copy text"""
        self.clipboard_clear()
        self.clipboard_append(self.text.selection_get())

    def cut(self, *args):
        """Cut text"""
        self.copy
        self.text.delete("sel.first", "sel.last")

    def paste(self, *args):
        """Paste text"""
        insertion = self.selection_get(selection = "CLIPBOARD")
        self.text.insert(0.0, insertion)

    def open(self, *args):
        """Opens a file dialog to open a plain text file."""
        filename = tkinter.filedialog.askopenfilename()

        with open(filename) as f:
            text = f.read()

        self.text.delete("1.0", "end")
        self.text.insert('insert', text)

    def save(self, *args):
        try:
            """Opens a file dialog to save the text in plain text format."""
            text = self.text.get("1.0", "end")
            filename = tkinter.filedialog.asksaveasfilename()

            with open(filename, 'w') as f:
                f.write(text)
        except FileNotFoundError:
            pass

    def exit(self, *args):
        """Exits the program."""
        self.quit()
コード例 #4
0
ファイル: TextEditor.py プロジェクト: Drax-il/TextEditor
class Application(tkinter.Tk):
    def __init__(self):
        """Initialize widgets, methods."""

        tkinter.Tk.__init__(self)
        self.grid()

        fontoptions = families(self)
        font = Font(family="Verdana", size=10)

        menubar = tkinter.Menu(self)
        fileMenu = tkinter.Menu(menubar, tearoff=0)
        editMenu = tkinter.Menu(menubar, tearoff=0)
        fsubmenu = tkinter.Menu(editMenu, tearoff=0)
        ssubmenu = tkinter.Menu(editMenu, tearoff=0)

        # adds fonts to the font submenu and associates lambda functions
        for option in fontoptions:
            fsubmenu.add_command(label=option, command = lambda: font.configure(family=option))
        # adds values to the size submenu and associates lambda functions
        for value in range(1,31):
            ssubmenu.add_command(label=str(value), command = lambda: font.configure(size=value))

        # adds commands to the menus
        menubar.add_cascade(label="File",underline=0, menu=fileMenu)
        menubar.add_cascade(label="Edit",underline=0, menu=editMenu)
        fileMenu.add_command(label="New", underline=1,
                             command=self.new, accelerator="Ctrl+N")
        fileMenu.add_command(label="Open", command=self.open, accelerator="Ctrl+O")
        fileMenu.add_command(label="Save", command=self.save, accelerator="Ctrl+S")
        fileMenu.add_command(label="Exit", underline=1,
                             command=exit, accelerator="Ctrl+Q")
        editMenu.add_command(label="Copy", command=self.copy, accelerator="Ctrl+C")
        editMenu.add_command(label="Cut", command=self.cut, accelerator="Ctrl+X")
        editMenu.add_command(label="Paste", command=self.paste, accelerator="Ctrl+V")
        editMenu.add_cascade(label="Font", underline=0, menu=fsubmenu)
        editMenu.add_cascade(label="Size", underline=0, menu=ssubmenu)
        editMenu.add_command(label="Color", command=self.color)
        editMenu.add_command(label="Bold", command=self.bold, accelerator="Ctrl+B")
        editMenu.add_command(label="Italic", command=self.italic, accelerator="Ctrl+I")
        editMenu.add_command(label="Underline", command=self.underline, accelerator="Ctrl+U")
        editMenu.add_command(label="Overstrike", command=self.overstrike, accelerator="Ctrl+T")
        editMenu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z")
        editMenu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y")
        self.config(menu=menubar)

        """Accelerator bindings. The cut, copy, and paste functions are not
        bound to keyboard shortcuts because Windows already binds them, so if
        Tkinter bound them as well whenever you typed ctrl+v the text would be
        pasted twice."""
        self.bind_all("<Control-n>", self.new)
        self.bind_all("<Control-o>", self.open)
        self.bind_all("<Control-s>", self.save)
        self.bind_all("<Control-q>", self.exit)
        self.bind_all("<Control-b>", self.bold)
        self.bind_all("<Control-i>", self.italic)
        self.bind_all("<Control-u>", self.underline)
        self.bind_all("<Control-T>", self.overstrike)
        self.bind_all("<Control-z>", self.undo)
        self.bind_all("<Control-y>", self.redo)

        self.text = ScrolledText(self, state='normal', height=30, wrap='word', font = font, pady=2, padx=3, undo=True)
        self.text.grid(column=0, row=0, sticky='NSEW')

        # Frame configuration
        self.grid_columnconfigure(0, weight=1)
        self.resizable(True, True)

    """Command functions. *args is included because the keyboard bindings pass
    two arguments to the functions, while clicking in the menu passes only 1."""

    def new(self, *args):
        """Creates a new window."""
        app = Application()
        app.title('Python Text Editor')
        app.option_add('*tearOff', False)
        app.mainloop()

    def color(self):
        """Changes selected text color."""
        try:
            (rgb, hx) = tkinter.colorchooser.askcolor()
            self.text.tag_add('color', 'sel.first', 'sel.last')
            self.text.tag_configure('color', foreground=hx)
        except TclError:
            pass

    def bold(self, *args):
        """Toggles bold for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "bold" in current_tags:
                self.text.tag_remove("bold", "sel.first", "sel.last")
            else:
                self.text.tag_add("bold", "sel.first", "sel.last")
                bold_font = Font(self.text, self.text.cget("font"))
                bold_font.configure(weight="bold")
                self.text.tag_configure("bold", font=bold_font)
        except TclError:
            pass

    def italic(self, *args):
        """Toggles italic for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "italic" in current_tags:
                self.text.tag_remove("italic", "sel.first", "sel.last")
            else:
                self.text.tag_add("italic", "sel.first", "sel.last")
                italic_font = Font(self.text, self.text.cget("font"))
                italic_font.configure(slant="italic")
                self.text.tag_configure("italic", font=italic_font)
        except TclError:
            pass

    def underline(self, *args):
        """Toggles underline for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "underline" in current_tags:
                self.text.tag_remove("underline", "sel.first", "sel.last")
            else:
                self.text.tag_add("underline", "sel.first", "sel.last")
                underline_font = Font(self.text, self.text.cget("font"))
                underline_font.configure(underline=1)
                self.text.tag_configure("underline", font=underline_font)
        except TclError:
            pass

    def overstrike(self, *args):
        """Toggles overstrike for selected text."""
        try:
            current_tags = self.text.tag_names("sel.first")
            if "overstrike" in current_tags:
                self.text.tag_remove("overstrike", "sel.first", "sel.last")
            else:
                self.text.tag_add("overstrike", "sel.first", "sel.last")
                overstrike_font = Font(self.text, self.text.cget("font"))
                overstrike_font.configure(overstrike=1)
                self.text.tag_configure("overstrike", font=overstrike_font)
        except TclError:
            pass

    def undo(self, *args):
        """Undo function"""
        try:
            self.text.edit_undo()
        except TclError:
            pass

    def redo(self, *args):
        """Redo function"""
        try:
            self.text.edit_redo()
        except TclError:
            pass

    def copy(self, *args):
        """Copy text"""
        self.clipboard_clear()
        self.clipboard_append(self.text.selection_get())

    def cut(self, *args):
        """Cut text"""
        self.copy
        self.text.delete("sel.first", "sel.last")

    def paste(self, *args):
        """Paste text"""
        insertion = self.selection_get(selection = "CLIPBOARD")
        self.text.insert(0.0, insertion)

    def open(self, *args):
        """Opens a file dialog to open a plain text file."""
        filename = tkinter.filedialog.askopenfilename()

        with open(filename) as f:
            text = f.read()

        self.text.delete("1.0", "end")
        self.text.insert('insert', text)

    def save(self, *args):
        try:
            """Opens a file dialog to save the text in plain text format."""
            text = self.text.get("1.0", "end")
            filename = tkinter.filedialog.asksaveasfilename()

            with open(filename, 'w') as f:
                f.write(text)
        except FileNotFoundError:
            pass

    def exit(self, *args):
        """Exits the program."""
        self.quit()