summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Tools/pynche/ChipViewer.py22
-rw-r--r--Tools/pynche/DetailsViewer.py12
-rw-r--r--Tools/pynche/ListViewer.py12
-rw-r--r--Tools/pynche/Main.py76
-rw-r--r--Tools/pynche/PyncheWidget.py104
-rw-r--r--Tools/pynche/StripViewer.py27
-rw-r--r--Tools/pynche/Switchboard.py20
-rw-r--r--Tools/pynche/TextViewer.py12
-rw-r--r--Tools/pynche/TypeinViewer.py4
-rw-r--r--Tools/pynche/pyColorChooser.py87
10 files changed, 256 insertions, 120 deletions
diff --git a/Tools/pynche/ChipViewer.py b/Tools/pynche/ChipViewer.py
index fbf9aad..5bd0bdf 100644
--- a/Tools/pynche/ChipViewer.py
+++ b/Tools/pynche/ChipViewer.py
@@ -23,7 +23,7 @@ class ChipWidget:
_HEIGHT = 80
def __init__(self,
- parent = None,
+ master = None,
width = _WIDTH,
height = _HEIGHT,
text = 'Color',
@@ -31,16 +31,16 @@ class ChipWidget:
presscmd = None,
releasecmd = None):
# create the text label
- self.__label = Label(parent, text=text)
+ self.__label = Label(master, text=text)
self.__label.grid(row=0, column=0)
# create the color chip, implemented as a frame
- self.__chip = Frame(parent, relief=RAISED, borderwidth=2,
+ self.__chip = Frame(master, relief=RAISED, borderwidth=2,
width=width,
height=height,
background=initialcolor)
self.__chip.grid(row=1, column=0)
# create the color name, ctor argument must be a string
- self.__name = Label(parent, text=initialcolor)
+ self.__name = Label(master, text=initialcolor)
self.__name.grid(row=2, column=0)
#
# set bindings
@@ -65,10 +65,10 @@ class ChipWidget:
class ChipViewer:
- def __init__(self, switchboard, parent=None):
+ def __init__(self, switchboard, master=None):
self.__sb = switchboard
- self.__frame = Frame(parent) #, relief=GROOVE, borderwidth=2)
- self.__frame.grid(row=3, column=0)
+ self.__frame = Frame(master, relief=RAISED, borderwidth=1)
+ self.__frame.grid(row=3, column=0, ipadx=5)
# create the chip that will display the currently selected color
# exactly
self.__sframe = Frame(self.__frame)
@@ -81,11 +81,6 @@ class ChipViewer:
self.__nearest = ChipWidget(self.__nframe, text='Nearest',
presscmd = self.__buttonpress,
releasecmd = self.__buttonrelease)
- self.__div = Frame(self.__frame,
- width=2,
- borderwidth=2,
- relief=RAISED)
- self.__div.grid(row=0, column=2, sticky='NS', padx=5)
def update_yourself(self, red, green, blue):
# TBD: should exactname default to X11 color name if their is an exact
@@ -110,6 +105,3 @@ class ChipViewer:
colorname = self.__nearest.get_color()
red, green, blue = self.__sb.colordb().find_byname(colorname)
self.__sb.update_views(red, green, blue)
-
- def save_options(self, optiondb):
- pass
diff --git a/Tools/pynche/DetailsViewer.py b/Tools/pynche/DetailsViewer.py
index da9bbf9..6996423 100644
--- a/Tools/pynche/DetailsViewer.py
+++ b/Tools/pynche/DetailsViewer.py
@@ -61,19 +61,19 @@ GRAV = 'Squash'
class DetailsViewer:
- def __init__(self, switchboard, parent=None):
+ def __init__(self, switchboard, master=None):
self.__sb = switchboard
optiondb = switchboard.optiondb()
self.__red, self.__green, self.__blue = switchboard.current_rgb()
# GUI
- root = self.__root = Toplevel(parent, class_='Pynche')
- root.protocol('WM_DELETE_WINDOW', self.__withdraw)
+ root = self.__root = Toplevel(master, class_='Pynche')
+ root.protocol('WM_DELETE_WINDOW', self.withdraw)
root.title('Pynche Details Window')
root.iconname('Pynche Details Window')
root.bind('<Alt-q>', self.__quit)
root.bind('<Alt-Q>', self.__quit)
- root.bind('<Alt-w>', self.__withdraw)
- root.bind('<Alt-W>', self.__withdraw)
+ root.bind('<Alt-w>', self.withdraw)
+ root.bind('<Alt-W>', self.withdraw)
# accelerators
root.bind('<KeyPress-Left>', self.__minus1)
root.bind('<KeyPress-Right>', self.__plus1)
@@ -158,7 +158,7 @@ class DetailsViewer:
def __quit(self, event=None):
self.__root.quit()
- def __withdraw(self, event=None):
+ def withdraw(self, event=None):
self.__root.withdraw()
def deiconify(self, event=None):
diff --git a/Tools/pynche/ListViewer.py b/Tools/pynche/ListViewer.py
index 9ba2a53..eb43a92 100644
--- a/Tools/pynche/ListViewer.py
+++ b/Tools/pynche/ListViewer.py
@@ -19,20 +19,20 @@ from Tkinter import *
import ColorDB
class ListViewer:
- def __init__(self, switchboard, parent=None):
+ def __init__(self, switchboard, master=None):
self.__sb = switchboard
optiondb = switchboard.optiondb()
self.__lastbox = None
self.__dontcenter = 0
# GUI
- root = self.__root = Toplevel(parent, class_='Pynche')
- root.protocol('WM_DELETE_WINDOW', self.__withdraw)
+ 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)
+ root.bind('<Alt-w>', self.withdraw)
+ root.bind('<Alt-W>', self.withdraw)
#
# create the canvas which holds everything, and its scrollbar
#
@@ -125,7 +125,7 @@ class ListViewer:
def __quit(self, event=None):
self.__root.quit()
- def __withdraw(self, event=None):
+ def withdraw(self, event=None):
self.__root.withdraw()
def deiconify(self, event=None):
diff --git a/Tools/pynche/Main.py b/Tools/pynche/Main.py
index bb5329e..f266a8d 100644
--- a/Tools/pynche/Main.py
+++ b/Tools/pynche/Main.py
@@ -104,34 +104,7 @@ def initial_color(s, colordb):
-def main():
- try:
- opts, args = getopt.getopt(
- sys.argv[1:],
- 'hd:i:X',
- ['database=', 'initfile=', 'ignore', 'help'])
- except getopt.error, msg:
- usage(1, msg)
-
- if len(args) == 0:
- initialcolor = None
- elif len(args) == 1:
- initialcolor = args[0]
- else:
- usage(1)
-
- ignore = 0
- initfile = os.path.expanduser('~/.pynche')
- for opt, arg in opts:
- if opt in ('-h', '--help'):
- usage(0)
- elif opt in ('-d', '--database'):
- RGB_TXT.insert(0, arg)
- elif opt in ('-X', '--ignore'):
- ignore = 1
- elif opt in ('-i', '--initfile'):
- initfile = arg
-
+def build(master=None, initialcolor=None, initfile=None, ignore=None):
# create the windows and go
for f in RGB_TXT:
try:
@@ -147,12 +120,12 @@ def main():
s = Switchboard(colordb, not ignore and initfile)
# create the application window decorations
- app = PyncheWidget(__version__, s)
- parent = app.parent()
+ app = PyncheWidget(__version__, s, master=master)
+ w = app.window()
- s.add_view(StripViewer(s, parent))
- s.add_view(ChipViewer(s, parent))
- s.add_view(TypeinViewer(s, parent))
+ 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
@@ -168,15 +141,48 @@ def main():
else:
red, green, blue = initial_color(initialcolor, colordb)
s.update_views(red, green, blue)
+ return app, s
+
+def run(app, s):
try:
app.start()
except KeyboardInterrupt:
pass
-
# save the option database
- s.save_views(initfile)
+ s.save_views()
+
+
+
+def main():
+ try:
+ opts, args = getopt.getopt(
+ sys.argv[1:],
+ 'hd:i:X',
+ ['database=', 'initfile=', 'ignore', 'help'])
+ except getopt.error, msg:
+ usage(1, msg)
+
+ if len(args) == 0:
+ initialcolor = None
+ elif len(args) == 1:
+ initialcolor = args[0]
+ else:
+ usage(1)
+
+ ignore = 0
+ initfile = os.path.expanduser('~/.pynche')
+ for opt, arg in opts:
+ if opt in ('-h', '--help'):
+ usage(0)
+ elif opt in ('-d', '--database'):
+ RGB_TXT.insert(0, arg)
+ elif opt in ('-X', '--ignore'):
+ ignore = 1
+ elif opt in ('-i', '--initfile'):
+ initfile = arg
+ run()
if __name__ == '__main__':
diff --git a/Tools/pynche/PyncheWidget.py b/Tools/pynche/PyncheWidget.py
index 4052357..fcabd24 100644
--- a/Tools/pynche/PyncheWidget.py
+++ b/Tools/pynche/PyncheWidget.py
@@ -13,36 +13,46 @@ KEEPALIVE_TIMER = 500
class PyncheWidget:
- def __init__(self, version, switchboard):
+ def __init__(self, version, switchboard, master=None):
self.__sb = switchboard
self.__version = version
self.__textwin = None
self.__listwin = None
self.__detailswin = None
- #
- # Is there already a default root for Tk, say because we're running
- # under Guido's IDE? :-) Two conditions say no, either the import
- # fails or _default_root is None.
- tkroot = None
- try:
- from Tkinter import _default_root
- tkroot = self.__tkroot = _default_root
- except ImportError:
- pass
- if not tkroot:
- tkroot = self.__tkroot = Tk(className='Pynche')
- # but this isn't our top level widget, so make it invisible
- tkroot.withdraw()
+ modal = self.__modal = not not master
+ # If a master was given, we are running as a modal dialog servant to
+ # some other application. We rearrange our UI in this case (there's
+ # no File menu and we get `Okay' and `Cancel' buttons), and we do a
+ # grab_set() to make ourselves modal
+ if modal:
+ self.__tkroot = tkroot = Toplevel(master, class_='Pynche')
+ tkroot.grab_set()
+ tkroot.withdraw()
+ else:
+ # Is there already a default root for Tk, say because we're
+ # running under Guido's IDE? :-) Two conditions say no, either the
+ # import fails or _default_root is None.
+ tkroot = None
+ try:
+ from Tkinter import _default_root
+ tkroot = self.__tkroot = _default_root
+ except ImportError:
+ pass
+ if not tkroot:
+ tkroot = self.__tkroot = Tk(className='Pynche')
+ # but this isn't our top level widget, so make it invisible
+ tkroot.withdraw()
# create the menubar
menubar = self.__menubar = Menu(tkroot)
#
# File menu
#
- filemenu = self.__filemenu = Menu(menubar, tearoff=0)
- filemenu.add_command(label='Quit',
- command=self.__quit,
- accelerator='Alt-Q',
- underline=0)
+ if not modal:
+ filemenu = self.__filemenu = Menu(menubar, tearoff=0)
+ filemenu.add_command(label='Quit',
+ command=self.__quit,
+ accelerator='Alt-Q',
+ underline=0)
#
# View menu
#
@@ -66,9 +76,10 @@ class PyncheWidget:
#
# Tie them all together
#
- menubar.add_cascade(label='File',
- menu=filemenu,
- underline=0)
+ if not modal:
+ menubar.add_cascade(label='File',
+ menu=filemenu,
+ underline=0)
menubar.add_cascade(label='View',
menu=viewmenu,
underline=0)
@@ -78,15 +89,44 @@ class PyncheWidget:
# now create the top level window
root = self.__root = Toplevel(tkroot, class_='Pynche', menu=menubar)
- root.protocol('WM_DELETE_WINDOW', self.__quit)
+ root.protocol('WM_DELETE_WINDOW',
+ modal and self.__beep or self.__quit)
root.title('Pynche %s' % version)
root.iconname('Pynche')
- root.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
- root.bind('<Alt-q>', self.__quit)
- root.bind('<Alt-Q>', self.__quit)
+ # Only bind accelerators for the File->Quit menu item if running as a
+ # standalone app
+ if not modal:
+ root.bind('<Alt-q>', self.__quit)
+ root.bind('<Alt-Q>', self.__quit)
+ else:
+ # We're a modal dialog so we have a new row of buttons
+ bframe = Frame(root, borderwidth=1, relief=RAISED)
+ bframe.grid(row=4, column=0, columnspan=2,
+ sticky='EW',
+ ipady=5)
+ okay = Button(bframe,
+ text='Okay',
+ command=self.__okay)
+ okay.pack(side=LEFT, expand=1)
+ cancel = Button(bframe,
+ text='Cancel',
+ command=self.__cancel)
+ cancel.pack(side=LEFT, expand=1)
def __quit(self, event=None):
- self.__root.quit()
+ self.__tkroot.quit()
+
+ def __beep(self, event=None):
+ self.__tkroot.beep()
+
+ def __okay(self, event=None):
+ self.__sb.withdraw_views()
+ self.__tkroot.grab_release()
+ self.__quit()
+
+ def __cancel(self, event=None):
+ self.__sb.canceled()
+ self.__okay()
def __keepalive(self):
# Exercise the Python interpreter regularly so keyboard interrupts get
@@ -94,10 +134,11 @@ class PyncheWidget:
self.__tkroot.tk.createtimerhandler(KEEPALIVE_TIMER, self.__keepalive)
def start(self):
- self.__keepalive()
+ if not self.__modal:
+ self.__keepalive()
self.__tkroot.mainloop()
- def parent(self):
+ def window(self):
return self.__root
def __popup_about(self, event=None):
@@ -135,3 +176,6 @@ email : bwarsaw@python.org''' % __version__)
self.__detailswin = DetailsViewer(self.__sb, self.__root)
self.__sb.add_view(self.__detailswin)
self.__detailswin.deiconify()
+
+ def withdraw(self):
+ self.__root.withdraw()
diff --git a/Tools/pynche/StripViewer.py b/Tools/pynche/StripViewer.py
index 7bbfcca..f085fec 100644
--- a/Tools/pynche/StripViewer.py
+++ b/Tools/pynche/StripViewer.py
@@ -147,7 +147,7 @@ class StripWidget:
_NUMCHIPS = 40
def __init__(self, switchboard,
- parent = None,
+ master = None,
chipwidth = _CHIPWIDTH,
chipheight = _CHIPHEIGHT,
numchips = _NUMCHIPS,
@@ -171,13 +171,12 @@ class StripWidget:
canvasheight = chipheight + 43 # TBD: Kludge
# create the canvas and pack it
- canvas = self.__canvas = Canvas(
- parent,
- width=canvaswidth,
- height=canvasheight,
-## borderwidth=2,
-## relief=GROOVE
- )
+ canvas = self.__canvas = Canvas(master,
+ width=canvaswidth,
+ height=canvasheight,
+## borderwidth=2,
+## relief=GROOVE
+ )
canvas.pack()
canvas.bind('<ButtonPress-1>', self.__select_chip)
@@ -296,11 +295,11 @@ class StripWidget:
class StripViewer:
- def __init__(self, switchboard, parent=None):
+ def __init__(self, switchboard, master=None):
self.__sb = switchboard
optiondb = switchboard.optiondb()
- # create a frame inside the parent
- self.__frame = Frame(parent) #, relief=GROOVE, borderwidth=2)
+ # create a frame inside the master
+ self.__frame = Frame(master, relief=RAISED, borderwidth=1)
self.__frame.grid(row=1, column=0, columnspan=2, sticky='EW')
uwd = self.__uwdvar = BooleanVar()
uwd.set(optiondb.get('UPWHILEDRAG', 0))
@@ -338,12 +337,6 @@ class StripViewer:
command=self.__togglehex)
self.__hex.grid(row=1, column=0, sticky=W)
- self.__div = Frame(self.__frame,
- height=2,
- borderwidth=2,
- relief=RAISED)
- self.__div.pack(expand=1, fill=X)
-
def update_yourself(self, red, green, blue):
self.__reds.update_yourself(red, green, blue)
self.__greens.update_yourself(red, green, blue)
diff --git a/Tools/pynche/Switchboard.py b/Tools/pynche/Switchboard.py
index 7ac3df1..d8fd14c 100644
--- a/Tools/pynche/Switchboard.py
+++ b/Tools/pynche/Switchboard.py
@@ -17,12 +17,14 @@ import marshal
class Switchboard:
def __init__(self, colordb, initfile):
+ self.__initfile = initfile
self.__colordb = colordb
self.__optiondb = {}
self.__views = []
self.__red = 0
self.__green = 0
self.__blue = 0
+ self.__canceled = 0
# read the initialization file
fp = None
if initfile:
@@ -61,17 +63,18 @@ class Switchboard:
def optiondb(self):
return self.__optiondb
- def save_views(self, file):
+ def save_views(self):
# save the current color
self.__optiondb['RED'] = self.__red
self.__optiondb['GREEN'] = self.__green
self.__optiondb['BLUE'] = self.__blue
for v in self.__views:
- v.save_options(self.__optiondb)
+ if hasattr(v, 'save_options'):
+ v.save_options(self.__optiondb)
fp = None
try:
try:
- fp = open(file, 'w')
+ fp = open(self.__initfile, 'w')
except IOError:
print 'Cannot write options to file:', file
else:
@@ -79,3 +82,14 @@ class Switchboard:
finally:
if fp:
fp.close()
+
+ def withdraw_views(self):
+ for v in self.__views:
+ if hasattr(v, 'withdraw'):
+ v.withdraw()
+
+ def canceled(self):
+ self.__canceled = 1
+
+ def canceled_p(self):
+ return self.__canceled
diff --git a/Tools/pynche/TextViewer.py b/Tools/pynche/TextViewer.py
index 7e8cec5..a3e9ac5 100644
--- a/Tools/pynche/TextViewer.py
+++ b/Tools/pynche/TextViewer.py
@@ -19,17 +19,17 @@ from Tkinter import *
import ColorDB
class TextViewer:
- def __init__(self, switchboard, parent=None):
+ def __init__(self, switchboard, master=None):
self.__sb = switchboard
optiondb = switchboard.optiondb()
- root = self.__root = Toplevel(parent, class_='Pynche')
- root.protocol('WM_DELETE_WINDOW', self.__withdraw)
+ root = self.__root = Toplevel(master, class_='Pynche')
+ root.protocol('WM_DELETE_WINDOW', self.withdraw)
root.title('Pynche Text Window')
root.iconname('Pynche Text Window')
root.bind('<Alt-q>', self.__quit)
root.bind('<Alt-Q>', self.__quit)
- root.bind('<Alt-w>', self.__withdraw)
- root.bind('<Alt-W>', self.__withdraw)
+ root.bind('<Alt-w>', self.withdraw)
+ root.bind('<Alt-W>', self.withdraw)
#
# create the text widget
#
@@ -114,7 +114,7 @@ and choosing a color.'''))
def __quit(self, event=None):
self.__root.quit()
- def __withdraw(self, event=None):
+ def withdraw(self, event=None):
self.__root.withdraw()
def deiconify(self, event=None):
diff --git a/Tools/pynche/TypeinViewer.py b/Tools/pynche/TypeinViewer.py
index 13cb9c7..d10d2a9 100644
--- a/Tools/pynche/TypeinViewer.py
+++ b/Tools/pynche/TypeinViewer.py
@@ -17,7 +17,7 @@ import string
import re
class TypeinViewer:
- def __init__(self, switchboard, parent=None):
+ def __init__(self, switchboard, master=None):
# non-gui ivars
self.__sb = switchboard
optiondb = switchboard.optiondb()
@@ -26,7 +26,7 @@ class TypeinViewer:
self.__uwtyping = BooleanVar()
self.__uwtyping.set(optiondb.get('UPWHILETYPE', 0))
# create the gui
- self.__frame = Frame(parent) #, relief=GROOVE, borderwidth=2)
+ self.__frame = Frame(master, relief=RAISED, borderwidth=1)
self.__frame.grid(row=3, column=1, sticky='NS')
# Red
self.__xl = Label(self.__frame, text='Red:')
diff --git a/Tools/pynche/pyColorChooser.py b/Tools/pynche/pyColorChooser.py
new file mode 100644
index 0000000..f2dc6ac
--- /dev/null
+++ b/Tools/pynche/pyColorChooser.py
@@ -0,0 +1,87 @@
+"""Color chooser implementing (almost) the tkColorColor interface
+"""
+
+import os
+from PyncheWidget import PyncheWidget
+import Main
+import ColorDB
+
+class Chooser:
+ """Ask for a color"""
+ def __init__(self,
+ master = None,
+ initialcolor = None,
+ databasefile = None,
+ initfile = None,
+ ignore = None):
+ self.__master = master
+ self.__initialcolor = initialcolor
+ self.__databasefile = databasefile
+ self.__initfile = initfile or os.path.expanduser('~/.pynche')
+ self.__ignore = ignore
+ self.__pw = None
+
+ def show(self):
+ if not self.__pw:
+ self.__pw, self.__sb = \
+ Main.build(master = self.__master,
+ initialcolor = self.__initialcolor,
+ initfile = self.__initfile,
+ ignore = self.__ignore)
+ 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
+ colordb = self.__sb.colordb()
+ # try to return the color name from the database if there is an exact
+ # match, otherwise use the "#rrggbb" spec. TBD: Forget about color
+ # aliases for now, maybe later we should return these too.
+ try:
+ name = colordb.find_byrgb(rgbtuple)[0]
+ except ColorDB.BadColor:
+ name = ColorDB.triplet_to_rrggbb(rgbtuple)
+ return rgbtuple, name
+
+
+
+# convenience stuff
+def askcolor(color = None, **options):
+ """Ask for a color"""
+ return apply(Chooser, (), options).show()
+
+
+
+# test stuff
+if __name__ == '__main__':
+ class Tester:
+ def __init__(self):
+ from Tkinter import *
+ self.__root = tk = Tk()
+ b = Button(tk, text='Choose Color...', command=self.__choose)
+ b.pack()
+ self.__l = Label(tk)
+ self.__l.pack()
+ q = Button(tk, text='Quit', command=self.__quit)
+ q.pack()
+
+ def __choose(self, event=None):
+ rgb, name = askcolor(master=self.__root)
+ if rgb is None:
+ text = 'You hit CANCEL!'
+ else:
+ r, g, b = rgb
+ text = 'You picked %s (%3d/%3d/%3d)' % (name, r, g, b)
+ self.__l.configure(text=text)
+
+ def __quit(self, event=None):
+ self.__root.quit()
+
+ def run(self):
+ self.__root.mainloop()
+ t = Tester()
+ t.run()
+ # simpler
+## print 'color:', askcolor()
+## print 'color:', askcolor()