Example #1
0
    def __init__(self):
        super().__init__()
        self.text_area = TextArea(self, bg="white", fg="black", undo=True)
        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)
        self.scrollbar.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1)
        self.highlighter = Highlighter(self.text_area, 'languages/python.yaml')

        # first_100_numbers = [str(n+1) for n in range(100)]
        # self.line_numbers.insert(1.0, "\n".join(first_100_numbers))
        # self.line_numbers.configure(state="disabled", width=3)

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()
Example #2
0
    def __init__(self):
        super().__init__()

        self.title('Python Text Editor v3')
        self.geometry('800x600')

        self.foreground = 'black'
        self.background = 'lightgrey'
        self.text_foreground = 'black'
        self.text_background = 'white'

        self.load_scheme_file('schemes/default.yaml')
        self.configure_ttk_elements()

        self.font_size = 15
        self.font_family = "Ubuntu Mono"
        self.load_font_file('schemes/font.yaml')

        self.text_area = TextArea(self,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  font=(self.font_family, self.font_size))

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1)
        self.highlighter = Highlighter(self.text_area, 'languages/python.yaml')

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        self.all_menus = [self.menu]

        sub_menu_items = ["file", "edit", "tools", "help"]
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg=self.background,
                                        fg=self.foreground,
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        self.all_menus.append(self.right_click_menu)

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

        self.open_file = ''
Example #3
0
 def init_input(self, label, text=None):
     self.input_label = label
     self.input = TextArea(
         self.window,
         self.font,
         TextBuffer(text),
         window_border=(self.window.size[1] - self.height + self.border[0],
                        self.border[1], self.border[2],
                        (self.font.size[0] * len(label)) +
                        (2 * self.border[3])),
         line_spacing=0)
Example #4
0
def create_objects(configdir):
    smgr = SettingsManager(configdir)
    mw = MainWindow(smgr)
    txta = TextArea(mw, smgr)
    chsb = ChapterSidebar(smgr, txta.toPlainText, txta.textCursor)
    term = Terminal(mw, smgr, lambda: txta.file_path)
    # Ugly shit
    mw.set_is_modified_callback(txta.document().isModified)
    return OrderedDict((('chaptersidebar', chsb),
                        ('mainwindow', mw),
                        ('settingsmanager', smgr),
                        ('terminal', term),
                        ('textarea', txta)))
Example #5
0
def main():
    window = Gtk.Window(title="Hello")

    widget = TextArea()
    window.add(widget)

    window.connect("destroy", Gtk.main_quit)
    window.show_all()
    Gtk.main()
Example #6
0
    def __init__(self):
        super().__init__()

        self.text_area = TextArea(self, bg="white", fg="black", undo=True)

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1)
        self.highlighter = Highlighter(self.text_area, 'languages/python.yaml')

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()
Example #7
0
    def create_widget(self):
        self.text_area = TextArea(self.frame1,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  relief=tk.FLAT,
                                  font=(self.text_font_family,
                                        self.text_font_size),
                                  insertbackground=self.insertbackground)
        self.text_area.config(highlightthickness=0)
        self.text_area.grid(row=0, column=1, sticky='wens')
        self.text_area.focus_set()
        self.welcome(event=None)

        self.status_bar1 = StatusBar(self.frame2,
                                     bg="pink",
                                     width=30,
                                     height=10)
        self.status_bar2 = StatusBar(self.frame2,
                                     bg="orange",
                                     width=30,
                                     height=10)
        self.status_bar3 = StatusBar(self.frame2,
                                     bg="blue",
                                     width=30,
                                     height=10)
        self.status_bar4 = StatusBar(self.frame2,
                                     bg="green",
                                     width=30,
                                     height=10)
        self.status_bar5 = StatusBar(self.frame2,
                                     bg="purple",
                                     width=30,
                                     height=10)

        self.status_bar1.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar2.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar3.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar4.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar5.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
Example #8
0
File: main.py Project: echo8/editor
def run():
    (window_size, f) = get_args()

    tb = TextBuffer()
    if f:
        tb.load(f)

    sdl2.ext.init()
    window = sdl2.ext.Window(WINDOW_TITLE, size=window_size)
    window.show()

    factory = sdl2.ext.SpriteFactory(sdl2.ext.SOFTWARE)

    font_img = factory.from_image(FONT_IMG_PATH)
    sdl2.SDL_SetColorKey(
        font_img.surface, sdl2.SDL_TRUE,
        sdl2.SDL_MapRGB(font_img.surface.format, COLOR_KEY_R, COLOR_KEY_G,
                        COLOR_KEY_B))
    font = sdl2.ext.BitmapFont(font_img, FONT_SIZE, mapping=FONT_MAPPING)

    sb = StatusBar(window, tb, font, STATUS_BAR_COLOR,
                   (STATUS_BAR_BORDER_TOP, STATUS_BAR_BORDER_RIGHT,
                    STATUS_BAR_BORDER_BOTTOM, STATUS_BAR_BORDER_LEFT))
    ta = TextArea(window, font, tb,
                  (TEXT_AREA_BORDER_TOP, TEXT_AREA_BORDER_RIGHT,
                   sb.height + TEXT_AREA_BORDER_BOTTOM, TEXT_AREA_BORDER_LEFT),
                  TEXT_AREA_LINE_SPACING)
    state = EditState(Editor(None, window, ta, sb))

    sdl2.SDL_StartTextInput()

    while True:
        start = sdl2.SDL_GetTicks()
        state = state.update(sdl2.ext.get_events())
        if state is None:
            break
        ticks = sdl2.SDL_GetTicks() - start
        if ticks < 1000 / FRAMES_PER_SECOND:
            sdl2.SDL_Delay((1000 / FRAMES_PER_SECOND) - ticks)

    sdl2.SDL_StopTextInput()
    sdl2.ext.quit()
    return 0
class MainWindow(tk.Tk):
    '''
    @param tk.TK: Windows、Mac、Unix下TK GUI套件的标准Python接口,可实现GUI界面
    '''

    #窗口设置
    def __init__(self):
        '''
        @update 1.添加横向滚动条 2.修正行号与滚动条和窗口的关联 3.修正行号显示
        '''
        super().__init__()

        self.title('Python Text Editor v3')
        self.geometry('800x600')

        self.foreground = 'black'
        self.background = 'lightgrey'
        self.text_foreground = 'black'
        self.text_background = 'white'

        self.config_dir = os.path.join(str(Path.home()), '.tkedit')

        self.default_scheme_path = os.path.join(self.config_dir,
                                                'schemes/default.yaml')
        self.python_language_path = os.path.join(self.config_dir,
                                                 'languages/python.yaml')
        self.none_language_path = os.path.join(self.config_dir,
                                               'languages/None.yaml')
        self.font_scheme_path = os.path.join(self.config_dir,
                                             'fonts/font.yaml')
        self.create_config_directory_if_needed()

        self.load_scheme_file(self.default_scheme_path)
        self.configure_ttk_elements()

        self.font_size = 15
        self.font_family = "Ubuntu Mono"
        self.load_font_file(self.font_scheme_path)

        self.text_area = TextArea(self,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  font=(self.font_family, self.font_size))

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.text_area.yview)
        self.scrollbar2 = ttk.Scrollbar(orient="horizontal",
                                        command=self.text_area.xview)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1,
                                        font=(self.font_family,
                                              self.font_size))
        self.scrollbar.config(command=self.text_area.yview)
        self.text_area.config(yscrollcommand=self.scrollbar.set,
                              xscrollcommand=self.scrollbar2.set)
        self.highlighter = Highlighter(self.text_area, self.none_language_path)

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        self.all_menus = [self.menu]

        sub_menu_items = ["file", "edit", "tools", "help"]
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg=self.background,
                                        fg=self.foreground,
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        self.all_menus.append(self.right_click_menu)

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.scrollbar2.pack(side=tk.BOTTOM, fill=tk.X)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

        self.open_file = ''

    #绑定事件
    def bind_events(self):
        self.text_area.bind("<MouseWheel>", self.scroll_text)
        self.text_area.bind("<Button-4>", self.scroll_text)
        self.text_area.bind("<Button-5>", self.scroll_text)
        self.text_area.bind("<Button-3>", self.show_right_click_menu)

        self.bind('<Control-f>', self.show_find_window)

        self.bind('<Control-n>', self.file_new)
        self.bind('<Control-o>', self.file_open)
        self.bind('<Control-s>', self.file_save)

        self.bind('<Control-h>', self.help_about)

        self.bind('<Control-m>', self.tools_change_syntax_highlighting)
        self.bind('<Control-g>', self.tools_change_colour_scheme)
        self.bind('<Control-l>', self.tools_change_font)

        self.line_numbers.bind("<MouseWheel>", lambda e: "break")
        self.line_numbers.bind("<Button-4>", lambda e: "break")
        self.line_numbers.bind("<Button-5>", lambda e: "break")

    #滚动事件
    def scroll_text(self, *args):
        if len(args) > 1:
            self.text_area.yview_moveto(args[1])
            self.line_numbers.yview_moveto(args[1])
        else:
            event = args[0]
            if event.delta:
                move = -1 * (event.delta / 120)
            else:
                if event.num == 5:
                    move = 1
                else:
                    move = -1

            self.text_area.yview_scroll(int(move), "units")
            self.line_numbers.yview_scroll(int(move) * 3, "units")

    #内容查找、替换窗口
    def show_find_window(self, event=None):
        FindWindow(self.text_area)

    #显示右键菜单
    def show_right_click_menu(self, event):
        x = self.winfo_x() + self.text_area.winfo_x() + event.x
        y = self.winfo_y() + self.text_area.winfo_y() + event.y
        self.right_click_menu.post(x, y)

    #设置子菜单
    def generate_sub_menus(self, sub_menu_items):
        '''
        @param sub_menu_items: 子菜单项目
        '''
        window_methods = [
            method_name for method_name in dir(self)
            if callable(getattr(self, method_name))
        ]
        tkinter_methods = [
            method_name for method_name in dir(tk.Tk)
            if callable(getattr(tk.Tk, method_name))
        ]

        my_methods = [
            method for method in set(window_methods) - set(tkinter_methods)
        ]
        my_methods = sorted(my_methods)

        for item in sub_menu_items:
            sub_menu = tk.Menu(self.menu,
                               tearoff=0,
                               bg=self.background,
                               fg=self.foreground)
            matching_methods = []
            for method in my_methods:
                if method.startswith(item):
                    matching_methods.append(method)

            for match in matching_methods:
                actual_method = getattr(self, match)
                method_shortcut = actual_method.__doc__.strip()
                friendly_name = ' '.join(match.split('_')[1:])
                sub_menu.add_command(label=friendly_name.title(),
                                     command=actual_method,
                                     accelerator=method_shortcut)

            self.menu.add_cascade(label=item.title(), menu=sub_menu)
            self.all_menus.append(sub_menu)

    #显示关于
    def show_about_page(self):
        msg.showinfo(
            "About",
            "My text editor, version 2, written in Python3.6 using tkinter!")

    #加载文字高亮配色方案
    def load_syntax_highlighting_file(self):
        syntax_file = filedialog.askopenfilename(filetypes=[("YAML file",
                                                             ("*.yaml",
                                                              "*.yml"))])
        if syntax_file:
            self.highlighter.clear_highlight()
            self.highlighter = Highlighter(self.text_area, syntax_file)
            self.highlighter.force_highlight()

    #加载窗体配色方案
    def load_scheme_file(self, scheme):
        '''
        @param scheme: 目标配置文件
        @update GSC 预检测
        '''
        with open(scheme, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        if 'foreground' in config:
            self.foreground = config['foreground']
        if 'background' in config:
            self.background = config['background']
        if 'text_foreground' in config:
            self.text_foreground = config['text_foreground']
        if 'text_background' in config:
            self.text_background = config['text_background']

    #加载字体及字号方案
    def load_font_file(self, file_path):
        '''
        @param file_path: 方案存放路径及文件名
        '''
        with open(file_path, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        if 'family' in config:
            self.font_family = config['family']
        if 'size' in config:
            self.font_size = config['size']

    #修改窗体配色方案
    def change_colour_scheme(self):
        ColourChooser(self)

    #应用窗体配色方案
    def apply_colour_scheme(self, foreground, background, text_foreground,
                            text_background):
        '''
        @param foreground: 新窗体前景色
        @param background: 新窗体背景色
        @param text_foreground: 新字体前景色
        @param text_background: 新字体背景色
        '''
        self.text_area.configure(fg=text_foreground, bg=text_background)
        self.background = background
        self.foreground = foreground
        for menu in self.all_menus:
            menu.configure(bg=self.background, fg=self.foreground)
        self.configure_ttk_elements()

    #应用按钮、标签配色方案
    def configure_ttk_elements(self):
        style = ttk.Style()
        style.configure('editor.TLabel',
                        foreground=self.foreground,
                        background=self.background)
        style.configure('editor.TButton',
                        foreground=self.foreground,
                        background=self.background)

    #字体选择窗口
    def change_font(self):
        FontChooser(self)

    #更新字体
    def update_font(self):
        '''
        @update 1.添加行号字体更新
        '''
        self.load_font_file(self.font_scheme_path)
        self.text_area.configure(font=(self.font_family, self.font_size))
        self.line_numbers.configure(font=(self.font_family, self.font_size))

    #运行环境检测
    def create_config_directory_if_needed(self):
        if not os.path.exists(self.config_dir):
            os.mkdir(self.config_dir)
        if not os.path.exists(os.path.join(self.config_dir, 'schemes')):
            os.mkdir(os.path.join(self.config_dir, 'schemes'))
        if not os.path.exists(os.path.join(self.config_dir, 'languages')):
            os.mkdir(os.path.join(self.config_dir, 'languages'))
        if not os.path.exists(os.path.join(self.config_dir, 'fonts')):
            os.mkdir(os.path.join(self.config_dir, 'fonts'))

        self.create_default_scheme_if_needed()
        self.create_font_scheme_if_needed()
        self.create_python_language_if_needed()

    #运行环境创建 -- 窗体默认配置方案
    def create_default_scheme_if_needed(self):
        if not os.path.exists(self.default_scheme_path):
            yaml_file_contents = f"background: 'lightgrey'\n" \
                               + f"foreground: 'black'\n" \
                               + f"text_background: 'white'\n" \
                               + f"text_foreground: 'black'\n"

            with open(self.default_scheme_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    #运行环境创建 -- 字体默认配置方案
    def create_font_scheme_if_needed(self):
        if not os.path.exists(self.font_scheme_path):
            yaml_file_contents = f"family: Ubuntu Mono\n" \
                               + f"size: 15"

            with open(self.font_scheme_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    #运行环境创建 -- 语言文字高亮默认配置方案
    def create_python_language_if_needed(self):
        if not os.path.exists(self.python_language_path):
            yaml_file_contents = """
categories:
  keywords:
    colour: orange
    matches: [for, def, while, from, import, as, with, self]

  variables:
    colour: red4
    matches: ['True', 'False', None]

  conditionals:
    colour: green
    matches: [try, except, if, else, elif]

  functions:
    colour: blue4
    matches: [int, str, dict, list, set, float]

numbers:
  colour: purple

strings:
  colour: '#e1218b'
"""
            with open(self.python_language_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

        if not os.path.exists(self.none_language_path):
            yaml_file_contents = """

categories:
  keywords:
    colour: black
    matches: [for, def, while, from, import, as, with, self]

  variables:
    colour: black
    matches: ['True', 'False', None]

  conditionals:
    colour: black
    matches: [try, except, if, else, elif]

  functions:
    colour: black
    matches: [int, str, dict, list, set, float]

numbers:
  colour: black

strings:
  colour: black
"""
            with open(self.none_language_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    # =========== Menu Functions ==============

    #新建文件
    def file_new(self, event=None):
        """
        Ctrl+N
        """
        self.text_area.delete(1.0, tk.END)
        self.open_file = ""
        self.line_numbers.force_update()

    #打开文件
    def file_open(self, event=None):
        """
        Ctrl+O
        """
        file_to_open = filedialog.askopenfilename()
        if file_to_open:
            self.open_file = file_to_open

            self.text_area.display_file_contents(file_to_open)
            self.highlighter.force_highlight()
            self.line_numbers.force_update()

    #保存文件
    def file_save(self, event=None):
        """
        Ctrl+S
        """
        current_file = self.open_file if self.open_file else None
        if not current_file:
            current_file = filedialog.asksaveasfilename()

        if current_file:
            contents = self.text_area.get(1.0, tk.END)
            with open(current_file, 'w') as file:
                file.write(contents)

    #剪切
    def edit_cut(self, event=None):
        """
        Ctrl+X
        """
        self.text_area.event_generate("<Control-x>")
        self.line_numbers.force_update()

    #粘贴
    def edit_paste(self, event=None):
        """
        Ctrl+V
        """
        self.text_area.event_generate("<Control-v>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    #复制
    def edit_copy(self, event=None):
        """
        Ctrl+C
        """
        self.text_area.event_generate("<Control-c>")

    #全选
    def edit_select_all(self, event=None):
        """
        Ctrl+A
        """
        self.text_area.event_generate("<Control-a>")

    #查找和替换
    def edit_find_and_replace(self, event=None):
        """
        Ctrl+F
        """
        self.show_find_window()

    #帮助与关于
    def help_about(self, event=None):
        """
        Ctrl+H
        """
        self.show_about_page()

    #选择语言(文字高亮)
    def tools_change_syntax_highlighting(self, event=None):
        """
        Ctrl+M
        """
        self.load_syntax_highlighting_file()

    #选择窗体配色
    def tools_change_colour_scheme(self, event=None):
        """
        Ctrl+G
        """
        self.change_colour_scheme()

    #选择字体字号
    def tools_change_font(self, event=None):
        """
        Ctrl+L
        """
        self.change_font()
Example #10
0
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Text Editor')
        self.text_area = TextArea(self, bg="white", fg="black", undo=True)

        self.background = 'lightgrey'
        self.foreground = 'black'
        self.text_foreground = 'black'
        self.text_background = 'white'

        self.config_dir = os.path.join(str(Path.home()), '.tkedit')
        self.default_scheme_path = os.path.join(self.config_dir,
                                                'schemes/default.yaml')
        self.python_language_path = os.path.join(self.config_dir,
                                                 'languages/python.yaml')
        self.font_scheme_path = os.path.join(self.config_dir,
                                             'schemes/font.yaml')
        self.create_config_directory_if_needed()

        self.load_scheme_file(self.default_scheme_path)
        self.configure_ttk_elements()
        self.font_size = 15
        self.font_family = "Ubuntu Mono"
        self.load_font_file(self.font_scheme_path)

        self.highlighter = Highlighter(self.text_area,
                                       self.python_language_path)

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)

        self.all_menus = [self.menu]

        sub_menu_items = ['file', 'edit', 'tools', 'help']
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg='lightgrey',
                                        fg='black',
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        self.all_menus.append(self.right_click_menu)

        self.open_file = None

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg='grey',
                                        fg='white',
                                        width=1)
        '''
        self.line_numbers = tk.Text(self, bg="grey", fg="yellow")
        first_100_numbers = [str(n+1) for n in range(100)]

        self.line_numbers.insert(1.0, "\n".join(first_100_numbers))
        self.line_numbers.configure(state="disabled", width=3)
        '''

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

    def create_config_directory_if_needed(self):
        if not os.path.exists(self.config_dir):
            os.mkdir(self.config_dir)
            os.mkdir(os.path.join(self.config_dir, 'schemes'))
            os.mkdir(os.path.join(self.config_dir, 'languages'))

        self.create_default_scheme_if_needed()
        self.create_font_scheme_if_needed()
        self.create_python_language_if_needed()

    def create_default_scheme_if_needed(self):
        if not os.path.exists(self.default_scheme_path):
            yaml_file_contents = """
background: 'lightgrey'
foreground: 'black'
text_background: 'white'
text_foreground: 'black'
            """

            with open(self.default_scheme_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    def create_font_scheme_if_needed(self):
        if not os.path.exists(self.font_scheme_path):
            yaml_file_contents = """
family: Ubuntu Mono
size: 14
            """
            with open(self.font_scheme_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    def create_python_language_if_needed(self):
        if not os.path.exists(self.python_language_path):
            yaml_file_contents = """
categories:
    keywords:
        color: orange
        matches: [for, def, while, from, import, as, with, self]

    variables:
        color: red
        matches: ['True', 'False', None]

    conditionals:
        color: green
        matches: [try, except, if, else, elif]

    functions:
        color: blue
        matches: [int, str, dict, list, set, float]

numbers:
    color: purple

strings:
    color: '#e1218b'
                """
            with open(self.python_language_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    def bind_events(self):
        self.text_area.bind("<MouseWheel>", self.scroll_text)
        self.text_area.bind("<Button-4>", self.scroll_text)
        self.text_area.bind("<Button-5>", self.scroll_text)
        self.text_area.bind('<Button-3>', self.show_right_click_menu)

        self.bind('<Control-f>', self.show_find_window)

        self.line_numbers.bind("<MouseWheel>", lambda e: "break")
        self.line_numbers.bind("<Button-4>", lambda e: "break")
        self.line_numbers.bind("<Button-5>", lambda e: "break")

        self.bind('<Control-n>', self.file_new)
        self.bind('<Control-o>', self.file_open)
        self.bind('<Control-s>', self.file_save)
        self.bind('<Control-h>', self.help_about)
        self.bind('<Control-m>', self.tools_change_syntax_highlight)
        self.bind('<Control-g>', self.tools_Change_color_scheme)
        self.bind('<Control-l>', self.tools_change_font)

    def show_find_window(self, event=None):
        FindWindow(self.text_area)

    def scroll_text(self, *args):
        if len(args) > 1:
            self.text_area.yview_moveto(args[1])
            self.line_numbers.yview_moveto(args[1])
        else:
            event = args[0]
            if event.delta:
                move = -1 * (event.delta / 120)
            else:
                if event.num == 5:
                    move = 1
                else:
                    move = -1

            self.text_area.yview_scroll(int(move), "units")
            self.line_numbers.yview_scroll(int(move) * 3, "units")

    def generate_sub_menus(self, sub_menu_items):
        window_methods = [
            method_name for method_name in dir(self)
            if callable(getattr(self, method_name))
        ]
        tkinter_methods = [
            method_name for method_name in dir(tk.Tk)
            if callable(getattr(tk.Tk, method_name))
        ]
        my_methods = [
            method for method in set(window_methods) - set(tkinter_methods)
        ]
        my_methods = sorted(my_methods)

        for item in sub_menu_items:
            sub_menu = tk.Menu(self.menu,
                               tearoff=0,
                               bg=self.background,
                               fg=self.foreground)
            matching_methods = []
            for method in my_methods:
                if method.startswith(item):
                    matching_methods.append(method)
            for match in matching_methods:
                actual_method = getattr(self, match)
                method_shortcut = actual_method.__doc__.strip()
                friendly_name = ' '.join(match.split('_')[1:])
                sub_menu.add_command(label=friendly_name.title(),
                                     command=actual_method,
                                     accelerator=method_shortcut)
            self.menu.add_cascade(label=item.title(), menu=sub_menu)
            self.all_menus.append(sub_menu)

    def show_right_click_menu(self, event):
        x = self.winfo_x() + self.text_area.winfo_x() + event.x
        y = self.winfo_y() + self.text_area.winfo_y() + event.y
        self.right_click_menu.post(x, y)

    def edit_cut(self, event=None):
        """
        Ctrl+X
        """
        self.text_area.event_generate('<Control-x>')
        self.line_numbers.force_update()

    def edit_paste(self, event=None):
        """
        Ctrl+V
        """
        self.text_area.event_generate('<Control-v>')
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def edit_copy(self, event=None):
        """
        Ctrl+C
        """
        self.text_area.event_generate('<Control-c>')

    def file_open(self, event=None):
        """
        Ctrl+O
        """
        file_to_open = filedialog.askopenfilename()
        if file_to_open:
            self.open_file = file_to_open
            self.text_area.display_file_contents(file_to_open)
            self.highlighter.force_highlight()
            self.line_numbers.force_update()

    def file_save(self, event=None):
        """
        Ctrl+S
        """
        current_file = self.open_file if self.open_file else None
        if not current_file:
            current_file = filedialog.asksaveasfilename()

        if current_file:
            contents = self.text_area.get(1.0, tk.END)
            with open(current_file, 'w') as file:
                file.write(contents)

    def file_new(self, event=None):
        '''
        Ctrl+N
        '''
        self.text_area.delete(1.0, tk.END)
        self.open_file = None
        self.line_numbers.force_update()

    def edit_select_all(self, event=None):
        '''
        Ctrl+A
        '''
        self.text_area.event_generate('<Control-a>')

    def edit_find_and_replace(self, event=None):
        '''
        Ctrl+F
        '''
        self.show_find_window()

    def load_syntax_highlighting(self):
        syntax_file = filedialog.askopenfilename(filetypes=[('YAML file',
                                                             ('*.yaml',
                                                              '*.yml'))])
        if syntax_file:
            self.highlighter.clear_highlight()
            self.highlighter = Highlighter(self.text_area, syntax_file)
            self.highlighter.force_highlight()

    def tools_change_syntax_highlight(self, event=None):
        '''
        Ctrl+M
        '''
        self.load_syntax_highlighting()

    def update_font(self):
        self.load_font_file(self.font_scheme_path)
        self.text_area.configure(font=(self.font_family, self.font_size))

    def load_font_file(self, file_path):
        with open(file_path, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as e:
                print(e)
                return
        self.font_family = config['family']
        self.font_size = config['size']

    def load_scheme_file(self, scheme):
        with open(scheme, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        self.foreground = config['foreground']
        self.background = config['background']
        self.text_foreground = config['text_foreground']
        self.text_background = config['text_background']

    def change_font(self):
        FontChooser(self)

    def tools_change_font(self, event=None):
        '''
        Ctrl+L
        '''
        self.change_font()

    def apply_color_scheme(self, foreground, background, text_foreground,
                           text_background):
        self.background = background
        self.foreground = foreground
        self.text_area.configure(fg=text_foreground, bg=text_background)

        for menu in self.all_menus:
            menu.configure(bg=self.background, fg=self.foreground)
        self.configure_ttk_elements()

    def configure_ttk_elements(self):
        style = ttk.Style()
        style.configure('editor.TLabel',
                        foreground=self.foreground,
                        background=self.background)
        style.configure('editor.TButton',
                        foreground=self.foreground,
                        background=self.background)

    def change_color_scheme(self):
        ColorChooser(self)

    def tools_Change_color_scheme(self, event=None):
        '''
        Ctrl+G
        '''
        self.change_color_scheme()

    def show_about_page(self):
        msg.showinfo(
            'About',
            'My text editor , Version 3.0, written in python 3.7 using tkinter!'
        )

    def help_about(self, event=None):
        '''
        Ctrl+H
        '''
        self.show_about_page()
Example #11
0
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('THEE')
        self.minsize(550, 40)  # (width, height)
        self.winfo_screenwidth = self.winfo_screenwidth()
        self.winfo_screenheight = self.winfo_screenheight()
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)
        self.width = int(self.winfo_screenwidth / 3)
        self.height = int(self.winfo_screenheight / 3)
        self.geometry(f'{self.width}x{self.height}')

        self.thee_mode = 0  # 0: welcome, 1: editor, 2: terminal, 3: help
        self.count_text_changed = 0
        self.editor_mode_buffer = ""
        self.terminal_mode_buffer = ""
        self.key_buffer = []

        self.file_name = "untitled"
        self.status = "unsaved"
        self.spaces = 4
        self.line = 1
        self.column = 1

        self.foreground = config.color['foreground']
        self.background = config.color['background']
        self.text_foreground = config.color['text_foreground']
        self.text_background = config.color['text_background']
        self.insertbackground = config.color['insertbackground']
        self.statusbar_background = config.color['statusbarbg']

        self.frame1 = tk.Frame(self,
                               bg=self.background,
                               width=self.width,
                               height=self.height - 15)
        self.frame2 = tk.Frame(self,
                               bg=self.statusbar_background,
                               width=self.width,
                               height=10)

        self.frame1.grid(row=0, column=0, sticky='wens')
        self.frame2.grid(row=1, column=0, sticky='wens')

        self.frame1.grid_columnconfigure(1, weight=1)
        self.frame1.grid_rowconfigure(0, weight=1)

        self.config_dir = os.path.join(str(Path.home()), '.thee')

        self.text_font_size = config.font['text']['size']
        self.text_font_family = config.font['text']['family']

        self.statusbar_font_size = config.font['statusbar']['size']
        self.statusbar_font_family = config.font['statusbar']['family']

        self.create_widget()  # Entry point ==========#
        self.terminal = Terminal(self, self.text_area)  # run terminal

        self.bind_events()

        self.open_file = ''

        self.protocol("WM_DELETE_WINDOW", self.close_window)

    def create_widget(self):
        self.text_area = TextArea(self.frame1,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  relief=tk.FLAT,
                                  font=(self.text_font_family,
                                        self.text_font_size),
                                  insertbackground=self.insertbackground)
        self.text_area.config(highlightthickness=0)
        self.text_area.grid(row=0, column=1, sticky='wens')
        self.text_area.focus_set()
        self.welcome(event=None)

        self.status_bar1 = StatusBar(self.frame2,
                                     bg="pink",
                                     width=30,
                                     height=10)
        self.status_bar2 = StatusBar(self.frame2,
                                     bg="orange",
                                     width=30,
                                     height=10)
        self.status_bar3 = StatusBar(self.frame2,
                                     bg="blue",
                                     width=30,
                                     height=10)
        self.status_bar4 = StatusBar(self.frame2,
                                     bg="green",
                                     width=30,
                                     height=10)
        self.status_bar5 = StatusBar(self.frame2,
                                     bg="purple",
                                     width=30,
                                     height=10)

        self.status_bar1.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar2.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar3.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar4.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.status_bar5.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    def editor_mode(self, event=None):
        self.text_area.config(state=tk.NORMAL, tabs=4)
        self.text_area.delete('1.0', tk.END)
        self.text_area.insert(tk.END, self.editor_mode_buffer)
        self.highlighter = Highlighter(self.text_area)
        self.thee_mode = 1

        self.line_numbers = LineNumbers(self.frame1, self.text_area)
        self.line_numbers.config(bg=self.text_background,
                                 width=len(self.line_numbers.line_number) * 10,
                                 highlightthickness=0)
        self.line_numbers.grid(row=0, column=0, sticky='ns')

        self.status_bar1.set("Line %d, Column %d" % (self.line, self.column))
        self.status_bar3.set("%s" % self.file_name)
        self.status_bar4.set("Spaces: %d" % self.spaces)
        self.status_bar5.set("%s" % self.status)

    def terminal_mode(self, event=None):
        if self.thee_mode == 1:
            self.line_numbers.destroy()
        self.text_area.config(state=tk.NORMAL, tabs=4)
        self.text_area.delete('1.0', tk.END)
        self.text_area.insert(tk.END, self.terminal_mode_buffer)
        self.terminal.writeLoop()
        self.highlighter = Highlighter(self.text_area)
        self.thee_mode = 2

    def text_been_modified(self, event=None):
        flag = self.text_area.edit_modified()
        if flag:  # prevent from getting called twice
            if self.thee_mode == 1 and self.count_text_changed > 1:  # editor mode
                self.editor_mode_buffer = self.text_area.get(
                    1.0, tk.END + "-1c")
                self.status = "unsaved"
                self.status_bar5.set("%s" % self.status)
                self.update_line_column()
                self.line_numbers.config(
                    width=len(self.line_numbers.line_number) * 10)
            elif self.thee_mode == 2 and self.count_text_changed > 1:  # terminal mode
                self.terminal_mode_buffer = self.text_area.get(
                    1.0, tk.END + "-1c")
            self.count_text_changed += 1
        #reset so this will be called on the next change
        self.text_area.edit_modified(False)

    def retrieve_selected_line(self, event=None):
        if self.thee_mode == 1:
            self.current_line = self.text_area.get("1.0", 'end').rstrip()
            if event.keysym.isnumeric():
                self.key_buffer.append(event.keysym)
                # check buffer after 500ms (0.5s)
                self.after(500, self.selected_line_action)

    def selected_line_action(self):
        if self.key_buffer:
            index = int(''.join(self.key_buffer)) - 1
            self.key_buffer.clear()
            self.selected_line = self.current_line.split('\n')[index]
            selected_str = self.selected_line + "\n"
            # write selected code line(s) to the console in order to it running
            self.terminal.proc.stdin.write(selected_str.encode())
            self.terminal.proc.stdin.flush()
            self.terminal_mode()

    def update_line_column(self, event=None):
        if self.thee_mode == 1:
            line, column = self.text_area.index(tk.INSERT).split('.')
            self.line = int(line)
            self.column = int(column) + 1
            self.status_bar1.set("Line %d, Column %d" %
                                 (self.line, self.column))

    def close_window(self):
        if self.editor_mode_buffer and self.status == "unsaved":  #and self.status.get() == "unsaved": #SATUSBAR
            if msg.askokcancel("Quit", "Would you like to save the data?"):
                self.file_save()
                self.terminal.alive = False
                self.terminal.destroy()
            else:
                self.terminal.alive = False
                self.terminal.destroy()
        else:
            self.terminal.alive = False
            self.terminal.destroy()

    def bind_events(self):
        self.focus_set()
        self.text_area.bind_all('<<Modified>>', self.text_been_modified)
        self.text_area.bind('<Return>', self.enter)
        self.bind_all('<Button-1>', self.update_line_column)

        self.bind_all('<Control-e>', self.editor_mode)
        self.bind_all('<Control-t>', self.terminal_mode)
        self.bind_all('<Control-Key>', self.retrieve_selected_line)
        self.bind('<Control-f>', self.show_find_window)

        self.bind('<Control-n>', self.file_new)
        self.bind('<Control-o>', self.file_open)
        self.bind('<Control-s>', self.file_save)
        self.bind('<Control-S>', self.file_save_as)

        self.bind('<Control-w>', self.welcome)
        self.bind('<Control-h>', self.help_about)

    def enter(self, event=None):
        if self.thee_mode == 2:
            self.terminal.enter()

    def show_find_window(self, event=None):
        FindWindow(self.frame1, self.text_area)

    def show_welcome_page(self):
        if self.thee_mode == 1:
            self.line_numbers.destroy()
        self.text_area.config(state=tk.NORMAL)
        self.text_area.delete('1.0', tk.END)
        message = '''
   		\n\n
   		            THEE

   		         version 1.0

   	   THE simple python key bindings  Editor

   	     type   Ctrl-h 	for help information

   	by Fidel R. Monteiro <*****@*****.**>
   		\n

   	    The Pynosso Project | Sat, Jun 26 2020 
   		'''
        self.text_area.insert(tk.END, message)
        self.text_area.config(state=tk.DISABLED)
        self.thee_mode = 0

    def show_about_page(self):
        if self.thee_mode == 1:
            self.line_numbers.destroy()
        self.text_area.config(state=tk.NORMAL)
        self.text_area.delete('1.0', tk.END)
        message = '''
                        HELP

        Mode Commands
            Ctrl+e : Text mode
            Ctrl+t : Terminal mode
            Ctrl+<number> : Run selected line in python console

        Editing Commands
            Ctrl+a : Select all text
            Ctrl+x : Cut selected text
            Ctrl+c : Copy selected text
            Ctrl+v : Paste cut/copied text
            Ctrl+z : Undo
            Ctrl+y : Redo

        File Commands
            Ctrl+o : Open file
            Ctrl+s : Save current content
            Ctrl+S : Save current content as <filename>
            Ctrl+p : Print current content
            Ctrl+n : Open new file

        General
            Ctrl+m : Change syntax highlighting
            Ctrl+g : Change colour scheme
            Ctrl+l : Change font
            Ctrl+h : Display this help window

        AUTHOR
                Written by Fidel R. Monteiro (fm65)
                Sat, Jun 26 2020

        thee version 1.0

        "simple is better than complex"
        '''
        self.text_area.insert(tk.END, message)
        self.text_area.config(state=tk.DISABLED)
        self.thee_mode = 3

    def apply_colour_scheme(self, foreground, background, text_foreground,
                            text_background):
        self.text_area.configure(fg=text_foreground, bg=text_background)
        self.background = background
        self.foreground = foreground
        for menu in self.all_menus:
            menu.configure(bg=self.background, fg=self.foreground)

    def update_font(self):
        #self.load_font_file(self.font_scheme_path)
        self.text_area.configure(font=(self.text_font_family,
                                       self.text_font_size))

    def create_config_directory_if_needed(self):
        if not os.path.exists(self.config_dir):
            os.mkdir(self.config_dir)

    # =========== Menu Functions ==============

    def file_new(self, event=None):
        """
        Ctrl+N
        """
        self.text_area.delete(1.0, tk.END)
        self.open_file = None
        self.editor_mode()
        self.line_numbers.force_update()

    def file_open(self, event=None):
        """
        Ctrl+O
        """
        self.editor_mode()
        file_to_open = filedialog.askopenfilename(filetypes=[('Python files',
                                                              '*.py')],
                                                  defaultextension='.py')
        if file_to_open:
            self.open_file = file_to_open
            self.file_name = self.open_file.split('/')[-1]
            self.status_bar3.set("%s" % self.file_name)

            self.text_area.display_file_contents(file_to_open)
            self.highlighter.force_highlight()
            self.line_numbers.force_update()

    def file_save(self, event=None):
        """
        Ctrl+s
        """
        current_file = self.open_file if self.open_file else None
        if not current_file:
            current_file = filedialog.asksaveasfilename(filetypes=[
                ('Python files', '*.py')
            ],
                                                        defaultextension='.py')
            self.open_file = current_file
            self.file_name = current_file.split('/')[-1]
            self.status_bar3.set("%s" % self.file_name)

        if current_file:
            contents = self.text_area.get(1.0, tk.END)
            with open(current_file, 'w') as file:
                file.write(contents)
                self.status = "saved"
                self.status_bar5.set("%s" % self.status)

    def file_save_as(self, event=None):
        """
        Ctrl+S
        """
        new_file_name = filedialog.asksaveasfilename(filetypes=[
            ('Python files', '*.py')
        ],
                                                     defaultextension='.py',
                                                     confirmoverwrite=False)
        f = open(self.new_file_name, 'w')
        f.write(self.get('1.0', 'end'))
        f.close()
        self.status = "saved"
        self.status_bar5.set("%s" % self.status)

    def edit_cut(self, event=None):
        """
        Ctrl+X
        """
        self.text_area.event_generate("<Control-x>")
        self.line_numbers.force_update()

    def edit_paste(self, event=None):
        """
        Ctrl+V
        """
        self.text_area.event_generate("<Control-v>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def edit_copy(self, event=None):
        """
        Ctrl+C
        """
        self.text_area.event_generate("<Control-c>")

    def edit_select_all(self, event=None):
        """
        Ctrl+A
        """
        self.text_area.event_generate("<Control-a>")

    def edit_find_and_replace(self, event=None):
        """
        Ctrl+F
        """
        self.show_find_window()

    def welcome(self, event=None):
        """
        Ctrl+W
        """
        self.show_welcome_page()

    def help_about(self, event=None):
        """
        Ctrl+H
        """
        self.show_about_page()
Example #12
0
    def __init__(self):
        super().__init__()

        self.title('Text Editor')
        self.text_area = TextArea(self, bg="white", fg="black", undo=True)

        self.background = 'lightgrey'
        self.foreground = 'black'
        self.text_foreground = 'black'
        self.text_background = 'white'

        self.config_dir = os.path.join(str(Path.home()), '.tkedit')
        self.default_scheme_path = os.path.join(self.config_dir,
                                                'schemes/default.yaml')
        self.python_language_path = os.path.join(self.config_dir,
                                                 'languages/python.yaml')
        self.font_scheme_path = os.path.join(self.config_dir,
                                             'schemes/font.yaml')
        self.create_config_directory_if_needed()

        self.load_scheme_file(self.default_scheme_path)
        self.configure_ttk_elements()
        self.font_size = 15
        self.font_family = "Ubuntu Mono"
        self.load_font_file(self.font_scheme_path)

        self.highlighter = Highlighter(self.text_area,
                                       self.python_language_path)

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)

        self.all_menus = [self.menu]

        sub_menu_items = ['file', 'edit', 'tools', 'help']
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg='lightgrey',
                                        fg='black',
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        self.all_menus.append(self.right_click_menu)

        self.open_file = None

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg='grey',
                                        fg='white',
                                        width=1)
        '''
        self.line_numbers = tk.Text(self, bg="grey", fg="yellow")
        first_100_numbers = [str(n+1) for n in range(100)]

        self.line_numbers.insert(1.0, "\n".join(first_100_numbers))
        self.line_numbers.configure(state="disabled", width=3)
        '''

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()
Example #13
0
class StatusBar:
    def __init__(self, window, text_buffer, font, color, border):
        self.window = window
        self.text_buffer = text_buffer
        self.font = font
        self.color = color
        self.border = border
        self.height = font.size[1] + border[0] + border[2]
        self.width = window.size[0]
        self.msg = None
        self.msg_start = None
        self.input = None
        self.input_label = None

    def get_line_pos_text(self):
        return "{}:{}".format(self.text_buffer.cursor_pos[0] + 1,
                              self.text_buffer.cursor_pos[1] + 1)

    def draw(self):
        window_surface = self.window.get_surface()
        sb_y = self.window.size[1] - self.height
        sdl2.ext.fill(window_surface,
                      self.color,
                      area=(0, sb_y, self.width, self.height))

        text = self.get_line_pos_text()
        self.font.render_on(
            window_surface,
            text,
            offset=(self.window.size[0] -
                    ((self.font.size[0] * len(text)) + self.border[1]),
                    sb_y + self.border[0]))

        if self.msg_start is not None and sdl2.SDL_GetTicks(
        ) - self.msg_start < STATUS_BAR_MSG_DURATION:
            self.font.render_on(window_surface,
                                self.msg,
                                offset=(self.border[1], self.window.size[1] -
                                        self.height + self.border[0]))
        elif self.msg_start is not None:
            self.msg_start = None

    def init_input(self, label, text=None):
        self.input_label = label
        self.input = TextArea(
            self.window,
            self.font,
            TextBuffer(text),
            window_border=(self.window.size[1] - self.height + self.border[0],
                           self.border[1], self.border[2],
                           (self.font.size[0] * len(label)) +
                           (2 * self.border[3])),
            line_spacing=0)

    def draw_label(self):
        window_surface = self.window.get_surface()
        sdl2.ext.fill(window_surface,
                      self.color,
                      area=(0, self.window.size[1] - self.height, self.width,
                            self.height))
        self.font.render_on(window_surface,
                            self.input_label,
                            offset=(self.border[1], self.window.size[1] -
                                    self.height + self.border[0]))

    def draw_input(self):
        self.draw_label()
        self.input.draw()

    def handle_input(self, events):
        self.input.handle_input(events)

    def display_msg(self, msg):
        self.msg = msg
        self.msg_start = sdl2.SDL_GetTicks()
Example #14
0
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Python Text Editor v3')
        self.geometry('800x600')

        self.foreground = 'black'
        self.background = 'lightgrey'
        self.text_foreground = '#313131'
        self.text_background = '#f0f0f0'
        self.terminal_background = 'darkcyan'
        self.terminal_foreground = 'white'

        self.config_dir = os.path.join(str(Path.home()), '.tkedit')

        self.default_scheme_path = os.path.join(self.config_dir,
                                                'schemes/default.yaml')
        self.python_language_path = os.path.join(self.config_dir,
                                                 'languages/python.yaml')
        self.font_scheme_path = os.path.join(self.config_dir,
                                             'schemes/font.yaml')
        self.create_config_directory_if_needed()

        self.load_scheme_file(self.default_scheme_path)
        self.configure_ttk_elements()

        # Change
        self.font_size = 14
        self.font_family = "Droid Sana Mono"

        self.terminal_font_size = 12
        self.terminal_font_family = "Consolas"
        # Change

        self.load_font_file(self.font_scheme_path)

        self.text_area = TextArea(self,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  font=(self.font_family, self.font_size))

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1,
                                        font=(self.font_family,
                                              self.font_size))
        self.highlighter = Highlighter(self.text_area,
                                       self.python_language_path)
        self.terminal = Terminal(self,
                                 height=8,
                                 bg=self.terminal_background,
                                 fg=self.terminal_foreground,
                                 undo=True,
                                 font=(self.terminal_font_family,
                                       self.terminal_font_size))

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        self.all_menus = [self.menu]

        self.text_area.__setattr__("update_line",
                                   self.line_numbers.force_update)
        self.text_area.__setattr__("update_highlight",
                                   self.highlighter.force_highlight)

        sub_menu_items = ["file", "edit", "tools", "help"]
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg=self.background,
                                        fg=self.foreground,
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        # Change
        self.right_click_menu.add_command(label='Undo', command=self.edit_undo)
        self.right_click_menu.add_command(label='Redo', command=self.edit_redo)
        # Change
        self.all_menus.append(self.right_click_menu)

        # change
        self.count_area = tk.Text(self, height=1)
        self.count_area.pack(side=tk.BOTTOM, fill=tk.X)
        # change
        # Change
        self.terminal.pack(side=tk.BOTTOM, fill=tk.X)
        # Change
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

        self.open_file = ''

    def bind_events(self):
        self.text_area.bind("<MouseWheel>", self.scroll_text)
        self.text_area.bind("<Button-4>", self.scroll_text)
        self.text_area.bind("<Button-5>", self.scroll_text)
        self.text_area.bind("<Button-3>", self.show_right_click_menu)
        # Change
        self.count_area.bind(self.count_text())
        # Change

        self.bind('<Control-f>', self.show_find_window)

        self.bind('<Control-n>', self.file_new)
        self.bind('<Control-o>', self.file_open)
        self.bind('<Control-s>', self.file_save)

        self.bind('<Control-h>', self.help_about)

        self.bind('<Control-m>', self.tools_change_syntax_highlighting)
        self.bind('<Control-g>', self.tools_change_colour_scheme)
        self.bind('<Control-l>', self.tools_change_font)

        self.line_numbers.bind("<MouseWheel>", lambda e: "break")
        self.line_numbers.bind("<Button-4>", lambda e: "break")
        self.line_numbers.bind("<Button-5>", lambda e: "break")

    # change
    def count_text(self):
        contents = self.text_area.get(1.0, tk.END).replace(" ", "").split("\n")
        self.count_area.delete(1.0, tk.END)
        self.count_area.insert(
            tk.END,
            "当前字数为:" + str(CountWord(contents).bind_event(contents)) + " 字")
        return self.after(50, self.count_text)

    # change

    def scroll_text(self, *args):
        if len(args) > 1:
            self.text_area.yview_moveto(args[1])
            self.line_numbers.yview_moveto(args[1])
        else:
            event = args[0]
            if event.delta:
                move = -1 * (event.delta / 120)
            else:
                if event.num == 5:
                    move = 1
                else:
                    move = -1

            self.text_area.yview_scroll(int(move), "units")
            self.line_numbers.yview_scroll(int(move) * 3, "units")

    def show_find_window(self, event=None):
        FindWindow(self.text_area)

    def show_right_click_menu(self, event):
        x = self.winfo_x() + self.text_area.winfo_x() + event.x
        y = self.winfo_y() + self.text_area.winfo_y() + event.y
        self.right_click_menu.post(x, y)

    def generate_sub_menus(self, sub_menu_items):
        window_methods = [
            method_name for method_name in dir(self)
            if callable(getattr(self, method_name))
        ]
        tkinter_methods = [
            method_name for method_name in dir(tk.Tk)
            if callable(getattr(tk.Tk, method_name))
        ]

        my_methods = [
            method for method in set(window_methods) - set(tkinter_methods)
        ]
        my_methods = sorted(my_methods)

        for item in sub_menu_items:
            sub_menu = tk.Menu(self.menu,
                               tearoff=0,
                               bg=self.background,
                               fg=self.foreground)
            matching_methods = []
            for method in my_methods:
                if method.startswith(item):
                    matching_methods.append(method)

            for match in matching_methods:
                actual_method = getattr(self, match)
                method_shortcut = actual_method.__doc__.strip()
                friendly_name = ' '.join(match.split('_')[1:])
                sub_menu.add_command(label=friendly_name.title(),
                                     command=actual_method,
                                     accelerator=method_shortcut)

            self.menu.add_cascade(label=item.title(), menu=sub_menu)
            self.all_menus.append(sub_menu)

    def show_about_page(self):
        msg.showinfo(
            "About",
            "My text editor, version 2, written in Python3.6 using tkinter!")

    def load_syntax_highlighting_file(self):
        syntax_file = filedialog.askopenfilename(filetypes=[("YAML file",
                                                             ("*.yaml",
                                                              "*.yml"))])
        if syntax_file:
            self.highlighter.clear_highlight()
            self.highlighter = Highlighter(self.text_area, syntax_file)
            self.highlighter.force_highlight()

    def load_scheme_file(self, scheme):
        with open(scheme, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        self.foreground = config['foreground']
        self.background = config['background']
        self.text_foreground = config['text_foreground']
        self.text_background = config['text_background']

    def load_font_file(self, file_path):
        with open(file_path, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        self.font_family = config['family']
        self.font_size = config['size']

    def change_colour_scheme(self):
        ColourChooser(self)

    def apply_colour_scheme(self, foreground, background, text_foreground,
                            text_background):
        self.text_area.configure(fg=text_foreground, bg=text_background)
        self.background = background
        self.foreground = foreground
        for menu in self.all_menus:
            menu.configure(bg=self.background, fg=self.foreground)
        self.configure_ttk_elements()

    def configure_ttk_elements(self):
        style = ttk.Style()
        style.configure('editor.TLabel',
                        foreground=self.foreground,
                        background=self.background)
        style.configure('editor.TButton',
                        foreground=self.foreground,
                        background=self.background)

    def change_font(self):
        FontChooser(self)

    def update_font(self):
        self.load_font_file(self.font_scheme_path)
        self.text_area.configure(font=(self.font_family, self.font_size))

    def create_config_directory_if_needed(self):
        if not os.path.exists(self.config_dir):
            os.mkdir(self.config_dir)
            os.mkdir(os.path.join(self.config_dir, 'schemes'))
            os.mkdir(os.path.join(self.config_dir, 'languages'))

        self.create_default_scheme_if_needed()
        self.create_font_scheme_if_needed()
        self.create_python_language_if_needed()

    def create_default_scheme_if_needed(self):
        if not os.path.exists(self.default_scheme_path):
            yaml_file_contents = f"background: 'lightgrey'\n" \
                             + f"foreground: 'black'\n" \
                             + f"text_background: 'white'\n" \
                             + f"text_foreground: 'black'\n"

            with open(self.default_scheme_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    def create_font_scheme_if_needed(self):
        if not os.path.exists(self.font_scheme_path):
            yaml_file_contents = f"family: Ubuntu Mono\n" \
                               + f"size: 14"

            with open(self.font_scheme_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    def create_python_language_if_needed(self):
        if not os.path.exists(self.python_language_path):
            yaml_file_contents = """
categories:
  keywords:
    colour: orange
    matches: [for, def, while, from, import, as, with, self]

  variables:
    colour: red4
    matches: ['True', 'False', None]

  conditionals:
    colour: green
    matches: [try, except, if, else, elif]

  functions:
    colour: blue4
    matches: [int, str, dict, list, set, float]

numbers:
  colour: purple

strings:
  colour: '#e1218b'
"""
            with open(self.python_language_path, 'w') as yaml_file:
                yaml_file.write(yaml_file_contents)

    # =========== Menu Functions ==============

    def file_new(self, event=None):
        """
        Ctrl+N
        """
        self.text_area.delete(1.0, tk.END)
        self.open_file = None
        self.line_numbers.force_update()

    def file_open(self, event=None):
        """
        Ctrl+O
        """
        file_to_open = filedialog.askopenfilename()
        if file_to_open:
            self.open_file = file_to_open

            self.text_area.display_file_contents(file_to_open)
            self.highlighter.force_highlight()
            self.line_numbers.force_update()

    def file_save(self, event=None):
        """
        Ctrl+S
        """
        current_file = self.open_file if self.open_file else None
        if not current_file:
            current_file = filedialog.asksaveasfilename()

        if current_file:
            contents = self.text_area.get(1.0, tk.END)
            with open(current_file, 'w') as file:
                file.write(contents)

    def edit_cut(self, event=None):
        """
        Ctrl+X
        """
        self.text_area.event_generate("<Control-x>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def edit_paste(self, event=None):
        """
        Ctrl+V
        """
        self.text_area.event_generate("<Control-v>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def edit_copy(self, event=None):
        """
        Ctrl+C
        """
        self.text_area.event_generate("<Control-c>")

    def edit_select_all(self, event=None):
        """
        Ctrl+A
        """
        self.text_area.event_generate("<Control-a>")

    def edit_find_and_replace(self, event=None):
        """
        Ctrl+F
        """
        self.show_find_window()

    def edit_undo(self, event=None):
        """
        Ctrl+Z
        """
        self.text_area.event_generate("<Control-z>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def edit_redo(self, event=None):
        """
        Ctrl+Y
        """
        self.text_area.event_generate("<Control-y>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def help_about(self, event=None):
        """
        Ctrl+H
        """
        self.show_about_page()

    def tools_change_syntax_highlighting(self, event=None):
        """
        Ctrl+M
        """
        self.load_syntax_highlighting_file()

    def tools_change_colour_scheme(self, event=None):
        """
        Ctrl+G
        """
        self.change_colour_scheme()

    def tools_change_font(self, event=None):
        """
        Ctrl+L
        """
        self.change_font()
Example #15
0
    def __init__(self):
        super().__init__()

        self.title('Python Text Editor v3')
        self.geometry('800x600')

        self.foreground = 'black'
        self.background = 'lightgrey'
        self.text_foreground = '#313131'
        self.text_background = '#f0f0f0'
        self.terminal_background = 'darkcyan'
        self.terminal_foreground = 'white'

        self.config_dir = os.path.join(str(Path.home()), '.tkedit')

        self.default_scheme_path = os.path.join(self.config_dir,
                                                'schemes/default.yaml')
        self.python_language_path = os.path.join(self.config_dir,
                                                 'languages/python.yaml')
        self.font_scheme_path = os.path.join(self.config_dir,
                                             'schemes/font.yaml')
        self.create_config_directory_if_needed()

        self.load_scheme_file(self.default_scheme_path)
        self.configure_ttk_elements()

        # Change
        self.font_size = 14
        self.font_family = "Droid Sana Mono"

        self.terminal_font_size = 12
        self.terminal_font_family = "Consolas"
        # Change

        self.load_font_file(self.font_scheme_path)

        self.text_area = TextArea(self,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  font=(self.font_family, self.font_size))

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1,
                                        font=(self.font_family,
                                              self.font_size))
        self.highlighter = Highlighter(self.text_area,
                                       self.python_language_path)
        self.terminal = Terminal(self,
                                 height=8,
                                 bg=self.terminal_background,
                                 fg=self.terminal_foreground,
                                 undo=True,
                                 font=(self.terminal_font_family,
                                       self.terminal_font_size))

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        self.all_menus = [self.menu]

        self.text_area.__setattr__("update_line",
                                   self.line_numbers.force_update)
        self.text_area.__setattr__("update_highlight",
                                   self.highlighter.force_highlight)

        sub_menu_items = ["file", "edit", "tools", "help"]
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg=self.background,
                                        fg=self.foreground,
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        # Change
        self.right_click_menu.add_command(label='Undo', command=self.edit_undo)
        self.right_click_menu.add_command(label='Redo', command=self.edit_redo)
        # Change
        self.all_menus.append(self.right_click_menu)

        # change
        self.count_area = tk.Text(self, height=1)
        self.count_area.pack(side=tk.BOTTOM, fill=tk.X)
        # change
        # Change
        self.terminal.pack(side=tk.BOTTOM, fill=tk.X)
        # Change
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

        self.open_file = ''
Example #16
0
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()

        self.text_area = TextArea(self, bg="white", fg="black", undo=True)

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1)
        self.highlighter = Highlighter(self.text_area, 'languages/python.yaml')

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

    def bind_events(self):
        self.text_area.bind("<MouseWheel>", self.scroll_text)
        self.text_area.bind("<Button-4>", self.scroll_text)
        self.text_area.bind("<Button-5>", self.scroll_text)

        self.bind('<Control-f>', self.show_find_window)

        self.line_numbers.bind("<MouseWheel>", lambda e: "break")
        self.line_numbers.bind("<Button-4>", lambda e: "break")
        self.line_numbers.bind("<Button-5>", lambda e: "break")

    def scroll_text(self, *args):
        if len(args) > 1:
            self.text_area.yview_moveto(args[1])
            self.line_numbers.yview_moveto(args[1])
        else:
            event = args[0]
            if event.delta:
                move = -1 * (event.delta / 120)
            else:
                if event.num == 5:
                    move = 1
                else:
                    move = -1

            self.text_area.yview_scroll(int(move), "units")
            self.line_numbers.yview_scroll(int(move) * 3, "units")

    def show_find_window(self, event=None):
        FindWindow(self.text_area)
Example #17
0
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()

        self.text_area = TextArea(self, bg="white", fg="black", undo=True)

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = tk.Text(self, bg="grey", fg="white")
        first_100_numbers = [str(n + 1) for n in range(100)]

        self.line_numbers.insert(1.0, "\n".join(first_100_numbers))
        self.line_numbers.configure(state="disabled", width=3)

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

    def bind_events(self):
        self.text_area.bind("<MouseWheel>", self.scroll_text)
        self.text_area.bind("<Button-4>", self.scroll_text)
        self.text_area.bind("<Button-5>", self.scroll_text)

        self.line_numbers.bind("<MouseWheel>", lambda e: "break")
        self.line_numbers.bind("<Button-4>", lambda e: "break")
        self.line_numbers.bind("<Button-5>", lambda e: "break")

    def scroll_text(self, *args):
        if len(args) > 1:
            self.text_area.yview_moveto(args[1])
            self.line_numbers.yview_moveto(args[1])
        else:
            event = args[0]
            if event.delta:
                move = -1 * (event.delta / 120)
            else:
                if event.num == 5:
                    move = 1
                else:
                    move = -1

            self.text_area.yview_scroll(int(move), "units")
            self.line_numbers.yview_scroll(int(move) * 3, "units")
    def __init__(self):
        '''
        @update 1.添加横向滚动条 2.修正行号与滚动条和窗口的关联 3.修正行号显示
        '''
        super().__init__()

        self.title('Python Text Editor v3')
        self.geometry('800x600')

        self.foreground = 'black'
        self.background = 'lightgrey'
        self.text_foreground = 'black'
        self.text_background = 'white'

        self.config_dir = os.path.join(str(Path.home()), '.tkedit')

        self.default_scheme_path = os.path.join(self.config_dir,
                                                'schemes/default.yaml')
        self.python_language_path = os.path.join(self.config_dir,
                                                 'languages/python.yaml')
        self.none_language_path = os.path.join(self.config_dir,
                                               'languages/None.yaml')
        self.font_scheme_path = os.path.join(self.config_dir,
                                             'fonts/font.yaml')
        self.create_config_directory_if_needed()

        self.load_scheme_file(self.default_scheme_path)
        self.configure_ttk_elements()

        self.font_size = 15
        self.font_family = "Ubuntu Mono"
        self.load_font_file(self.font_scheme_path)

        self.text_area = TextArea(self,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  font=(self.font_family, self.font_size))

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.text_area.yview)
        self.scrollbar2 = ttk.Scrollbar(orient="horizontal",
                                        command=self.text_area.xview)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1,
                                        font=(self.font_family,
                                              self.font_size))
        self.scrollbar.config(command=self.text_area.yview)
        self.text_area.config(yscrollcommand=self.scrollbar.set,
                              xscrollcommand=self.scrollbar2.set)
        self.highlighter = Highlighter(self.text_area, self.none_language_path)

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        self.all_menus = [self.menu]

        sub_menu_items = ["file", "edit", "tools", "help"]
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg=self.background,
                                        fg=self.foreground,
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        self.all_menus.append(self.right_click_menu)

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.scrollbar2.pack(side=tk.BOTTOM, fill=tk.X)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

        self.open_file = ''
Example #19
0
class MinimalEdit(Tk):
    """The minimaledit application.
    
    Create, and then call the .mainloop() method.
    
    """

    is_fullscreen = False
    saved_geometry = None
    textarea = None

    def __init__(self):
        Tk.__init__(self)

        self.makewidgets()

        self.mapkeys()

        self.style()

        # Catch the "click on close" event.
        self.protocol("WM_DELETE_WINDOW", self.onquit)

    def style(self):
        self.config(background="#000000",
                    borderwidth=0,
                    highlightbackground="#000000")
        if os_sniffer.is_mac:
            # Trying to get rid of the title bar on a mac.
            # This must be done before the window is actually created.
            # If we want to be able to have a title bar in windowed mode and
            # have no title bar in minimal editing mode, we'll need to rebuild
            # the window.
            self.tk.call("::tk::unsupported::MacWindowStyle", "style", self._w, "plain", "noTitleBar")
            # On Mac OS X, attempt to make the window appear on top vs. behind
            # other windows.
            # This is a total hack, but it seems to work quite well.
            # We set up a delayed callback that will ensure the application is
            # up and running, force the application to be topmost which will,
            # even on mac move the application above all other windows in the
            # desktop, but then allow the window to lose focus later if the user
            # chooses to switch to another application in the desktop.
            # I'm working around an apparent bug according to the interwebs,
            # but it seems to work.
            # NOTE: The best I can do with this so far is setting the window on
            # top. Having the window have focus is not happening when not running
            # this application as a py2app.
            # TODO: test running as a py2app to see if I can grab focus.
            def mac_osx_lift_callback():
                self.tk.call('wm', 'attributes', '.', '-topmost', '1')
                self.tk.call('update')
                self.tk.call('wm', 'attributes', '.', '-topmost', '0')
                self.tk.call('update')
            self.after(100, mac_osx_lift_callback)

    def makewidgets(self):
        self.title("MinimalEdit")
        self.textarea = TextArea(self)

    def mapkeys(self):
        if os_sniffer.is_mac:
            command_key = "Command"
        else:
            command_key = "Control"
        self.bind("<"+command_key+"-n>", lambda a: self.onnew())
        self.bind("<"+command_key+"-l>", lambda a: self.onload())
        self.bind("<"+command_key+"-s>", lambda a: self.onsave())
        self.bind("<"+command_key+"-f>", lambda a: self.onfind())
        self.bind("<"+command_key+"-q>", lambda a: self.onquit())
        self.bind("<Escape>", lambda a: self.toggleminimal())

    def onquit(self):
        ans = askokcancel("Verify exit", "Really quit?")
        if ans:
            # NOTE: On Mac, there seems to be a bug with preventing the
            # program from quitting. We can intercept the event and do
            # what clean up we need to do here. However, once this function 
            # exits, on mac os x (but not on windows) our program will close
            # no matter what. This is a tkinter version problem on mac.
            # TODO: Need to confirm that I'm using the non-Apple tkinter.
            self.quit()

    def onnew(self):
        ans = askokcancel("Verify new file", "Really start a new file?")
        if ans:
            self.textarea.settext(text='')

    def onload(self):
        filename = askopenfilename()
        if filename:
            f = open(filename, 'r')
            alltext = f.read()
            self.textarea.settext(alltext)
            f.close()

    def onsave(self):
        filename = asksaveasfilename()
        if filename:
            alltext = self.textarea.gettext()
            f = open(filename, 'w') 
            f.write(alltext)
            f.close()

    def onfind(self):
        target = askstring('Search String', '')
        if target:
            self.textarea.findtext(target)

    def storegeometry(self):
        pg = re.split(r"x|\+", self.geometry())
        self.saved_geometry = tuple(pg)

    def restoregeometry(self):
        if self.saved_geometry:
            self.geometry("{0[0]}x{0[1]}+{0[2]}+{0[3]}".format(self.saved_geometry))
    
    def setfullscreenview(self):
        # Store the previous geometry
        self.storegeometry()

        if os_sniffer.is_mac:
            # Assuming this is TK 8.5 or higher
            self.wm_attributes('-fullscreen', 1)
        # Default for all systems
        self.overrideredirect(1)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth(), self.winfo_screenheight()))

    def setwindowedview(self):
        if os_sniffer.is_mac:
            # Assuming this is TK 8.5 or higher
            self.wm_attributes('-fullscreen', 0)
        # Default for all systems
        self.overrideredirect(0)
        self.restoregeometry()

    def toggleminimal(self):
        if self.is_fullscreen == False:
            self.is_fullscreen = True
            self.setfullscreenview()
            self.textarea.toggleminimal()            
        else:
            self.is_fullscreen = False
            self.setwindowedview()
            self.textarea.toggleminimal()
Example #20
0
 def makewidgets(self):
     self.title("MinimalEdit")
     self.textarea = TextArea(self)
Example #21
0
class MainWindow(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Python Text Editor v3')
        self.geometry('800x600')

        self.foreground = 'black'
        self.background = 'lightgrey'
        self.text_foreground = 'black'
        self.text_background = 'white'

        self.load_scheme_file('schemes/default.yaml')
        self.configure_ttk_elements()

        self.font_size = 15
        self.font_family = "Ubuntu Mono"
        self.load_font_file('schemes/font.yaml')

        self.text_area = TextArea(self,
                                  bg=self.text_background,
                                  fg=self.text_foreground,
                                  undo=True,
                                  font=(self.font_family, self.font_size))

        self.scrollbar = ttk.Scrollbar(orient="vertical",
                                       command=self.scroll_text)
        self.text_area.configure(yscrollcommand=self.scrollbar.set)

        self.line_numbers = LineNumbers(self,
                                        self.text_area,
                                        bg="grey",
                                        fg="white",
                                        width=1)
        self.highlighter = Highlighter(self.text_area, 'languages/python.yaml')

        self.menu = tk.Menu(self, bg=self.background, fg=self.foreground)
        self.all_menus = [self.menu]

        sub_menu_items = ["file", "edit", "tools", "help"]
        self.generate_sub_menus(sub_menu_items)
        self.configure(menu=self.menu)

        self.right_click_menu = tk.Menu(self,
                                        bg=self.background,
                                        fg=self.foreground,
                                        tearoff=0)
        self.right_click_menu.add_command(label='Cut', command=self.edit_cut)
        self.right_click_menu.add_command(label='Copy', command=self.edit_copy)
        self.right_click_menu.add_command(label='Paste',
                                          command=self.edit_paste)
        self.all_menus.append(self.right_click_menu)

        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.line_numbers.pack(side=tk.LEFT, fill=tk.Y)
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.bind_events()

        self.open_file = ''

    def bind_events(self):
        self.text_area.bind("<MouseWheel>", self.scroll_text)
        self.text_area.bind("<Button-4>", self.scroll_text)
        self.text_area.bind("<Button-5>", self.scroll_text)
        self.text_area.bind("<Button-3>", self.show_right_click_menu)

        self.bind('<Control-f>', self.show_find_window)

        self.bind('<Control-n>', self.file_new)
        self.bind('<Control-o>', self.file_open)
        self.bind('<Control-s>', self.file_save)

        self.bind('<Control-h>', self.help_about)

        self.bind('<Control-m>', self.tools_change_syntax_highlighting)
        self.bind('<Control-g>', self.tools_change_color_scheme)
        self.bind('<Control-l>', self.tools_change_font)

        self.line_numbers.bind("<MouseWheel>", lambda e: "break")
        self.line_numbers.bind("<Button-4>", lambda e: "break")
        self.line_numbers.bind("<Button-5>", lambda e: "break")

    def scroll_text(self, *args):
        if len(args) > 1:
            self.text_area.yview_moveto(args[1])
            self.line_numbers.yview_moveto(args[1])
        else:
            event = args[0]
            if event.delta:
                move = -1 * (event.delta / 120)
            else:
                if event.num == 5:
                    move = 1
                else:
                    move = -1

            self.text_area.yview_scroll(int(move), "units")
            self.line_numbers.yview_scroll(int(move) * 3, "units")

    def show_find_window(self, event=None):
        FindWindow(self.text_area)

    def show_right_click_menu(self, event):
        x = self.winfo_x() + self.text_area.winfo_x() + event.x
        y = self.winfo_y() + self.text_area.winfo_y() + event.y
        self.right_click_menu.post(x, y)

    def generate_sub_menus(self, sub_menu_items):
        window_methods = [
            method_name for method_name in dir(self)
            if callable(getattr(self, method_name))
        ]
        tkinter_methods = [
            method_name for method_name in dir(tk.Tk)
            if callable(getattr(tk.Tk, method_name))
        ]

        my_methods = [
            method for method in set(window_methods) - set(tkinter_methods)
        ]
        my_methods = sorted(my_methods)

        for item in sub_menu_items:
            sub_menu = tk.Menu(self.menu,
                               tearoff=0,
                               bg=self.background,
                               fg=self.foreground)
            matching_methods = []
            for method in my_methods:
                if method.startswith(item):
                    matching_methods.append(method)

            for match in matching_methods:
                actual_method = getattr(self, match)
                method_shortcut = actual_method.__doc__.strip()
                friendly_name = ' '.join(match.split('_')[1:])
                sub_menu.add_command(label=friendly_name.title(),
                                     command=actual_method,
                                     accelerator=method_shortcut)

            self.menu.add_cascade(label=item.title(), menu=sub_menu)
            self.all_menus.append(sub_menu)

    def show_about_page(self):
        msg.showinfo(
            "About",
            "My text editor, version 2, written in Python3.6 using tkinter!")

    def load_syntax_highlighting_file(self):
        syntax_file = filedialog.askopenfilename(filetypes=[("YAML file",
                                                             ("*.yaml",
                                                              "*.yml"))])
        if syntax_file:
            self.highlighter.clear_highlight()
            self.highlighter = Highlighter(self.text_area, syntax_file)
            self.highlighter.force_highlight()

    def load_scheme_file(self, scheme):
        with open(scheme, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        self.foreground = config['foreground']
        self.background = config['background']
        self.text_foreground = config['text_foreground']
        self.text_background = config['text_background']

    def load_font_file(self, file_path):
        with open(file_path, 'r') as stream:
            try:
                config = yaml.load(stream)
            except yaml.YAMLError as error:
                print(error)
                return

        self.font_family = config['family']
        self.font_size = config['size']

    def change_color_scheme(self):
        colorChooser(self)

    def apply_color_scheme(self, foreground, background, text_foreground,
                           text_background):
        self.text_area.configure(fg=text_foreground, bg=text_background)
        self.background = background
        self.foreground = foreground
        for menu in self.all_menus:
            menu.configure(bg=self.background, fg=self.foreground)
        self.configure_ttk_elements()

    def configure_ttk_elements(self):
        style = ttk.Style()
        style.configure('editor.TLabel',
                        foreground=self.foreground,
                        background=self.background)
        style.configure('editor.TButton',
                        foreground=self.foreground,
                        background=self.background)

    def change_font(self):
        FontChooser(self)

    def update_font(self):
        self.load_font_file('schemes/font.yaml')
        self.text_area.configure(font=(self.font_family, self.font_size))

    # =========== Menu Functions ==============

    def file_new(self, event=None):
        """
        Ctrl+N
        """
        self.text_area.delete(1.0, tk.END)
        self.open_file = None
        self.line_numbers.force_update()

    def file_open(self, event=None):
        """
        Ctrl+O
        """
        file_to_open = filedialog.askopenfilename()
        if file_to_open:
            self.open_file = file_to_open

            self.text_area.display_file_contents(file_to_open)
            self.highlighter.force_highlight()
            self.line_numbers.force_update()

    def file_save(self, event=None):
        """
        Ctrl+S
        """
        current_file = self.open_file if self.open_file else None
        if not current_file:
            current_file = filedialog.asksaveasfilename()

        if current_file:
            contents = self.text_area.get(1.0, tk.END)
            with open(current_file, 'w') as file:
                file.write(contents)

    def edit_cut(self, event=None):
        """
        Ctrl+X
        """
        self.text_area.event_generate("<Control-x>")
        self.line_numbers.force_update()

    def edit_paste(self, event=None):
        """
        Ctrl+V
        """
        self.text_area.event_generate("<Control-v>")
        self.line_numbers.force_update()
        self.highlighter.force_highlight()

    def edit_copy(self, event=None):
        """
        Ctrl+C
        """
        self.text_area.event_generate("<Control-c>")

    def edit_select_all(self, event=None):
        """
        Ctrl+A
        """
        self.text_area.event_generate("<Control-a>")

    def edit_find_and_replace(self, event=None):
        """
        Ctrl+F
        """
        self.show_find_window()

    def help_about(self, event=None):
        """
        Ctrl+H
        """
        self.show_about_page()

    def tools_change_syntax_highlighting(self, event=None):
        """
        Ctrl+M
        """
        self.load_syntax_highlighting_file()

    def tools_change_color_scheme(self, event=None):
        """
        Ctrl+G
        """
        self.change_color_scheme()

    def tools_change_font(self, event=None):
        """
        Ctrl+L
        """
        self.change_font()
Example #22
0
    "textarea",
)
reoptions = [('s', 'dotall', 'Dot Match All'),
             ('i', 'ignorecase', 'Case Insensitive'),
             ('m', 'multiline', '^$ at line breaks'),
             ('x', 'verbose', 'Free-Spacing'), ('u', 'unicode', 'Unicode')]

funcs = [
    '', 'Import regex library',
    'If/else branch whether the regex matches (part of) a string'
]

langs = ('python', )
app = web.application(urls, globals())
flag = Option()
text = TextArea()
env = Environment(loader=PackageLoader('index', 'templates'))


#the home page(the only page)
class index:
    def GET(self):
        template = env.get_template('index.html')
        return template.render(reoptions=reoptions,
                               functions=funcs,
                               langs=langs)


#when option changes in the front,
class options:
    def POST(self):