• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 as 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()
230