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