PageRenderTime 26ms CodeModel.GetById 7ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/Tools/pynche/Main.py

http://unladen-swallow.googlecode.com/
Python | 229 lines | 188 code | 19 blank | 22 comment | 25 complexity | cbdf48883c6dd1fbc816785be1d7dbfe MD5 | raw file
  1"""Pynche -- The PYthon Natural Color and Hue Editor.
  2
  3Contact: %(AUTHNAME)s
  4Email:   %(AUTHEMAIL)s
  5Version: %(__version__)s
  6
  7Pynche is based largely on a similar color editor I wrote years ago for the
  8SunView window system.  That editor was called ICE: the Interactive Color
  9Editor.  I'd always wanted to port the editor to X but didn't feel like
 10hacking X and C code to do it.  Fast forward many years, to where Python +
 11Tkinter provides such a nice programming environment, with enough power, that
 12I finally buckled down and implemented it.  I changed the name because these
 13days, too many other systems have the acronym `ICE'.
 14
 15This program currently requires Python 2.2 with Tkinter.
 16
 17Usage: %(PROGRAM)s [-d file] [-i file] [-X] [-v] [-h] [initialcolor]
 18
 19Where:
 20    --database file
 21    -d file
 22        Alternate location of a color database file
 23
 24    --initfile file
 25    -i file
 26        Alternate location of the initialization file.  This file contains a
 27        persistent database of the current Pynche options and color.  This
 28        means that Pynche restores its option settings and current color when
 29        it restarts, using this file (unless the -X option is used).  The
 30        default is ~/.pynche
 31
 32    --ignore
 33    -X
 34        Ignore the initialization file when starting up.  Pynche will still
 35        write the current option settings to this file when it quits.
 36
 37    --version
 38    -v
 39        print the version number and exit
 40
 41    --help
 42    -h
 43        print this message
 44
 45    initialcolor
 46        initial color, as a color name or #RRGGBB format
 47"""
 48
 49__version__ = '1.4.1'
 50
 51import sys
 52import os
 53import getopt
 54import ColorDB
 55
 56from PyncheWidget import PyncheWidget
 57from Switchboard import Switchboard
 58from StripViewer import StripViewer
 59from ChipViewer import ChipViewer
 60from TypeinViewer import TypeinViewer
 61
 62
 63
 64PROGRAM = sys.argv[0]
 65AUTHNAME = 'Barry Warsaw'
 66AUTHEMAIL = 'barry@python.org'
 67
 68# Default locations of rgb.txt or other textual color database
 69RGB_TXT = [
 70    # Solaris OpenWindows
 71    '/usr/openwin/lib/rgb.txt',
 72    # Linux
 73    '/usr/lib/X11/rgb.txt',
 74    # The X11R6.4 rgb.txt file
 75    os.path.join(sys.path[0], 'X/rgb.txt'),
 76    # add more here
 77    ]
 78
 79
 80
 81# Do this because PyncheWidget.py wants to get at the interpolated docstring
 82# too, for its Help menu.
 83def docstring():
 84    return __doc__ % globals()
 85
 86
 87def usage(code, msg=''):
 88    print docstring()
 89    if msg:
 90        print msg
 91    sys.exit(code)
 92
 93
 94
 95def initial_color(s, colordb):
 96    # function called on every color
 97    def scan_color(s, colordb=colordb):
 98        try:
 99            r, g, b = colordb.find_byname(s)
100        except ColorDB.BadColor:
101            try:
102                r, g, b = ColorDB.rrggbb_to_triplet(s)
103            except ColorDB.BadColor:
104                return None, None, None
105        return r, g, b
106    #
107    # First try the passed in color
108    r, g, b = scan_color(s)
109    if r is None:
110        # try the same color with '#' prepended, since some shells require
111        # this to be escaped, which is a pain
112        r, g, b = scan_color('#' + s)
113    if r is None:
114        print 'Bad initial color, using gray50:', s
115        r, g, b = scan_color('gray50')
116    if r is None:
117        usage(1, 'Cannot find an initial color to use')
118        # does not return
119    return r, g, b
120
121
122
123def build(master=None, initialcolor=None, initfile=None, ignore=None,
124          dbfile=None):
125    # create all output widgets
126    s = Switchboard(not ignore and initfile)
127    # defer to the command line chosen color database, falling back to the one
128    # in the .pynche file.
129    if dbfile is None:
130        dbfile = s.optiondb().get('DBFILE')
131    # find a parseable color database
132    colordb = None
133    files = RGB_TXT[:]
134    if dbfile is None:
135        dbfile = files.pop()
136    while colordb is None:
137        try:
138            colordb = ColorDB.get_colordb(dbfile)
139        except (KeyError, IOError):
140            pass
141        if colordb is None:
142            if not files:
143                break
144            dbfile = files.pop(0)
145    if not colordb:
146        usage(1, 'No color database file found, see the -d option.')
147    s.set_colordb(colordb)
148
149    # create the application window decorations
150    app = PyncheWidget(__version__, s, master=master)
151    w = app.window()
152
153    # these built-in viewers live inside the main Pynche window
154    s.add_view(StripViewer(s, w))
155    s.add_view(ChipViewer(s, w))
156    s.add_view(TypeinViewer(s, w))
157
158    # get the initial color as components and set the color on all views.  if
159    # there was no initial color given on the command line, use the one that's
160    # stored in the option database
161    if initialcolor is None:
162        optiondb = s.optiondb()
163        red = optiondb.get('RED')
164        green = optiondb.get('GREEN')
165        blue = optiondb.get('BLUE')
166        # but if there wasn't any stored in the database, use grey50
167        if red is None or blue is None or green is None:
168            red, green, blue = initial_color('grey50', colordb)
169    else:
170        red, green, blue = initial_color(initialcolor, colordb)
171    s.update_views(red, green, blue)
172    return app, s
173
174
175def run(app, s):
176    try:
177        app.start()
178    except KeyboardInterrupt:
179        pass
180
181
182
183def main():
184    try:
185        opts, args = getopt.getopt(
186            sys.argv[1:],
187            'hd:i:Xv',
188            ['database=', 'initfile=', 'ignore', 'help', 'version'])
189    except getopt.error, msg:
190        usage(1, msg)
191
192    if len(args) == 0:
193        initialcolor = None
194    elif len(args) == 1:
195        initialcolor = args[0]
196    else:
197        usage(1)
198
199    ignore = False
200    dbfile = None
201    initfile = os.path.expanduser('~/.pynche')
202    for opt, arg in opts:
203        if opt in ('-h', '--help'):
204            usage(0)
205        elif opt in ('-v', '--version'):
206            print """\
207Pynche -- The PYthon Natural Color and Hue Editor.
208Contact: %(AUTHNAME)s
209Email:   %(AUTHEMAIL)s
210Version: %(__version__)s""" % globals()
211            sys.exit(0)
212        elif opt in ('-d', '--database'):
213            dbfile = arg
214        elif opt in ('-X', '--ignore'):
215            ignore = True
216        elif opt in ('-i', '--initfile'):
217            initfile = arg
218
219    app, sb = build(initialcolor=initialcolor,
220                    initfile=initfile,
221                    ignore=ignore,
222                    dbfile=dbfile)
223    run(app, sb)
224    sb.save_views()
225
226
227
228if __name__ == '__main__':
229    main()