Fix an amazing number of typos & malformed sentences reported by Detlef
[python/dscho.git] / Tools / pynche / ListViewer.py
blobeb43a928607424c67cdec3180616002febf773dd
1 """ListViewer class.
3 This class implements an input/output view on the color model. It lists every
4 unique color (e.g. unique r/g/b value) found in the color database. Each
5 color is shown by small swatch and primary color name. Some colors have
6 aliases -- more than one name for the same r/g/b value. These aliases are
7 displayed in the small listbox at the bottom of the screen.
9 Clicking on a color name or swatch selects that color and updates all other
10 windows. When a color is selected in a different viewer, the color list is
11 scrolled to the selected color and it is highlighted. If the selected color
12 is an r/g/b value without a name, no scrolling occurs.
14 You can turn off Update On Click if all you want to see is the alias for a
15 given name, without selecting the color.
16 """
18 from Tkinter import *
19 import ColorDB
21 class ListViewer:
22 def __init__(self, switchboard, master=None):
23 self.__sb = switchboard
24 optiondb = switchboard.optiondb()
25 self.__lastbox = None
26 self.__dontcenter = 0
27 # GUI
28 root = self.__root = Toplevel(master, class_='Pynche')
29 root.protocol('WM_DELETE_WINDOW', self.withdraw)
30 root.title('Pynche Color List')
31 root.iconname('Pynche Color List')
32 root.bind('<Alt-q>', self.__quit)
33 root.bind('<Alt-Q>', self.__quit)
34 root.bind('<Alt-w>', self.withdraw)
35 root.bind('<Alt-W>', self.withdraw)
37 # create the canvas which holds everything, and its scrollbar
39 frame = self.__frame = Frame(root)
40 frame.pack()
41 canvas = self.__canvas = Canvas(frame, width=160, height=300,
42 borderwidth=2, relief=SUNKEN)
43 self.__scrollbar = Scrollbar(frame)
44 self.__scrollbar.pack(fill=Y, side=RIGHT)
45 canvas.pack(fill=BOTH, expand=1)
46 canvas.configure(yscrollcommand=(self.__scrollbar, 'set'))
47 self.__scrollbar.configure(command=(canvas, 'yview'))
49 # create all the buttons
50 colordb = switchboard.colordb()
51 row = 0
52 widest = 0
53 bboxes = self.__bboxes = []
54 for name in colordb.unique_names():
55 exactcolor = ColorDB.triplet_to_rrggbb(colordb.find_byname(name))
56 canvas.create_rectangle(5, row*20 + 5,
57 20, row*20 + 20,
58 fill=exactcolor)
59 textid = canvas.create_text(25, row*20 + 13,
60 text=name,
61 anchor=W)
62 x1, y1, textend, y2 = canvas.bbox(textid)
63 boxid = canvas.create_rectangle(3, row*20+3,
64 textend+3, row*20 + 23,
65 outline='',
66 tags=(exactcolor,))
67 canvas.bind('<ButtonRelease>', self.__onrelease)
68 bboxes.append(boxid)
69 if textend+3 > widest:
70 widest = textend+3
71 row = row + 1
72 canvheight = (row-1)*20 + 25
73 canvas.config(scrollregion=(0, 0, 150, canvheight))
74 for box in bboxes:
75 x1, y1, x2, y2 = canvas.coords(box)
76 canvas.coords(box, x1, y1, widest, y2)
78 # Update on click
79 self.__uoc = BooleanVar()
80 self.__uoc.set(optiondb.get('UPONCLICK', 1))
81 self.__uocbtn = Checkbutton(root,
82 text='Update on Click',
83 variable=self.__uoc,
84 command=self.__toggleupdate)
85 self.__uocbtn.pack(expand=1, fill=BOTH)
87 # alias list
88 self.__alabel = Label(root, text='Aliases:')
89 self.__alabel.pack()
90 self.__aliases = Listbox(root, height=5,
91 selectmode=BROWSE)
92 self.__aliases.pack(expand=1, fill=BOTH)
94 def __onrelease(self, event=None):
95 canvas = self.__canvas
96 # find the current box
97 x = canvas.canvasx(event.x)
98 y = canvas.canvasy(event.y)
99 ids = canvas.find_overlapping(x, y, x, y)
100 for boxid in ids:
101 if boxid in self.__bboxes:
102 break
103 else:
104 ## print 'No box found!'
105 return
106 tags = self.__canvas.gettags(boxid)
107 for t in tags:
108 if t[0] == '#':
109 break
110 else:
111 ## print 'No color tag found!'
112 return
113 red, green, blue = ColorDB.rrggbb_to_triplet(t)
114 self.__dontcenter = 1
115 if self.__uoc.get():
116 self.__sb.update_views(red, green, blue)
117 else:
118 self.update_yourself(red, green, blue)
119 self.__red, self.__green, self.__blue = red, green, blue
121 def __toggleupdate(self, event=None):
122 if self.__uoc.get():
123 self.__sb.update_views(self.__red, self.__green, self.__blue)
125 def __quit(self, event=None):
126 self.__root.quit()
128 def withdraw(self, event=None):
129 self.__root.withdraw()
131 def deiconify(self, event=None):
132 self.__root.deiconify()
134 def update_yourself(self, red, green, blue):
135 canvas = self.__canvas
136 # turn off the last box
137 if self.__lastbox:
138 canvas.itemconfigure(self.__lastbox, outline='')
139 # turn on the current box
140 colortag = ColorDB.triplet_to_rrggbb((red, green, blue))
141 canvas.itemconfigure(colortag, outline='black')
142 self.__lastbox = colortag
143 # fill the aliases
144 self.__aliases.delete(0, END)
145 try:
146 aliases = self.__sb.colordb().aliases_of(red, green, blue)[1:]
147 except ColorDB.BadColor:
148 self.__aliases.insert(END, '<no matching color>')
149 return
150 if not aliases:
151 self.__aliases.insert(END, '<no aliases>')
152 else:
153 for name in aliases:
154 self.__aliases.insert(END, name)
155 # maybe scroll the canvas so that the item is visible
156 if self.__dontcenter:
157 self.__dontcenter = 0
158 else:
159 height = canvas['height']
160 ig, ig, ig, y1 = canvas.coords(colortag)
161 ig, ig, ig, y2 = canvas.coords(self.__bboxes[-1])
162 h = int(canvas['height']) * 0.5
163 canvas.yview('moveto', (y1-h) / y2)
165 def save_options(self, optiondb):
166 optiondb['UPONCLICK'] = self.__uoc.get()