blob: bb5329e751d02fbc4629ef8c8671f4c5ab4ca9f7 [file] [log] [blame]
Barry Warsaw516f1891998-01-27 03:19:00 +00001"""Pynche: The PYthon Natural Color and Hue Editor.
2
3Pynche is based largely on a similar color editor I wrote years ago for the
4Sunview window system. That editor was called ICE: the Interactive Color
5Editor. I'd always wanted to port the editor to X but didn't feel like
6hacking X and C code to do it. Fast forward many years, to where Python +
Barry Warsaw04c78861998-09-28 16:28:04 +00007Tkinter provides such a nice programming environment, with enough power, that
8I finally buckled down and implemented it. I changed the name because these
9days, too many other systems have the acronym `ICE'.
Barry Warsaw516f1891998-01-27 03:19:00 +000010
Barry Warsaw04c78861998-09-28 16:28:04 +000011This program currently requires Python 1.5 with Tkinter. It has only been
12tested on Solaris 2.6. Feedback is greatly appreciated. Send email to
13bwarsaw@python.org
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000014
Barry Warsaw8a09e1c1998-10-20 20:45:46 +000015Usage: %(PROGRAM)s [-d file] [-i file] [-X] [-h] [initialcolor]
Barry Warsaw516f1891998-01-27 03:19:00 +000016
17Where:
Barry Warsaw04c78861998-09-28 16:28:04 +000018 --database file
19 -d file
20 Alternate location of a color database file
Barry Warsaweab81a91998-02-11 18:56:13 +000021
Barry Warsaw8a09e1c1998-10-20 20:45:46 +000022 --initfile file
23 -i file
24 Alternate location of the initialization file. This file contains a
25 persistent database of the current Pynche options and color. This
26 means that Pynche restores its option settings and current color when
27 it restarts, using this file (unless the -X option is used). The
28 default is ~/.pynche
29
30 --ignore
31 -X
32 Ignore the initialization file when starting up. Pynche will still
33 write the current option settings to this file when it quits.
34
Barry Warsaw516f1891998-01-27 03:19:00 +000035 --help
36 -h
37 print this message
38
Barry Warsaw04c78861998-09-28 16:28:04 +000039 initialcolor
40 initial color, as a color name or #RRGGBB format
41
Barry Warsaw516f1891998-01-27 03:19:00 +000042"""
43
44__version__ = '1.0'
45
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000046import sys
Barry Warsaw6bfd6551998-10-06 20:44:14 +000047import os
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000048import getopt
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000049import ColorDB
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000050from PyncheWidget import PyncheWidget
Barry Warsaw04c78861998-09-28 16:28:04 +000051from Switchboard import Switchboard
Barry Warsaw63c9e981998-09-28 23:41:53 +000052from StripViewer import StripViewer
Barry Warsaw4ab5d851998-10-01 16:47:06 +000053from ChipViewer import ChipViewer
54from TypeinViewer import TypeinViewer
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000055
56
57
58PROGRAM = sys.argv[0]
59
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000060# Default locations of rgb.txt or other textual color database
61RGB_TXT = [
62 # Solaris OpenWindows
63 '/usr/openwin/lib/rgb.txt',
Barry Warsaw6bfd6551998-10-06 20:44:14 +000064 # The X11R6.4 rgb.txt file
Barry Warsaw8a09e1c1998-10-20 20:45:46 +000065 os.path.join(sys.path[0], 'X/rgb.txt'),
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000066 # add more here
67 ]
68
69
70
71def usage(status, msg=''):
Barry Warsaw14e2caf1998-10-06 15:21:04 +000072 print __doc__ % globals()
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000073 if msg:
74 print msg
Barry Warsawf7c1e5a1998-01-31 23:39:28 +000075 sys.exit(status)
76
77
78
Barry Warsawe7f4a471998-10-06 19:50:33 +000079def initial_color(s, colordb):
80 # function called on every color
81 def scan_color(s, colordb=colordb):
82 try:
83 r, g, b = colordb.find_byname(s)
84 except ColorDB.BadColor:
85 try:
86 r, g, b = ColorDB.rrggbb_to_triplet(s)
87 except ColorDB.BadColor:
88 return None, None, None
89 return r, g, b
90 #
91 # First try the passed in color
92 r, g, b = scan_color(s)
93 if r is None:
94 # try the same color with '#' prepended, since some shells require
95 # this to be escaped, which is a pain
96 r, g, b = scan_color('#' + s)
97 if r is None:
98 print 'Bad initial color, using gray50:', s
99 r, g, b = scan_color('gray50')
100 if r is None:
101 usage(1, 'Cannot find an initial color to use')
102 # does not return
103 return r, g, b
104
105
106
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000107def main():
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000108 try:
Barry Warsaw04c78861998-09-28 16:28:04 +0000109 opts, args = getopt.getopt(
110 sys.argv[1:],
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000111 'hd:i:X',
112 ['database=', 'initfile=', 'ignore', 'help'])
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000113 except getopt.error, msg:
114 usage(1, msg)
115
Barry Warsaw04c78861998-09-28 16:28:04 +0000116 if len(args) == 0:
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000117 initialcolor = None
Barry Warsaw04c78861998-09-28 16:28:04 +0000118 elif len(args) == 1:
119 initialcolor = args[0]
120 else:
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000121 usage(1)
122
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000123 ignore = 0
124 initfile = os.path.expanduser('~/.pynche')
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000125 for opt, arg in opts:
126 if opt in ('-h', '--help'):
127 usage(0)
Barry Warsaw04c78861998-09-28 16:28:04 +0000128 elif opt in ('-d', '--database'):
129 RGB_TXT.insert(0, arg)
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000130 elif opt in ('-X', '--ignore'):
131 ignore = 1
132 elif opt in ('-i', '--initfile'):
133 initfile = arg
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000134
135 # create the windows and go
136 for f in RGB_TXT:
137 try:
138 colordb = ColorDB.get_colordb(f)
Barry Warsaw14e2caf1998-10-06 15:21:04 +0000139 if colordb:
140 break
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000141 except IOError:
142 pass
143 else:
Barry Warsaw14e2caf1998-10-06 15:21:04 +0000144 usage(1, 'No color database file found, see the -d option.')
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000145
Barry Warsaw63c9e981998-09-28 23:41:53 +0000146 # create all output widgets
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000147 s = Switchboard(colordb, not ignore and initfile)
Barry Warsaw4ab5d851998-10-01 16:47:06 +0000148
149 # create the application window decorations
150 app = PyncheWidget(__version__, s)
151 parent = app.parent()
152
Barry Warsaw63c9e981998-09-28 23:41:53 +0000153 s.add_view(StripViewer(s, parent))
Barry Warsaw4ab5d851998-10-01 16:47:06 +0000154 s.add_view(ChipViewer(s, parent))
155 s.add_view(TypeinViewer(s, parent))
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000156
157 # get the initial color as components and set the color on all views. if
158 # there was no initial color given on the command line, use the one that's
159 # stored in the option database
160 if initialcolor is None:
161 optiondb = s.optiondb()
162 red = optiondb.get('RED')
163 green = optiondb.get('GREEN')
164 blue = optiondb.get('BLUE')
165 # but if there wasn't any stored in the database, use grey50
166 if red is None or blue is None or green is None:
167 red, green, blue = initial_color('grey50', colordb)
168 else:
169 red, green, blue = initial_color(initialcolor, colordb)
Barry Warsaw63c9e981998-09-28 23:41:53 +0000170 s.update_views(red, green, blue)
171
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000172 try:
Barry Warsaw63c9e981998-09-28 23:41:53 +0000173 app.start()
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000174 except KeyboardInterrupt:
175 pass
176
Barry Warsaw8a09e1c1998-10-20 20:45:46 +0000177 # save the option database
178 s.save_views(initfile)
179
Barry Warsawf7c1e5a1998-01-31 23:39:28 +0000180
181
182if __name__ == '__main__':
183 main()