mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			313 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			313 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
 | 
						||
 | 
						||
This window provides the basic decorations, primarily including the menubar.
 | 
						||
It is used to bring up other windows.
 | 
						||
"""
 | 
						||
 | 
						||
import sys
 | 
						||
import os
 | 
						||
from tkinter import *
 | 
						||
from tkinter import messagebox, filedialog
 | 
						||
import ColorDB
 | 
						||
 | 
						||
# Milliseconds between interrupt checks
 | 
						||
KEEPALIVE_TIMER = 500
 | 
						||
 | 
						||
 | 
						||
 | 
						||
class PyncheWidget:
 | 
						||
    def __init__(self, version, switchboard, master=None, extrapath=[]):
 | 
						||
        self.__sb = switchboard
 | 
						||
        self.__version = version
 | 
						||
        self.__textwin = None
 | 
						||
        self.__listwin = None
 | 
						||
        self.__detailswin = None
 | 
						||
        self.__helpwin = None
 | 
						||
        self.__dialogstate = {}
 | 
						||
        modal = self.__modal = not not master
 | 
						||
        # If a master was given, we are running as a modal dialog servant to
 | 
						||
        # some other application.  We rearrange our UI in this case (there's
 | 
						||
        # no File menu and we get `Okay' and `Cancel' buttons), and we do a
 | 
						||
        # grab_set() to make ourselves modal
 | 
						||
        if modal:
 | 
						||
            self.__tkroot = tkroot = Toplevel(master, class_='Pynche')
 | 
						||
            tkroot.grab_set()
 | 
						||
            tkroot.withdraw()
 | 
						||
        else:
 | 
						||
            # Is there already a default root for Tk, say because we're
 | 
						||
            # running under Guido's IDE? :-) Two conditions say no, either the
 | 
						||
            # import fails or _default_root is None.
 | 
						||
            tkroot = None
 | 
						||
            try:
 | 
						||
                from Tkinter import _default_root
 | 
						||
                tkroot = self.__tkroot = _default_root
 | 
						||
            except ImportError:
 | 
						||
                pass
 | 
						||
            if not tkroot:
 | 
						||
                tkroot = self.__tkroot = Tk(className='Pynche')
 | 
						||
            # but this isn't our top level widget, so make it invisible
 | 
						||
            tkroot.withdraw()
 | 
						||
        # create the menubar
 | 
						||
        menubar = self.__menubar = Menu(tkroot)
 | 
						||
        #
 | 
						||
        # File menu
 | 
						||
        #
 | 
						||
        filemenu = self.__filemenu = Menu(menubar, tearoff=0)
 | 
						||
        filemenu.add_command(label='Load palette...',
 | 
						||
                             command=self.__load,
 | 
						||
                             underline=0)
 | 
						||
        if not modal:
 | 
						||
            filemenu.add_command(label='Quit',
 | 
						||
                                 command=self.__quit,
 | 
						||
                                 accelerator='Alt-Q',
 | 
						||
                                 underline=0)
 | 
						||
        #
 | 
						||
        # View menu
 | 
						||
        #
 | 
						||
        views = make_view_popups(self.__sb, self.__tkroot, extrapath)
 | 
						||
        viewmenu = Menu(menubar, tearoff=0)
 | 
						||
        for v in views:
 | 
						||
            viewmenu.add_command(label=v.menutext(),
 | 
						||
                                 command=v.popup,
 | 
						||
                                 underline=v.underline())
 | 
						||
        #
 | 
						||
        # Help menu
 | 
						||
        #
 | 
						||
        helpmenu = Menu(menubar, name='help', tearoff=0)
 | 
						||
        helpmenu.add_command(label='About Pynche...',
 | 
						||
                             command=self.__popup_about,
 | 
						||
                             underline=0)
 | 
						||
        helpmenu.add_command(label='Help...',
 | 
						||
                             command=self.__popup_usage,
 | 
						||
                             underline=0)
 | 
						||
        #
 | 
						||
        # Tie them all together
 | 
						||
        #
 | 
						||
        menubar.add_cascade(label='File',
 | 
						||
                            menu=filemenu,
 | 
						||
                            underline=0)
 | 
						||
        menubar.add_cascade(label='View',
 | 
						||
                            menu=viewmenu,
 | 
						||
                            underline=0)
 | 
						||
        menubar.add_cascade(label='Help',
 | 
						||
                            menu=helpmenu,
 | 
						||
                            underline=0)
 | 
						||
 | 
						||
        # now create the top level window
 | 
						||
        root = self.__root = Toplevel(tkroot, class_='Pynche', menu=menubar)
 | 
						||
        root.protocol('WM_DELETE_WINDOW',
 | 
						||
                      modal and self.__bell or self.__quit)
 | 
						||
        root.title('Pynche %s' % version)
 | 
						||
        root.iconname('Pynche')
 | 
						||
        # Only bind accelerators for the File->Quit menu item if running as a
 | 
						||
        # standalone app
 | 
						||
        if not modal:
 | 
						||
            root.bind('<Alt-q>', self.__quit)
 | 
						||
            root.bind('<Alt-Q>', self.__quit)
 | 
						||
        else:
 | 
						||
            # We're a modal dialog so we have a new row of buttons
 | 
						||
            bframe = Frame(root, borderwidth=1, relief=RAISED)
 | 
						||
            bframe.grid(row=4, column=0, columnspan=2,
 | 
						||
                        sticky='EW',
 | 
						||
                        ipady=5)
 | 
						||
            okay = Button(bframe,
 | 
						||
                          text='Okay',
 | 
						||
                          command=self.__okay)
 | 
						||
            okay.pack(side=LEFT, expand=1)
 | 
						||
            cancel = Button(bframe,
 | 
						||
                            text='Cancel',
 | 
						||
                            command=self.__cancel)
 | 
						||
            cancel.pack(side=LEFT, expand=1)
 | 
						||
 | 
						||
    def __quit(self, event=None):
 | 
						||
        self.__tkroot.quit()
 | 
						||
 | 
						||
    def __bell(self, event=None):
 | 
						||
        self.__tkroot.bell()
 | 
						||
 | 
						||
    def __okay(self, event=None):
 | 
						||
        self.__sb.withdraw_views()
 | 
						||
        self.__tkroot.grab_release()
 | 
						||
        self.__quit()
 | 
						||
 | 
						||
    def __cancel(self, event=None):
 | 
						||
        self.__sb.canceled()
 | 
						||
        self.__okay()
 | 
						||
 | 
						||
    def __keepalive(self):
 | 
						||
        # Exercise the Python interpreter regularly so keyboard interrupts get
 | 
						||
        # through.
 | 
						||
        self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
 | 
						||
 | 
						||
    def start(self):
 | 
						||
        if not self.__modal:
 | 
						||
            self.__keepalive()
 | 
						||
        self.__tkroot.mainloop()
 | 
						||
 | 
						||
    def window(self):
 | 
						||
        return self.__root
 | 
						||
 | 
						||
    def __popup_about(self, event=None):
 | 
						||
        from Main import __version__
 | 
						||
        messagebox.showinfo('About Pynche ' + __version__,
 | 
						||
                              '''\
 | 
						||
Pynche %s
 | 
						||
The PYthonically Natural
 | 
						||
Color and Hue Editor
 | 
						||
 | 
						||
For information
 | 
						||
contact: Barry A. Warsaw
 | 
						||
email:   bwarsaw@python.org''' % __version__)
 | 
						||
 | 
						||
    def __popup_usage(self, event=None):
 | 
						||
        if not self.__helpwin:
 | 
						||
            self.__helpwin = Helpwin(self.__root, self.__quit)
 | 
						||
        self.__helpwin.deiconify()
 | 
						||
 | 
						||
    def __load(self, event=None):
 | 
						||
        while 1:
 | 
						||
            idir, ifile = os.path.split(self.__sb.colordb().filename())
 | 
						||
            file = filedialog.askopenfilename(
 | 
						||
                filetypes=[('Text files', '*.txt'),
 | 
						||
                           ('All files', '*'),
 | 
						||
                           ],
 | 
						||
                initialdir=idir,
 | 
						||
                initialfile=ifile)
 | 
						||
            if not file:
 | 
						||
                # cancel button
 | 
						||
                return
 | 
						||
            try:
 | 
						||
                colordb = ColorDB.get_colordb(file)
 | 
						||
            except IOError:
 | 
						||
                messagebox.showerror('Read error', '''\
 | 
						||
Could not open file for reading:
 | 
						||
%s''' % file)
 | 
						||
                continue
 | 
						||
            if colordb is None:
 | 
						||
                messagebox.showerror('Unrecognized color file type', '''\
 | 
						||
Unrecognized color file type in file:
 | 
						||
%s''' % file)
 | 
						||
                continue
 | 
						||
            break
 | 
						||
        self.__sb.set_colordb(colordb)
 | 
						||
 | 
						||
    def withdraw(self):
 | 
						||
        self.__root.withdraw()
 | 
						||
 | 
						||
    def deiconify(self):
 | 
						||
        self.__root.deiconify()
 | 
						||
 | 
						||
 | 
						||
 | 
						||
class Helpwin:
 | 
						||
    def __init__(self, master, quitfunc):
 | 
						||
        from Main import docstring
 | 
						||
        self.__root = root = Toplevel(master, class_='Pynche')
 | 
						||
        root.protocol('WM_DELETE_WINDOW', self.__withdraw)
 | 
						||
        root.title('Pynche Help Window')
 | 
						||
        root.iconname('Pynche Help Window')
 | 
						||
        root.bind('<Alt-q>', quitfunc)
 | 
						||
        root.bind('<Alt-Q>', quitfunc)
 | 
						||
        root.bind('<Alt-w>', self.__withdraw)
 | 
						||
        root.bind('<Alt-W>', self.__withdraw)
 | 
						||
 | 
						||
        # more elaborate help is available in the README file
 | 
						||
        readmefile = os.path.join(sys.path[0], 'README')
 | 
						||
        try:
 | 
						||
            fp = None
 | 
						||
            try:
 | 
						||
                fp = open(readmefile)
 | 
						||
                contents = fp.read()
 | 
						||
                # wax the last page, it contains Emacs cruft
 | 
						||
                i = contents.rfind('\f')
 | 
						||
                if i > 0:
 | 
						||
                    contents = contents[:i].rstrip()
 | 
						||
            finally:
 | 
						||
                if fp:
 | 
						||
                    fp.close()
 | 
						||
        except IOError:
 | 
						||
            sys.stderr.write("Couldn't open Pynche's README, "
 | 
						||
                             'using docstring instead.\n')
 | 
						||
            contents = docstring()
 | 
						||
 | 
						||
        self.__text = text = Text(root, relief=SUNKEN,
 | 
						||
                                  width=80, height=24)
 | 
						||
        self.__text.focus_set()
 | 
						||
        text.insert(0.0, contents)
 | 
						||
        scrollbar = Scrollbar(root)
 | 
						||
        scrollbar.pack(fill=Y, side=RIGHT)
 | 
						||
        text.pack(fill=BOTH, expand=YES)
 | 
						||
        text.configure(yscrollcommand=(scrollbar, 'set'))
 | 
						||
        scrollbar.configure(command=(text, 'yview'))
 | 
						||
 | 
						||
    def __withdraw(self, event=None):
 | 
						||
        self.__root.withdraw()
 | 
						||
 | 
						||
    def deiconify(self):
 | 
						||
        self.__root.deiconify()
 | 
						||
 | 
						||
 | 
						||
 | 
						||
import functools
 | 
						||
@functools.total_ordering
 | 
						||
class PopupViewer:
 | 
						||
    def __init__(self, module, name, switchboard, root):
 | 
						||
        self.__m = module
 | 
						||
        self.__name = name
 | 
						||
        self.__sb = switchboard
 | 
						||
        self.__root = root
 | 
						||
        self.__menutext = module.ADDTOVIEW
 | 
						||
        # find the underline character
 | 
						||
        underline = module.ADDTOVIEW.find('%')
 | 
						||
        if underline == -1:
 | 
						||
            underline = 0
 | 
						||
        else:
 | 
						||
            self.__menutext = module.ADDTOVIEW.replace('%', '', 1)
 | 
						||
        self.__underline = underline
 | 
						||
        self.__window = None
 | 
						||
 | 
						||
    def menutext(self):
 | 
						||
        return self.__menutext
 | 
						||
 | 
						||
    def underline(self):
 | 
						||
        return self.__underline
 | 
						||
 | 
						||
    def popup(self, event=None):
 | 
						||
        if not self.__window:
 | 
						||
            # class and module must have the same name
 | 
						||
            class_ = getattr(self.__m, self.__name)
 | 
						||
            self.__window = class_(self.__sb, self.__root)
 | 
						||
            self.__sb.add_view(self.__window)
 | 
						||
        self.__window.deiconify()
 | 
						||
 | 
						||
    def __eq__(self, other):
 | 
						||
        return self.__menutext == other.__menutext
 | 
						||
 | 
						||
    def __lt__(self, other):
 | 
						||
        return self.__menutext < other.__menutext
 | 
						||
 | 
						||
 | 
						||
def make_view_popups(switchboard, root, extrapath):
 | 
						||
    viewers = []
 | 
						||
    # where we are in the file system
 | 
						||
    dirs = [os.path.dirname(__file__)] + extrapath
 | 
						||
    for dir in dirs:
 | 
						||
        if dir == '':
 | 
						||
            dir = '.'
 | 
						||
        for file in os.listdir(dir):
 | 
						||
            if file[-9:] == 'Viewer.py':
 | 
						||
                name = file[:-3]
 | 
						||
                try:
 | 
						||
                    module = __import__(name)
 | 
						||
                except ImportError:
 | 
						||
                    # Pynche is running from inside a package, so get the
 | 
						||
                    # module using the explicit path.
 | 
						||
                    pkg = __import__('pynche.'+name)
 | 
						||
                    module = getattr(pkg, name)
 | 
						||
                if hasattr(module, 'ADDTOVIEW') and module.ADDTOVIEW:
 | 
						||
                    # this is an external viewer
 | 
						||
                    v = PopupViewer(module, name, switchboard, root)
 | 
						||
                    viewers.append(v)
 | 
						||
    # sort alphabetically
 | 
						||
    viewers.sort()
 | 
						||
    return viewers
 |