~ubuntu-branches/ubuntu/trusty/python3.4/trusty-proposed

« back to all changes in this revision

Viewing changes to Tools/pynche/DetailsViewer.py

  • Committer: Package Import Robot
  • Author(s): Matthias Klose
  • Date: 2013-11-25 09:44:27 UTC
  • Revision ID: package-import@ubuntu.com-20131125094427-lzxj8ap5w01lmo7f
Tags: upstream-3.4~b1
ImportĀ upstreamĀ versionĀ 3.4~b1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""DetailsViewer class.
 
2
 
 
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.
 
7
 
 
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
 
14
grey level.
 
15
 
 
16
The behavior at the boundaries (0 and 255) are defined by the `At boundary'
 
17
option menu:
 
18
 
 
19
    Stop
 
20
        When the increment or decrement would send any of the tied variations
 
21
        out of bounds, the entire delta is discarded.
 
22
 
 
23
    Wrap Around
 
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.
 
28
 
 
29
    Preserve Distance
 
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.
 
35
 
 
36
    Squash
 
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.
 
41
 
 
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:
 
44
 
 
45
Left arrow == -1
 
46
Right arrow == +1
 
47
 
 
48
Control + Left == -10
 
49
Control + Right == 10
 
50
 
 
51
Shift + Left == -25
 
52
Shift + Right == +25
 
53
"""
 
54
 
 
55
from tkinter import *
 
56
 
 
57
STOP = 'Stop'
 
58
WRAP = 'Wrap Around'
 
59
RATIO = 'Preserve Distance'
 
60
GRAV = 'Squash'
 
61
 
 
62
ADDTOVIEW = 'Details Window...'
 
63
 
 
64
 
 
65
class DetailsViewer:
 
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()
 
70
        # GUI
 
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)
 
79
        # accelerators
 
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)
 
86
        #
 
87
        # color ties
 
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',
 
95
                                    variable=self.__rvar,
 
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)
 
115
        self.__effect()
 
116
        #
 
117
        # Boundary behavior
 
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)
 
126
        #
 
127
        # Buttons
 
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)
 
148
 
 
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):
 
152
            text = ''
 
153
        else:
 
154
            text = '(= %s Level)' % {3: 'Cyan',
 
155
                                     5: 'Magenta',
 
156
                                     6: 'Yellow',
 
157
                                     7: 'Grey'}[tie]
 
158
        self.__l2.configure(text=text)
 
159
 
 
160
    def __quit(self, event=None):
 
161
        self.__root.quit()
 
162
 
 
163
    def withdraw(self, event=None):
 
164
        self.__root.withdraw()
 
165
 
 
166
    def deiconify(self, event=None):
 
167
        self.__root.deiconify()
 
168
 
 
169
    def __minus25(self, event=None):
 
170
        self.__delta(-25)
 
171
 
 
172
    def __minus10(self, event=None):
 
173
        self.__delta(-10)
 
174
 
 
175
    def __minus1(self, event=None):
 
176
        self.__delta(-1)
 
177
 
 
178
    def __plus1(self, event=None):
 
179
        self.__delta(1)
 
180
 
 
181
    def __plus10(self, event=None):
 
182
        self.__delta(10)
 
183
 
 
184
    def __plus25(self, event=None):
 
185
        self.__delta(25)
 
186
 
 
187
    def __delta(self, delta):
 
188
        tie = []
 
189
        if self.__rvar.get():
 
190
            red = self.__red + delta
 
191
            tie.append(red)
 
192
        else:
 
193
            red = self.__red
 
194
        if self.__gvar.get():
 
195
            green = self.__green + delta
 
196
            tie.append(green)
 
197
        else:
 
198
            green = self.__green
 
199
        if self.__bvar.get():
 
200
            blue = self.__blue + delta
 
201
            tie.append(blue)
 
202
        else:
 
203
            blue = self.__blue
 
204
        # now apply at boundary behavior
 
205
        atbound = self.__boundvar.get()
 
206
        if atbound == STOP:
 
207
            if red < 0 or green < 0 or blue < 0 or \
 
208
               red > 255 or green > 255 or blue > 255:
 
209
                # then
 
210
                red, green, blue = self.__red, self.__green, self.__blue
 
211
        elif atbound == WRAP or (atbound == RATIO and len(tie) < 2):
 
212
            if red < 0:
 
213
                red += 256
 
214
            if green < 0:
 
215
                green += 256
 
216
            if blue < 0:
 
217
                blue += 256
 
218
            if red > 255:
 
219
                red -= 256
 
220
            if green > 255:
 
221
                green -= 256
 
222
            if blue > 255:
 
223
                blue -= 256
 
224
        elif atbound == RATIO:
 
225
            # for when 2 or 3 colors are tied together
 
226
            dir = 0
 
227
            for c in tie:
 
228
                if c < 0:
 
229
                    dir = -1
 
230
                elif c > 255:
 
231
                    dir = 1
 
232
            if dir == -1:
 
233
                delta = max(tie)
 
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
 
240
            elif dir == 1:
 
241
                delta = min(tie)
 
242
                if self.__rvar.get():
 
243
                    red = red - delta
 
244
                if self.__gvar.get():
 
245
                    green = green - delta
 
246
                if self.__bvar.get():
 
247
                    blue = blue - delta
 
248
        elif atbound == GRAV:
 
249
            if red < 0:
 
250
                red = 0
 
251
            if green < 0:
 
252
                green = 0
 
253
            if blue < 0:
 
254
                blue = 0
 
255
            if red > 255:
 
256
                red = 255
 
257
            if green > 255:
 
258
                green = 255
 
259
            if blue > 255:
 
260
                blue = 255
 
261
        self.__sb.update_views(red, green, blue)
 
262
        self.__root.update_idletasks()
 
263
 
 
264
    def update_yourself(self, red, green, blue):
 
265
        self.__red = red
 
266
        self.__green = green
 
267
        self.__blue = blue
 
268
 
 
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()