def update_yourself(self, red, green, blue): # Selected always shows the #rrggbb name of the color, nearest always # shows the name of the nearest color in the database. TBD: should # an exact match be indicated in some way? # # Always use the #rrggbb style to actually set the color, since we may # not be using X color names (e.g. "web-safe" names) colordb = self.__sb.colordb() rgbtuple = (red, green, blue) rrggbb = ColorDB.triplet_to_rrggbb(rgbtuple) # find the nearest nearest = colordb.nearest(red, green, blue) nearest_tuple = colordb.find_byname(nearest) nearest_rrggbb = ColorDB.triplet_to_rrggbb(nearest_tuple) self.__selected.set_color(rrggbb) self.__nearest.set_color(nearest_rrggbb, nearest)
def __onrelease(self, event=None): canvas = self.__canvas # find the current box x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) ids = canvas.find_overlapping(x, y, x, y) for boxid in ids: if boxid in self.__bboxes: break else: ## print 'No box found!' return tags = self.__canvas.gettags(boxid) for t in tags: if t[0] == '#': break else: ## print 'No color tag found!' return red, green, blue = ColorDB.rrggbb_to_triplet(t) self.__dontcenter = 1 if self.__uoc.get(): self.__sb.update_views(red, green, blue) else: self.update_yourself(red, green, blue) self.__red, self.__green, self.__blue = red, green, blue
def update_yourself(self, red, green, blue): canvas = self.__canvas # turn off the last box if self.__lastbox: canvas.itemconfigure(self.__lastbox, outline='') # turn on the current box colortag = ColorDB.triplet_to_rrggbb((red, green, blue)) canvas.itemconfigure(colortag, outline='black') self.__lastbox = colortag # fill the aliases self.__aliases.delete(0, END) try: aliases = self.__sb.colordb().aliases_of(red, green, blue)[1:] except ColorDB.BadColor: self.__aliases.insert(END, '<no matching color>') return if not aliases: self.__aliases.insert(END, '<no aliases>') else: for name in aliases: self.__aliases.insert(END, name) # maybe scroll the canvas so that the item is visible if self.__dontcenter: self.__dontcenter = 0 else: height = canvas['height'] ig, ig, ig, y1 = canvas.coords(colortag) ig, ig, ig, y2 = canvas.coords(self.__bboxes[-1]) h = int(canvas['height']) * 0.5 canvas.yview('moveto', (y1-h) / y2)
def __populate(self): # # create all the buttons colordb = self.__sb.colordb() canvas = self.__canvas row = 0 widest = 0 bboxes = self.__bboxes = [] for name in colordb.unique_names(): exactcolor = ColorDB.triplet_to_rrggbb(colordb.find_byname(name)) canvas.create_rectangle(5, row*20 + 5, 20, row*20 + 20, fill=exactcolor) textid = canvas.create_text(25, row*20 + 13, text=name, anchor=W) x1, y1, textend, y2 = canvas.bbox(textid) boxid = canvas.create_rectangle(3, row*20+3, textend+3, row*20 + 23, outline='', tags=(exactcolor, 'all')) canvas.bind('<ButtonRelease>', self.__onrelease) bboxes.append(boxid) if textend+3 > widest: widest = textend+3 row = row + 1 canvheight = (row-1)*20 + 25 canvas.config(scrollregion=(0, 0, 150, canvheight)) for box in bboxes: x1, y1, x2, y2 = canvas.coords(box) canvas.coords(box, x1, y1, widest, y2)
def __load(self, event=None): while 1: idir, ifile = os.path.split(self.__sb.colordb().filename()) file = tkFileDialog.askopenfilename( filetypes=[('Text files', '*.txt'), ('All files', '*'), ], initialdir=idir, initialfile=ifile) if not file: # cancel button return try: colordb = ColorDB.get_colordb(file) except IOError: tkMessageBox.showerror('Read error', '''\ Could not open file for reading: %s''' % file) continue if colordb is None: tkMessageBox.showerror('Unrecognized color file type', '''\ Unrecognized color file type in file: %s''' % file) continue break self.__sb.set_colordb(colordb)
def __trackarrow(self, chip, rgbtuple): # invert the last chip if self.__lastchip is not None: color = self.__canvas.itemcget(self.__lastchip, 'fill') self.__canvas.itemconfigure(self.__lastchip, outline=color) self.__lastchip = chip # get the arrow's text coloraxis = rgbtuple[self.__axis] if self.__hexp.get(): # hex text = hex(coloraxis) else: # decimal text = repr(coloraxis) # move the arrow, and set it's text if coloraxis <= 128: # use the left arrow self.__leftarrow.set_text(text) self.__leftarrow.move_to(self.__arrow_x(chip-1)) self.__rightarrow.move_to(-100) else: # use the right arrow self.__rightarrow.set_text(text) self.__rightarrow.move_to(self.__arrow_x(chip-1)) self.__leftarrow.move_to(-100) # and set the chip's outline brightness = ColorDB.triplet_to_brightness(rgbtuple) if brightness <= 128: outline = 'white' else: outline = 'black' self.__canvas.itemconfigure(chip, outline=outline)
def __load(self, event=None): while 1: idir, ifile = os.path.split(self.__sb.colordb().filename()) file = filedialog.askopenfilename( filetypes=[('Text files', '*.txt'), ('All files', '*'), ], initialdir=idir, initialfile=ifile) if not file: # cancel button return try: colordb = ColorDB.get_colordb(file) except IOError: messagebox.showerror('Read error', '''\ Could not open file for reading: %s''' % file) continue if colordb is None: messagebox.showerror('Unrecognized color file type', '''\ Unrecognized color file type in file: %s''' % file) continue break self.__sb.set_colordb(colordb)
def __trackarrow(self, chip, rgbtuple): # invert the last chip if self.__lastchip is not None: color = self.__canvas.itemcget(self.__lastchip, 'fill') self.__canvas.itemconfigure(self.__lastchip, outline=color) self.__lastchip = chip # get the arrow's text coloraxis = rgbtuple[self.__axis] if self.__hexp.get(): # hex text = hex(coloraxis) else: # decimal text = repr(coloraxis) # move the arrow, and set its text if coloraxis <= 128: # use the left arrow self.__leftarrow.set_text(text) self.__leftarrow.move_to(self.__arrow_x(chip - 1)) self.__rightarrow.move_to(-100) else: # use the right arrow self.__rightarrow.set_text(text) self.__rightarrow.move_to(self.__arrow_x(chip - 1)) self.__leftarrow.move_to(-100) # and set the chip's outline brightness = ColorDB.triplet_to_brightness(rgbtuple) if brightness <= 128: outline = 'white' else: outline = 'black' self.__canvas.itemconfigure(chip, outline=outline)
def update_yourself(self, red, green, blue): canvas = self.__canvas # turn off the last box if self.__lastbox: canvas.itemconfigure(self.__lastbox, outline='') # turn on the current box colortag = ColorDB.triplet_to_rrggbb((red, green, blue)) canvas.itemconfigure(colortag, outline='black') self.__lastbox = colortag # fill the aliases self.__aliases.delete(0, END) try: aliases = self.__sb.colordb().aliases_of(red, green, blue)[1:] except ColorDB.BadColor: self.__aliases.insert(END, '<no matching color>') return if not aliases: self.__aliases.insert(END, '<no aliases>') else: for name in aliases: self.__aliases.insert(END, name) # maybe scroll the canvas so that the item is visible if self.__dontcenter: self.__dontcenter = 0 else: ig, ig, ig, y1 = canvas.coords(colortag) ig, ig, ig, y2 = canvas.coords(self.__bboxes[-1]) h = int(canvas['height']) * 0.5 canvas.yview('moveto', (y1-h) / y2)
def __populate(self): # # create all the buttons colordb = self.__sb.colordb() canvas = self.__canvas row = 0 widest = 0 bboxes = self.__bboxes = [] for name in colordb.unique_names(): exactcolor = ColorDB.triplet_to_rrggbb(colordb.find_byname(name)) canvas.create_rectangle(5, row*20 + 5, 20, row*20 + 20, fill=exactcolor) textid = canvas.create_text(25, row*20 + 13, text=name, anchor=W) x1, y1, textend, y2 = canvas.bbox(textid) boxid = canvas.create_rectangle(3, row*20+3, textend+3, row*20 + 23, outline='', tags=(exactcolor, 'all')) canvas.bind('<ButtonRelease>', self.__onrelease) bboxes.append(boxid) if textend+3 > widest: widest = textend+3 row += 1 canvheight = (row-1)*20 + 25 canvas.config(scrollregion=(0, 0, 150, canvheight)) for box in bboxes: x1, y1, x2, y2 = canvas.coords(box) canvas.coords(box, x1, y1, widest, y2)
def build(master=None, initialcolor=None, initfile=None, ignore=None): # create all output widgets s = Switchboard(not ignore and initfile) # load the color database colordb = None try: dbfile = s.optiondb()['DBFILE'] colordb = ColorDB.get_colordb(dbfile) except (KeyError, IOError): # scoot through the files listed above to try to find a usable color # database file for f in RGB_TXT: try: colordb = ColorDB.get_colordb(f) if colordb: break except IOError: pass 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 show(self, color, options): # scan for options that can override the ctor options self.__wantspec = options.get('wantspec', self.__wantspec) dbfile = options.get('databasefile', self.__databasefile) # load the database file colordb = None if dbfile <> self.__databasefile: colordb = ColorDB.get_colordb(dbfile) if not self.__master: from Tkinter import Tk self.__master = Tk() if not self.__pw: self.__pw, self.__sb = \ Main.build(master = self.__master, initfile = self.__initfile, ignore = self.__ignore) else: self.__pw.deiconify() # convert color if colordb: self.__sb.set_colordb(colordb) else: colordb = self.__sb.colordb() if color: r, g, b = Main.initial_color(color, colordb) self.__sb.update_views(r, g, b) # reset the canceled flag and run it self.__sb.canceled(0) Main.run(self.__pw, self.__sb) rgbtuple = self.__sb.current_rgb() self.__pw.withdraw() # check to see if the cancel button was pushed if self.__sb.canceled_p(): return None, None # Try to return the color name from the database if there is an exact # match, otherwise use the "#rrggbb" spec. BAW: Forget about color # aliases for now, maybe later we should return these too. name = None if not self.__wantspec: try: name = colordb.find_byrgb(rgbtuple)[0] except ColorDB.BadColor: pass if name is None: name = ColorDB.triplet_to_rrggbb(rgbtuple) return rgbtuple, name
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
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 update_yourself(self, red, green, blue): # TBD: should exactname default to X11 color name if their is an exact # match for the rgb triplet? Part of me says it's nice to see both # names for the color, the other part says that it's better to # feedback the exact match. rgbtuple = (red, green, blue) try: allcolors = self.__sb.colordb().find_byrgb(rgbtuple) exactname = allcolors[0] except ColorDB.BadColor: exactname = ColorDB.triplet_to_rrggbb(rgbtuple) nearest = self.__sb.colordb().nearest(red, green, blue) self.__selected.set_color(exactname) self.__nearest.set_color(nearest)
def update_yourself(self, red, green, blue): if self.__trackp.get(): colorname = ColorDB.triplet_to_rrggbb((red, green, blue)) which = self.__which.get() if which == 0: self.__text.configure(foreground=colorname) elif which == 1: self.__text.configure(background=colorname) elif which == 2: self.__text.configure(selectforeground=colorname) elif which == 3: self.__text.configure(selectbackground=colorname) elif which == 5: self.__text.configure(insertbackground=colorname)
def __select_chip(self, event=None): x = event.x y = event.y canvas = self.__canvas chip = canvas.find_overlapping(x, y, x, y) if chip and (1 <= chip[0] <= self.__numchips): color = self.__chips[chip[0] - 1] red, green, blue = ColorDB.rrggbb_to_triplet(color) etype = int(event.type) if (etype == BTNUP or self.__uwd.get()): # update everyone self.__sb.update_views(red, green, blue) else: # just track the arrows self.__trackarrow(chip[0], (red, green, blue))
def __select_chip(self, event=None): x = event.x y = event.y canvas = self.__canvas chip = canvas.find_overlapping(x, y, x, y) if chip and (1 <= chip[0] <= self.__numchips): color = self.__chips[chip[0]-1] red, green, blue = ColorDB.rrggbb_to_triplet(color) etype = int(event.type) if (etype == BTNUP or self.__uwd.get()): # update everyone self.__sb.update_views(red, green, blue) else: # just track the arrows self.__trackarrow(chip[0], (red, green, blue))
def __set_color(self, event=None): which = self.__which.get() text = self.__text if which == 0: color = text['foreground'] elif which == 1: color = text['background'] elif which == 2: color = text['selectforeground'] elif which == 3: color = text['selectbackground'] elif which == 5: color = text['insertbackground'] try: red, green, blue = ColorDB.rrggbb_to_triplet(color) except ColorDB.BadColor: # must have been a color name red, green, blue = self.__sb.colordb().find_byname(color) self.__sb.update_views(red, green, blue)
def update_yourself(self, red, green, blue): assert self.__generator i = 1 chip = 0 chips = self.__chips = [] tk = self.__canvas.tk # get the red, green, and blue components for all chips for t in self.__generator(self.__numchips, red, green, blue): rrggbb = ColorDB.triplet_to_rrggbb(t) chips.append(rrggbb) tred, tgreen, tblue = t if tred <= red and tgreen <= green and tblue <= blue: chip = i i = i + 1 # call the raw tcl script colors = SPACE.join(chips) tk.eval('setcolor %s {%s}' % (self.__canvas._w, colors)) # move the arrows around self.__trackarrow(chip, (red, green, blue))
def build(master=None, initialcolor=None, initfile=None, ignore=None): # create the windows and go for f in RGB_TXT: try: colordb = ColorDB.get_colordb(f) if colordb: break except IOError: pass else: usage(1, 'No color database file found, see the -d option.') # create all output widgets s = Switchboard(colordb, not ignore and initfile) # create the application window decorations app = PyncheWidget(__version__, s, master=master) w = app.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 __init__(self, switchboard, master=None): self.__sb = switchboard optiondb = switchboard.optiondb() self.__lastbox = None self.__dontcenter = 0 # GUI root = self.__root = Toplevel(master, class_='Pynche') root.protocol('WM_DELETE_WINDOW', self.withdraw) root.title('Pynche Color List') root.iconname('Pynche Color List') root.bind('<Alt-q>', self.__quit) root.bind('<Alt-Q>', self.__quit) root.bind('<Alt-w>', self.withdraw) root.bind('<Alt-W>', self.withdraw) # # create the canvas which holds everything, and its scrollbar # frame = self.__frame = Frame(root) frame.pack() canvas = self.__canvas = Canvas(frame, width=160, height=300, borderwidth=2, relief=SUNKEN) self.__scrollbar = Scrollbar(frame) self.__scrollbar.pack(fill=Y, side=RIGHT) canvas.pack(fill=BOTH, expand=1) canvas.configure(yscrollcommand=(self.__scrollbar, 'set')) self.__scrollbar.configure(command=(canvas, 'yview')) # # create all the buttons colordb = switchboard.colordb() row = 0 widest = 0 bboxes = self.__bboxes = [] for name in colordb.unique_names(): exactcolor = ColorDB.triplet_to_rrggbb(colordb.find_byname(name)) canvas.create_rectangle(5, row*20 + 5, 20, row*20 + 20, fill=exactcolor) textid = canvas.create_text(25, row*20 + 13, text=name, anchor=W) x1, y1, textend, y2 = canvas.bbox(textid) boxid = canvas.create_rectangle(3, row*20+3, textend+3, row*20 + 23, outline='', tags=(exactcolor,)) canvas.bind('<ButtonRelease>', self.__onrelease) bboxes.append(boxid) if textend+3 > widest: widest = textend+3 row = row + 1 canvheight = (row-1)*20 + 25 canvas.config(scrollregion=(0, 0, 150, canvheight)) for box in bboxes: x1, y1, x2, y2 = canvas.coords(box) canvas.coords(box, x1, y1, widest, y2) # # Update on click self.__uoc = BooleanVar() self.__uoc.set(optiondb.get('UPONCLICK', 1)) self.__uocbtn = Checkbutton(root, text='Update on Click', variable=self.__uoc, command=self.__toggleupdate) self.__uocbtn.pack(expand=1, fill=BOTH) # # alias list self.__alabel = Label(root, text='Aliases:') self.__alabel.pack() self.__aliases = Listbox(root, height=5, selectmode=BROWSE) self.__aliases.pack(expand=1, fill=BOTH)
"""Strip viewer and related widgets.
"""ListViewer class.
"""TextViewer class.
"""Chip viewer and widget.
"""Color chooser implementing (almost) the tkColorColor interface
def __init__(self, switchboard, master=None): self.__sb = switchboard optiondb = switchboard.optiondb() self.__lastbox = None self.__dontcenter = 0 # GUI root = self.__root = Toplevel(master, class_='Pynche') root.protocol('WM_DELETE_WINDOW', self.withdraw) root.title('Pynche Color List') root.iconname('Pynche Color List') root.bind('<Alt-q>', self.__quit) root.bind('<Alt-Q>', self.__quit) root.bind('<Alt-w>', self.withdraw) root.bind('<Alt-W>', self.withdraw) # # create the canvas which holds everything, and its scrollbar # frame = self.__frame = Frame(root) frame.pack() canvas = self.__canvas = Canvas(frame, width=160, height=300, borderwidth=2, relief=SUNKEN) self.__scrollbar = Scrollbar(frame) self.__scrollbar.pack(fill=Y, side=RIGHT) canvas.pack(fill=BOTH, expand=1) canvas.configure(yscrollcommand=(self.__scrollbar, 'set')) self.__scrollbar.configure(command=(canvas, 'yview')) # # create all the buttons colordb = switchboard.colordb() row = 0 widest = 0 bboxes = self.__bboxes = [] for name in colordb.unique_names(): exactcolor = ColorDB.triplet_to_rrggbb(colordb.find_byname(name)) canvas.create_rectangle(5, row * 20 + 5, 20, row * 20 + 20, fill=exactcolor) textid = canvas.create_text(25, row * 20 + 13, text=name, anchor=W) x1, y1, textend, y2 = canvas.bbox(textid) boxid = canvas.create_rectangle(3, row * 20 + 3, textend + 3, row * 20 + 23, outline='', tags=(exactcolor, )) canvas.bind('<ButtonRelease>', self.__onrelease) bboxes.append(boxid) if textend + 3 > widest: widest = textend + 3 row = row + 1 canvheight = (row - 1) * 20 + 25 canvas.config(scrollregion=(0, 0, 150, canvheight)) for box in bboxes: x1, y1, x2, y2 = canvas.coords(box) canvas.coords(box, x1, y1, widest, y2) # # Update on click self.__uoc = BooleanVar() self.__uoc.set(optiondb.get('UPONCLICK', 1)) self.__uocbtn = Checkbutton(root, text='Update on Click', variable=self.__uoc, command=self.__toggleupdate) self.__uocbtn.pack(expand=1, fill=BOTH) # # alias list self.__alabel = Label(root, text='Aliases:') self.__alabel.pack() self.__aliases = Listbox(root, height=5, selectmode=BROWSE) self.__aliases.pack(expand=1, fill=BOTH)
"""Pynche -- The PYthon Natural Color and Hue Editor.
"""Main Pynche (Pythonically Natural Color and Hue Editor) widget.
def __buttonrelease(self, event=None): self.__nearest.release() rrggbb = self.__nearest.get_color() red, green, blue = ColorDB.rrggbb_to_triplet(rrggbb) self.__sb.update_views(red, green, blue)