1
"""DetailsViewer class.
3
This class implements a pure input window which allows you to meticulously
4
edit the current color. You have both mouse control of the color (via the
5
buttons along the bottom row), and there are keyboard bindings for each of the
6
increment/decrement buttons.
8
The top three check buttons allow you to specify which of the three color
9
variations are tied together when incrementing and decrementing. Red, green,
10
and blue are self evident. By tying together red and green, you can modify
11
the yellow level of the color. By tying together red and blue, you can modify
12
the magenta level of the color. By tying together green and blue, you can
13
modify the cyan level, and by tying all three together, you can modify the
16
The behavior at the boundaries (0 and 255) are defined by the `At boundary'
20
When the increment or decrement would send any of the tied variations
21
out of bounds, the entire delta is discarded.
24
When the increment or decrement would send any of the tied variations
25
out of bounds, the out of bounds variation is wrapped around to the
26
other side. Thus if red were at 238 and 25 were added to it, red
27
would have the value 7.
30
When the increment or decrement would send any of the tied variations
31
out of bounds, all tied variations are wrapped as one, so as to
32
preserve the distance between them. Thus if green and blue were tied,
33
and green was at 238 while blue was at 223, and an increment of 25
34
were applied, green would be at 15 and blue would be at 0.
37
When the increment or decrement would send any of the tied variations
38
out of bounds, the out of bounds variation is set to the ceiling of
39
255 or floor of 0, as appropriate. In this way, all tied variations
40
are squashed to one edge or the other.
42
The following key bindings can be used as accelerators. Note that Pynche can
43
fall behind if you hold the key down as a key repeat:
59
RATIO = 'Preserve Distance'
62
ADDTOVIEW = 'Details Window...'
66
def __init__(self, switchboard, master=None):
67
self.__sb = switchboard
68
optiondb = switchboard.optiondb()
69
self.__red, self.__green, self.__blue = switchboard.current_rgb()
71
root = self.__root = Toplevel(master, class_='Pynche')
72
root.protocol('WM_DELETE_WINDOW', self.withdraw)
73
root.title('Pynche Details Window')
74
root.iconname('Pynche Details Window')
75
root.bind('<Alt-q>', self.__quit)
76
root.bind('<Alt-Q>', self.__quit)
77
root.bind('<Alt-w>', self.withdraw)
78
root.bind('<Alt-W>', self.withdraw)
80
root.bind('<KeyPress-Left>', self.__minus1)
81
root.bind('<KeyPress-Right>', self.__plus1)
82
root.bind('<Control-KeyPress-Left>', self.__minus10)
83
root.bind('<Control-KeyPress-Right>', self.__plus10)
84
root.bind('<Shift-KeyPress-Left>', self.__minus25)
85
root.bind('<Shift-KeyPress-Right>', self.__plus25)
88
frame = self.__frame = Frame(root)
89
frame.pack(expand=YES, fill=X)
90
self.__l1 = Label(frame, text='Move Sliders:')
91
self.__l1.grid(row=1, column=0, sticky=E)
92
self.__rvar = IntVar()
93
self.__rvar.set(optiondb.get('RSLIDER', 4))
94
self.__radio1 = Checkbutton(frame, text='Red',
96
command=self.__effect,
97
onvalue=4, offvalue=0)
98
self.__radio1.grid(row=1, column=1, sticky=W)
99
self.__gvar = IntVar()
100
self.__gvar.set(optiondb.get('GSLIDER', 2))
101
self.__radio2 = Checkbutton(frame, text='Green',
102
variable=self.__gvar,
103
command=self.__effect,
104
onvalue=2, offvalue=0)
105
self.__radio2.grid(row=2, column=1, sticky=W)
106
self.__bvar = IntVar()
107
self.__bvar.set(optiondb.get('BSLIDER', 1))
108
self.__radio3 = Checkbutton(frame, text='Blue',
109
variable=self.__bvar,
110
command=self.__effect,
111
onvalue=1, offvalue=0)
112
self.__radio3.grid(row=3, column=1, sticky=W)
113
self.__l2 = Label(frame)
114
self.__l2.grid(row=4, column=1, sticky=W)
118
self.__l3 = Label(frame, text='At boundary:')
119
self.__l3.grid(row=5, column=0, sticky=E)
120
self.__boundvar = StringVar()
121
self.__boundvar.set(optiondb.get('ATBOUND', STOP))
122
self.__omenu = OptionMenu(frame, self.__boundvar,
123
STOP, WRAP, RATIO, GRAV)
124
self.__omenu.grid(row=5, column=1, sticky=W)
125
self.__omenu.configure(width=17)
128
frame = self.__btnframe = Frame(frame)
129
frame.grid(row=0, column=0, columnspan=2, sticky='EW')
130
self.__down25 = Button(frame, text='-25',
131
command=self.__minus25)
132
self.__down10 = Button(frame, text='-10',
133
command=self.__minus10)
134
self.__down1 = Button(frame, text='-1',
135
command=self.__minus1)
136
self.__up1 = Button(frame, text='+1',
137
command=self.__plus1)
138
self.__up10 = Button(frame, text='+10',
139
command=self.__plus10)
140
self.__up25 = Button(frame, text='+25',
141
command=self.__plus25)
142
self.__down25.pack(expand=YES, fill=X, side=LEFT)
143
self.__down10.pack(expand=YES, fill=X, side=LEFT)
144
self.__down1.pack(expand=YES, fill=X, side=LEFT)
145
self.__up1.pack(expand=YES, fill=X, side=LEFT)
146
self.__up10.pack(expand=YES, fill=X, side=LEFT)
147
self.__up25.pack(expand=YES, fill=X, side=LEFT)
149
def __effect(self, event=None):
150
tie = self.__rvar.get() + self.__gvar.get() + self.__bvar.get()
151
if tie in (0, 1, 2, 4):
154
text = '(= %s Level)' % {3: 'Cyan',
158
self.__l2.configure(text=text)
160
def __quit(self, event=None):
163
def withdraw(self, event=None):
164
self.__root.withdraw()
166
def deiconify(self, event=None):
167
self.__root.deiconify()
169
def __minus25(self, event=None):
172
def __minus10(self, event=None):
175
def __minus1(self, event=None):
178
def __plus1(self, event=None):
181
def __plus10(self, event=None):
184
def __plus25(self, event=None):
187
def __delta(self, delta):
189
if self.__rvar.get():
190
red = self.__red + delta
194
if self.__gvar.get():
195
green = self.__green + delta
199
if self.__bvar.get():
200
blue = self.__blue + delta
204
# now apply at boundary behavior
205
atbound = self.__boundvar.get()
207
if red < 0 or green < 0 or blue < 0 or \
208
red > 255 or green > 255 or blue > 255:
210
red, green, blue = self.__red, self.__green, self.__blue
211
elif atbound == WRAP or (atbound == RATIO and len(tie) < 2):
224
elif atbound == RATIO:
225
# for when 2 or 3 colors are tied together
234
if self.__rvar.get():
235
red = red + 255 - delta
236
if self.__gvar.get():
237
green = green + 255 - delta
238
if self.__bvar.get():
239
blue = blue + 255 - delta
242
if self.__rvar.get():
244
if self.__gvar.get():
245
green = green - delta
246
if self.__bvar.get():
248
elif atbound == GRAV:
261
self.__sb.update_views(red, green, blue)
262
self.__root.update_idletasks()
264
def update_yourself(self, red, green, blue):
269
def save_options(self, optiondb):
270
optiondb['RSLIDER'] = self.__rvar.get()
271
optiondb['GSLIDER'] = self.__gvar.get()
272
optiondb['BSLIDER'] = self.__bvar.get()
273
optiondb['ATBOUND'] = self.__boundvar.get()