1
2
3
4
5
6
7
8
9
10
11
12
13
14 import Tkinter, Pmw, Numeric, os
15
16 from types import ListType, TupleType
17 from mglutil.util.callback import CallBackFunction, CallbackManager
18 from mglutil.util.colorUtil import ToRGB, ToHSV, ToHEX
19 from mglutil.gui.InputForm.Tk.gui import InputFormDescr,InputForm,evalString
20 from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ExtendedSliderWidget
21 from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser
22 from mglutil.gui.BasicWidgets.Tk.fileBrowsers import fileOpenAsk, fileSaveAsk
23 import tkMessageBox
24 import os, math
25
27 - def __init__(self, master, title=None, callback=None, immediate=1):
28 if not master:
29 master = Tkinter.Toplevel()
30
31 if title is not None:
32 master.title(title)
33
34 f = self.frame = Tkinter.Frame(master)
35 path = __import__('mglutil').__path__
36 iconfile = os.path.join(path[0],'gui/BasicWidgets/Tk/cw.ppm')
37 self.iconfile = iconfile
38 self.cwim = Tkinter.PhotoImage(file=iconfile)
39 self.width = self.cwim.width()
40 self.height = self.cwim.height()
41 self.cwcanvas = Tkinter.Canvas(f, width=self.width,
42 height=self.height,
43 borderwidth=3 )
44 self.cwcanvas.create_image(3, 3, anchor=Tkinter.NW, image=self.cwim)
45 self.cwcanvas.pack()
46 self.frame.pack()
47
48
49 self.cbManager = CallbackManager()
50 if callback:
51 if type(callback) in [ListType, TupleType]:
52 map(self.cbManager.AddCallback, callback)
53 else:
54 self.cbManager.AddCallback(callback)
55 self.afterID = None
56 self.immediate = immediate
57 self.x = 0
58 self.y = 0
59 self.radius = 55
60 cx = self.cx = self.width/2 + 3
61 cy = self.cy = self.height/2 + 3
62
63 self.cursor = self.cwcanvas.create_line(
64
65 cx-3, cy-3, cx-3, cy+3, cx+3,cy+3, cx+3, cy-3, cx-3, cy-3 )
66
67 self.hsvColor = [1.,1.,1.]
68
69 self.cwcanvas.bind('<ButtonPress-1>', self.mouse1Down)
70
71
72
74
75 s = math.sqrt(x*x + y*y) / self.radius
76 if s > 1.0:
77 x = x / s
78 y = y / s
79 s = 1.0
80
81
82 if x or y:
83 angle = math.atan2(y, x)
84 if angle < 0.0:
85 angle = angle + (2.*math.pi)
86 h = 1. - angle / (2.0 * math.pi)
87 else:
88 h = 0
89
90 if self.hsvColor[0] != h or self.hsvColor[1] != s:
91 if trigger==1:
92 self.hsvColor[0] = h
93 self.hsvColor[1] = s
94 cx = self.cx+x
95 cy = self.cy+y
96 self.cwcanvas.coords( self.cursor, cx-3, cy-3, cx-3, cy+3,
97 cx+3,cy+3, cx+3, cy-3, cx-3, cy-3 )
98
99 if self.cbManager.callbacks:
100 self.cbManager.CallCallbacks(self.get('RGB'))
101
103 self.cwcanvas.bind('<B1-Motion>', self.mouse1Move)
104 self.cwcanvas.bind('<ButtonRelease-1>', self.mouse1Up)
105 self._MoveCursor(event.x - self.cx, event.y - self.cy)
106
107
109 if self.immediate:
110 if self.afterID is not None:
111 self.cwcanvas.after_cancel(self.afterID)
112 self.afterID = None
113 else:
114 self.afterID = self.cwcanvas.after(15,self._MoveCursor ,
115 event.x - self.cx,
116 event.y - self.cy)
117
118 else:
119 self._MoveCursor(event.x - self.cx, event.y - self.cy,
120 trigger=0)
121
122
124 self._MoveCursor(event.x - self.cx, event.y - self.cy)
125 self.cwcanvas.unbind('<B1-Motion>')
126 self.cwcanvas.unbind('<ButtonRelease-1>')
127
128
129 - def get(self, mode='HSV'):
130 """Get the current color"""
131 if mode == 'RGB':
132 rgb = ToRGB(self.hsvColor)
133
134 return rgb
135
136 elif mode == 'HSV':
137
138 return self.hsvColor
139
140 elif mode == 'HEX':
141 col = Numeric.array(ToRGB(self.hsvColor[:]), 'f') * 255
142 return ToHEX(col)
143
144
145 - def set(self, color, mode='HSV', trigger=1):
146 """Set the current color"""
147 assert len(color)==3
148
149 if mode=='RGB': color = ToHSV(color[:])
150 self.hsvColor = list(color[:])
151
152
153 rad = self.hsvColor[1] * self.radius
154 angle = 2.0 * math.pi * (1. - self.hsvColor[0])
155 cx = self.cx + int(rad * math.cos(angle))
156 cy = self.cy + int(rad * math.sin(angle))
157 self.cwcanvas.coords( self.cursor, cx-3, cy-3, cx-3, cy+3,
158 cx+3,cy+3, cx+3, cy-3, cx-3, cy-3 )
159
160 if trigger==1 and self.immediate and self.cbManager.callbacks:
161 self.cbManager.CallCallbacks(self.get('RGB'))
162
163
165 """
166 The ColorEditor is a widget providing a colorwheel, a value scale,
167 HSV entries, RGB entries and HEX(HexTriplet) entries
168 """
169 - def __init__(self, master=None, currentColor=(1.0,1.0,1.0), mode='RGB',
170 commands = None, immediate=1):
171 assert mode in ['RGB', 'HSV','HEX']
172 self.mode = mode
173 if not master:
174 self.master = Tkinter.Toplevel()
175 else:
176 self.master = master
177 self.afterID = None
178 self.immediate = immediate
179
180 self.editFrame = Tkinter.Frame(self.master, borderwidth=2,
181 relief='ridge')
182 self.cbManager = CallbackManager()
183 if commands:
184 if type(commands) in [ListType, TupleType]:
185 map(self.cbManager.AddCallback, commands)
186 else:
187 self.cbManager.AddCallback(commands)
188
189 if mode == 'HSV':
190 self.currentHSV = list(currentColor)
191 self.currentRGB = list(ToRGB(currentColor))
192 self.currentHEX = ToHEX(currentColor, mode = 'HSV')
193
194 elif mode == 'RGB':
195 self.currentRGB = list(currentColor)
196 self.currentHSV = list(ToHSV(currentColor))
197 self.currentHEX = ToHEX(currentColor, mode='RGB')
198
199 elif mode == 'HEX':
200 self.currentRGB = ToHEX(currentColor, mode='RGB')
201 self.currentHSV = ToHEX(currentColor, mode='HSV')
202 self.currentHEX = currentColor
203 else:
204 print 'mode not recognized mode set to RGB'
205 self.createColorEditor()
206
208
209 chooserFrame = Tkinter.Frame(self.editFrame)
210
211 self.vScale = Tkinter.Scale(chooserFrame,
212 from_ = 1.0, to_ = 0.0,
213 orient='vertical', resolution=0.01,)
214
215 if self.immediate:
216 self.vScale.configure(command=self.scale_cb)
217 else:
218 self.vScale.bind('<ButtonRelease-1>', self.scaleUp_cb)
219
220
221
222
223
224
225 self.vScale.pack(side='right', padx=5, pady=5, expand=1,
226 fill='both')
227 self.vScale.set(1.0)
228
229
230 wheelFrame = Tkinter.Frame(chooserFrame, relief='ridge',
231 borderwidth=1)
232
233 wheelFrame.pack(side='left',pady=5, padx=10,fill='both',
234 expand = 1)
235
236
237
238
239 self.cw = ColorWheel(wheelFrame,None,self.colorWidget_cb,self.immediate)
240
241
242
243
244
245 self.cw.set(self.currentRGB, mode='RGB', trigger=0)
246
247
248
249 chooserFrame.pack(expand=1,fill='both')
250
251 bottomFrame = Tkinter.Frame(self.editFrame)
252
253 previewFrame = Tkinter.Frame(bottomFrame)
254 previewFrame.pack(side='left', fill='both', expand=1)
255 preview = Tkinter.Frame(previewFrame,)
256 bg = self.currentHEX
257 self.chip = Tkinter.Frame(previewFrame,
258 borderwidth=3, width=50,
259 height=30, bg=bg, relief='ridge')
260
261 self.chip.pack(fill='both', expand = 1)
262
263
264
265 entriesFrame = Tkinter.Frame(bottomFrame)
266 entriesOption = {'labelpos':'w',
267 'validate':{'validator':'real',
268 'min':0.0, 'max':1.0},
269 'entry_width':4,
270 }
271
272
273 hsvFrame = Tkinter.Frame(entriesFrame)
274
275 entriesOption['label_text'] = 'H'
276 entriesOption['value'] = "%4.2f"%self.currentHSV[0]
277 entriesOption['command'] = self.hVal_cb
278 self.hVal = apply(Pmw.EntryField, (hsvFrame,), entriesOption)
279 self.hVal.pack(side = 'left')
280
281 entriesOption['label_text'] = 'S'
282 entriesOption['value'] = "%4.2f"%self.currentHSV[1]
283 entriesOption['command'] = self.sVal_cb
284 self.sVal = apply(Pmw.EntryField, (hsvFrame,), entriesOption)
285 self.sVal.pack(side = 'left')
286
287 entriesOption['label_text'] = 'V'
288 entriesOption['value'] = "%4.2f"%self.currentHSV[2]
289 entriesOption['command'] = self.vVal_cb
290 self.vVal= apply(Pmw.EntryField, (hsvFrame,), entriesOption)
291 self.vVal.pack(side = 'left')
292
293 hsvFrame.pack(padx=4, pady=4,fill='both',expand=1)
294
295 rgbFrame = Tkinter.Frame(entriesFrame)
296
297 entriesOption['label_text'] = 'R'
298 entriesOption['value'] = "%4.2f"%self.currentRGB[0]
299 entriesOption['command'] = self.rVal_cb
300 self.rVal = apply(Pmw.EntryField, (rgbFrame,), entriesOption)
301 self.rVal.pack(side = 'left')
302
303 entriesOption['label_text'] = 'G'
304 entriesOption['value'] = "%4.2f"%self.currentRGB[1]
305 entriesOption['command'] = self.gVal_cb
306 self.gVal = apply(Pmw.EntryField, (rgbFrame,), entriesOption)
307 self.gVal.pack(side = 'left')
308
309 entriesOption['label_text'] = 'B'
310 entriesOption['value'] = "%4.2f"%self.currentRGB[2]
311 entriesOption['command'] = self.bVal_cb
312 self.bVal = apply(Pmw.EntryField, (rgbFrame,), entriesOption)
313 self.bVal.pack(side = 'left')
314 rgbFrame.pack(padx=4, pady=4,fill='both',expand=1)
315
316 hexFrame = Tkinter.Frame(entriesFrame)
317 entriesOption['label_text'] = 'Hex triplet'
318 entriesOption['value'] = self.currentHEX
319 entriesOption['command'] = self.hexVal_cb
320 del entriesOption['validate']
321 entriesOption['entry_width']=8
322
323 self.hexVal = apply(Pmw.EntryField, (hexFrame,), entriesOption)
324 self.hexVal.pack(padx=4, pady=4,side = 'left')
325 hexFrame.pack(fill='both',expand=1)
326
327 entriesFrame.pack(side = 'right', fill='both',expand=1)
328 bottomFrame.pack(side='bottom',fill='both', expand=1)
329
330
331
332
333
334
335
336 - def set(self, color, mode='RGB', trigger=1):
337 """Set the current color"""
338
339 assert mode in ['HSV', 'RGB', 'HEX']
340 self.mode = mode
341 if mode == 'HSV':
342 newRGB = map(lambda x: float("%4.2f"%x), ToRGB(color))
343 elif mode == 'HEX':
344 newRGB = ToRGB(color, mode = 'HEX')
345 else: newRGB = color
346 if newRGB != self.currentRGB:
347 self.updateWidgetsColor(newRGB)
348 if trigger==1 and self.immediate and self.cbManager.callbacks:
349 self.cbManager.CallCallbacks(self.currentRGB)
350
351 - def get(self, mode = 'RGB'):
352 assert mode in ['RGB','HSV', 'HEX']
353 self.mode = mode
354 if mode == 'RGB':
355 return self.currentRGB
356 elif mode == 'HSV':
357 return self.currentHSV
358 elif mode == 'HEX':
359 col = ToHEX(self.currentRGB, mode='HEX')
360 return col
361
362 - def pack(self,*args, **kw):
364
367
368 - def grid(self,*args, **kw):
370
373
374
375
376
377
387
389 if self.afterID is not None:
390 self.vScale.after_cancel(self.afterID)
391 self.afterID = None
392 else:
393 self.afterID = self.vScale.after(17, self.scaleImm_cb, val)
394
395
400
406
415
423
431
433 val = float(self.rVal.get())
434 newColor = self.currentRGB[:]
435 newColor[0] = val
436 newRGB = map(lambda x: float("%4.2f"%x), newColor)
437 if newRGB != self.currentRGB:
438 self.updateWidgetsColor(newRGB, who='r')
439
440
442 val = float(self.gVal.get())
443 newColor = self.currentRGB[:]
444 newColor[1] = val
445 newRGB = map(lambda x: float("%4.2f"%x), newColor)
446 if newRGB != self.currentRGB:
447 self.updateWidgetsColor(newRGB, who='g')
448
450 val = float(self.bVal.get())
451 newColor = self.currentRGB[:]
452 newColor[2] = val
453 newRGB = map(lambda x: float("%4.2f"%x), newColor)
454 if newRGB != self.currentRGB:
455 self.updateWidgetsColor(newRGB, who='b')
456
457
465
466
467
468
535
536
537
539 - def __init__(self, master=None, title = 'Chooser', commands = None,
540 immediate=0, exitFunction=None):
563
564
566
567 self.menuBar = Pmw.MenuBar(self.masterFrame,
568 hull_relief = 'raised',
569 hull_borderwidth = 1)
570 self.menuBar.addmenu('File', 'Close this window or exit')
571
572 self.mainFrame = Tkinter.Frame(self.masterFrame,
573 borderwidth=2, relief='ridge',
574 width=150, height=200)
575
576 self.menuBar.pack(fill = 'x')
577
578
579 self.ce = ColorEditor(self.mainFrame, immediate=self.immediate)
580
581 self.hidden=1
582 self.mainFrame.pack(fill='both', expand=1)
583
584
585
586
587
588
590 pass
591
592 - def pack(self, *args, **kw):
594
597
598 - def grid(self ,*args, **kw):
600
603
604
605
607 - def __init__(self, master=None, title = 'Chooser', commands = None,
608 immediate=0, exitFunction=None, colorsFile=None,
609 colorsName=None):
610
611 self.exitFunc = exitFunction
612
613 if colorsFile is None or colorsName is None:
614 path = __import__('mglutil').__path__
615 self.customFilename = os.path.join(path[0],'gui/BasicWidgets/Tk/defaultColors.py')
616 self.colorsName = 'defaultColor'
617
618 else:
619 self.customFilename = colorsFile
620 self.colorsName = colorsName
621
622 Chooser.__init__(self, master=master, title=title, commands = commands,
623 immediate=immediate, exitFunction=exitFunction)
624 try:
625 self.master.protocol('WM_DELETE_WINDOW', self.exit)
626 except:
627 pass
628
630 self.ccFrame = Tkinter.Frame(self.mainFrame)
631
632
633 self.menuBar.addmenuitem('File', 'command', 'Load custom',
634 command = self.load,
635 label='Load')
636
637 self.menuBar.addmenuitem('File', 'command', 'Save Colors',
638 command = self.save,
639 label='Save')
640
641 self.menuBar.addmenuitem('File', 'separator')
642
643 self.menuBar.addmenuitem('File', 'command', 'Exit',
644 command=self.exit,
645 label='Exit')
646
647 self.menuBar.addmenu('Edit', 'editing commands')
648
649 self.menuBar.addmenuitem('Edit', 'command','Add New Color',
650 command = self.addColor,
651 label='Add New Color')
652 self.add = 0
653
654 self.menuBar.addmenuitem('Edit', 'command','Edit Custom Color',
655 command = self.editColor,
656 label='Edit Selected Color')
657 self.edit = 0
658
659 self.menuBar.addmenuitem('Edit', 'command','Hide Color Editor',
660 command = self.hideCE,
661 label='Hide Color Editor')
662
663
664
665 self.ccFrame.pack(side='left',expand=1, fill='both')
666 self.addButton = Tkinter.Button(self.ccFrame, text='Add to custom',
667 command=self.addToCustom_cb)
668 self.addHidden = 1
669
670
671
672 chipsSFrame = Pmw.ScrolledFrame(self.ccFrame, usehullsize=1,
673 hull_width=130,
674 hull_height=200,
675 hscrollmode = 'none')
676 chipsSFrame.pack(padx = 5, pady = 3, fill = 'both', expand = 1)
677
678
679 self.chipsFrame = chipsSFrame.interior()
680
681 self.colorChips=Pmw.RadioSelect(self.chipsFrame,
682 label_text='Default Colors',
683 labelpos='nw', orient='vertical',
684 buttontype='radiobutton',
685 command = self.colButton_cb)
686 self.mod = {}
687 execfile(self.customFilename, self.mod)
688 self.cFlag=0
689 self.addCustomCol(paletteName = self.colorsName)
690
691
693 ftypes = [ ('Python files', '*.py') ]
694 filename = fileOpenAsk(self.master, types=ftypes,
695 title='Load custom colors' )
696
697 if filename is None: return
698 self.customFilename = filename
699 self.mod = {}
700 execfile( self.customFilename, self.mod)
701 self.mod.keys()
702 colName = filter(lambda x: x[:2]!='__',self.mod.keys())
703 entries = map(lambda x: (x, None), colName)
704
705 self.showChooser(entries)
706
708 if self.cFlag == 1:
709 self.palChooser.clear()
710 map(self.palChooser.add, entries)
711 self.root.deiconify()
712 else:
713 self.root = Tkinter.Toplevel()
714 self.chooserFrame = Tkinter.Frame(self.root)
715 self.palChooser = ListChooser(self.chooserFrame, mode = 'extended',
716 title='Customized colors groups',
717 entries = entries,
718 command=self.addCustomCol,)
719 self.cFlag=1
720 dismissChooser = Tkinter.Button(self.chooserFrame,
721 text='Dismiss',
722 command=self.root.withdraw)
723 self.palChooser.pack()
724 dismissChooser.pack()
725 self.chooserFrame.pack()
726
728 if self.hidden == 0:
729 self.ce.pack_forget()
730 self.hidden=1
731 if self.addHidden == 0:
732 self.addButton.pack_forget()
733 self.addHidden=1
734 self.add =0
735 self.edit=0
736
737
739 if paletteName is None:
740 paletteName = self.palChooser.get()[0]
741 self.colorsName = paletteName
742
743 if not self.mod.has_key(paletteName):
744 self.colDict={}
745 return
746 else:
747 self.colDict = self.mod[paletteName]
748 if len(self.colorChips._buttonList)!=0:
749 self.colorChips.deleteall()
750
751 self.colorChips.configure(label_text=paletteName)
752 items = self.colDict.items()
753 items.sort()
754 for name, value in items:
755 col = ToHEX(value)
756 self.colorChips.add(name, bg = col,
757 activebackground=col,
758 fg = col, activeforeground = col,
759 indicatoron=0,selectcolor=col,
760 width=10,height=1,
761 value = name)
762 self.colorChips.pack(fill='x', expand=1)
763 self.ce.cbManager.AddCallback(self.editChip)
764
765 if hasattr(self, 'chooserFrame'):
766 self.chooserFrame.master.withdraw()
767
768 - def save(self, fileName = None, paletteName=None):
769 """Save the color palette """
770 if paletteName is None or fileName is None:
771 if hasattr(self, 'saveHidden'):
772 if self.saveHidden == 1:
773 self.root.deiconify()
774 self.saveHidden = 0
775 else:
776 self.root = Tkinter.Toplevel()
777 self.saveFrame = Tkinter.Frame(self.root, )
778 groupFrame = Tkinter.Frame(self.saveFrame)
779 self.groupEntry = Pmw.EntryField(groupFrame,
780 label_text='Group name:',
781 labelpos='w',
782 value=self.colorsName)
783 label = Tkinter.Label(groupFrame, text="\t\t",
784 )
785 self.groupEntry.pack(side='left')
786 label.pack(side='right', fill='x', expand=1)
787 groupFrame.pack(fill='x', expand=1)
788
789 fileFrame = Tkinter.Frame(self.saveFrame)
790
791 self.fileEntry = Pmw.EntryField(fileFrame,
792 label_text='Python File name:',
793 labelpos='w',
794 value=self.customFilename)
795
796 browseBut = Tkinter.Button(fileFrame, text='Browse',
797 command=self.browse)
798 self.fileEntry.pack(side='left')
799 browseBut.pack(side='right', fill='x', expand=1)
800 fileFrame.pack(fill='x', expand=1)
801
802 buttonFrame = Tkinter.Frame(self.saveFrame)
803 ok = Tkinter.Button(buttonFrame, text='OK', command=self.ok)
804 cancel = Tkinter.Button(buttonFrame, text='Cancel',
805 command=self.cancel)
806 ok.pack(side='left', fill='x',expand=1)
807 cancel.pack(side='right', fill='x', expand=1)
808 buttonFrame.pack(side='bottom', fill='both', expand=1)
809 self.saveFrame.pack(fill='both', expand=1)
810
811 self.saveHidden = 0
812
814 filename= self.fileEntry.get()
815 groupname = self.groupEntry.get()
816 if not groupname:
817 print 'ERROR'
818 if filename is None: return
819 if not os.path.isfile(filename):
820 f = open(filename, 'w')
821 s = groupname+'='+repr(self.colDict)
822 f.write(s)
823 f.write('\n')
824 f.close()
825 else:
826 mod = {}
827 execfile(filename, mod)
828 colName = filter(lambda x: x[:2]!='__',dir(mod.keys()))
829 if groupname in colName:
830 f = open(filename, 'w')
831 for name in colName:
832 if name == groupname:
833 s = groupname+'='+repr(self.colDict)
834 else:
835 dict = getattr(self.mod,name)
836 s = name+'='+repr(dict)
837 else:
838 f = open(filename, 'a+')
839 f.write('\n')
840 s = groupname+'='+repr(self.colDict)
841 f.write(s)
842 f.write('\n')
843 f.close()
844 self.root.withdraw()
845
846
850
858
862
864 self.hideCE()
865 if self.exitFunc is None:
866 if hasattr(self.masterFrame.master,'withdraw'):
867 self.masterFrame.master.withdraw()
868 else:
869 self.exitFunc()
870
872 if self.edit == 1:
873 return
874 self.edit = 1
875 if self.hidden == 1:
876 self.ce.pack(side = 'right', fill='both', expand=1)
877 self.hidden = 0
878 else:
879 if self.add == 0:
880 self.ce.pack_forget()
881 self.hidden=1
882 if self.addHidden == 0:
883 self.addButton.pack_forget()
884 self.addHidden=1
885 self.ce.immediate=1
886 self.add = 0
887
889 if self.add ==1: return
890 if self.hidden:
891 self.ce.pack(side = 'right', fill='both', expand=1)
892 self.hidden=0
893 else:
894 if self.edit == 0:
895 self.ce.pack_forget()
896 self.hidden=1
897 if self.addHidden:
898 self.addButton.pack(side = 'bottom', fill='x', expand=1)
899 self.addHidden=0
900 self.ce.immediate=0
901 self.add = 1
902 self.edit = 0
903
904
905
906
907
909 hexcol = ToHEX(col)
910 chipName = self.colorChips.getcurselection()
911 if chipName is None: return
912 chip = self.colorChips.button(chipName)
913 chip.configure(bg=hexcol, fg=hexcol, activebackground=hexcol,
914 activeforeground=hexcol, selectcolor=hexcol)
915 self.colDict[chipName]=col
916
922
923
924
926 rgbcol = self.ce.get()
927 newKey = str(len(self.colDict)+1)
928 self.colDict[newKey]=rgbcol
929 col = ToHEX(rgbcol)
930 self.colorChips.add(newKey, bg = col,
931 activebackground=col,
932 fg = col, activeforeground = col,
933 indicatoron=0,selectcolor=col,
934 width=10,height=1, value = newKey)
935
937 pass
938