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
.__minus
1)
81 root
.bind('<KeyPress-Right>', self
.__plus
1)
82 root
.bind('<Control-KeyPress-Left>', self
.__minus
10)
83 root
.bind('<Control-KeyPress-Right>', self
.__plus
10)
84 root
.bind('<Shift-KeyPress-Left>', self
.__minus
25)
85 root
.bind('<Shift-KeyPress-Right>', self
.__plus
25)
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
.__radio
1 = Checkbutton(frame
, text
='Red',
96 command
=self
.__effect
,
97 onvalue
=4, offvalue
=0)
98 self
.__radio
1.grid(row
=1, column
=1, sticky
=W
)
99 self
.__gvar
= IntVar()
100 self
.__gvar
.set(optiondb
.get('GSLIDER', 2))
101 self
.__radio
2 = Checkbutton(frame
, text
='Green',
102 variable
=self
.__gvar
,
103 command
=self
.__effect
,
104 onvalue
=2, offvalue
=0)
105 self
.__radio
2.grid(row
=2, column
=1, sticky
=W
)
106 self
.__bvar
= IntVar()
107 self
.__bvar
.set(optiondb
.get('BSLIDER', 1))
108 self
.__radio
3 = Checkbutton(frame
, text
='Blue',
109 variable
=self
.__bvar
,
110 command
=self
.__effect
,
111 onvalue
=1, offvalue
=0)
112 self
.__radio
3.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
.__down
25 = Button(frame
, text
='-25',
131 command
=self
.__minus
25)
132 self
.__down
10 = Button(frame
, text
='-10',
133 command
=self
.__minus
10)
134 self
.__down
1 = Button(frame
, text
='-1',
135 command
=self
.__minus
1)
136 self
.__up
1 = Button(frame
, text
='+1',
137 command
=self
.__plus
1)
138 self
.__up
10 = Button(frame
, text
='+10',
139 command
=self
.__plus
10)
140 self
.__up
25 = Button(frame
, text
='+25',
141 command
=self
.__plus
25)
142 self
.__down
25.pack(expand
=YES
, fill
=X
, side
=LEFT
)
143 self
.__down
10.pack(expand
=YES
, fill
=X
, side
=LEFT
)
144 self
.__down
1.pack(expand
=YES
, fill
=X
, side
=LEFT
)
145 self
.__up
1.pack(expand
=YES
, fill
=X
, side
=LEFT
)
146 self
.__up
10.pack(expand
=YES
, fill
=X
, side
=LEFT
)
147 self
.__up
25.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()