| """Pynche -- The PYthon Natural Color and Hue Editor. | 
 |  | 
 | Contact: %(AUTHNAME)s | 
 | Email:   %(AUTHEMAIL)s | 
 | Version: %(__version__)s | 
 |  | 
 | Pynche is based largely on a similar color editor I wrote years ago for the | 
 | SunView window system.  That editor was called ICE: the Interactive Color | 
 | Editor.  I'd always wanted to port the editor to X but didn't feel like | 
 | hacking X and C code to do it.  Fast forward many years, to where Python + | 
 | Tkinter provides such a nice programming environment, with enough power, that | 
 | I finally buckled down and implemented it.  I changed the name because these | 
 | days, too many other systems have the acronym `ICE'. | 
 |  | 
 | This program currently requires Python 2.2 with Tkinter. | 
 |  | 
 | Usage: %(PROGRAM)s [-d file] [-i file] [-X] [-v] [-h] [initialcolor] | 
 |  | 
 | Where: | 
 |     --database file | 
 |     -d file | 
 |         Alternate location of a color database file | 
 |  | 
 |     --initfile file | 
 |     -i file | 
 |         Alternate location of the initialization file.  This file contains a | 
 |         persistent database of the current Pynche options and color.  This | 
 |         means that Pynche restores its option settings and current color when | 
 |         it restarts, using this file (unless the -X option is used).  The | 
 |         default is ~/.pynche | 
 |  | 
 |     --ignore | 
 |     -X | 
 |         Ignore the initialization file when starting up.  Pynche will still | 
 |         write the current option settings to this file when it quits. | 
 |  | 
 |     --version | 
 |     -v | 
 |         print the version number and exit | 
 |  | 
 |     --help | 
 |     -h | 
 |         print this message | 
 |  | 
 |     initialcolor | 
 |         initial color, as a color name or #RRGGBB format | 
 | """ | 
 |  | 
 | __version__ = '1.4.1' | 
 |  | 
 | import sys | 
 | import os | 
 | import getopt | 
 | import ColorDB | 
 |  | 
 | from PyncheWidget import PyncheWidget | 
 | from Switchboard import Switchboard | 
 | from StripViewer import StripViewer | 
 | from ChipViewer import ChipViewer | 
 | from TypeinViewer import TypeinViewer | 
 |  | 
 |  | 
 |  | 
 | PROGRAM = sys.argv[0] | 
 | AUTHNAME = 'Barry Warsaw' | 
 | AUTHEMAIL = 'barry@python.org' | 
 |  | 
 | # Default locations of rgb.txt or other textual color database | 
 | RGB_TXT = [ | 
 |     # Solaris OpenWindows | 
 |     '/usr/openwin/lib/rgb.txt', | 
 |     # Linux | 
 |     '/usr/lib/X11/rgb.txt', | 
 |     # The X11R6.4 rgb.txt file | 
 |     os.path.join(sys.path[0], 'X/rgb.txt'), | 
 |     # add more here | 
 |     ] | 
 |  | 
 |  | 
 |  | 
 | # Do this because PyncheWidget.py wants to get at the interpolated docstring | 
 | # too, for its Help menu. | 
 | def docstring(): | 
 |     return __doc__ % globals() | 
 |  | 
 |  | 
 | def usage(code, msg=''): | 
 |     print(docstring()) | 
 |     if msg: | 
 |         print(msg) | 
 |     sys.exit(code) | 
 |  | 
 |  | 
 |  | 
 | def initial_color(s, colordb): | 
 |     # function called on every color | 
 |     def scan_color(s, colordb=colordb): | 
 |         try: | 
 |             r, g, b = colordb.find_byname(s) | 
 |         except ColorDB.BadColor: | 
 |             try: | 
 |                 r, g, b = ColorDB.rrggbb_to_triplet(s) | 
 |             except ColorDB.BadColor: | 
 |                 return None, None, None | 
 |         return r, g, b | 
 |     # | 
 |     # First try the passed in color | 
 |     r, g, b = scan_color(s) | 
 |     if r is None: | 
 |         # try the same color with '#' prepended, since some shells require | 
 |         # this to be escaped, which is a pain | 
 |         r, g, b = scan_color('#' + s) | 
 |     if r is None: | 
 |         print('Bad initial color, using gray50:', s) | 
 |         r, g, b = scan_color('gray50') | 
 |     if r is None: | 
 |         usage(1, 'Cannot find an initial color to use') | 
 |         # does not return | 
 |     return r, g, b | 
 |  | 
 |  | 
 |  | 
 | def build(master=None, initialcolor=None, initfile=None, ignore=None, | 
 |           dbfile=None): | 
 |     # create all output widgets | 
 |     s = Switchboard(not ignore and initfile) | 
 |     # defer to the command line chosen color database, falling back to the one | 
 |     # in the .pynche file. | 
 |     if dbfile is None: | 
 |         dbfile = s.optiondb().get('DBFILE') | 
 |     # find a parseable color database | 
 |     colordb = None | 
 |     files = RGB_TXT[:] | 
 |     if dbfile is None: | 
 |         dbfile = files.pop() | 
 |     while colordb is None: | 
 |         try: | 
 |             colordb = ColorDB.get_colordb(dbfile) | 
 |         except (KeyError, IOError): | 
 |             pass | 
 |         if colordb is None: | 
 |             if not files: | 
 |                 break | 
 |             dbfile = files.pop(0) | 
 |     if not colordb: | 
 |         usage(1, 'No color database file found, see the -d option.') | 
 |     s.set_colordb(colordb) | 
 |  | 
 |     # create the application window decorations | 
 |     app = PyncheWidget(__version__, s, master=master) | 
 |     w = app.window() | 
 |  | 
 |     # these built-in viewers live inside the main Pynche window | 
 |     s.add_view(StripViewer(s, w)) | 
 |     s.add_view(ChipViewer(s, w)) | 
 |     s.add_view(TypeinViewer(s, w)) | 
 |  | 
 |     # get the initial color as components and set the color on all views.  if | 
 |     # there was no initial color given on the command line, use the one that's | 
 |     # stored in the option database | 
 |     if initialcolor is None: | 
 |         optiondb = s.optiondb() | 
 |         red = optiondb.get('RED') | 
 |         green = optiondb.get('GREEN') | 
 |         blue = optiondb.get('BLUE') | 
 |         # but if there wasn't any stored in the database, use grey50 | 
 |         if red is None or blue is None or green is None: | 
 |             red, green, blue = initial_color('grey50', colordb) | 
 |     else: | 
 |         red, green, blue = initial_color(initialcolor, colordb) | 
 |     s.update_views(red, green, blue) | 
 |     return app, s | 
 |  | 
 |  | 
 | def run(app, s): | 
 |     try: | 
 |         app.start() | 
 |     except KeyboardInterrupt: | 
 |         pass | 
 |  | 
 |  | 
 |  | 
 | def main(): | 
 |     try: | 
 |         opts, args = getopt.getopt( | 
 |             sys.argv[1:], | 
 |             'hd:i:Xv', | 
 |             ['database=', 'initfile=', 'ignore', 'help', 'version']) | 
 |     except getopt.error as msg: | 
 |         usage(1, msg) | 
 |  | 
 |     if len(args) == 0: | 
 |         initialcolor = None | 
 |     elif len(args) == 1: | 
 |         initialcolor = args[0] | 
 |     else: | 
 |         usage(1) | 
 |  | 
 |     ignore = False | 
 |     dbfile = None | 
 |     initfile = os.path.expanduser('~/.pynche') | 
 |     for opt, arg in opts: | 
 |         if opt in ('-h', '--help'): | 
 |             usage(0) | 
 |         elif opt in ('-v', '--version'): | 
 |             print("""\ | 
 | Pynche -- The PYthon Natural Color and Hue Editor. | 
 | Contact: %(AUTHNAME)s | 
 | Email:   %(AUTHEMAIL)s | 
 | Version: %(__version__)s""" % globals()) | 
 |             sys.exit(0) | 
 |         elif opt in ('-d', '--database'): | 
 |             dbfile = arg | 
 |         elif opt in ('-X', '--ignore'): | 
 |             ignore = True | 
 |         elif opt in ('-i', '--initfile'): | 
 |             initfile = arg | 
 |  | 
 |     app, sb = build(initialcolor=initialcolor, | 
 |                     initfile=initfile, | 
 |                     ignore=ignore, | 
 |                     dbfile=dbfile) | 
 |     run(app, sb) | 
 |     sb.save_views() | 
 |  | 
 |  | 
 |  | 
 | if __name__ == '__main__': | 
 |     main() |