def __init__(self,
                 master,
                 title=None,
                 callback=None,
                 size=5,
                 border=1,
                 tkCol=None,
                 immediate=1):
        #tkCol is a list of list where each elemnt is a color
        # tkCol[0][0] = a Tk color
        # size = size of the sqare representing the Tkcolor on the canvas
        # border = border size
        #
        if not master:
            master = tkinter.Toplevel()

        if title is not None:
            master.title(title)

        f = self.frame = tkinter.Frame(master)

        if tkCol:
            self.Xelemt = len(tkCol)
            self.Yelemt = len(tkCol[0])
            self.size = size
            self.border = border
            self.width = (self.Xelemt * self.size + 2 * self.border)
            self.height = (self.Yelemt * self.size + 2 * self.border)
            self.cwcanvas = tkinter.Canvas(f,
                                           width=self.width,
                                           height=self.height,
                                           borderwidth=3)

            xo = self.border
            for i in range(self.Xelemt):
                xe = xo + self.size
                yo = self.border
                for j in range(self.Yelemt):
                    ye = yo + self.size
                    self.cwcanvas.create_rectangle(xo,
                                                   yo,
                                                   xe,
                                                   ye,
                                                   fill=tkCol[i][j])
                    yo = ye
                xo = xe

        self.cwcanvas.pack()
        #self.frame.pack()

        # CallBack Manager
        self.cbManager = CallbackManager()
        if callback:
            if type(callback) in [list, tuple]:
                list(map(self.cbManager.AddCallback, callback))
            else:
                self.cbManager.AddCallback(callback)
Beispiel #2
0
    def __init__(self,
                 master=None,
                 name='XYZ',
                 callback=None,
                 callbackX=None,
                 widthX=100,
                 heightX=26,
                 wheelPadX=4,
                 labcfgX={'text': None},
                 widthY=100,
                 heightY=26,
                 wheelPadY=4,
                 labcfgY={'text': None},
                 callbackY=None,
                 widthZ=100,
                 heightZ=26,
                 wheelPadZ=4,
                 callbackZ=None,
                 labcfgZ={'text': None},
                 **kw):

        self.callback = callback  # user specified callback
        self.name = name  # title inside canvas

        self.widthX = widthX
        self.heightX = heightX
        self.wheelPadX = wheelPadX
        self.labcfgX = labcfgX
        self.widthY = widthY
        self.heightY = heightY
        self.wheelPadY = wheelPadY
        self.labcfgY = labcfgY
        self.widthZ = widthZ
        self.heightZ = heightZ
        self.wheelPadZ = wheelPadZ
        self.labcfgZ = labcfgZ

        #self.master = master = Tkinter.Frame(master)
        #Tkinter.Frame.__init__(self, master)
        #Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        self.frame = tkinter.Frame(master, relief='sunken', borderwidth=5)
        self.frame.pack(expand=1, fill='x')
        self.createEntries(self.frame)

        if self.callback:
            self.callbacks.AddCallback(self.callback)
    def __init__(self,
                 master,
                 title=None,
                 width=150,
                 height=50,
                 callback=None):
        #tkCol is a list of list where each elemnt is a color
        # tkCol[0][0] = a Tk color
        # size = size of the sqare representing the Tkcolor on the canvas
        # border = border size
        #
        if not master:
            master = tkinter.Toplevel()

        if title is not None:
            master.title(title)

        f = self.frame = tkinter.Frame(master)

        self.coeff = 0.0
        self.value = "%.1f" % self.coeff + '%'
        self.width = width
        self.height = height

        self.cwcanvas = tkinter.Canvas(f, width=self.width, height=self.height)
        self.wrect = self.cwcanvas.create_rectangle(0,
                                                    0,
                                                    100,
                                                    10,
                                                    outline='black',
                                                    fill='white')
        self.rrect = self.cwcanvas.create_rectangle(0,
                                                    0,
                                                    self.coeff,
                                                    10,
                                                    outline='black',
                                                    fill='red')
        self.labelvalue = self.cwcanvas.create_text(120, 10, text=self.value)

        self.cwcanvas.pack(side='top')
        #self.frame.pack()

        # CallBack Manager
        self.cbManager = CallbackManager()
        if callback:
            if type(callback) in [list, tuple]:
                list(map(self.cbManager.AddCallback, callback))
            else:
                self.cbManager.AddCallback(callback)
Beispiel #4
0
    def __init__(self,
                 master=None,
                 currentColor=(1.0, 1.0, 1.0),
                 mode='RGB',
                 commands=None,
                 immediate=1):
        assert mode in ['RGB', 'HSV', 'HEX']
        self.mode = mode
        if not master:
            self.master = tkinter.Toplevel()
        else:
            self.master = master
        self.afterID = None
        self.immediate = immediate
        # The editFrame is the main Frame of the widget
        self.editFrame = tkinter.Frame(self.master,
                                       borderwidth=2,
                                       relief='ridge')
        self.cbManager = CallbackManager()
        if commands:
            if type(commands) in [ListType, TupleType]:
                list(map(self.cbManager.AddCallback, commands))
            else:
                self.cbManager.AddCallback(commands)

        if mode == 'HSV':
            self.currentHSV = list(currentColor)
            self.currentRGB = list(ToRGB(currentColor))
            self.currentHEX = ToHEX(currentColor, mode='HSV')

        elif mode == 'RGB':
            self.currentRGB = list(currentColor)
            self.currentHSV = list(ToHSV(currentColor))
            self.currentHEX = ToHEX(currentColor, mode='RGB')

        elif mode == 'HEX':
            self.currentRGB = ToHEX(currentColor, mode='RGB')
            self.currentHSV = ToHEX(currentColor, mode='HSV')
            self.currentHEX = currentColor
        else:
            print('mode not recognized mode set to RGB')
        self.createColorEditor()
Beispiel #5
0
class GraphApp:
    
      
    # Initialization
    def __init__(self,master=None,callback=None,continuous=1):
               
        self.master=master
        self.callback = None
        self.callbacks = CallbackManager()
        self.canvas=canvas = Canvas(self.master,width=345,height=320,bg='white') 
        self.toolbar = Frame(master)             # Create Toolbar
        self.toolbar.pack(side='top', expand=1, fill='both') 
        self.menuFrame1 = Tkinter.Frame(self.toolbar, relief='raised', borderwidth=3)
        self.menuFrame1.pack(side='top', expand=1, fill='x')
        self.filebutton = Tkinter.Menubutton(self.menuFrame1, text='File')
        self.filebutton.pack(side='left')
        self.filemenu = Tkinter.Menu(self.filebutton, {})
        self.filemenu.add_command(label='Read', command=self.read_cb)
        self.filemenu.add_command(label='Write', command=self.write_cb)
        self.filebutton['menu'] = self.filemenu
        self.editbutton = Tkinter.Menubutton(self.menuFrame1, text='Edit')
        self.editbutton.pack(side='left', anchor='w')
        self.editmenu = Tkinter.Menu(self.editbutton, {})
        self.editmenu.add_command(label='Reset to first in history', command=self.resetAll_cb)
        self.editmenu.add_command(label='Step back in history loop', command=self.stepBack_cb)
        self.editmenu.add_command(label='Default Curve', command=self.defaultcurve_cb)
        self.editmenu.add_command(label='Invert Curve',command=self.invertGraph)
        self.histvar=IntVar()
        self.histvar.set(1)
        self.editmenu.add_checkbutton(label='Histogram',var=self.histvar,command=self.drawHistogram)
        self.editbutton['menu'] = self.editmenu
        self.optionType = IntVar()
        self.updatebutton = Tkinter.Menubutton(self.menuFrame1, text='Update')
        self.updatebutton.pack(side='left', anchor='w')
        self.updatemenu = Tkinter.Menu(self.updatebutton,{} )
        for v,s in {0:'Continuous',1:'MouseButtonUp',2:'Update'}.items():
            self.updatemenu.add_radiobutton(label=s,
                                var=self.optionType,
                                value = v,command=self.calloption)
        if continuous==1:
            self.optionType.set(0)
        self.updatebutton['menu'] = self.updatemenu
        #Curve Type
        self.CurveType = IntVar()
        self.CurveType.set(0) 
        self.Smooth=1
        self.curvebutton = Tkinter.Menubutton(self.menuFrame1, text='Curve')
        self.curvebutton.pack(side='left', anchor='w')
        self.curvemenu = Tkinter.Menu(self.curvebutton,{} )
        for v,s in {0:'Smooth',1:'Freehand'}.items():
            self.curvemenu.add_radiobutton(label=s,
                                var=self.CurveType,
                                value = v,command=self.curveoption)
        
            
        self.curvebutton['menu'] = self.curvemenu
        f1 = Tkinter.Frame(self.master)
        f1.pack(side='bottom', fill='both', expand=1)
        self.d1scalewheellab=Label(f1,text="Sensitivity")
        self.d1scalewheellab.pack(side="left")
        self.d1scalewheel=ThumbWheel(width=100, height=26,wheelPad=4,master=f1,labcfg={'fg':'black', 'side':'left', 'text':'Test:'},wheelLabcfg1={'font':(ensureFontCase('times'),14,'bold')},wheelLabcfg2={'font':(ensureFontCase('times'),14,'bold')},canvascfg={'bg':'blue'},min = 0.0,max = 1.0,precision =4,showlabel =0,value =0.013,continuous =0,oneTurn =0.01,size = 200)
        self.d1scalewheel.pack(side="left")
        #tooltip
        self.balloon = Pmw.Balloon(f1)
        self.balloon.bind(self.d1scalewheel,"cutoff value for differences in Z xoordinates,small values generate more contours")
        self.Updatebutton=Button(f1,text='  Update  ',command=self.Update)
        self.Updatebutton.pack(side=LEFT)
        
        self.Quitbutton=Button(f1,text=' Dismiss ',command=self.dismiss_cb)
        self.Quitbutton.pack(side=RIGHT)
        self.canvas.bind("<Button-1>", self.OnCanvasClicked)
        self.canvas.bind("<B1-Motion>", self.OnCanvasMouseDrag)
        self.canvas.bind("<ButtonRelease-1>", self.OnCanvasMouseUp)
        self.canvas.config(closeenough=2.0)
        self.canvas.pack(side=BOTTOM, fill=BOTH,expand=1)
        self.startpoint=(px,py)=(50,275)
        self.endpoint=(px1,py1)=(305,20)
        self.newpoints=[(px,py),(px1,py1)]
        self.canvas.create_rectangle([(px-1,py),(px1+1,py1)],fill='white',outline="black",width=1)
        self.canvas.create_text(46,281,text=0,anchor=N)
                  
        #Drawing Graph Sheet
        for i in range(1,6):
            x=50+i*50
            canvas.create_line(x,280,x,275,width=1)
            canvas.create_text(x,281,text='%d' %(50*i),anchor=N)
        for i in range(1,5):
            x=50+i*50
            canvas.create_line(x,275,x,20,width=1,fill="gray80")
        for i in range(1,6):
            y=275-i*50
            canvas.create_line(45,y,50,y,width=1)
            canvas.create_text(44,y,text='%d' %(50*i),anchor=E)
        for i in range(1,5):
            y=275-i*50
            canvas.create_line(50,y,305,y,width=1,fill="gray80")
        (x,y)=self.newpoints[0]
        (x1,y1)=self.newpoints[-1]
        self.curline=canvas.create_line(self.newpoints,fill='black',width=1)
        
        #GRAY SCALE
        grays=[]
        for i in range(0,100,1):
            grays.append("gray"+"%d" %i)
        #grays.reverse()
        #bottom one
        x1=48
        x2=51
        self.canvas.create_rectangle([(50,315),(307,300)],fill='white',outline="black",width=0.5)
        for a in grays:
            if x1>306:
                
               x1=x2=306
            self.canvas.create_rectangle([(x1+2.5,314),(x2+2.5,301)],fill=a,outline=a,width=1)
            x1=x1+2.5
            x2=x2+2.5
        #left one
        y1=274
        y2=271
        self.canvas.create_rectangle([(20,275),(5,20)],fill='black',outline="black",width=0.5)
        for a in grays:
            if y1>275:
                y1=y2=275
            self.canvas.create_rectangle([(19,y1-2.5),(6,y2-2.5)],fill=a,outline=a,width=1)    
            y1=y1-2.5
            y2=y2-2.5
              
        self.oldpoints=[]
        self.canvas.configure(cursor='cross')
        self.curovals=[]
        self.default_points=[(50,275),(88, 238), (101, 150), (154, 78), (75, 271),(305,20)]
        # now set the constructor options correctly using the configure method
        apply( self.configure, (),{'callback':callback,'continuous':continuous})
        self.continuous=continuous
        self.mousebuttonup=0
        self.update=0
        self.range_points=[]
        self.history=[]
        self.bars=[]
        self.default_ramp=[]
        self.histvalues=[]
        
    def calloption(self):
        tag=self.optionType.get()
        self.continuous=0
        self.mousebuttonup=0
        self.update=0
        if tag==0:
            self.continuous=1
        elif tag==1:
            self.mousebuttonup=1
        elif tag==2:    
            self.update=1
        
    def curveoption(self):
        tag=self.CurveType.get()
        self.Smooth=0
        self.Freehand=0
        if tag==0:
            self.Smooth=1
            self.canvas.delete(self.curline)
            self.curline=self.canvas.create_line(self.getControlPoints(),smooth=1)
        elif tag==1:
            self.Freehand=1
            self.canvas.delete(self.curline)
            self.curline=self.canvas.create_line(self.getControlPoints())
            
    def OnCanvasClicked(self,event):
        """Appends last drag point to controlpoint list if not appended by mouseleave func.
        when clicked on any controlpoint removes control point and draws line with remaining 
        control points.""" 
        self.CLICK_NODRAG=1 
        if self.history!=[]:
            if self.history[-1][1]!=self.d1scalewheel.get():
                self.history[-1]=(self.history[-1][0],self.d1scalewheel.get())
        if hasattr(self,"curx"): 
            if (self.curx,self.cury) :#not in [self.startpoint,self.endpoint]:
                (self.ox,self.oy)=(self.curx,self.cury)
                if (self.ox,self.oy) not in self.oldpoints:
                    self.oldpoints.append((self.ox,self.oy))
                    if hasattr(self,"curoval"):
                        self.curovals.append(self.curoval)
        self.OrgX=event.x
        self.OrgY=event.y
        CtlPoints=[]
        xcoords=[]
        ycoords=[]
        #Limiting points not to cross
        self.limit_xcoord=[]
        for i in range(0,10):
            xcoords.append(self.OrgX-i)
            ycoords.append(self.OrgY-i)
            xcoords.append(self.OrgX+i)
            ycoords.append(self.OrgY+i)
            
        if xcoords!=[] and ycoords!=[]:
            for x in xcoords:
                for y in ycoords:
                    CtlPoints.append((x,y))
            self.range_points=self.oldpoints
            self.range_points.sort()
            for c in CtlPoints:
             if  c in self.range_points:
                    index_c=self.range_points.index(c)
                    if index_c<len(self.range_points)-1:
                        self.limit_xcoord.append(self.range_points[index_c+1])
                        
                        if index_c>0:
                            self.limit_xcoord.append(self.range_points[index_c-1])
                            return
                        else:
                            self.limit_xcoord.append(self.startpoint)
                            return
                    elif index_c==len(self.range_points)-1:
                        self.limit_xcoord.append(self.range_points[index_c-1])
                        self.limit_xcoord.append(self.endpoint)
                        return 
        self.newd1ramp= self.caluculate_ramp()
        
    
    def OnCanvasMouseUp(self,event):
             
        CtlPoints=[]
        xcoords=[]
        ycoords=[]
        if hasattr(self,"curx"): 
            (self.ox,self.oy)=(self.curx,self.cury)
            if (self.ox,self.oy) not in self.oldpoints :#not in [self.startpoint,self.endpoint] :
                self.oldpoints.append((self.ox,self.oy))     
                if hasattr(self,"curoval"):
                    if self.curoval not in self.curovals:
                        self.curovals.append(self.curoval)
        
        if self.CLICK_NODRAG==1:
         #finding out points around the selected point
         for i in range(0,10):
            xcoords.append(self.OrgX-i)
            ycoords.append(self.OrgY-i)
            xcoords.append(self.OrgX+i)
            ycoords.append(self.OrgY+i)
            
         if xcoords!=[] and ycoords!=[]:
            for x in xcoords:
                for y in ycoords:
                    CtlPoints.append((x,y))
            
            for c in CtlPoints:
             if  c in self.oldpoints:
                ind=self.oldpoints.index(c)
                op=self.oldpoints[ind]
                if ind>0:
                    prev_oldpoint=self.oldpoints[ind-1]
                else:
                    prev_oldpoint=self.endpoint
                del self.oldpoints[ind]
                
                for co in self.curovals:
                    ov_point1=self.canvas.coords(co)
                    if len(ov_point1)!=0:
                        ov_point=(int(ov_point1[0]+2),int(ov_point1[1]+2))
                                    
                        if ov_point==c  and ov_point not in [self.startpoint,self.endpoint]:
                            self.canvas.delete(co)
                            self.curovals.remove(co) 
                            if hasattr(self,"curx"): 
                             if ov_point==(self.curx,self.cury):
                                (self.curx,self.cury)=prev_oldpoint
                                                            
                            self.draw()
        if  self.mousebuttonup:
            self.newd1ramp=self.caluculate_ramp()
            self.callbacks.CallCallbacks(self.newd1ramp)
        
        self.history.append((deepCopySeq(self.oldpoints),self.d1scalewheel.get()))
        
    
        
    
    def OnCanvasMouseDrag(self,event):
        self.CLICK_NODRAG=0
        CtlPoints=[]
        xcoords=[]
        ycoords=[]
        #making active clickrange to be ten points around clicked point  
        for i in range(0,10):
            xcoords.append(self.OrgX-i)
            ycoords.append(self.OrgY-i)
            xcoords.append(self.OrgX+i)
            ycoords.append(self.OrgY+i)
            
        if xcoords!=[] and ycoords!=[]:
            for x in xcoords:
                for y in ycoords:
                    CtlPoints.append((x,y))
            
            for c in CtlPoints:
             if  c in self.oldpoints:
                ind=self.oldpoints.index(c)
                op=self.oldpoints[ind]
                del self.oldpoints[ind]
                
                for co in self.curovals:
                    ov_point1=self.canvas.coords(co)
                    if len(ov_point1)!=0:
                        ov_point=(int(round(ov_point1[0],3))+2,int(round(ov_point1[1],3))+2)
                                    
                        if ov_point==c :
                            self.canvas.delete(co)
                            self.curovals.remove(co)
                            
        self.curx=dx=event.x
        self.cury=dy=event.y
        self.draw() 
        
    def draw(self):
        """Draws line,ovals with current controlpoints. """
        new1points=[]
        curve_points=[]
        self.smoothened_points=[]
        if self.CLICK_NODRAG==0:
            dx=self.curx
            dy=self.cury
        else:
            (dx,dy)=(self.curx,self.cury)=(self.endpoint)
        ###Limiting  xcoords of the current point not to cross adjacent points
        if hasattr(self,"limit_xcoord"):
         if self.limit_xcoord!=[]:
            self.limit_xcoord.sort()
            if  (self.curx,self.cury) not in [self.startpoint,self.endpoint]:
                if (self.curx,self.cury)< self.limit_xcoord[0]:
                    if self.curx<=self.limit_xcoord[0][0] and self.cury<self.limit_xcoord[0][1]:
                        dx=self.curx=self.limit_xcoord[0][0]+1
                    if  self.curx<=self.limit_xcoord[0][0] and self.cury>self.limit_xcoord[0][1]:
                        dx=self.curx=self.limit_xcoord[0][0]
                if  (self.curx,self.cury)> self.limit_xcoord[1]:
                    if self.curx>=self.limit_xcoord[1][0] and self.cury>self.limit_xcoord[1][1]:
                        dx=self.curx=self.limit_xcoord[1][0]-1
                    if self.curx>=self.limit_xcoord[1][0] and self.cury<self.limit_xcoord[1][1]:
                        dx=self.curx=self.limit_xcoord[1][0]
        #Limit graph with in the axis
        if self.curx not in range(50,305):
                if self.curx<50:
                    self.curx=dx=50
                else:
                    self.curx=dx=305
                    
        if self.cury not in range(20,275):
                if self.cury<20:
                    self.cury=dy=20
                else:
                    self.cury=dy=275
        #adding start,end points  
        new1points.append(self.startpoint)
        new1points.append(self.endpoint)
        #adding current point to list
        if (dx,dy) not in new1points and (dx,dy) not in [self.startpoint,self.endpoint]:
            new1points.append((dx,dy))
        #adding oldpoints to list
        if hasattr(self,"ox"):
          for op in self.oldpoints:
                if op not in new1points:
                    new1points.append(op)
        new1points.sort()
        #removing oval point that is on drag
        if hasattr(self,"curoval"):
            if self.curoval not in self.curovals:
               self.canvas.delete(self.curoval)
        self.canvas.delete(self.curline)
        #if points that start with 50 or 51  or 305,304 other than start ,end
        #points exists remove start or end points
        #remove ovals
        #finding oval for start point and endpoint
        for i in new1points:
            if i[0]==51 or i[0]==50:
                if i!=self.startpoint:
                    if self.startpoint in new1points:
                        new1points.remove(self.startpoint)
                        ###removing start point oval 
                        x = 50
                        y = 275
                        st_oval_1= self.canvas.find_enclosed(x-3,y-3,x+3,y+3)
                         
                        if st_oval_1:
                            for so in st_oval_1:
                                if so!=[]:
                                    st_oval=so
                                    st_oval_coords=self.canvas.coords(st_oval)
                                    if (int(st_oval_coords[0]+2),int(st_oval_coords[1]+2))==self.startpoint: 
                                        self.canvas.delete(st_oval)
                                        if st_oval in self.curovals:
                                            self.curovals.remove(st_oval)
                        
                        
        for i in new1points:   
            if i[0]==304 or i[0]==305: 
                if i!=self.endpoint :
                    if self.endpoint in new1points:
                        new1points.remove(self.endpoint)
                        ###removing end point oval
                        x = 305
                        y = 20
                        end_oval_1= self.canvas.find_enclosed(x-3,y-3,x+3,y+3)
                        if end_oval_1:
                            for eo in end_oval_1:
                                if eo!=[]:
                                    end_oval=eo
                                    end_oval_coords=self.canvas.coords(end_oval)
                                    if (int(end_oval_coords[0]+2),int(end_oval_coords[1]+2))==self.endpoint: 
                                        self.canvas.delete(end_oval)
                                        if end_oval in self.curovals:
                                            self.curovals.remove(end_oval)
        new1points.sort()
          
        for (x,y) in new1points:
            curve_points.append(x)
            curve_points.append(y)
        self.smoothened_points= self.smooth(curve_points)
        #drawing line
        if len(self.smoothened_points)>2: 
            if self.Smooth:
                self.curline=self.canvas.create_line(self.smoothened_points)
            else:
                self.curline=self.canvas.create_line(curve_points)
        else:
            
            if curve_points[0]==50 or 51:
                 if self.Smooth:
                    self.curline=self.canvas.create_line(curve_points,smooth=1)
                 else:
                    self.curline=self.canvas.create_line(curve_points)   
            else:    
                self.curline=self.canvas.create_line(self.startpoint,self.endpoint)
        
        ##Adding oval when start or end point in new1points
        coval_coords=[]
        for i in self.curovals:
            coval_coords.append(self.canvas.coords(i))
        if self.endpoint in new1points:
            co=self.canvas.create_oval(self.endpoint[0]-2,self.endpoint[-1]-2,self.endpoint[0]+2,self.endpoint[-1]+2,width=1,outline='black',fill='black')
            endco_coords =self.canvas.coords(co)
            if endco_coords not in  coval_coords:
                self.curovals.append(co)
        if self.startpoint in new1points:
            co=self.canvas.create_oval(self.startpoint[0]-2,self.startpoint[-1]-2,self.startpoint[0]+2,self.startpoint[-1]+2,width=1,outline='black',fill='black')          
            startco_coords=self.canvas.coords(co)
            if startco_coords not in  coval_coords:
                self.curovals.append(co)
        #drawing ovals
        if (self.curx,self.cury)!=self.endpoint:
            self.curoval=self.canvas.create_oval(self.curx-2,self.cury-2,self.curx+2,self.cury+2,width=1,outline='black',fill='black') 
            
        if (self.curx,self.cury)==self.endpoint and self.endpoint in new1points:
            self.curoval=self.canvas.create_oval(self.curx-2,self.cury-2,self.curx+2,self.cury+2,width=1,outline='black',fill='black')
        self.newd1ramp= self.caluculate_ramp()
        if self.continuous:
                self.callbacks.CallCallbacks(self.newd1ramp)
            
  
        
    ########  convert coordinates to ramp##################  
    def caluculate_ramp(self):
        """ 
        """
        dramp=[] 
        mypoints=[]
        mynewpoints=[]
        self.oldpoints.sort()
        calcpoints=[]
        #if self.continuous :
        if hasattr(self,"curx"):
                if (self.curx,self.cury) not in self.oldpoints and (self.curx,self.cury) not in [self.startpoint,self.endpoint]:
                    calcpoints.append((self.curx,self.cury))
        if len(self.oldpoints)!=0:
            for o in self.oldpoints:
                if o not in calcpoints:
                    calcpoints.append(o)
        if self.startpoint not in calcpoints:
                calcpoints.append(self.startpoint)
        if self.endpoint not in calcpoints:
                calcpoints.append(self.endpoint)
        
        calcpoints.sort()    
        length=len(calcpoints)
        for l in range(length):
            if l+1<=length-1:
                mypoints=[calcpoints[l],calcpoints[l+1]]
                if calcpoints[l] not in mynewpoints:
                    mynewpoints.append( calcpoints[l])   
                
                (x1,y1)=calcpoints[l]
                (x2,y2)=calcpoints[l+1]
                if x1>x2:
                    dcx=x1-x2
                    px=x1-1
                else:
                    dcx=x2-x1
                    px=x1+1
                if y1>y2:
                    dcy=y1-y2
                    if dcx>=1:
                        py=y1-float(dcy)/float(dcx)
                    else:
                        py=y1
                else:   
                    dcy=y2-y1
                    if dcx>=1:
                        py=y1+float(dcy)/float(dcx)
                    else:
                        py=y2
                mynewpoints.append( (px,int(round(py))))
                for dc in range(dcx-1):
                    
                    if x1>x2:
                        px=px-1
                    else:
                        px=px+1
                    if y1>y2:
                        if dcx>=1:
                            py=py-float(dcy)/float(dcx)
                        else:
                            py=y1
                    else:
                        if dcx>=1:
                            py=py+float(dcy)/float(dcx)
                        else:
                            py=y2
                    mynewpoints.append( (px,int(round(py))))
        ramp=[]
        for r in mynewpoints:
            #scale
            ra=float(275-r[1])
            if ra>=256:
                ra=255.0
            ramp.append(ra)
            dramp=Numeric.array(ramp,'f')
        if len(dramp)!=0:
            return   dramp     
        else:
            dramp=Numeric.arange(0,256,1,'f')
            return   dramp
        
    def get(self):
        if hasattr(self,"newd1ramp"):
           return self.newd1ramp
        else:    
            return self.caluculate_ramp()
        
    def configure(self, **kw):
        if 'type' in kw.keys(): # make sure type is set first
            self.setType(kw['type'])
            del kw['type']
            
        for key,value in kw.items():
            if key=='callback': 
                self.setCallbacks(value)
            
   
    def setCallbacks(self, cb):
        """Set widget callback. Must be callable function. Callback is called
every time the widget value is set/modified"""

        assert cb is None or callable(cb) or type(cb) is types.ListType,\
               "Illegal callback: must be either None or callable. Got %s"%cb
        if cb is None: return
        elif type(cb) is types.ListType:
            for func in cb:
                assert callable(func), "Illegal callback must be callable. Got %s"%func
                self.callbacks.AddCallback(func)
        else:
            self.callbacks.AddCallback(cb)
        self.callback = cb
        

    def invertGraph(self):
        """This function is for inverting graph by reverse computing controlpoints"""
        if self.history!=[]:
            if self.history[-1][1]!=self.d1scalewheel.get():
                self.history[-1]=(self.history[-1][0],self.d1scalewheel.get())
        invert_points=[]
        #self.oldpoints=[]
        points=self.getControlPoints()
        if len(points)<2:
            points=[self.startpoint,self.endpoint]
        for p in points:
            if p[1] in range(20,276):
                y=275 -(p[1]-20)
                invert_points.append((p[0],y))
        self.reset()
        ###################################################
        #Some times start and end points are not deleted 
        #So for deleting them canvas.find_enclosed points at
        #startpoint and endpoint are caluculated(returns alist of
        #canvas objects present there) and if the coords of
        #any canvas objects matches with start or end point that gets deleted
        #####################################################             
        x = 50
        y = 275
        st_oval_1= self.canvas.find_enclosed(x-3,y-3,x+3,y+3)
        if st_oval_1:
            for so in st_oval_1:
                if so!=[]:
                    st_oval=so
                    st_oval_coords=self.canvas.coords(st_oval)
                    if (int(st_oval_coords[0]+2),int(st_oval_coords[1]+2))==self.startpoint: 
                        self.canvas.delete(st_oval)
                        if st_oval in self.curovals:
                            self.curovals.remove(st_oval)
        x = 305
        y = 20
        end_oval_1= self.canvas.find_enclosed(x-3,y-3,x+3,y+3)
        if end_oval_1:
            for eo in end_oval_1:
                if eo!=[]:
                    end_oval=eo
                    end_oval_coords=self.canvas.coords(end_oval)
                    if (int(end_oval_coords[0]+2),int(end_oval_coords[1]+2))==self.endpoint: 
                        self.canvas.delete(end_oval)
                        if end_oval in self.curovals:
                            self.curovals.remove(end_oval)
        self.canvas.delete(self.curline)
        if self.Smooth:
              self.curline=self.canvas.create_line(invert_points,smooth=1)  
        else:
                self.curline=self.canvas.create_line(invert_points)
        self.oldpoints=invert_points
        for p in invert_points:
            self.curoval=self.canvas.create_oval(p[0]-2,p[1]-2,p[0]+2,p[1]+2,width=1,outline='black',fill='black')
            self.curovals.append(self.curoval)
        (self.curx,self.cury) =invert_points[-2]    
        if self.continuous or self.mousebuttonup:
            self.newd1ramp=self.caluculate_ramp()
            self.callbacks.CallCallbacks([self.newd1ramp])
        self.history.append((deepCopySeq(self.oldpoints),self.d1scalewheel.get()))
         

    def defaultcurve_cb(self):
        """draws curve with default points"""
        if self.history!=[]:
            if self.history[-1][1]!=self.d1scalewheel.get():
                self.history[-1]=(self.history[-1][0],self.d1scalewheel.get())
        points=[]
        self.default_points=[]
        self.oldpoints=[]
        self.d1scalewheel.set(0.013)
        self.default_points=[(50,275),(88, 238), (101, 150), (154, 78), (75, 271),(305,20)]
        self.reset()
        self.canvas.delete(self.curline)
        self.default_points.sort()
        if self.Smooth:
            self.curline=self.canvas.create_line(self.default_points,smooth=1) 
        else:
                self.curline=self.canvas.create_line(self.default_points)
        self.oldpoints=self.default_points
        for p in self.default_points:
            self.curoval=self.canvas.create_oval(p[0]-2,p[1]-2,p[0]+2,p[1]+2,width=1,outline='black',fill='black')
            self.curovals.append(self.curoval)
        (self.curx,self.cury) =self.default_points[-2]    
        if self.continuous or self.mousebuttonup:
            self.newd1ramp=self.caluculate_ramp()
            self.callbacks.CallCallbacks(self.newd1ramp)
        self.history.append((deepCopySeq(self.oldpoints),self.d1scalewheel.get()))
        self.default_ramp= self.newd1ramp
        
    def read_cb(self):
        fileTypes = [("Graph",'*_Graph.py'), ("any file",'*.*')]
        fileBrowserTitle = "Read Graph"
        fileName  = self.fileOpenAsk(types=fileTypes,
                                     title=fileBrowserTitle)
        if not fileName:
            return
        self.read(fileName)

    def read( self,fileName):
        if self.history!=[]:
            if self.history[-1][1]!=self.d1scalewheel.get():
                self.history[-1]=(self.history[-1][0],self.d1scalewheel.get())
        fptr=open(fileName,"r")
        data=fptr.readlines()
        cpoints=data[0][:-1]
        sensitivity=data[1]
        self.d1scalewheel.set(eval(sensitivity))
        if len(cpoints)==0:
            return
        else:
            points=cpoints
        self.oldpoints=[]        
        self.reset()
        if hasattr(self,"curline"):
            self.canvas.delete(self.curline)
            for c in self.curovals:
                self.canvas.delete(c)
                self.curovals.remove(c)
            if hasattr(self,"curoval"):
                self.canvas.delete(self.curoval)
            self.curovals=[]
            if self.Smooth:
                self.curline=self.canvas.create_line(eval(points),smooth=1)
            else:
                self.curline=self.canvas.create_line(eval(points))
            self.readpoints=self.oldpoints=eval(points)[1:-1]
            for p in eval(points)[1:-1]:
                self.curoval=self.canvas.create_oval(p[0]-2,p[1]-2,p[0]+2,p[1]+2,width=1,outline='black',fill='black')
                self.curovals.append(self.curoval)
            (self.curx,self.cury) =eval(points)[-2]
            self.history.append((deepCopySeq(self.oldpoints),self.d1scalewheel.get()))

    def fileOpenAsk(self, idir=None, ifile=None, types=None,
                    title='Open'):
        if types==None: types = [ ('All files', '*') ]
        file = tkFileDialog.askopenfilename( filetypes=types,
                                             initialdir=idir,
                                             initialfile=ifile,
                                             title=title)
        if file=='': file = None
        return file 
    
    def write_cb(self):
        fileTypes = [("Graph",'*_Graph.py'), ("any file",'*.*')]
        fileBrowserTitle = "Write Graph"
        fileName  = self.fileSaveAsk(types=fileTypes,
                                     title=fileBrowserTitle)
        if not fileName:
            return
        self.write(fileName)
    
    def write(self,fileName):
        fptr=open(fileName,"w")
        points= self.getControlPoints()        
        points.sort()
        fptr.write(str(points))
        fptr.write("\n")
        fptr.write(str(self.d1scalewheel.get()))
        fptr.close()
        
    def fileSaveAsk(self, idir=None, ifile=None, types = None,
                title='Save'):
        if types==None: types = [ ('All files', '*') ]
        file = tkFileDialog.asksaveasfilename( filetypes=types,
                                               initialdir=idir,
                                               initialfile=ifile,
                                               title=title)
        if file=='': file = None
        return file
        
    def reset(self):
        """This function deletes current line removes current ovals"""  
        self.canvas.delete(self.curline)
        self.oldpoints=[]
        for c in self.curovals:
            self.canvas.delete(c)
        if hasattr(self,"curoval"):
            self.canvas.delete(self.curoval)
        self.curovals=[]
        if hasattr(self,"curoval"):
            delattr(self,"curoval")
        if hasattr(self,"curx"):
            delattr(self,"curx")
        

    def resetAll_cb(self):
        """Resetting curve as slant line 0 to 255"""
        self.reset()    
        self.curline=self.canvas.create_line([self.startpoint,self.endpoint],width=1,fill='black')
        for p in [self.startpoint,self.endpoint]:
            self.curoval=self.canvas.create_oval(p[0]-2,p[1]-2,p[0]+2,p[1]+2,width=1,outline='black',fill='black') 
            self.curovals.append(self.curoval)
        self.oldpoints=[self.startpoint,self.endpoint]
        (self.curx,self.cury)=self.endpoint
        self.d1scalewheel.set(0.013)
        
        if self.continuous or self.mousebuttonup:
            self.newd1ramp=Numeric.arange(0,256,1,'f')
            self.callbacks.CallCallbacks(self.newd1ramp)
        #self.histvar.set(0)
        self.history=[]
        
        
    def stepBack_cb(self):
        """when stepBack button clicked previous step is displayed.History of
        all the steps done is remembered and when stepback clicked from history
        list previous step is shown and that step is removed from history list """
        
        if self.history!=[]:
            if len(self.history)==1:
                self.resetAll_cb()
            
            else:
                del self.history[-1]
                pns = self.history[-1][0]
                #deleting 
                self.oldpoints=pns
                self.canvas.delete(self.curline)
                for c in self.curovals:
                    self.canvas.delete(c)
                if hasattr(self,"curoval"):
                    self.canvas.delete(self.curoval)
                self.curovals=[]
                ###################################################
                #Some times start and end points are not deleted 
                #So for deleting them canvas.find_enclosed points at
                #startpoint and endpoint are caluculated(returns alist of
                #canvas objects present there) and if the coords of
                #any canvas objects matches with start or end point that gets deleted
                #####################################################             
                x = 50
                y = 275
                st_oval_1= self.canvas.find_enclosed(x-3,y-3,x+3,y+3)
                if st_oval_1:
                            for so in st_oval_1:
                                if so!=[]:
                                    st_oval=so
                                    st_oval_coords=self.canvas.coords(st_oval)
                                    if (int(st_oval_coords[0]+2),int(st_oval_coords[1]+2))==self.startpoint: 
                                        self.canvas.delete(st_oval)
                                        if st_oval in self.curovals:
                                            self.curovals.remove(st_oval)
                x = 305
                y = 20
                end_oval_1= self.canvas.find_enclosed(x-3,y-3,x+3,y+3)
                if end_oval_1:
                            for eo in end_oval_1:
                                if eo!=[]:
                                    end_oval=eo
                                    end_oval_coords=self.canvas.coords(end_oval)
                                    if (int(end_oval_coords[0]+2),int(end_oval_coords[1]+2))==self.endpoint: 
                                        self.canvas.delete(end_oval)
                                        if end_oval in self.curovals:
                                            self.curovals.remove(end_oval)
                
                
                
                pns.sort()
                #if no start or end points 
                if pns[0][0]>51 :
                    pns.insert(0,self.startpoint)
                l=len(pns) 
                if pns[-1][0]<304:
                    pns.insert(l,self.endpoint)
                
                #if start or endpoints and points with (50or 51) or (305or305)
                if self.startpoint in pns:
                    for p in pns:
                        if p!=self.startpoint:
                            if p[0]== 50 or p[0]==51:
                               pns.remove(self.startpoint)
                if self.endpoint in pns:
                    for p in pns:
                        if p!=self.endpoint:
                            if p[0]==305 or p[0]==304:
                                pns.remove(self.endpoint)
                      
                print pns
                if self.Smooth:
                    self.curline=self.canvas.create_line(pns,width=1,fill='black',smooth=1)
                else:
                    self.curline=self.canvas.create_line(pns,width=1,fill='black')
                
                for p in pns:
                    self.curoval=self.canvas.create_oval(p[0]-2,p[1]-2,p[0]+2,p[1]+2,width=1,outline='black',fill='black')
                    self.curovals.append(self.curoval)
                self.d1scalewheel.set(self.history[-1][1])
                
                 
                if self.continuous or self.mousebuttonup:
                    self.newd1ramp=Numeric.arange(0,256,1,'f')
                    self.callbacks.CallCallbacks(self.newd1ramp)
                (self.curx,self.cury)=self.endpoint    
    def getControlPoints(self):
        """fuction to get current control points of the curve"""
        if not self.oldpoints==[self.startpoint,self.endpoint]:
          for i in range(len(self.oldpoints)):
            if self.startpoint  in self.oldpoints:
                self.oldpoints.remove(self.startpoint)
            if self.endpoint in self.oldpoints:
                self.oldpoints.remove(self.endpoint)
        self.controlpoints=[]
        
        if hasattr(self,"curoval"):
           c=self.canvas.coords(self.curoval)
           if len(c)!=0:
                if (int(c[0]+2),int(c[1]+2)) not in self.oldpoints and (int(c[0]+2),int(c[1]+2)) not in [self.startpoint,self.endpoint]:
                    self.controlpoints.append((int(c[0]+2),int(c[1]+2))) 
        for op in self.oldpoints:
                self.controlpoints.append(op)
        self.controlpoints.sort()
        if len(self.controlpoints)>0:
            if self.controlpoints[0][0]==50 or self.controlpoints[0][0]==51 :
                pass
            else:
                self.controlpoints.append(self.startpoint)
            self.controlpoints.sort()
            if self.controlpoints[-1][0]==305 or self.controlpoints[-1][0]==304:
                pass
            else:
                self.controlpoints.append(self.endpoint)
            self.controlpoints.sort() 
        return  self.controlpoints   
                
    def setControlPoints(self,points):
        """function to set curve control points"""
        assert isinstance(points, types.ListType),"Illegal type for points"
        
        for (x,y) in points:
            assert  x in range(50,306),"coordinates are out of range,x should be in [50,305]"
            assert  y in range(20,276),"coordinates are out of range,y should be in [20,275]"
                
        self.oldpoints=[]
        self.controlpoints=[]
        self.reset()
        self.oldpoints=self.controlpoints=points
        self.controlpoints.sort()
        if self.controlpoints[0]!=self.startpoint:
            self.controlpoints.append(self.startpoint)
        if  self.controlpoints[-1]!=self.endpoint:
            self.controlpoints.append(self.endpoint)
        self.canvas.delete(self.curline)   
        self.controlpoints.sort()
        if self.Smooth:
            self.curline=self.canvas.create_line( self.controlpoints,smooth=1)
        else:
            self.curline=self.canvas.create_line( self.controlpoints)
        for p in self.controlpoints[1:-1]:
            self.curoval=self.canvas.create_oval(p[0]-2,p[1]-2,p[0]+2,p[1]+2,width=1,outline='black',fill='black')
            self.curovals.append(self.curoval)
        (self.curx,self.cury)=   self.controlpoints[-2] 
        self.history.append((deepCopySeq(self.oldpoints),self.d1scalewheel.get()))
        if self.continuous or self.mousebuttonup:
            self.newd1ramp=self.caluculate_ramp()
            self.callbacks.CallCallbacks(self.newd1ramp)
             
    def setSensitivity(self,val):
        self.d1scalewheel.set(val)
        
    def Update(self):
        if self.update==1:
            dramp=self.caluculate_ramp()
            self.newd1ramp=dramp
            self.callbacks.CallCallbacks(dramp)
                
    def dismiss_cb(self):
       
       try:
            if self.master.winfo_ismapped():
                self.master.withdraw()
       except:
            if self.master.master.winfo_ismapped():
                self.master.master.withdraw()

        
    #draw Histogram

    def removeHistogram(self):
        """removes Histograms"""
        for b in self.bars:
            self.canvas.delete(b)
        self.bars=[]
    
    def drawHistogram(self):
       """This function draws histogram from list of pixel counts ,one for
            each value in the source image"""        
       self.removeHistogram()
       if self.histvar.get():
           h=self.histvalues 
           if h==[]:
            return
           list_pixels_count=h
           c=[]
           maxc=max(list_pixels_count)
           if maxc==0:
            return
           if list_pixels_count.index(maxc):
                
                list_pixels_count.remove(maxc)
                list_pixels_count.insert(255,0)
           
           for i in list_pixels_count[:256]:
                max_list=max(list_pixels_count)
                if max_list==0:
                    return
                val=i*200/max_list
                c.append(val)
           
           for i in range(0,len(c)):
                x1=50+i
                x2=50+i
                y1=275-c[i]
                y2=275
                r=self.canvas.create_line([(x1,y1),(x2,y2)],fill="gray70",width=1)
                
                self.bars.append(r)
           #displaying line and ovals ontop
           self.canvas.tkraise(self.curline)
           for i in self.curovals:
                self.canvas.tkraise(i)
           if hasattr(self,"curoval"):
                self.canvas.tkraise(self.curoval)
           self.canvas.update()
           ##Update Histograms on Graphtool
           #if self.update!=1:
           #      prev_option=self.optionType.get()
           #      self.optionType.set(2)
           #      self.update=1
           #      self.Update()
           #      self.optionType.set(prev_option)
           #      self.update=0
           #      return
           
               
    ################SMOOTHING  CODE############################
    def addcurve(self,out, xy, steps):
        
        add = out.append
        for i in range(1, steps+1):
            t = float(i) / steps; t2 = t*t; t3 = t2*t
            u = 1.0 - t; u2 = u*u; u3 = u2*u
            add(xy[0]*u3 + 3*(xy[2]*t*u2 + xy[4]*t2*u) + xy[6]*t3)
            add(xy[1]*u3 + 3*(xy[3]*t*u2 + xy[5]*t2*u) + xy[7]*t3)

    def smooth(self,xy, steps=12):
        
        if not xy:
            return xy
        closed = xy[0] == xy[-2] and xy[1] == xy[-1]
        out = []
        if closed:
            # connect end segment to first segment
            control = (
            0.500*xy[-4] + 0.500*xy[0],
            0.500*xy[-3] + 0.500*xy[1],
            0.167*xy[-4] + 0.833*xy[0],
            0.167*xy[-3] + 0.833*xy[1],
            0.833*xy[0]  + 0.167*xy[2],
            0.833*xy[1]  + 0.167*xy[3],
            0.500*xy[0]  + 0.500*xy[2],
            0.500*xy[1]  + 0.500*xy[3],
            )
            out = [control[0], control[1]]
            self.addcurve(out, control, steps)
        else:
            out = [xy[0], xy[1]]
        for i in range(0, len(xy)-4, 2):
            if i == 0 and not closed:
                control = (xy[i],xy[i+1],0.333*xy[i] + 0.667*xy[i+2],0.333*xy[i+1] + 0.667*xy[i+3],)
            else:
                control = (
                0.500*xy[i] + 0.500*xy[i+2],
                0.500*xy[i+1] + 0.500*xy[i+3],
                0.167*xy[i] + 0.833*xy[i+2],
                0.167*xy[i+1] + 0.833*xy[i+3],
                )
            if i == len(xy)-6 and not closed:
                control = control + (
                0.667*xy[i+2] + 0.333*xy[i+4],
                0.667*xy[i+3] + 0.333*xy[i+5],
                xy[i+4],
                xy[i+5],
                )
            else:
                control = control + (
                0.833*xy[i+2] + 0.167*xy[i+4],
                0.833*xy[i+3] + 0.167*xy[i+5],
                0.500*xy[i+2] + 0.500*xy[i+4],
                0.500*xy[i+3] + 0.500*xy[i+5],
                )
            if ((xy[i] == xy[i+2] and xy[i+1] == xy[i+3]) or
                (xy[i+2] == xy[i+4] and xy[i+3] == xy[i+5])):
                out.append(control[6])
                out.append(control[7])
            else:
                self.addcurve(out, control, steps)
        return out 
Beispiel #6
0
    def __init__(self,
                 master=None,
                 type='float',
                 labCfg={
                     'fg': 'black',
                     'side': 'left',
                     'text': None
                 },
                 min=None,
                 max=None,
                 increment=.0,
                 precision=2,
                 showLabel=1,
                 value=0.0,
                 continuous=1,
                 oneTurn=360.,
                 size=50,
                 callback=None,
                 lockMin=0,
                 lockBMin=0,
                 lockMax=0,
                 lockBMax=0,
                 lockIncrement=0,
                 lockBIncrement=0,
                 lockPrecision=0,
                 lockShowLabel=0,
                 lockValue=0,
                 lockType=0,
                 lockContinuous=0,
                 lockOneTurn=0,
                 **kw):

        Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        # initialize various attributes with default values
        self.precision = 2  # decimal places
        self.min = None  # minimum value
        self.max = None  # maximum value
        self.increment = increment  # value increment
        self.minOld = 0.  # used to store old values
        self.maxOld = 0.
        self.incrementOld = increment
        self.size = 50  # defines widget size
        self.offsetValue = 0.  # used to set increment correctly
        self.lab = None  # label
        self.callback = None  # user specified callback
        self.opPanel = None  # option panel widget
        self.oneTurn = 360.  # value increment for 1 full turn
        self.value = 0.0  # current value of widget
        self.oldValue = 0.0  # old value of widget
        self.showLabel = 1  # turn on to display label on
        self.continuous = 1  # set to 1 to call callbacks at
        # each value change, else gets called
        # on button release event
        self.angle = 0.  # angle corresponding to value

        self.labCfg = labCfg  # Tkinter Label options
        self.labelFont = (ensureFontCase('helvetica'), 14, 'bold'
                          )  # label font
        self.labelColor = 'yellow'  # label color
        self.canvas = None  # the canvas to create the widget in
        self.usedArcColor = '#aaaaaa'  # filled arc color of used portion
        self.unusedArcColor = '#cccccc'  # filled arc color of unused portion
        self.pyOver180 = math.pi / 180.0  # constants used in various places
        self.threeSixtyOver1turn = 1
        self.piOver1turn = math.pi / 360.

        self.lockMin = lockMin  # lock<X> vars are used in self.lock()
        self.lockMax = lockMax  # to lock/unlock entries in optionpanel
        self.lockIncrement = lockIncrement
        self.lockBMin = lockBMin
        self.lockBMax = lockBMax
        self.lockBIncrement = lockBIncrement
        self.lockPrecision = lockPrecision
        self.lockShowLabel = lockShowLabel
        self.lockValue = lockValue
        self.lockType = lockType
        self.lockContinuous = lockContinuous
        self.lockOneTurn = lockOneTurn

        self.setArrow()

        # configure with user-defined values
        self.setSize(size)
        self.setCallback(callback)
        self.setContinuous(continuous)

        self.setType(type)
        self.setPrecision(precision)
        self.setOneTurn(oneTurn)
        self.setMin(min)
        self.setMax(max)
        self.setIncrement(increment)

        self.setShowLabel(showLabel)

        self.setValue(value)

        self.setLabel(self.labCfg)

        self.createCanvas(master)

        canvas = self.canvas
        canvas.bind("<ButtonPress-1>", self.mouseDown)
        canvas.bind("<ButtonRelease-1>", self.mouseUp)
        canvas.bind("<B1-Motion>", self.mouseMove)
        canvas.bind("<Button-3>", self.toggleOptPanel)

        if os.name == 'nt':  #sys.platform == 'win32':
            canvas.bind("<MouseWheel>", self.mouseWheel)
        else:
            canvas.bind("<Button-4>", self.mouseWheel)
            canvas.bind("<Button-5>", self.mouseWheel)

        KeyboardEntry.__init__(self, (canvas, ), self.setFromEntry)

        self.opPanel = OptionsPanel(master=self, title="Dial Options")
Beispiel #7
0
class Dial(Tkinter.Frame, KeyboardEntry):
    """This class implements a Dial widget.
The widget has a pointer that can be moved around a circle.
The range corresponding to one full turn can be specified as well as the min
and max values that are allowed. By defaults these are set to None meaning that
there is no min and no max. One turn corresponds to 360 units by default.
A dial can also operate in discrete mode (if self.increment is set to x). In
this mode the values will be restrained to be multiples of self.increment.

The Widget has a Callback manager. Callback functions get called at every value
change if self.contiguous is set to 1, else they get called when the mouse
button is released. They always get called with the current value as an
argument.

An optional label can be displayed at the center of the Dial widget.
The size of the dial has to be specified at instanciation. Other parameters
can be set after the widget has been created.
The widget tried to adjust automatically the size of the arrow according to
the size of the dial.

The widget has a configure() method: type, min, max, increment, precision,
showLabel, value, continuous, oneTurn can be set this way.

master, labCfg and size can be passed only to the constructor.

a lock() method is used to disable the various gui components of the
options panel. Usage: <instance>.lock(<component>=<value>)
components see configure(). value is 0 or 1. 1 disables,
0 enables.

Setting values with increment enabled:
if using the method set(), the actual value will 'snap' to the next increment.
i.e., if the value is set to 3, and the increment is set to 2, setting the
value to 6 will actually result in 7  (3,5,7,9,.....)
To still be able to set the value, disregarding the current active increment,
the set method understands the optional keyword force=True, i.e.
dial.set(<value>, force=True)), which will set the value to <value>. The
increment will now be added to this new <value>
 
"""
    def __init__(self,
                 master=None,
                 type='float',
                 labCfg={
                     'fg': 'black',
                     'side': 'left',
                     'text': None
                 },
                 min=None,
                 max=None,
                 increment=.0,
                 precision=2,
                 showLabel=1,
                 value=0.0,
                 continuous=1,
                 oneTurn=360.,
                 size=50,
                 callback=None,
                 lockMin=0,
                 lockBMin=0,
                 lockMax=0,
                 lockBMax=0,
                 lockIncrement=0,
                 lockBIncrement=0,
                 lockPrecision=0,
                 lockShowLabel=0,
                 lockValue=0,
                 lockType=0,
                 lockContinuous=0,
                 lockOneTurn=0,
                 **kw):

        Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        # initialize various attributes with default values
        self.precision = 2  # decimal places
        self.min = None  # minimum value
        self.max = None  # maximum value
        self.increment = increment  # value increment
        self.minOld = 0.  # used to store old values
        self.maxOld = 0.
        self.incrementOld = increment
        self.size = 50  # defines widget size
        self.offsetValue = 0.  # used to set increment correctly
        self.lab = None  # label
        self.callback = None  # user specified callback
        self.opPanel = None  # option panel widget
        self.oneTurn = 360.  # value increment for 1 full turn
        self.value = 0.0  # current value of widget
        self.oldValue = 0.0  # old value of widget
        self.showLabel = 1  # turn on to display label on
        self.continuous = 1  # set to 1 to call callbacks at
        # each value change, else gets called
        # on button release event
        self.angle = 0.  # angle corresponding to value

        self.labCfg = labCfg  # Tkinter Label options
        self.labelFont = (ensureFontCase('helvetica'), 14, 'bold'
                          )  # label font
        self.labelColor = 'yellow'  # label color
        self.canvas = None  # the canvas to create the widget in
        self.usedArcColor = '#aaaaaa'  # filled arc color of used portion
        self.unusedArcColor = '#cccccc'  # filled arc color of unused portion
        self.pyOver180 = math.pi / 180.0  # constants used in various places
        self.threeSixtyOver1turn = 1
        self.piOver1turn = math.pi / 360.

        self.lockMin = lockMin  # lock<X> vars are used in self.lock()
        self.lockMax = lockMax  # to lock/unlock entries in optionpanel
        self.lockIncrement = lockIncrement
        self.lockBMin = lockBMin
        self.lockBMax = lockBMax
        self.lockBIncrement = lockBIncrement
        self.lockPrecision = lockPrecision
        self.lockShowLabel = lockShowLabel
        self.lockValue = lockValue
        self.lockType = lockType
        self.lockContinuous = lockContinuous
        self.lockOneTurn = lockOneTurn

        self.setArrow()

        # configure with user-defined values
        self.setSize(size)
        self.setCallback(callback)
        self.setContinuous(continuous)

        self.setType(type)
        self.setPrecision(precision)
        self.setOneTurn(oneTurn)
        self.setMin(min)
        self.setMax(max)
        self.setIncrement(increment)

        self.setShowLabel(showLabel)

        self.setValue(value)

        self.setLabel(self.labCfg)

        self.createCanvas(master)

        canvas = self.canvas
        canvas.bind("<ButtonPress-1>", self.mouseDown)
        canvas.bind("<ButtonRelease-1>", self.mouseUp)
        canvas.bind("<B1-Motion>", self.mouseMove)
        canvas.bind("<Button-3>", self.toggleOptPanel)

        if os.name == 'nt':  #sys.platform == 'win32':
            canvas.bind("<MouseWheel>", self.mouseWheel)
        else:
            canvas.bind("<Button-4>", self.mouseWheel)
            canvas.bind("<Button-5>", self.mouseWheel)

        KeyboardEntry.__init__(self, (canvas, ), self.setFromEntry)

        self.opPanel = OptionsPanel(master=self, title="Dial Options")

##         if self.callback:
##             self.callbacks.AddCallback(self.callback)

    def setFromEntry(self, valueString):
        try:
            self.set(self.type(valueString))
        except ValueError:
            # fixme we would like to pop this up in a window maybe
            import traceback
            traceback.print_stack()
            traceback.print_exc()

    def handleKeyStroke(self, event):
        # handle key strokes for numbers only in widget keyboard entry label
        key = event.keysym

        if key.isdigit() or key == 'period' or key == 'minus' or key == 'plus':
            if key == 'period':
                key = '.'
            elif key == 'minus':
                key = '-'
            elif key == 'plus':
                key = '+'
            self.typedValue += key
            self.typedValueTK.configure(text=self.typedValue)

        else:
            KeyboardEntry.handleKeyStroke(self, event)

    def setSize(self, size):
        """Set widget size. Size must be of type int and greater than 0"""

        assert isinstance(size, types.IntType),\
               "Illegal size: expected type %s, got %s"%(type(1), type(size) )
        assert size > 0, "Illegal size: must be > 0, got %s" % size
        self.size = size

    def setCallback(self, cb):
        """Set widget callback. Must be callable function. Callback is called
every time the widget value is set/modified"""

        assert cb is None or callable(cb) or type(cb) is types.ListType,\
               "Illegal callback: must be either None or callable, or list. Got %s"%cb
        if cb is None: return
        elif type(cb) is types.ListType:
            for func in cb:
                assert callable(
                    func), "Illegal callback must be callable. Got %s" % func
                self.callbacks.AddCallback(func)
        else:
            self.callbacks.AddCallback(cb)
        self.callback = cb

    def toggleOptPanel(self, event=None):
        if self.opPanel.flag:
            self.opPanel.Dismiss_cb()
        else:
            if not hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.displayPanel(create=1)
            else:
                self.opPanel.displayPanel(create=0)

    def setArrow(self, size=None):
        if size is not None:
            self.setSize(size)
        aS = self.size / 40
        self.arrowLength = max(3, 3 * aS)  # arrow head length
        self.arrowWidth = max(2, aS)  # half the arrow body width
        self.arrowBorderwidth = max(1, self.arrowWidth / 2)  # width of arrow
        # shadow lines
        self.arrowHeadWidth = 2 * self.arrowWidth  # width of arrow head base

    def mouseDown(self, event):
        # remember where the mouse went down
        self.lastx = event.x
        self.lasty = event.y

    def mouseUp(self, event):
        # call callbacks if not in continuous mode
        if not self.continuous:
            self.callbacks.CallCallbacks(self.opPanel.valInput.get())
        if self.showLabel == 2:
            # no widget labels on mouse release
            self.canvas.itemconfigure(self.labelId2, text='')
            self.canvas.itemconfigure(self.labelId, text='')

    def mouseMove(self, event):
        dx = event.x - self.xm
        dy = self.ym - event.y

        n = math.sqrt(dx * dx + dy * dy)
        if n == 0.0: v = [0.0, 0.0]
        else: v = [dx / n, dy / n]

        # find the cosine of the angle between new hand position and previous
        # hand position
        ma = v[0] * self.vector[0] + v[1] * self.vector[1]

        # assure no rounding errors
        if ma > 1.0: ma = 1.0
        elif ma < -1.0: ma = -1.0

        # compute angle increment compared to current vector
        ang = math.acos(ma)

        # find the sign of the rotation, sign of z component of vector prod.
        oldv = self.vector
        normz = oldv[0] * v[1] - oldv[1] * v[0]
        if normz > 0: ang = -1. * ang

        # compute the new value
        val = self.value + ang * self.oneTurnOver2pi

        self.set(val)

        self.lastx = event.x
        self.lasty = event.y

    def mouseWheel(self, event):
        #print "mouseWheel", event, event.num
        if os.name == 'nt':  #sys.platform == 'win32':
            if event.delta > 0:
                lEventNum = 4
            else:
                lEventNum = 5
        else:
            lEventNum = event.num
        if lEventNum == 4:
            self.set(self.value + self.oneTurn)
        else:
            self.set(self.value - self.oneTurn)

    def get(self):
        return self.type(self.value)

    def printLabel(self):
        if self.canvas is None:
            return
        self.canvas.itemconfigure(self.labelId2,
                                  text=self.labelFormat % self.value)  #newVal)
        self.canvas.itemconfigure(self.labelId,
                                  text=self.labelFormat % self.value)  #newVal)

    def set(self, val, update=1, force=0):
        # if force is set to 1, we call this method regardless of the
        # widget configuration. This is for example the case if the dial
        # is set to continuous=0, but the value is set in the options panel

        # snap to closest increment
        if self.increment is not None and self.increment != 0. and not force:
            offset = self.offsetValue % self.increment
            dval = round(val / self.increment) * self.increment

            if val < dval:
                dval = dval + offset - self.increment
            else:
                dval = dval + offset

            if self.min is not None and dval < self.min:
                dval = self.min
            elif self.max is not None and dval > self.max:
                dval = self.max

            # recompute vector and angle corresponding to val
            self.angle = (dval % self.oneTurn) * self.threeSixtyOver1turn
            if dval < 0.0:
                self.angle = self.angle - 360.0
            a = self.angle * self.pyOver180
            self.vector = [math.sin(a), math.cos(a)]
            self.value = dval
            self.offsetValue = dval

        else:
            # 'regular' mode, i.e. no step-wise increment
            if self.min is not None and val < self.min: val = self.min
            elif self.max is not None and val > self.max: val = self.max

            # recompute vector and angle corresponding to val
            self.angle = (val % self.oneTurn) * self.threeSixtyOver1turn
            if val < 0.0: self.angle = self.angle - 360.0
            a = self.angle * self.pyOver180
            self.vector = [math.sin(a), math.cos(a)]
            self.value = val
            self.offsetValue = val

        #update arrow in display
        self.drawArrow()
        newVal = self.get()

        if self.continuous or force:
            if update and self.oldValue != newVal or force:
                self.oldValue = newVal
                self.callbacks.CallCallbacks(newVal)
            if self.showLabel == 2:
                self.printLabel()
        else:
            if self.showLabel == 2:
                self.printLabel()

        if self.showLabel == 1:
            self.printLabel()
        if self.opPanel:
            self.opPanel.valInput.set(self.labelFormat % newVal)

    def drawArrow(self):
        if self.canvas is None:
            return
        # end point
        x1 = self.xm + self.vector[0] * self.rad
        y1 = self.ym - self.vector[1] * self.rad
        # point at arrow head base
        xb = self.xm + self.vector[0] * self.radNoArrow
        yb = self.xm - self.vector[1] * self.radNoArrow
        # vector orthogonal to arrow
        n = [-self.vector[1], -self.vector[0]]
        pts1 = [
            self.xm + n[0] * self.arrowWidth, self.ym + n[1] * self.arrowWidth,
            xb + n[0] * self.arrowWidth, yb + n[1] * self.arrowWidth,
            xb + n[0] * self.arrowHeadWidth, yb + n[1] * self.arrowHeadWidth,
            x1, y1
        ]
        pts2 = [
            x1, y1, xb - n[0] * self.arrowHeadWidth,
            yb - n[1] * self.arrowHeadWidth, xb - n[0] * self.arrowWidth,
            yb - n[1] * self.arrowWidth, self.xm - n[0] * self.arrowWidth,
            self.ym - n[1] * self.arrowWidth
        ]
        canvas = self.canvas
        if self.vector[0] > 0.0:
            col1 = '#DDDDDD'
            col2 = 'black'
        else:
            col1 = 'black'
            col2 = '#DDDDDD'
        apply(canvas.coords, (self.arrowPolId, ) + tuple(pts1 + pts2))
        apply(canvas.coords, (self.arrowPolborder1, ) + tuple(pts1))
        canvas.itemconfigure(self.arrowPolborder1, fill=col1)
        apply(canvas.coords, (self.arrowPolborder2, ) + tuple(pts2))
        canvas.itemconfigure(self.arrowPolborder2, fill=col2)
        canvas.itemconfigure(self.arcId, extent=0.0 - self.angle)

    def createCanvas(self, master):
        size = self.size
        self.frame = Tkinter.Frame(self, borderwidth=3, relief='sunken')

        self.canvas = Tkinter.Canvas(self.frame,
                                     width=size + 2,
                                     height=size + 2)

        self.xm = self.ym = size / 2 + 2
        self.rad = size / 2
        self.radNoArrow = self.rad - self.arrowLength
        self.vector = [0, 1]
        x1 = self.xm + self.vector[0] * self.rad
        y1 = self.ym + self.vector[1] * self.rad
        canvas = self.canvas
        self.circleId = canvas.create_oval(2,
                                           2,
                                           size,
                                           size,
                                           width=1,
                                           fill=self.unusedArcColor)
        self.arcId = canvas.create_arc(2,
                                       2,
                                       size,
                                       size,
                                       start=90.,
                                       extent=0,
                                       fill=self.usedArcColor)
        canvas.create_line(2, self.ym, size + 2, self.ym)
        canvas.create_line(self.xm, 2, self.ym, size + 2)

        self.arrowPolId = canvas.create_polygon(0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                0,
                                                fill='gray75')
        self.arrowPolborder1 = canvas.create_line(0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  fill='black',
                                                  width=self.arrowBorderwidth)
        self.arrowPolborder2 = canvas.create_line(0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  0,
                                                  fill='white',
                                                  width=self.arrowBorderwidth)

        r = size / 20
        off = self.arrowBorderwidth
        canvas.create_oval(self.xm - r,
                           self.ym - r - off / 2,
                           self.xm + r,
                           self.ym + r - off / 2,
                           fill='#DDDDDD',
                           outline='white')

        canvas.create_oval(self.xm - r,
                           self.ym - r + off,
                           self.xm + r,
                           self.ym + r + off,
                           fill='black',
                           outline='black')

        canvas.create_oval(self.xm - r,
                           self.ym - r,
                           self.xm + r,
                           self.ym + r,
                           fill='gray70',
                           outline='#DDDDDD')

        self.labelId2 = canvas.create_text(self.xm + 2,
                                           self.ym + 2,
                                           fill='black',
                                           justify='center',
                                           text='',
                                           font=self.labelFont)
        self.labelId = canvas.create_text(self.xm,
                                          self.ym,
                                          fill=self.labelColor,
                                          justify='center',
                                          text='',
                                          font=self.labelFont)

        self.drawArrow()

        self.opPanel = OptionsPanel(master=self, title="Dial Options")

        # pack em up
        self.canvas.pack(side=Tkinter.TOP)
        self.frame.pack(expand=1, fill='x')
        self.toggleWidgetLabel(self.showLabel)

    def toggleWidgetLabel(self, val):
        if val == 0:
            # no widget labels
            self.showLabel = 0
            self.canvas.itemconfigure(self.labelId2, text='')
            self.canvas.itemconfigure(self.labelId, text='')

        if val == 1:
            # show always widget labels
            self.showLabel = 1
            self.printLabel()

        if val == 2:
            # show widget labels only when mouse moves
            self.showLabel = 2
            self.canvas.itemconfigure(self.labelId2, text='')
            self.canvas.itemconfigure(self.labelId, text='')

    def setValue(self, val):

        if type(val) == types.StringType:
            val = float(val)

        assert type(val) in [types.IntType, types.FloatType],\
               "Illegal type for value: expected %s or %s, got %s"%(
                   type(1), type(1.0), type(val) )

        # setValue does NOT call a callback!
        if self.min is not None and val < self.min: val = self.min
        if self.max is not None and val > self.max: val = self.max
        self.value = self.type(val)
        self.offsetValue = self.value
        self.oldValue = self.value

        #update arrow in display
        self.angle = (self.value % self.oneTurn) * self.threeSixtyOver1turn
        if self.value < 0.0: self.angle = self.angle - 360.0
        a = self.angle * self.pyOver180
        self.vector = [math.sin(a), math.cos(a)]
        self.drawArrow()

        if self.showLabel == 1:
            self.printLabel()
        if self.opPanel:
            self.opPanel.valInput.set(self.labelFormat % self.value)

    def setLabel(self, labCfg):
        self.labCfg = labCfg

        text = labCfg.get('text', None)
        if text is None or text == '':
            return

        d = {}
        for k, w in self.labCfg.items():
            if k == 'side': continue
            else: d[k] = w
        if not 'side' in self.labCfg.keys():
            self.labCfg['side'] = 'left'

        if not self.lab:
            self.lab = Tkinter.Label(self, d)
            self.lab.pack(side=self.labCfg['side'])
            self.lab.bind("<Button-3>", self.toggleOptPanel)
        else:
            self.lab.configure(text)

#####################################################################
# the 'configure' methods:
#####################################################################

    def configure(self, **kw):
        for key, value in kw.items():
            # the 'set' parameter callbacks
            if key == 'labCfg': self.setLabel(value)
            elif key == 'type': self.setType(value)
            elif key == 'min': self.setMin(value)
            elif key == 'max': self.setMax(value)
            elif key == 'increment': self.setIncrement(value)
            elif key == 'precision': self.setPrecision(value)
            elif key == 'showLabel': self.setShowLabel(value)
            elif key == 'continuous': self.setContinuous(value)
            elif key == 'oneTurn':
                self.setOneTurn(value)

                # the 'lock' entries callbacks
            elif key == 'lockType':
                self.lockTypeCB(value)
            elif key == 'lockMin':
                self.lockMinCB(value)
            elif key == 'lockBMin':
                self.lockBMinCB(value)
            elif key == 'lockMax':
                self.lockMaxCB(value)
            elif key == 'lockBMax':
                self.lockBMaxCB(value)
            elif key == 'lockIncrement':
                self.lockIncrementCB(value)
            elif key == 'lockBIncrement':
                self.lockBIncrementCB(value)
            elif key == 'lockPrecision':
                self.lockPrecisionCB(value)
            elif key == 'lockShowLabel':
                self.lockShowLabelCB(value)
            elif key == 'lockValue':
                self.lockValueCB(value)
            elif key == 'lockContinuous':
                self.lockContinuousCB(value)
            elif key == 'lockOneTurn':
                self.lockOneTurnCB(value)

    def setType(self, Type):

        assert type(Type) in [types.StringType, types.TypeType],\
               "Illegal type for datatype. Expected %s or %s, got %s"%(
                   type('a'), type(type), type(Type) )

        if type(Type) == type(""):  # type str
            assert Type in ('int','float'),\
            "Illegal type descriptor. Expected 'int' or 'float', got '%s'"%Type
            self.type = eval(Type)
        else:
            self.type = Type

        if self.type == int:
            self.labelFormat = "%d"
            self.int_value = self.value
        else:
            self.labelFormat = "%." + str(self.precision) + "f"

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togIntFloat']['widget']
            if self.type == int:
                w.setvalue('int')
            elif self.type == 'float':
                w.setvalue('float')

        if self.opPanel:
            self.opPanel.updateDisplay()

        # and update the printed label
        if self.canvas and self.showLabel == 1:
            self.printLabel()

    def setMin(self, min):
        if min is not None:

            assert type(min) in [types.IntType, types.FloatType],\
                 "Illegal type for minimum. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(min) )

            if self.max and min > self.max:
                min = self.max

            self.min = self.type(min)

            if self.showLabel == 1:
                self.printLabel()

            if self.value < self.min:
                self.set(self.min)

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.minInput.set(self.labelFormat % self.min)

                self.opPanel.toggleMin.set(1)
                self.opPanel.min_entry.configure(state='normal', fg='gray0')
            self.minOld = self.min

        else:
            self.min = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleMin.set(0)
                self.opPanel.min_entry.configure(state='disabled', fg='gray40')

    def setMax(self, max):
        if max is not None:

            assert type(max) in [types.IntType, types.FloatType],\
                 "Illegal type for maximum. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(max) )

            if self.min and max < self.min:
                max = self.min

            self.max = self.type(max)

            if self.showLabel == 1:
                self.printLabel()

            if self.value > self.max:
                self.set(self.max)

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.maxInput.set(self.labelFormat % self.max)

                self.opPanel.toggleMax.set(1)
                self.opPanel.max_entry.configure(state='normal', fg='gray0')
            self.maxOld = self.max

        else:
            self.max = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleMax.set(0)
                self.opPanel.max_entry.configure(state='disabled', fg='gray40')

    def setIncrement(self, incr):
        if incr is not None:

            assert type(incr) in [types.IntType, types.FloatType],\
                "Illegal type for increment. Expected type %s or %s, got %s"%(
                    type(0), type(0.0), type(incr) )

            self.increment = self.type(incr)
            self.offsetValue = self.value
            self.incrementOld = self.increment
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.incrInput.set(self.labelFormat % self.increment)
                self.opPanel.toggleIncr.set(1)
                self.opPanel.incr_entry.configure(state='normal', fg='gray0')

        else:
            self.increment = self.type(0)
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleIncr.set(0)
                self.opPanel.incrInput.set(self.labelFormat % 0)
                self.opPanel.incr_entry.configure(state='disabled',
                                                  fg='gray40')

    def setPrecision(self, val):
        assert type(val) in [types.IntType, types.FloatType],\
               "Illegal type for precision. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(val) )
        val = int(val)

        if val > 10:
            val = 10
        if val < 1:
            val = 1
        self.precision = val

        if self.type == float:
            self.labelFormat = "%." + str(self.precision) + "f"
        else:
            self.labelFormat = "%d"

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['selPrec']['widget']
            w.setvalue(val)

        if self.opPanel:
            self.opPanel.updateDisplay()

        # and update the printed label
        if self.canvas and self.showLabel == 1:
            self.printLabel()

    def setContinuous(self, cont):
        """ cont can be None, 0 or 1 """

        assert cont in [None, 0, 1],\
             "Illegal value for continuous: expected None, 0 or 1, got %s"%cont

        if cont != 1:
            cont = None
        self.continuous = cont
        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togCont']['widget']
            if cont:
                w.setvalue('on')  #i=1
            else:
                w.setvalue('off')  #i=0

        if self.opPanel:
            self.opPanel.updateDisplay()

    def setShowLabel(self, val):
        """Show label can be 0, 1 or 2
0: no label
1: label is always shown
2: show label only when value changes"""

        assert val in [0,1,2],\
               "Illegal value for showLabel. Expected 0, 1 or 2, got %s"%val

        if val != 0 and val != 1 and val != 2:
            print "Illegal value. Must be 0, 1 or 2"
            return
        self.showLabel = val
        self.toggleWidgetLabel(val)

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togLabel']['widget']
            if self.showLabel == 0:
                label = 'never'
            elif self.showLabel == 1:
                label = 'always'
            elif self.showLabel == 2:
                label = 'move'
            w.setvalue(label)

        if self.opPanel:
            self.opPanel.updateDisplay()

    def setOneTurn(self, oneTurn):
        assert type(oneTurn) in [types.IntType, types.FloatType],\
               "Illegal type for oneTurn. Expected %s or %s, got %s"%(
                   type(0), type(0.0), type(oneTurn) )

        self.oneTurn = oneTurn
        self.threeSixtyOver1turn = 360. / oneTurn
        self.piOver1turn = math.pi / oneTurn
        self.oneTurnOver2pi = oneTurn / (2 * math.pi)

        if self.opPanel:
            self.opPanel.updateDisplay()

#####################################################################
# the 'lock' methods:
#####################################################################

    def lockTypeCB(self, mode):
        if mode != 0: mode = 1
        self.lockType = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockMinCB(self, mode):  #min entry field
        if mode != 0: mode = 1
        self.lockMin = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBMinCB(self, mode):  # min checkbutton
        if mode != 0: mode = 1
        self.lockBMin = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockMaxCB(self, mode):  # max entry field
        if mode != 0: mode = 1
        self.lockMax = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBMaxCB(self, mode):  # max checkbutton
        if mode != 0: mode = 1
        self.lockBMax = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockIncrementCB(self, mode):  # increment entry field
        if mode != 0: mode = 1
        self.lockIncrement = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBIncrementCB(self, mode):  # increment checkbutton
        if mode != 0: mode = 1
        self.lockBIncrement = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockPrecisionCB(self, mode):
        if mode != 0: mode = 1
        self.lockPrecision = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockShowLabelCB(self, mode):
        if mode != 0: mode = 1
        self.lockShowLabel = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockValueCB(self, mode):
        if mode != 0: mode = 1
        self.lockValue = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockContinuousCB(self, mode):
        if mode != 0: mode = 1
        self.lockContinuous = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockOneTurnCB(self, mode):
        if mode != 0: mode = 1
        self.lockOneTurn = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()
Beispiel #8
0
    def __init__(self,
                 master=None,
                 labCfg={
                     'fg': 'black',
                     'side': 'left',
                     'text': None
                 },
                 wheelLabCfg={},
                 canvasCfg={},
                 callback=None,
                 type='float',
                 min=None,
                 max=None,
                 increment=0.0,
                 precision=2,
                 showLabel=1,
                 value=0.0,
                 continuous=True,
                 width=200,
                 height=40,
                 oneTurn=10.,
                 wheelPad=6,
                 lockMin=0,
                 lockBMin=0,
                 lockMax=0,
                 lockBMax=0,
                 lockIncrement=0,
                 lockBIncrement=0,
                 lockPrecision=0,
                 lockShowLabel=0,
                 lockValue=0,
                 lockType=0,
                 lockContinuous=0,
                 lockOneTurn=0,
                 orient=None,
                 reportDelta=0,
                 **kw):

        # See FIXME init
        #        if __debug__:
        #            checkkeywords(kw)

        Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self, side='left', anchor='w')

        #FIXME: nblines are not dynamically computed
        self.nblines = 30
        self.callback = None
        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        self.width = 200
        self.height = 40
        self.setWidth(width)
        self.setHeight(height)
        # set widget orientation: either horizontal or vertical
        self.setOrient(orient)

        # initialize various attributes with default values
        self.precision = 2  # decimal places
        self.min = None  # minimum value
        self.max = None  # maximum value
        self.increment = increment  # value increment
        self.minOld = 0.  # used to store old values
        self.maxOld = 0.
        self.incrementOld = increment
        self.size = 50  # defines widget size
        self.offsetValue = 0.  # used to set increment correctly
        self.lab = None  # label
        self.opPanel = None  # option panel widget
        self.oneTurn = 360.  # value increment for 1 full turn
        self.value = 0.0  # current value of widget
        self.oldValue = 0.0  # old value of widget
        self.showLabel = 1  # turn on to display label on
        self.continuous = True  # set to 1 to call callbacks at
        # each value change, else gets called
        # on button release event
        self.angle = 0.  # angle corresponding to value

        self.labCfg = labCfg  # Tkinter Label options
        self.labelFont = (ensureFontCase('helvetica'), 14, 'bold'
                          )  # label font
        self.labelColor = 'yellow'  # label color
        self.canvas = None  # the canvas to create the widget in
        self.usedArcColor = '#aaaaaa'  # filled arc color of used portion
        self.unusedArcColor = '#cccccc'  # filled arc color of unused portion
        self.pyOver180 = math.pi / 180.0  # constants used in various places
        self.threeSixtyOver1turn = 1
        self.piOver1turn = math.pi / 360.

        self.wheelLabCfg = wheelLabCfg  # Tkinter wheel label options
        self.canvasCfg = canvasCfg  # Tkinter Canvas options
        self.wheelPad = wheelPad  # pad between wheel and widget borders
        self.deltaVal = 0.  # delta with value at last callback

        self.valueLabel = None  # Tkinter Label
        self.setType(type)  # can be float or int

        self.discreteValue = 0.  # value in discrete space

        self.lockMin = lockMin  # lock<X> variables in configure()
        self.lockMax = lockMax  # to lock/unlock entries in options
        # panel

        self.lockMin = lockMin  # lock<X> vars are used in self.lock()
        self.lockMax = lockMax  # to lock/unlock entries in optionpanel
        self.lockIncrement = lockIncrement
        self.lockBMin = lockBMin
        self.lockBMax = lockBMax
        self.lockBIncrement = lockBIncrement
        self.lockPrecision = lockPrecision
        self.lockShowLabel = lockShowLabel
        self.lockValue = lockValue
        self.lockType = lockType
        self.lockContinuous = lockContinuous
        self.lockOneTurn = lockOneTurn
        self.reportDelta = reportDelta

        self.setLabel(self.labCfg)

        self.createCanvas(master, wheelPad=wheelPad)
        self.canvas.bind("<ButtonPress-1>", self.mouseDown)
        self.canvas.bind("<ButtonRelease-1>", self.mouseUp)
        self.canvas.bind("<B1-Motion>", self.mouseMove)
        self.canvas.bind("<Button-3>", self.toggleOptPanel)

        self.valueLabel.bind("<ButtonPress-1>", self.mouseDown)
        self.valueLabel.bind("<ButtonRelease-1>", self.mouseUp)
        self.valueLabel.bind("<B1-Motion>", self.mouseMove)
        self.valueLabel.bind("<Button-3>", self.toggleOptPanel)

        if os.name == 'nt':  #sys.platform == 'win32':
            self.canvas.bind("<MouseWheel>", self.mouseWheel)
            self.valueLabel.bind("<MouseWheel>", self.mouseWheel)
        else:
            self.canvas.bind("<Button-4>", self.mouseWheel)
            self.valueLabel.bind("<Button-4>", self.mouseWheel)
            self.canvas.bind("<Button-5>", self.mouseWheel)
            self.valueLabel.bind("<Button-5>", self.mouseWheel)

        self.bind("<Button-3>", self.toggleOptPanel)

        KeyboardEntry.__init__(self, (self, self.canvas, self.valueLabel),
                               self.setFromEntry)

        self.opPanel = OptionsPanel(master=self, title="Thumbwheel Options")

        # now set the constructor options correctly using the configure method
        self.setValue(value)
        apply(
            self.configure, (), {
                'type': type,
                'min': min,
                'max': max,
                'increment': increment,
                'precision': precision,
                'showLabel': showLabel,
                'continuous': continuous,
                'oneTurn': oneTurn,
                'lockType': lockType,
                'lockMin': lockMin,
                'lockBMin': lockBMin,
                'lockMax': lockMax,
                'lockBMax': lockBMax,
                'lockIncrement': lockIncrement,
                'lockBIncrement': lockBIncrement,
                'lockPrecision': lockPrecision,
                'lockShowLabel': lockShowLabel,
                'lockValue': lockValue,
                'lockContinuous': lockContinuous,
                'lockOneTurn': lockOneTurn,
                'orient': orient,
                'reportDelta': reportDelta,
                'callback': callback
            })
Beispiel #9
0
class ThumbWheel(Tkinter.Frame, KeyboardEntry):
    """ This class builds a thumbwheel put onto a wheelpad.
constructor options:
- master: the master into the thumwheel can be packed. If one is specified,
  the widget gets packed in a toplevel() window
- height, width, orient specify the size and orientation of the widget.
- wheelpad specifies the pad onto which the thumbwheel gets packed
  optional is a canvascfg to configure the wheelpad canvas Tkinter options.
  for example if the wheelpad needs a blue background: canvascfg={'bg':'blue'}
- continuous: boolean. When set to True, continuous is 'on' and the callback functions
  will be called each time the value changes. Otherwise continuous will be 'off' and
  callback functions will be called on mouse release.
- callback: (None, callable function or list of callable functions).to specify function
  to be called when the value of the thumbwheel is modified.
- type: ('float', 'int' ...) string describing the type of the thumbwheel
- min, max, increment, precision, oneTurn specify the parameters of the thumbwheel.
- labCfg describes the label of the thumbwheel which will be packed to the left of the widget by default unless 'side' is specified. Possible keywords are text and side.

- wheelLabCfg describes the label located on the wheel where the value of the thumbwheel
  will be displayed
- showLabel Flag to specify whether to display the wheelLabel always 1, never 0,
  only on motion 2.
- canvasCfg describe the canvas containing the thumbwheel.
An option panel is available to the user to modify the thumbwheel settings by right clicking
on the widget
- lockMin, lockBMin, lockMax, lockBMax, lockIncrement, lockBIncrement,
  lockPrecision, lockShowLabel, lockValue,  lockType, lockContinuous, lockOneTurn:
  These flags specifies whether (when set to 1) or not (when set to 0) the user will be
  allowed to change the setting of the thumbwheel.
- reportDelta is flag to specify whether value differences should be reported
  rathe than absolute values
  
The widget has a configure() method: type, min, max, increment, precision,
showLabel, value, continuous, oneTurn, orient, reportDelta  can be set this
way.

a lock() method is used to disable the various gui components of the
options panel. Usage: <instance>.configure(<component>=<value>)
components see configure(). value is 0 or 1. 1 disables,0 enables.    
    """

    #FIXME: this would be the mechanism to remove all arguments from the
    # init (see DejaVu)
    #    keywords = [
    #        'master',
    #        'oneTurn',
    #        ]
    def __init__(self,
                 master=None,
                 labCfg={
                     'fg': 'black',
                     'side': 'left',
                     'text': None
                 },
                 wheelLabCfg={},
                 canvasCfg={},
                 callback=None,
                 type='float',
                 min=None,
                 max=None,
                 increment=0.0,
                 precision=2,
                 showLabel=1,
                 value=0.0,
                 continuous=True,
                 width=200,
                 height=40,
                 oneTurn=10.,
                 wheelPad=6,
                 lockMin=0,
                 lockBMin=0,
                 lockMax=0,
                 lockBMax=0,
                 lockIncrement=0,
                 lockBIncrement=0,
                 lockPrecision=0,
                 lockShowLabel=0,
                 lockValue=0,
                 lockType=0,
                 lockContinuous=0,
                 lockOneTurn=0,
                 orient=None,
                 reportDelta=0,
                 **kw):

        # See FIXME init
        #        if __debug__:
        #            checkkeywords(kw)

        Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self, side='left', anchor='w')

        #FIXME: nblines are not dynamically computed
        self.nblines = 30
        self.callback = None
        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        self.width = 200
        self.height = 40
        self.setWidth(width)
        self.setHeight(height)
        # set widget orientation: either horizontal or vertical
        self.setOrient(orient)

        # initialize various attributes with default values
        self.precision = 2  # decimal places
        self.min = None  # minimum value
        self.max = None  # maximum value
        self.increment = increment  # value increment
        self.minOld = 0.  # used to store old values
        self.maxOld = 0.
        self.incrementOld = increment
        self.size = 50  # defines widget size
        self.offsetValue = 0.  # used to set increment correctly
        self.lab = None  # label
        self.opPanel = None  # option panel widget
        self.oneTurn = 360.  # value increment for 1 full turn
        self.value = 0.0  # current value of widget
        self.oldValue = 0.0  # old value of widget
        self.showLabel = 1  # turn on to display label on
        self.continuous = True  # set to 1 to call callbacks at
        # each value change, else gets called
        # on button release event
        self.angle = 0.  # angle corresponding to value

        self.labCfg = labCfg  # Tkinter Label options
        self.labelFont = (ensureFontCase('helvetica'), 14, 'bold'
                          )  # label font
        self.labelColor = 'yellow'  # label color
        self.canvas = None  # the canvas to create the widget in
        self.usedArcColor = '#aaaaaa'  # filled arc color of used portion
        self.unusedArcColor = '#cccccc'  # filled arc color of unused portion
        self.pyOver180 = math.pi / 180.0  # constants used in various places
        self.threeSixtyOver1turn = 1
        self.piOver1turn = math.pi / 360.

        self.wheelLabCfg = wheelLabCfg  # Tkinter wheel label options
        self.canvasCfg = canvasCfg  # Tkinter Canvas options
        self.wheelPad = wheelPad  # pad between wheel and widget borders
        self.deltaVal = 0.  # delta with value at last callback

        self.valueLabel = None  # Tkinter Label
        self.setType(type)  # can be float or int

        self.discreteValue = 0.  # value in discrete space

        self.lockMin = lockMin  # lock<X> variables in configure()
        self.lockMax = lockMax  # to lock/unlock entries in options
        # panel

        self.lockMin = lockMin  # lock<X> vars are used in self.lock()
        self.lockMax = lockMax  # to lock/unlock entries in optionpanel
        self.lockIncrement = lockIncrement
        self.lockBMin = lockBMin
        self.lockBMax = lockBMax
        self.lockBIncrement = lockBIncrement
        self.lockPrecision = lockPrecision
        self.lockShowLabel = lockShowLabel
        self.lockValue = lockValue
        self.lockType = lockType
        self.lockContinuous = lockContinuous
        self.lockOneTurn = lockOneTurn
        self.reportDelta = reportDelta

        self.setLabel(self.labCfg)

        self.createCanvas(master, wheelPad=wheelPad)
        self.canvas.bind("<ButtonPress-1>", self.mouseDown)
        self.canvas.bind("<ButtonRelease-1>", self.mouseUp)
        self.canvas.bind("<B1-Motion>", self.mouseMove)
        self.canvas.bind("<Button-3>", self.toggleOptPanel)

        self.valueLabel.bind("<ButtonPress-1>", self.mouseDown)
        self.valueLabel.bind("<ButtonRelease-1>", self.mouseUp)
        self.valueLabel.bind("<B1-Motion>", self.mouseMove)
        self.valueLabel.bind("<Button-3>", self.toggleOptPanel)

        if os.name == 'nt':  #sys.platform == 'win32':
            self.canvas.bind("<MouseWheel>", self.mouseWheel)
            self.valueLabel.bind("<MouseWheel>", self.mouseWheel)
        else:
            self.canvas.bind("<Button-4>", self.mouseWheel)
            self.valueLabel.bind("<Button-4>", self.mouseWheel)
            self.canvas.bind("<Button-5>", self.mouseWheel)
            self.valueLabel.bind("<Button-5>", self.mouseWheel)

        self.bind("<Button-3>", self.toggleOptPanel)

        KeyboardEntry.__init__(self, (self, self.canvas, self.valueLabel),
                               self.setFromEntry)

        self.opPanel = OptionsPanel(master=self, title="Thumbwheel Options")

        # now set the constructor options correctly using the configure method
        self.setValue(value)
        apply(
            self.configure, (), {
                'type': type,
                'min': min,
                'max': max,
                'increment': increment,
                'precision': precision,
                'showLabel': showLabel,
                'continuous': continuous,
                'oneTurn': oneTurn,
                'lockType': lockType,
                'lockMin': lockMin,
                'lockBMin': lockBMin,
                'lockMax': lockMax,
                'lockBMax': lockBMax,
                'lockIncrement': lockIncrement,
                'lockBIncrement': lockBIncrement,
                'lockPrecision': lockPrecision,
                'lockShowLabel': lockShowLabel,
                'lockValue': lockValue,
                'lockContinuous': lockContinuous,
                'lockOneTurn': lockOneTurn,
                'orient': orient,
                'reportDelta': reportDelta,
                'callback': callback
            })

    def setFromEntry(self, valueString):
        try:
            self.set(self.type(valueString), force=1)
        except ValueError:
            # fixme we would like to pop this up in a window maybe
            import traceback
            traceback.print_stack()
            traceback.print_exc()

    def handleKeyStroke(self, event):
        # handle key strokes for numbers only in widget keyboard entry label
        key = event.keysym

        if key.isdigit() or key == 'period' or key == 'minus' or key == 'plus':
            if key == 'period':
                key = '.'
            elif key == 'minus':
                key = '-'
            elif key == 'plus':
                key = '+'
            self.typedValue += key
            self.typedValueTK.configure(text=self.typedValue)

        else:
            KeyboardEntry.handleKeyStroke(self, event)

    def setWidth(self, width):
        assert isinstance(width, types.IntType),\
               "Illegal width: expected %s, got %s"%(type(1),type(width))
        assert width > 0, "Illegal width: must be > 0, got %s" % width
        self.width = width

    def setHeight(self, height):
        assert isinstance(height, types.IntType),\
               "Illegal height: expected %s, got %s"%(type(1),type(height))
        assert height > 0, "Illegal height: must be > 0, got %s" % height
        self.height = height

    def setCallbacks(self, cb):
        """Set widget callback. Must be callable function. Callback is called
every time the widget value is set/modified"""

        assert cb is None or callable(cb) or type(cb) is types.ListType,\
               "Illegal callback: must be either None or callable. Got %s"%cb
        if cb is None: return
        elif type(cb) is types.ListType:
            for func in cb:
                assert callable(
                    func), "Illegal callback must be callable. Got %s" % func
                self.callbacks.AddCallback(func)
        else:
            self.callbacks.AddCallback(cb)
        self.callback = cb

    def toggleOptPanel(self, event=None):
        if self.opPanel.flag:
            self.opPanel.Dismiss_cb()
        else:
            if not hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.displayPanel(create=1)
            else:
                self.opPanel.displayPanel(create=0)

    def mouseDown(self, event):
        # remember where the mouse went down
        if self.orient == 'horizontal':
            self.lastx = event.x
        else:
            self.lastx = event.y

    def mouseUp(self, event):
        # call callbacks if not in continuous mode
        newVal = self.get()
        if self.oldValue != newVal:
            if not self.continuous:
                self.oldValue = newVal
                self.callbacks.CallCallbacks(newVal)
            if self.showLabel == 2:
                # no widget labels on mouse release
                self.valueLabel.place_forget()

    def mouseMove(self, event):
        if self.orient == 'horizontal':
            dx = event.x - self.lastx
            self.lastx = event.x
        else:
            dx = event.y - self.lastx
            self.lasty = event.y
        dang = dx * math.pi / 180.
        val = dang * self.oneTurnOver2pi
        self.computeNewValue(val)

    def mouseWheel(self, event):
        #print "mouseWheel", event, event.num
        if os.name == 'nt':  #sys.platform == 'win32':
            if event.delta > 0:
                lEventNum = 4
            else:
                lEventNum = 5
        else:
            lEventNum = event.num
        if lEventNum == 4:
            self.computeNewValue(self.oneTurn / 10)
        else:
            self.computeNewValue(-self.oneTurn / 10)

    def get(self):
        if self.reportDelta:
            return self.type(self.deltaVal)
        else:
            return self.type(self.value)

    def printLabel(self):
        if not self.showLabel in [1, 2]:
            return
        hl = self.valueLabel.winfo_reqheight()
        wl = self.valueLabel.winfo_reqwidth()
        h = self.canvas.winfo_reqheight()
        w = self.canvas.winfo_reqwidth()
        self.valueLabel.place(in_=self.canvas,
                              x=(w - wl) * .5,
                              y=((h - hl) * 0.5) - self.height / 4 + 2)
        self.valueLabel.configure(text=self.labelFormat % self.value)

    def set(self, val, update=1, force=0):
        # if force is set to 1, we call this method regardless of the
        # widget configuration. This is for example the case if the thumwheel
        # is set to continuous=0, but the value is set in the options panel
        if self.min is not None and val <= self.min:
            val = self.min
        elif self.max is not None and val >= self.max:
            val = self.max

        oldval = self.value
        self.value = val
        self.deltaVal = self.value - oldval

        newVal = self.get()
        if update and self.continuous or force:
            if self.oldValue != self.value or force:
                self.oldValue = newVal
                self.callbacks.CallCallbacks(newVal)
            if self.showLabel == 2:
                self.printLabel()

        if self.showLabel == 1:
            self.printLabel()

        if self.opPanel:
            self.opPanel.valInput.set(self.labelFormat % self.value)

    #FIXME: this could be renamed increment (to parallel the set method)
    # some code in this method is duplicated in set method
    def computeNewValue(self, val):
        # snap to closest increment
        oldval = self.value
        if self.increment is not None and self.increment != 0.:
            self.discreteValue = self.discreteValue + val
            if self.discreteValue >= self.increment:
                self.value = self.value + self.increment
                self.discreteValue = 0.
            elif -self.discreteValue >= self.increment:
                self.value = self.value - self.increment
                self.discreteValue = 0.
        else:
            self.value = self.value + val

        if self.min is not None and self.value <= self.min:
            self.value = self.min
            val = 0
        elif self.max is not None and self.value >= self.max:
            self.value = self.max
            val = 0

        self.deltaVal = self.value - oldval

        # self.angle is used in drawLines()
        self.angle = val / self.oneTurnOver2pi
        self.drawLines()

        if self.showLabel > 0:  # ALWAYS
            self.printLabel()

        if self.opPanel:
            self.opPanel.valInput.set(self.labelFormat % self.value)

        newVal = self.get()
        if self.oldValue != newVal and not self.reportDelta:
            # this part is called either when the value is float OR when
            # continuous is off
            if self.continuous:
                self.oldValue = newVal
                self.callbacks.CallCallbacks(newVal)
            else:
                pass
        else:
            # this part is usually called when the datatype is INT AND
            # continuous is on
            if self.oldValue != newVal:
                # only call this part when we "reach" a new value
                self.oldValue = newVal
                self.callbacks.CallCallbacks(newVal)
            else:
                # else we need nothing to do
                pass

    def createCanvas(self, master, wheelPad=6):
        bw = self.borderWidth = wheelPad  # distance between wheel and raise

        cd = {
            'width': self.width + bw,
            'height': self.height + bw,
            'relief': 'raised',
            'borderwidth': 3
        }

        for k, w in self.canvasCfg.items():
            cd[k] = w

        self.canvas = Tkinter.Canvas(self, cd)
        cbdw = int(self.canvas.cget('borderwidth'))
        bd = self.borderWidth + cbdw + 1  # +1 for pixel0 that is not drawn

        height = self.height - bw
        width = self.width - bw
        cp = self.canvas.create_polygon
        self.outline1 = cp(bd,
                           bd,
                           bd,
                           height + cbdw,
                           width + cbdw,
                           height + cbdw,
                           width + cbdw,
                           bd,
                           bd,
                           bd,
                           width=1,
                           outline='gray60',
                           fill='gray85')

        ul = bd + 1  # upper left pixel
        l = (width + cbdw - 1) - (bd + 1)  # length of the inner box
        cl25 = 2. * l / 25.
        cl = self.canvas.create_line
        self.outline2 = cl(ul + int(cl25),
                           ul,
                           ul,
                           ul,
                           ul,
                           height + cbdw - 1,
                           ul + int(cl25),
                           height + cbdw - 1,
                           width=1,
                           fill='gray20')
        self.outline3 = cl(ul + int(cl25),
                           ul,
                           ul + int(3 * cl25),
                           ul,
                           width=1,
                           fill='gray60')
        self.outline4 = cl(ul + int(cl25),
                           height + cbdw - 1,
                           ul + int(3 * cl25),
                           height + cbdw - 1,
                           width=1,
                           fill='gray60')
        self.outline5 = cl(ul + int(5 * cl25),
                           ul,
                           ul + int(7.5 * cl25),
                           ul,
                           width=1,
                           fill='white')
        self.outline4 = cl(ul + int(5 * cl25),
                           height + cbdw - 1,
                           ul + int(7.5 * cl25),
                           height + cbdw - 1,
                           width=1,
                           fill='white')
        self.outline6 = cl(ul + int(9.5 * cl25),
                           ul,
                           ul + int(11.5 * cl25),
                           ul,
                           width=1,
                           fill='gray60')
        self.outline7 = cl(ul + int(9.5 * cl25),
                           height + cbdw - 1,
                           ul + int(11.5 * cl25),
                           height + cbdw - 1,
                           width=1,
                           fill='gray60')

        re = ul + l
        self.outline8 = cl(ul + int(11.5 * cl25),
                           ul,
                           re,
                           ul,
                           re,
                           height + cbdw - 1,
                           ul + int(11.5 * cl25),
                           height + cbdw - 1,
                           width=1,
                           fill='gray20')

        # corners of the box where the lines have to be drawn
        self.innerbox = (ul + 1, ul + 1, re - 1, height + cbdw - 1)

        self.circlePtsAngles = []
        inc = 2 * math.pi / float(self.nblines)
        for i in range(self.nblines):
            self.circlePtsAngles.append(i * inc)
        self.circlePtsAngles = Numeric.array(self.circlePtsAngles, 'f')
        self.linesIds = []
        self.shLinesIds = []
        # this table should depend on the number of lines
        # currently it is of length 15 (self.nblines/2)
        # It should be resized automatically to self.nblines/2
        self.shadowLinesOptions = [
            (0, 'black', 1),  # offset, color, width
            (2, 'gray30', 1),
            (2, 'gray30', 1),
            (0, 'gray30', 1),
            (-1, 'white', 1),
            (-1, 'white', 1),
            (-1, 'white', 2),
            (-1, 'white', 2),
            (-1, 'white', 2),
            (-1, 'white', 2),
            (-1, 'white', 1),
            (-1, 'white', 1),
            (0, 'gray30', 1),
            (-2, 'gray30', 1),
            (-2, 'gray30', 1),
            (0, 'black', 1),  # offset, color, width
            (0, 'black', 1),  # offset, color, width
        ]

        for i in range(self.nblines):
            self.linesIds.append(cl(0, 0, 0, 0, width=1, fill='black'))
            self.shLinesIds.append(cl(0, 0, 0, 0))

        wlabCfg = {'padx': 0, 'pady': 0}
        wlabCfg.update(self.wheelLabCfg)
        self.valueLabel = apply(Tkinter.Label, (self.master, ), wlabCfg)

        self.drawLines()
        self.canvas.pack(side=Tkinter.LEFT)
        self.toggleWidgetLabel(self.showLabel)

    def drawLines(self):
        # angle has to be provided in radians
        angle = self.angle

        self.circlePtsAngles = self.circlePtsAngles + angle
        self.circlePtsAngles = Numeric.remainder(self.circlePtsAngles,
                                                 2 * math.pi)
        xcoords = Numeric.cos(self.circlePtsAngles)
        xsin = Numeric.sin(self.circlePtsAngles)
        if self.orient == 'horizontal':
            w = self.innerbox[2] - self.innerbox[0]
            r = w / 2
            c = self.innerbox[0] + r
            y1 = self.innerbox[1]
            y2 = self.innerbox[3]
        else:
            w = self.innerbox[3] - self.innerbox[1]
            r = w / 2
            c = self.innerbox[1] + r
            y1 = self.innerbox[0]
            y2 = self.innerbox[2]

        cl = self.canvas.create_line
        setCoords = self.canvas.coords
        setOpt = self.canvas.itemconfigure
        pi2 = math.pi / 2.
        drawLines = 0
        co = Numeric.take(xcoords,
                          Numeric.nonzero(Numeric.greater_equal(xsin, 0.0)))
        co = Numeric.sort(co)
        co = [-1] + list(co)
        for i in range(len(co)):
            x = c - int(co[i] * r)
            if self.orient == 'horizontal':
                setCoords(self.linesIds[i], x, y1, x, y2)
            else:
                setCoords(self.linesIds[i], y1, x, y2, x)
            shopt = self.shadowLinesOptions[i]
            x = x + shopt[0]
            if self.orient == 'horizontal':
                setCoords(self.shLinesIds[i], x, y1, x, y2)
            else:
                setCoords(self.shLinesIds[i], y1, x, y2, x)
            setOpt(self.shLinesIds[i], fill=shopt[1], width=shopt[2])

    def toggleWidgetLabel(self, val):
        if val == 0:
            # no widget labels
            self.showLabel = 0
            self.valueLabel.place_forget()

        if val == 1:
            # show always widget labels
            self.showLabel = 1
            self.printLabel()

        if val == 2:
            # show widget labels only when mouse moves
            self.showLabel = 2
            self.valueLabel.place_forget()

    def setValue(self, val):
        assert type(val) in [types.IntType, types.FloatType],\
               "Illegal type for value: expected %s or %s, got %s"%(
                   type(1), type(1.0), type(val) )

        # setValue does NOT call a callback!
        if self.min is not None and val < self.min: val = self.min
        if self.max is not None and val > self.max: val = self.max
        self.value = self.type(val)
        self.oldValue = self.value
        self.offsetValue = self.value
        if self.showLabel == 1:
            self.printLabel()

#####################################################################
# the 'configure' methods:
#####################################################################

    def configure(self, **kw):
        if 'type' in kw.keys():  # make sure type is set first
            self.setType(kw['type'])
            del kw['type']

        for key, value in kw.items():
            # the 'set' parameter callbacks
            if key == 'labCfg': self.setLabel(value)
            elif key == 'callback': self.setCallbacks(value)
            elif key == 'wheelLabCfg':
                self.wheelLablCfg.update(value)
                self.printLabel()
            elif key == 'min':
                self.setMin(value)
            elif key == 'max':
                self.setMax(value)
            elif key == 'increment':
                self.setIncrement(value)
            elif key == 'precision':
                self.setPrecision(value)
            elif key == 'showLabel':
                self.setShowLabel(value)
            elif key == 'continuous':
                self.setContinuous(value)
            elif key == 'oneTurn':
                self.setOneTurn(value)
            elif key == 'orient':
                self.setOrient(value)
            elif key == 'reportDelta':
                self.setReportDelta(value)

                # the 'lock' entries callbacks
            elif key == 'lockType':
                self.lockTypeCB(value)
            elif key == 'lockMin':
                self.lockMinCB(value)
            elif key == 'lockBMin':
                self.lockBMinCB(value)
            elif key == 'lockMax':
                self.lockMaxCB(value)
            elif key == 'lockBMax':
                self.lockBMaxCB(value)
            elif key == 'lockIncrement':
                self.lockIncrementCB(value)
            elif key == 'lockBIncrement':
                self.lockBIncrementCB(value)
            elif key == 'lockPrecision':
                self.lockPrecisionCB(value)
            elif key == 'lockShowLabel':
                self.lockShowLabelCB(value)
            elif key == 'lockValue':
                self.lockValueCB(value)
            elif key == 'lockContinuous':
                self.lockContinuousCB(value)
            elif key == 'lockOneTurn':
                self.lockOneTurnCB(value)

    def setLabel(self, labCfg):
        self.labCfg = labCfg

        text = labCfg.get('text', None)
        if text is None or text == '':
            return

        d = {}
        for k, w in self.labCfg.items():
            if k == 'side': continue
            else: d[k] = w
        if not 'side' in self.labCfg.keys():
            self.labCfg['side'] = 'left'

        if not self.lab:
            self.lab = Tkinter.Label(self, d)
            self.lab.pack(side=self.labCfg['side'])
            self.lab.bind("<Button-3>", self.toggleOptPanel)
        else:
            self.lab.configure(text)

    def setType(self, Type):
        assert type(Type) in [types.StringType, types.TypeType],\
               "Illegal type for datatype. Expected %s or %s, got %s"%(
                   type('a'), type(type), type(Type) )

        if type(Type) == type(""):  # type str
            assert Type in ('int','float'),\
           "Illegal type descriptor. Expected 'int' or 'float', got '%s'"%Type
            self.type = eval(Type)
        else:
            self.type = Type

        if self.type == int:
            self.labelFormat = "%d"
            self.int_value = self.value
        else:
            self.labelFormat = "%." + str(self.precision) + "f"

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togIntFloat']['widget']
            if self.type == int:
                w.setvalue('int')
            elif self.type == 'float':
                w.setvalue('float')

        if self.opPanel:
            self.opPanel.updateDisplay()

        if self.valueLabel and self.showLabel == 1:
            self.printLabel()

    def setMin(self, min):
        if min is not None:

            assert type(min) in [types.IntType, types.FloatType],\
                 "Illegal type for minimum. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(min) )

            if self.max and min > self.max:
                min = self.max

            self.min = self.type(min)

            if self.showLabel == 1:
                self.printLabel()

            if self.value < self.min:
                self.set(self.min)

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.minInput.set(self.labelFormat % self.min)

                self.opPanel.toggleMin.set(1)
                self.opPanel.min_entry.configure(state='normal', fg='gray0')
            self.minOld = self.min

        else:
            self.min = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleMin.set(0)
                self.opPanel.min_entry.configure(state='disabled', fg='gray40')

    def setMax(self, max):
        if max is not None:

            assert type(max) in [types.IntType, types.FloatType],\
                 "Illegal type for maximum. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(max) )

            if self.min and max < self.min:
                max = self.min

            self.max = self.type(max)

            if self.showLabel == 1:
                self.printLabel()

            if self.value > self.max:
                self.set(self.max)

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.maxInput.set(self.labelFormat % self.max)

                self.opPanel.toggleMax.set(1)
                self.opPanel.max_entry.configure(state='normal', fg='gray0')
            self.maxOld = self.max

        else:
            self.max = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleMax.set(0)
                self.opPanel.max_entry.configure(state='disabled', fg='gray40')

    def setIncrement(self, incr):
        if incr is not None:

            assert type(incr) in [types.IntType, types.FloatType],\
               "Illegal type for increment. Expected type %s or %s, got %s"%(
                   type(0), type(0.0), type(incr) )

            self.increment = self.type(incr)
            self.offsetValue = self.value
            self.incrementOld = self.increment

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.incrInput.set(self.labelFormat % self.increment)

                self.opPanel.toggleIncr.set(1)
                self.opPanel.incr_entry.configure(state='normal', fg='gray0')

        else:
            self.increment = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleIncr.set(0)
                self.opPanel.incr_entry.configure(state='disabled',
                                                  fg='gray40')

    def setPrecision(self, val):
        assert type(val) in [types.IntType, types.FloatType],\
               "Illegal type for precision. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(val) )
        val = int(val)

        if val > 10:
            val = 10
        if val < 1:
            val = 1
        self.precision = val
        if self.type == float:
            self.labelFormat = "%." + str(self.precision) + "f"
        else:
            self.labelFormat = "%d"

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['selPrec']['widget']
            w.setvalue(val)

        if self.opPanel:
            self.opPanel.updateDisplay()

        # and update the printed label
        if self.canvas and self.showLabel == 1:
            self.printLabel()

    def setContinuous(self, cont):
        """ cont can be None, 0 or 1 """

        assert cont in [True, False, 0, 1],\
             "Illegal value for continuous: expecting a boolean True, False, got %s"%cont

        self.continuous = cont
        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togCont']['widget']
            if cont:
                w.setvalue('on')
            else:
                w.setvalue('off')

    def setShowLabel(self, val):
        """Show label can be 0, 1 or 2
0: no label
1: show label only when value changes
2: label is always shown"""

        assert val in [0,1,2],\
               "Illegal value for showLabel. Expected 0, 1 or 2, got %s"%val

        if val != 0 and val != 1 and val != 2:
            print "Illegal value. Must be 0, 1 or 2"
            return
        self.showLabel = val
        self.toggleWidgetLabel(val)

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togLabel']['widget']
            if self.showLabel == 0:
                label = 'never'
            elif self.showLabel == 1:
                label = 'always'
            elif self.showLabel == 2:
                label = 'move'
            w.setvalue(label)

        if self.opPanel:
            self.opPanel.updateDisplay()

    def setOneTurn(self, oneTurn):
        assert type(oneTurn) in [types.IntType, types.FloatType],\
               "Illegal type for oneTurn. Expected %s or %s, got %s"%(
                   type(0), type(0.0), type(oneTurn) )

        self.oneTurn = oneTurn
        self.threeSixtyOver1turn = 360. / oneTurn
        self.piOver1turn = math.pi / oneTurn
        self.oneTurnOver2pi = oneTurn / (2 * math.pi)
        if self.opPanel:
            self.opPanel.updateDisplay()

    def setOrient(self, orient):
        if orient is None:
            if self.width > self.height:
                orient = 'horizontal'
            else:
                orient = 'vertical'
        assert orient in ['horizontal', 'vertical'],\
               "Expected 'vertical' or 'horizontal', got '%s'"%orient
        self.orient = orient

    def setReportDelta(self, rD):
        assert rD in [None, 0, 1],\
               "Expected None, 0 or 1, got %s"%rD
        if rD is None or rD == 0:
            self.reportDelta = 0
        else:
            self.reportDelta = 1

#####################################################################
# the 'lock' methods:
#####################################################################

    def lockTypeCB(self, mode):
        if mode != 0: mode = 1
        self.lockType = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockMinCB(self, mode):  #min entry field
        if mode != 0: mode = 1
        self.lockMin = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBMinCB(self, mode):  # min checkbutton
        if mode != 0: mode = 1
        self.lockBMin = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockMaxCB(self, mode):  # max entry field
        if mode != 0: mode = 1
        self.lockMax = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBMaxCB(self, mode):  # max checkbutton
        if mode != 0: mode = 1
        self.lockBMax = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockIncrementCB(self, mode):  # increment entry field
        if mode != 0: mode = 1
        self.lockIncrement = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBIncrementCB(self, mode):  # increment checkbutton
        if mode != 0: mode = 1
        self.lockBIncrement = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockPrecisionCB(self, mode):
        if mode != 0: mode = 1
        self.lockPrecision = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockShowLabelCB(self, mode):
        if mode != 0: mode = 1
        self.lockShowLabel = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockValueCB(self, mode):
        if mode != 0: mode = 1
        self.lockValue = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockContinuousCB(self, mode):
        if mode != 0: mode = 1
        self.lockContinuous = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockOneTurnCB(self, mode):
        if mode != 0: mode = 1
        self.lockOneTurn = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()
Beispiel #10
0
    def __init__(self,
                 master=None,
                 type='float',
                 labCfg={
                     'fg': 'black',
                     'side': 'left',
                     'text': None
                 },
                 min=None,
                 max=None,
                 showLabel=1,
                 value=0.0,
                 continuous=1,
                 precision=2,
                 callback=None,
                 lockMin=0,
                 lockBMin=0,
                 lockMax=0,
                 lockBMax=0,
                 lockPrecision=0,
                 lockShowLabel=0,
                 lockValue=0,
                 lockType=0,
                 lockContinuous=0,
                 signatures=None,
                 **kw):

        Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        # initialize various attributes with default values
        self.height = 100  # widget height
        self.width = 256  # widget height
        self.widthMinusOne = self.width - 1

        self.min = 0  # minimum value
        self.max = 1  # maximum value
        self.range = self.max - self.min

        self.precision = 2  # decimal places
        self.minOld = 0.  # used to store old values
        self.maxOld = 0.
        self.size = 50  # defines widget size
        self.offsetValue = 0.  # used to set increment correctly
        self.lab = None  # label
        self.callback = None  # user specified callback
        self.opPanel = None  # option panel widget
        self.value = 0.0  # current value of widget
        self.oldValue = 0.0  # old value of widget
        self.showLabel = 1  # turn on to display label on
        self.continuous = 1  # set to 1 to call callbacks at
        # each value change, else gets called
        # on button release event

        self.labCfg = labCfg  # Tkinter Label options
        self.labelFont = (ensureFontCase('helvetica'), 14, 'bold'
                          )  # label font
        self.labelColor = 'yellow'  # label color
        self.canvas = None  # the canvas to create the widget in

        self.lockMin = lockMin  # lock<X> vars are used in self.lock()
        self.lockMax = lockMax  # to lock/unlock entries in optionpanel
        self.lockBMin = lockBMin
        self.lockBMax = lockBMax
        self.lockPrecision = 0
        self.lockShowLabel = lockShowLabel
        self.lockValue = lockValue
        self.lockType = lockType
        self.lockContinuous = lockContinuous

        # configure with user-defined values
        self.setCallback(callback)
        self.setContinuous(continuous)

        self.setType(type)
        self.setPrecision(precision)
        self.setMin(min)
        self.setMax(max)
        self.setShowLabel(showLabel)
        self.setValue(value)
        self.setLabel(self.labCfg)

        if master is None:
            master = Tkinter.Toplevel()

        self.master = master  # widget master

        self.createCanvas(master)

        Tkinter.Widget.bind(self.canvas, "<ButtonPress-1>", self.mouseDown)
        Tkinter.Widget.bind(self.canvas, "<B1-Motion>", self.mouseMove)
        Tkinter.Widget.bind(self.canvas, "<ButtonRelease-1>", self.mouseUp)

        # create cursor
        self.cursorTk = self.canvas.create_line(0, 0, 0, 0, tags=['cursor'])

        self.increment = 0.0
        self.incrementOld = 0.
        self.lockIncrement = 0
        self.lockBIncrement = 0
        self.oneTurn = 360.
        self.lockOneTurn = 0
        self.opPanel = OptionsPanel(master=self, title="Slider graph Options")

        self.signatures = None  # Signature objects fro isocontouring lib
        self.sigData = []  # list of (x,y) values arrays for each signature
        self.maxFun = []  # max Y value in each signature
        self.minFun = []  # min Y value in each signature
        self.yratios = []  # normalization factors
        self.colors = ['red', 'green', 'blue', 'orange']
        self.tkLines = []  # list of Tkids for lines
        if signatures:
            self.setSignatures(signatures)
Beispiel #11
0
class PatternCanvas:
    
    def __init__(self,master,title=None,callback=None,
                 size=5,border=1,tkCol=None,immediate=1):
        #tkCol is a list of list where each elemnt is a color
        # tkCol[0][0] = a Tk color
        # size = size of the sqare representing the Tkcolor on the canvas
        # border = border size
        # 
        if not master:
            master = Tkinter.Toplevel()

        if title is not None:
            master.title(title)
        
        f = self.frame = Tkinter.Frame(master)

        
        if tkCol:
            self.Xelemt = len(tkCol)
            self.Yelemt = len(tkCol[0])
            self.size = size
            self.border = border
            self.width =(self.Xelemt*self.size+2*self.border)
            self.height =(self.Yelemt*self.size+2*self.border)
            self.cwcanvas = Tkinter.Canvas(f,width=self.width,
                                           height=self.height, 
                                           borderwidth=3 )
                                           
            xo = self.border
            for i in range(self.Xelemt):
                xe = xo + self.size
                yo = self.border
                for j in range(self.Yelemt):
                    ye = yo + self.size
                    self.cwcanvas.create_rectangle(xo, yo, xe, ye,
                                                   fill=tkCol[i][j])
                    yo = ye
                xo = xe

        self.cwcanvas.pack()
        #self.frame.pack()

        # CallBack Manager
        self.cbManager = CallbackManager()
        if callback:
            if type(callback) in [types.ListType, types.TupleType]:
                map(self.cbManager.AddCallback, callback)
            else:
                self.cbManager.AddCallback(callback)


    def get(self):
        pass
    
    def set(self):
        pass
    
    def pack(self,*args, **kw):
        apply(self.frame.pack, args, kw)
        
    def pack_forget(self,*args, **kw):
        apply(self.frame.pack_forget, args, kw)
                         
    def grid(self,*args, **kw):
        apply(self.frame.grid, args, kw)

    def grid_forget(self,*args, **kw):
        apply(self.frame.grid_forget, args, kw)

    def destroy(self,*args, **kw):
        apply(self.frame.destroy, args, kw)
    def __init__(self,
                 master=None,
                 name='vector',
                 size=200,
                 continuous=1,
                 vector=[0.0, 0.0, 1.0],
                 mode='XY',
                 precision=5,
                 lockContinuous=0,
                 lockPrecision=0,
                 lockMode=0,
                 callback=None,
                 labelSide='top'):

        KeyboardModifierMonitor.__init__(self)

        self.callback = callback  # user specified callback
        self.name = name  # title inside canvas
        self.labelSide = labelSide  # where title gets packed
        self.mode = mode  # axe mode: can be 'XY', 'X', 'Y' or 'Z'
        self.precision = precision  # floating number digits
        self.continuous = continuous  # can be 1 or 0
        self.vector = vector  # initial vector value
        self.size = size  # size of vector widget

        self.lockContinuous = lockContinuous  # set to 1 to lock menus in
        # option panel
        self.lockPrecision = lockPrecision
        self.lockMode = lockMode

        self.r = self.size / 2
        self.r2 = self.r * self.r

        self.drawShadowX = 0
        self.drawShadowY = 1
        self.drawShadowZ = 0
        self.fillShadowPlanes = 1

        self.master = master = tkinter.Frame(master)
        #Tkinter.Frame.__init__(self, master)
        #Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument
        self.zeros = numpy.array((0, 0, 0), numpy.int16)
        self.viewingMatInv = numpy.array(
            [[0.96770716, -0.03229283, -0.25, 0.],
             [0.03229283, -0.96770716, 0.25, 0.], [0.25, 0.25, 0.93541437, 0.],
             [0., 0., 0., 1.]], 'f')
        self.viewingMat = numpy.transpose(self.viewingMatInv)
        self.createCanvas(master, size)
        self.createEntries(self.frame)
        tkinter.Widget.bind(self.canvas, "<ButtonPress-1>", self.mouseDown)
        tkinter.Widget.bind(self.canvas, "<ButtonRelease-1>", self.mouseUp)
        tkinter.Widget.bind(self.canvas, "<B1-Motion>", self.mouseMove)

        self.setEntries()

        self.opPanel = VectorOptionsPanel(master=self,
                                          title="Vector GUI Options")
        tkinter.Widget.bind(self.canvas, "<Button-3>", self.toggleOptPanel)

        if self.callback:
            self.callbacks.AddCallback(self.callback)
class vectorGUI(KeyboardModifierMonitor):
    """ This class implements a vector widget.
    The widget has a vector which can be moved within a sphere to generate
    a 3D vector. Values are normalized and stored in self.vector
    In addition, the vector can be rotated with 3 thumbwheels.
    Values can be entered directly by typing them into the 3 entry forms.
    Then, the 'normalize and set' button has to be pressed in order to
    normalize and set the new vector.

    The widget has a configure() method: vector, mode, precision and
    continuous can be set this way.
    vector is a list of 3 floating values, e.g. [0., 0., 1.]
    mode describes the axis movement (rotation around an axis): is type
    string and can be either 'X', 'Y' or 'Z'. Free movement (standard
    value) is 'XY'.
    continuous can be either 0 (or None) or 1. Default is 0
    precision is type int and ranges from 1 - 10
    master, name and size can be passed only to the constructor.

    a lock() method is used to disable the various gui components of the
    options panel. Usage: <instance>.lock(<component>=<value>)
    component is continuous, precision or mode. value is 0 or 1. 1 disables,
    0 enables.
    """
    def pack(self, *args, **kw):
        self.master.pack(args, **kw)

    def grid(self, *args, **kw):
        self.master.grid(args, **kw)

    def bind(self, *args, **kw):
        self.master.bind(args, **kw)

    def unbind(self, *args, **kw):
        self.master.unbind(args, **kw)

    def grid_forget(self):
        self.master.grid_forget()

    def __init__(self,
                 master=None,
                 name='vector',
                 size=200,
                 continuous=1,
                 vector=[0.0, 0.0, 1.0],
                 mode='XY',
                 precision=5,
                 lockContinuous=0,
                 lockPrecision=0,
                 lockMode=0,
                 callback=None,
                 labelSide='top'):

        KeyboardModifierMonitor.__init__(self)

        self.callback = callback  # user specified callback
        self.name = name  # title inside canvas
        self.labelSide = labelSide  # where title gets packed
        self.mode = mode  # axe mode: can be 'XY', 'X', 'Y' or 'Z'
        self.precision = precision  # floating number digits
        self.continuous = continuous  # can be 1 or 0
        self.vector = vector  # initial vector value
        self.size = size  # size of vector widget

        self.lockContinuous = lockContinuous  # set to 1 to lock menus in
        # option panel
        self.lockPrecision = lockPrecision
        self.lockMode = lockMode

        self.r = self.size / 2
        self.r2 = self.r * self.r

        self.drawShadowX = 0
        self.drawShadowY = 1
        self.drawShadowZ = 0
        self.fillShadowPlanes = 1

        self.master = master = tkinter.Frame(master)
        #Tkinter.Frame.__init__(self, master)
        #Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument
        self.zeros = numpy.array((0, 0, 0), numpy.int16)
        self.viewingMatInv = numpy.array(
            [[0.96770716, -0.03229283, -0.25, 0.],
             [0.03229283, -0.96770716, 0.25, 0.], [0.25, 0.25, 0.93541437, 0.],
             [0., 0., 0., 1.]], 'f')
        self.viewingMat = numpy.transpose(self.viewingMatInv)
        self.createCanvas(master, size)
        self.createEntries(self.frame)
        tkinter.Widget.bind(self.canvas, "<ButtonPress-1>", self.mouseDown)
        tkinter.Widget.bind(self.canvas, "<ButtonRelease-1>", self.mouseUp)
        tkinter.Widget.bind(self.canvas, "<B1-Motion>", self.mouseMove)

        self.setEntries()

        self.opPanel = VectorOptionsPanel(master=self,
                                          title="Vector GUI Options")
        tkinter.Widget.bind(self.canvas, "<Button-3>", self.toggleOptPanel)

        if self.callback:
            self.callbacks.AddCallback(self.callback)

    def toggleOptPanel(self, event=None):
        # opens and closes options panel by right clicking on widget
        if self.opPanel.flag:
            self.opPanel.Dismiss_cb()
        else:
            if not hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.displayPanel(create=1)
            else:
                self.opPanel.displayPanel(create=0)

    def mouseUp(self, event):
        if not self.continuous:
            self.callbacks.CallCallbacks(self.vector)

    def mouseDown(self, event):
        # remember where the mouse went down
        xc = event.x - self.xm
        yc = self.ym - event.y
        # compute the intersection point between
        z2 = self.r2 - (xc * xc) - (yc * yc)

        if z2 >= 0:  # we picked inside the sphere. going for a XY rotation
            self.lastPt3D = (xc, yc, math.sqrt(z2))
        else:  # going for a Z rotation
            pass

    def mouseMove(self, event):
        # simple trackball, only works inside cirle
        # creates an XY rotation defined by pts intersecting the spheres
        xc = event.x - self.xm
        yc = self.ym - event.y
        # compute the intersection point between
        xc2 = xc * xc
        yc2 = yc * yc
        z2 = self.r2 - xc2 - yc2

        if z2 < 0:
            lInvMag = 1. / math.sqrt(xc2 + yc2)
            xc *= lInvMag * (self.r)
            yc *= lInvMag * (self.r)
            z2 = 0

        # compute rotation angle
        a = self.lastPt3D
        b = (xc, yc, math.sqrt(z2))
        ang = math.acos((a[0] * b[0] + a[1] * b[1] + a[2] * b[2]) / self.r2)
        if self.mode == 'XY':
            #compute rotation axis
            rotaxis = numpy.array(
                (a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
                 a[0] * b[1] - a[1] * b[0]), 'f')
        elif self.mode == 'X':
            rotaxis = numpy.array((1., 0., 0.), 'f')
        elif self.mode == 'Y':
            rotaxis = numpy.array((0., 1., 0.), 'f')
        elif self.mode == 'Z':
            rotaxis = numpy.array((0., 0., 1.), 'f')
        mat = rotax(self.zeros, rotaxis, ang)
        self.lastPt3D = b
        self.updateVector(mat)

    def updateVector(self, mat):
        mat = numpy.reshape(mat, (4, 4))
        newPts = self.vector + [1]
        newPts = numpy.dot([newPts], mat)[0]
        self.vector = [newPts[0], newPts[1], newPts[2]]
        self.setEntries()
        self.drawVector()
        if self.continuous:
            self.callbacks.CallCallbacks(self.vector)

    def drawVector(self):
        coords3D = self.vector + [1]
        # apply viewing transformation to vector
        newPtsWithView = numpy.dot([coords3D], self.viewingMat)[0]
        # compute 2D projection of vector (broken on 2 segments for
        # depth cueing
        x1 = self.xm + int(newPtsWithView[0] * (self.xm))
        y1 = self.ym + int(newPtsWithView[1] * (self.ym))

        # change vector's segments coordinates
        self.canvas.coords(self.lId1, self.xm, self.ym, x1, y1)

        # update vector shadows
        # Y=0 plane
        if self.drawShadowY:
            pt = [coords3D[0], 0, coords3D[2], 1.]
            newPtsWithView = numpy.dot([pt], self.viewingMat)[0]
            xm = self.xm + int(newPtsWithView[0] * (self.xm))
            ym = self.ym + int(newPtsWithView[1] * (self.ym))
            if self.fillShadowPlanes:
                self.canvas.coords(self.shadowPY, self.xm, self.ym, xm, ym, x1,
                                   y1)
            self.canvas.coords(self.shadowY, self.xm, self.ym, xm, ym, x1, y1)

# X=0 plane
        if self.drawShadowX:
            pt = [0, coords3D[1], coords3D[2], 1.]
            newPtsWithView = numpy.dot([pt], self.viewingMat)[0]
            xm = self.xm + int(newPtsWithView[0] * (self.xm))
            ym = self.ym + int(newPtsWithView[1] * (self.ym))
            if self.fillShadowPlanes:
                self.canvas.coords(self.shadowPX, self.xm, self.ym, xm, ym, x1,
                                   y1)
            self.canvas.coords(self.shadowX, self.xm, self.ym, xm, ym, x1, y1)

# Z=0 plane
        if self.drawShadowZ:
            pt = [coords3D[0], coords3D[1], 0, 1.]
            newPtsWithView = numpy.dot([pt], self.viewingMat)[0]
            xm = self.xm + int(newPtsWithView[0] * (self.xm))
            ym = self.ym + int(newPtsWithView[1] * (self.ym))
            if self.fillShadowPlanes:
                self.canvas.coords(self.shadowPZ, self.xm, self.ym, xm, ym, x1,
                                   y1)
            self.canvas.coords(self.shadowZ, self.xm, self.ym, xm, ym, x1, y1)

        if self.vector[0] < 0.0:
            self.canvas.tag_raise('verticalCircle', 'moving')
        else:
            self.canvas.tag_lower('verticalCircle', 'moving')

        if self.vector[1] < 0.0:
            self.canvas.tag_raise('horizontalCircle', 'moving')
        else:
            self.canvas.tag_lower('horizontalCircle', 'moving')

        if self.vector[2] < 0.0 or self.vector[1] < 0.0:
            self.canvas.tag_raise('axis', 'moving')
        else:
            self.canvas.tag_lower('axis', 'moving')

    def thumbx_cb(self, events=None):
        val = self.thumbx.value

        ##          valX=self.thumbx.value
        ##          valY=self.thumby.value
        ##          valZ=self.thumbz.value

        ##          n = math.sqrt(valX*valX+valY*valY+valZ*valZ)
        ##          if n == 0.0: v = [0.0, 0.0, 1.0]
        ##          else: v = [valX/n, valY/n, valZ/n]
        ##          val = v[0]

        rot = numpy.zeros((4, 4), 'f')
        rot[0][0] = 1.0
        rot[1][1] = math.cos(val)
        rot[1][2] = -math.sin(val)
        rot[2][1] = math.sin(val)
        rot[2][2] = math.cos(val)
        self.updateVector(rot)

    def thumby_cb(self, events=None):
        val = self.thumby.value
        rot = numpy.zeros((4, 4), 'f')
        rot[0][0] = math.cos(val)
        rot[0][2] = -math.sin(val)
        rot[1][1] = 1.0
        rot[2][0] = math.sin(val)
        rot[2][2] = math.cos(val)
        self.updateVector(rot)

    def thumbz_cb(self, events=None):
        val = self.thumbz.value
        rot = numpy.zeros((4, 4), 'f')
        rot[0][0] = math.cos(val)
        rot[0][1] = -math.sin(val)
        rot[1][0] = math.sin(val)
        rot[1][1] = math.cos(val)
        rot[2][2] = 1.0
        self.updateVector(rot)

    def entryX_cb(self, event=None):
        val = self.entryXTk.get()
        if len(val) == 0: val = self.vector[0]
        try:
            val = float(val)
            self.entryXTk.set(self.thumbx.labelFormat % val)
        except ValueError:
            # put back original value if someone types garbage
            self.entryXTk.set(self.thumbx.labelFormat % self.vector[0])

    def entryY_cb(self, event=None):
        val = self.entryYTk.get()
        if len(val) == 0: val = self.vector[1]
        try:
            val = float(val)
            self.entryYTk.set(self.thumby.labelFormat % val)
        except ValueError:
            # put back original value if someone types garbage
            self.entryYTk.set(self.thumby.labelFormat % self.vector[1])

    def entryZ_cb(self, event=None):
        val = self.entryZTk.get()
        if len(val) == 0: val = self.vector[2]
        try:
            val = float(val)
            self.entryZTk.set(self.thumbz.labelFormat % val)
        except ValueError:
            # put back original value if someone types garbage
            self.entryZTk.set(self.thumbz.labelFormat % self.vector[2])

    def entryV_cb(self, event=None):
        v = self.entryVTk.get()
        try:
            val = string.split(v)
        except:
            self.setEntries()
            return

        if val is None or len(val) != 3:
            self.setEntries()
            return

        try:
            valX = float(val[0])
            valY = float(val[1])
            valZ = float(val[2])
        except:
            self.setEntries()
            return

        # compute normalized vector
        n = math.sqrt(valX * valX + valY * valY + valZ * valZ)
        if n == 0.0: v = [0.0, 0.0, 1.0]
        else: v = [valX / n, valY / n, valZ / n]
        self.vector = v
        self.setEntries()
        self.drawVector()
        if self.continuous:
            self.callbacks.CallCallbacks(self.vector)

    def setButton_cb(self, event=None):
        valX = float(self.entryXTk.get())
        valY = float(self.entryYTk.get())
        valZ = float(self.entryZTk.get())

        # compute normalized vector
        n = math.sqrt(valX * valX + valY * valY + valZ * valZ)
        if n == 0.0: v = [0.0, 0.0, 1.0]
        else: v = [valX / n, valY / n, valZ / n]
        self.vector = v
        self.setEntries()
        self.drawVector()
        if self.continuous:
            self.callbacks.CallCallbacks(self.vector)

    def createEntries(self, master):
        self.f = tkinter.Frame(master)

        #self.f.grid(column=3, rowspan=3)

        def fX():
            self.vector = [1., 0., 0.]
            self.setEntries()
            self.callbacks.CallCallbacks(self.vector)

        def fY():
            self.vector = [0., 1., 0.]
            self.setEntries()
            self.callbacks.CallCallbacks(self.vector)

        def fZ():
            self.vector = [0., 0., 1.]
            self.setEntries()
            self.callbacks.CallCallbacks(self.vector)

        f1 = tkinter.Frame(master)
        f2 = tkinter.Frame(master)
        f3 = tkinter.Frame(master)
        f1.pack(side='top')
        f2.pack(side='top')
        f3.pack(side='top')
        lX = tkinter.Button(master=f1, text='x', command=fX)
        lX.pack(side='left')
        lY = tkinter.Button(master=f2, text='y', command=fY)
        lY.pack(side='left')
        lZ = tkinter.Button(master=f3, text='z', command=fZ)
        lZ.pack(side='left')

        #lX = Tkinter.Button(master=self.f, text='x', command=fX)
        #lY = Tkinter.Button(master=self.f, text='y', command=fY)
        #lZ = Tkinter.Button(master=self.f, text='z', command=fZ)
        #lX.grid(row=0, column=0)
        #lY.grid(row=1, column=0)
        #lZ.grid(row=2, column=0)

        #self.thumbx = ThumbWheel(master=self.f, width=50,
        self.thumbx = ThumbWheel(master=f1,
                                 width=50,
                                 height=20,
                                 labcfg={
                                     'text': 'X:',
                                     'side': 'left'
                                 },
                                 wheelPad=2,
                                 oneTurn=.1,
                                 min=-1,
                                 max=1,
                                 showLabel=0,
                                 precision=5,
                                 type=float)
        self.thumbx.callbacks.AddCallback(self.thumbx_cb)
        self.thumbx.unbind("<Button-3>")
        self.thumbx.canvas.unbind("<Button-3>")
        #self.thumbx.grid(row=0, column=1)
        self.thumbx.pack(side='left')

        #self.thumby = ThumbWheel(master=self.f, width=50,
        self.thumby = ThumbWheel(master=f2,
                                 width=50,
                                 height=20,
                                 labcfg={
                                     'text': 'Y:',
                                     'side': 'left'
                                 },
                                 wheelPad=2,
                                 oneTurn=.1,
                                 min=-1,
                                 max=1,
                                 showLabel=0,
                                 precision=5,
                                 type=float)
        self.thumby.callbacks.AddCallback(self.thumby_cb)
        self.thumby.unbind("<Button-3>")
        self.thumby.canvas.unbind("<Button-3>")
        #self.thumby.grid(row=1, column=1)
        self.thumby.pack(side='left')

        #self.thumbz = ThumbWheel(master=self.f, width=50,
        self.thumbz = ThumbWheel(master=f3,
                                 width=50,
                                 height=20,
                                 labcfg={
                                     'text': 'Z:',
                                     'side': 'left'
                                 },
                                 wheelPad=2,
                                 oneTurn=.1,
                                 min=-1,
                                 max=1,
                                 showLabel=0,
                                 precision=5,
                                 type=float)
        self.thumbz.callbacks.AddCallback(self.thumbz_cb)
        self.thumbz.unbind("<Button-3>")
        self.thumbz.canvas.unbind("<Button-3>")
        #self.thumbz.grid(row=2, column=1)
        self.thumbz.pack(side='left')

        self.entryXTk = tkinter.StringVar()
        #self.entryX = Tkinter.Entry(master=self.f, textvariable=self.entryXTk,
        self.entryX = tkinter.Entry(master=f1,
                                    textvariable=self.entryXTk,
                                    width=8)
        self.entryX.bind('<Return>', self.entryX_cb)
        #self.entryX.grid(row=0, column=2)
        self.entryX.pack(side='left')

        self.entryYTk = tkinter.StringVar()
        #self.entryY = Tkinter.Entry(master=self.f, textvariable=self.entryYTk,
        self.entryY = tkinter.Entry(master=f2,
                                    textvariable=self.entryYTk,
                                    width=8)
        self.entryY.bind('<Return>', self.entryY_cb)
        #self.entryY.grid(row=1, column=2)
        self.entryY.pack(side='left')

        self.entryZTk = tkinter.StringVar()
        #self.entryZ = Tkinter.Entry(master=self.f, textvariable=self.entryZTk,
        self.entryZ = tkinter.Entry(master=f3,
                                    textvariable=self.entryZTk,
                                    width=8)
        self.entryZ.bind('<Return>', self.entryZ_cb)
        #self.entryZ.grid(row=2, column=2)
        self.entryZ.pack(side='left')

        self.entryVTk = tkinter.StringVar()
        self.entryV = tkinter.Entry(master,
                                    textvariable=self.entryVTk,
                                    width=18)

        self.entryV.bind('<Return>', self.entryV_cb)

        self.f.pack(side='top', expand=1)

        self.entryV.pack()

        self.setButton = tkinter.Button(master,
                                        text='normalize and set',
                                        command=self.setButton_cb)
        self.setButton.pack(side='bottom')

    def setEntries(self):
        self.entryXTk.set(self.thumbx.labelFormat % self.vector[0])
        self.entryYTk.set(self.thumby.labelFormat % self.vector[1])
        self.entryZTk.set(self.thumbz.labelFormat % self.vector[2])

        lf = '%.3f'
        self.entryVTk.set(lf%self.vector[0]+' '+lf%self.vector[1]+' '\
                          +lf%self.vector[2])
        self.drawVector()

    def createCanvas(self, master, size=200):

        self.frame = tkinter.Frame(self.master, relief='sunken', borderwidth=5)

        if self.name is not None:
            self.title = tkinter.Label(self.frame, text=self.name)
            self.title.pack(side=self.labelSide)

        self.canvas = tkinter.Canvas(self.frame, width=size, height=size)

        # set the focus so that we get keyboard events, and add callbacks
        self.canvas.bind('<KeyPress>', self.modifierDown)
        self.canvas.bind("<KeyRelease>", self.modifierUp)

        xm = self.xm = ym = self.ym = self.r
        self.canvas.create_oval(0, 0, size, size)
        self.canvas.create_oval(xm - (xm / 4),
                                0,
                                xm + (xm / 4),
                                size,
                                tags='verticalCircle')
        self.canvas.create_oval(0,
                                ym - (ym / 4),
                                size,
                                ym + (ym / 4),
                                tags='horizontalCircle')

        # apply viewing transformation to vector
        XaxisWithView = numpy.dot([(1., 0., 0., 1.)], self.viewingMat)[0]
        x1 = self.xm + int(XaxisWithView[0] * (self.xm))
        y1 = self.ym + int(XaxisWithView[1] * (self.ym))
        self.canvas.create_line(xm, ym, x1, y1, fill='red', tags='axis')

        XaxisWithView = numpy.dot([(0., 1., 0., 1.)], self.viewingMat)[0]
        x2 = self.xm + int(XaxisWithView[0] * (self.xm))
        y2 = self.ym + int(XaxisWithView[1] * (self.ym))
        self.canvas.create_line(xm, ym, x2, y2, fill='green', tags='axis')

        XaxisWithView = numpy.dot([(0., 0., 1., 1.)], self.viewingMat)[0]
        x3 = self.xm + int(XaxisWithView[0] * (self.xm))
        y3 = self.ym + int(XaxisWithView[1] * (self.ym))
        self.canvas.create_line(xm, ym, x3, y3, fill='blue', tags='axis')

        self.textId = self.canvas.create_text(0, size, anchor='sw', text="XY")

        # shadow line in X=0 plane
        self.shadowPX = self.canvas.create_polygon(0,
                                                   0,
                                                   0,
                                                   0,
                                                   0,
                                                   0,
                                                   fill='red',
                                                   tag='moving')
        self.shadowPY = self.canvas.create_polygon(0,
                                                   0,
                                                   0,
                                                   0,
                                                   0,
                                                   0,
                                                   fill='green',
                                                   tag='moving')
        self.shadowPZ = self.canvas.create_polygon(0,
                                                   0,
                                                   0,
                                                   0,
                                                   0,
                                                   0,
                                                   fill='blue',
                                                   tag='moving')

        self.shadowX = self.canvas.create_line(0,
                                               0,
                                               0,
                                               0,
                                               fill='black',
                                               tag='moving')
        self.shadowY = self.canvas.create_line(0,
                                               0,
                                               0,
                                               0,
                                               fill='black',
                                               tag='moving')
        self.shadowZ = self.canvas.create_line(0,
                                               0,
                                               0,
                                               0,
                                               fill='black',
                                               tag='moving')

        self.lId1 = self.canvas.create_line(0,
                                            0,
                                            0,
                                            0,
                                            fill='black',
                                            width=3,
                                            arrow='last')
        self.canvas.pack(side='top')
        self.frame.pack(expand=1, fill='x')
        self.xm = self.ym = self.r
        self.drawVector()

    def setVector(self, value):
        #setVector does not call a callback!
        v = value
        # compute normalized vector
        n = math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2])
        if n == 0.0: v = [0.0, 0.0, 1.0]
        else: v = [v[0] / n, v[1] / n, v[2] / n]
        self.vector = v
        self.setEntries()
        self.drawVector()

#####################################################################
# the 'configure' methods:
#####################################################################

    def configure(self, **kw):
        for key, value in list(kw.items()):
            # the 'set parameter' callbacks
            if key == 'continuous': self.setContinuous(value)
            elif key == 'mode': self.setMode(value)
            elif key == 'precision':
                self.setPrecision(value)

                # the 'lock entries' callbacks
            elif key == 'lockContinuous':
                self.lockContinuousCB(value)
            elif key == 'lockMode':
                self.lockModeCB(value)
            elif key == 'lockPrecision':
                self.lockPrecisionCB(value)

    def setContinuous(self, cont):
        """ cont can be None, 0 or 1 """
        if cont != 1:
            cont = None
        self.continuous = cont
        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togCont']['widget']
            if cont:
                w.setvalue('on')
            else:
                w.setvalue('off')

    def setMode(self, mode):
        if mode != 'XY' and mode != 'X' and mode != 'Y' and mode != 'Z':
            mode = 'XY'
        self.canvas.itemconfigure(self.textId, text=mode)
        self.mode = mode

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togAxes']['widget']
            w.setvalue(mode)

    def setPrecision(self, val):
        val = int(val)
        if val > 10: val = 10
        if val < 1: val = 1

        self.thumbx.configure(precision=val)
        self.thumby.configure(precision=val)
        self.thumbz.configure(precision=val)

        self.entryXTk.set(self.thumbx.labelFormat % self.vector[0])
        self.entryYTk.set(self.thumby.labelFormat % self.vector[1])
        self.entryZTk.set(self.thumbz.labelFormat % self.vector[2])

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['selPrec']['widget']
            w.setvalue(val)

        if self.opPanel:
            self.opPanel.updateDisplay()

#####################################################################
# the 'lock' methods:
#####################################################################

    def lockContinuousCB(self, mode):
        if mode != 0: mode = 1
        self.lockContinuous = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockPrecisionCB(self, mode):
        if mode != 0: mode = 1
        self.lockPrecision = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockModeCB(self, mode):
        if mode != 0: mode = 1
        self.lockMode = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()
Beispiel #14
0
    def __init__(self):
        self.kbdModifier = {
            'Shift_L':0,
            'Alt_L':0,
            'Control_L':0,
            'Shift_R':0,
            'Alt_R':0,
            'Control_R':0,
            }
	self.keybdModifierCallbacksDown = {
	    'Shift_L':CallbackManager(),
            'Alt_L':CallbackManager(),
            'Control_L':CallbackManager(),
            'Shift_R':CallbackManager(),
            'Alt_R':CallbackManager(),
            'Control_R':CallbackManager(),
	}
	self.keybdModifierCallbacksUp = {
	    'Shift_L':CallbackManager(),
            'Alt_L':CallbackManager(),
            'Control_L':CallbackManager(),
            'Shift_R':CallbackManager(),
            'Alt_R':CallbackManager(),
            'Control_R':CallbackManager(),
	}
Beispiel #15
0
 def __init__(self,master=None,callback=None,continuous=1):
            
     self.master=master
     self.callback = None
     self.callbacks = CallbackManager()
     self.canvas=canvas = Canvas(self.master,width=345,height=320,bg='white') 
     self.toolbar = Frame(master)             # Create Toolbar
     self.toolbar.pack(side='top', expand=1, fill='both') 
     self.menuFrame1 = Tkinter.Frame(self.toolbar, relief='raised', borderwidth=3)
     self.menuFrame1.pack(side='top', expand=1, fill='x')
     self.filebutton = Tkinter.Menubutton(self.menuFrame1, text='File')
     self.filebutton.pack(side='left')
     self.filemenu = Tkinter.Menu(self.filebutton, {})
     self.filemenu.add_command(label='Read', command=self.read_cb)
     self.filemenu.add_command(label='Write', command=self.write_cb)
     self.filebutton['menu'] = self.filemenu
     self.editbutton = Tkinter.Menubutton(self.menuFrame1, text='Edit')
     self.editbutton.pack(side='left', anchor='w')
     self.editmenu = Tkinter.Menu(self.editbutton, {})
     self.editmenu.add_command(label='Reset to first in history', command=self.resetAll_cb)
     self.editmenu.add_command(label='Step back in history loop', command=self.stepBack_cb)
     self.editmenu.add_command(label='Default Curve', command=self.defaultcurve_cb)
     self.editmenu.add_command(label='Invert Curve',command=self.invertGraph)
     self.histvar=IntVar()
     self.histvar.set(1)
     self.editmenu.add_checkbutton(label='Histogram',var=self.histvar,command=self.drawHistogram)
     self.editbutton['menu'] = self.editmenu
     self.optionType = IntVar()
     self.updatebutton = Tkinter.Menubutton(self.menuFrame1, text='Update')
     self.updatebutton.pack(side='left', anchor='w')
     self.updatemenu = Tkinter.Menu(self.updatebutton,{} )
     for v,s in {0:'Continuous',1:'MouseButtonUp',2:'Update'}.items():
         self.updatemenu.add_radiobutton(label=s,
                             var=self.optionType,
                             value = v,command=self.calloption)
     if continuous==1:
         self.optionType.set(0)
     self.updatebutton['menu'] = self.updatemenu
     #Curve Type
     self.CurveType = IntVar()
     self.CurveType.set(0) 
     self.Smooth=1
     self.curvebutton = Tkinter.Menubutton(self.menuFrame1, text='Curve')
     self.curvebutton.pack(side='left', anchor='w')
     self.curvemenu = Tkinter.Menu(self.curvebutton,{} )
     for v,s in {0:'Smooth',1:'Freehand'}.items():
         self.curvemenu.add_radiobutton(label=s,
                             var=self.CurveType,
                             value = v,command=self.curveoption)
     
         
     self.curvebutton['menu'] = self.curvemenu
     f1 = Tkinter.Frame(self.master)
     f1.pack(side='bottom', fill='both', expand=1)
     self.d1scalewheellab=Label(f1,text="Sensitivity")
     self.d1scalewheellab.pack(side="left")
     self.d1scalewheel=ThumbWheel(width=100, height=26,wheelPad=4,master=f1,labcfg={'fg':'black', 'side':'left', 'text':'Test:'},wheelLabcfg1={'font':(ensureFontCase('times'),14,'bold')},wheelLabcfg2={'font':(ensureFontCase('times'),14,'bold')},canvascfg={'bg':'blue'},min = 0.0,max = 1.0,precision =4,showlabel =0,value =0.013,continuous =0,oneTurn =0.01,size = 200)
     self.d1scalewheel.pack(side="left")
     #tooltip
     self.balloon = Pmw.Balloon(f1)
     self.balloon.bind(self.d1scalewheel,"cutoff value for differences in Z xoordinates,small values generate more contours")
     self.Updatebutton=Button(f1,text='  Update  ',command=self.Update)
     self.Updatebutton.pack(side=LEFT)
     
     self.Quitbutton=Button(f1,text=' Dismiss ',command=self.dismiss_cb)
     self.Quitbutton.pack(side=RIGHT)
     self.canvas.bind("<Button-1>", self.OnCanvasClicked)
     self.canvas.bind("<B1-Motion>", self.OnCanvasMouseDrag)
     self.canvas.bind("<ButtonRelease-1>", self.OnCanvasMouseUp)
     self.canvas.config(closeenough=2.0)
     self.canvas.pack(side=BOTTOM, fill=BOTH,expand=1)
     self.startpoint=(px,py)=(50,275)
     self.endpoint=(px1,py1)=(305,20)
     self.newpoints=[(px,py),(px1,py1)]
     self.canvas.create_rectangle([(px-1,py),(px1+1,py1)],fill='white',outline="black",width=1)
     self.canvas.create_text(46,281,text=0,anchor=N)
               
     #Drawing Graph Sheet
     for i in range(1,6):
         x=50+i*50
         canvas.create_line(x,280,x,275,width=1)
         canvas.create_text(x,281,text='%d' %(50*i),anchor=N)
     for i in range(1,5):
         x=50+i*50
         canvas.create_line(x,275,x,20,width=1,fill="gray80")
     for i in range(1,6):
         y=275-i*50
         canvas.create_line(45,y,50,y,width=1)
         canvas.create_text(44,y,text='%d' %(50*i),anchor=E)
     for i in range(1,5):
         y=275-i*50
         canvas.create_line(50,y,305,y,width=1,fill="gray80")
     (x,y)=self.newpoints[0]
     (x1,y1)=self.newpoints[-1]
     self.curline=canvas.create_line(self.newpoints,fill='black',width=1)
     
     #GRAY SCALE
     grays=[]
     for i in range(0,100,1):
         grays.append("gray"+"%d" %i)
     #grays.reverse()
     #bottom one
     x1=48
     x2=51
     self.canvas.create_rectangle([(50,315),(307,300)],fill='white',outline="black",width=0.5)
     for a in grays:
         if x1>306:
             
            x1=x2=306
         self.canvas.create_rectangle([(x1+2.5,314),(x2+2.5,301)],fill=a,outline=a,width=1)
         x1=x1+2.5
         x2=x2+2.5
     #left one
     y1=274
     y2=271
     self.canvas.create_rectangle([(20,275),(5,20)],fill='black',outline="black",width=0.5)
     for a in grays:
         if y1>275:
             y1=y2=275
         self.canvas.create_rectangle([(19,y1-2.5),(6,y2-2.5)],fill=a,outline=a,width=1)    
         y1=y1-2.5
         y2=y2-2.5
           
     self.oldpoints=[]
     self.canvas.configure(cursor='cross')
     self.curovals=[]
     self.default_points=[(50,275),(88, 238), (101, 150), (154, 78), (75, 271),(305,20)]
     # now set the constructor options correctly using the configure method
     apply( self.configure, (),{'callback':callback,'continuous':continuous})
     self.continuous=continuous
     self.mousebuttonup=0
     self.update=0
     self.range_points=[]
     self.history=[]
     self.bars=[]
     self.default_ramp=[]
     self.histvalues=[]
Beispiel #16
0
class CoefCanvas:
    
    def __init__(self,master,title=None,width=150,height=50,
                 callback=None):
        #tkCol is a list of list where each elemnt is a color
        # tkCol[0][0] = a Tk color
        # size = size of the sqare representing the Tkcolor on the canvas
        # border = border size
        # 
        if not master:
            master = Tkinter.Toplevel()

        if title is not None:
            master.title(title)
        
        f = self.frame = Tkinter.Frame(master)

        
        self.coeff = 0.0
        self.value = "%.1f"%self.coeff+'%'
        self.width = width
        self.height = height
        
        self.cwcanvas = Tkinter.Canvas(f,width=self.width,
                                       height=self.height)
        self.wrect = self.cwcanvas.create_rectangle(0,0,100,10,
                                                    outline='black',
                                                    fill='white')
        self.rrect = self.cwcanvas.create_rectangle(0,0,self.coeff,10,
                                                    outline='black',
                                                    fill='red')
        self.labelvalue = self.cwcanvas.create_text(120,10,text=self.value)

        self.cwcanvas.pack(side='top')
        #self.frame.pack()

        # CallBack Manager
        self.cbManager = CallbackManager()
        if callback:
            if type(callback) in [types.ListType, types.TupleType]:
                map(self.cbManager.AddCallback, callback)
            else:
                self.cbManager.AddCallback(callback)


    def get(self):
        pass
    
    def set(self,coeff,color):

        self.cwcanvas.coords(self.rrect,0,0,coeff,10)
        self.cwcanvas.itemconfigure(self.rrect,fill=color)
        self.cwcanvas.itemconfigure(self.labelvalue,text="%.1f"%coeff+'%')
    
    def pack(self,*args, **kw):
        apply(self.frame.pack, args, kw)
        
    def pack_forget(self,*args, **kw):
        apply(self.frame.pack_forget, args, kw)
                         
    def grid(self,*args, **kw):
        apply(self.frame.grid, args, kw)

    def grid_forget(self,*args, **kw):
        apply(self.frame.grid_forget, args, kw)

    def destroy(self,*args, **kw):
        apply(self.frame.destroy, args, kw)
Beispiel #17
0
class ColorEditor:
    """
    The ColorEditor is a widget providing a colorwheel, a value scale,
    HSV entries, RGB entries and HEX(HexTriplet) entries
    """
    def __init__(self,
                 master=None,
                 currentColor=(1.0, 1.0, 1.0),
                 mode='RGB',
                 commands=None,
                 immediate=1):
        assert mode in ['RGB', 'HSV', 'HEX']
        self.mode = mode
        if not master:
            self.master = tkinter.Toplevel()
        else:
            self.master = master
        self.afterID = None
        self.immediate = immediate
        # The editFrame is the main Frame of the widget
        self.editFrame = tkinter.Frame(self.master,
                                       borderwidth=2,
                                       relief='ridge')
        self.cbManager = CallbackManager()
        if commands:
            if type(commands) in [ListType, TupleType]:
                list(map(self.cbManager.AddCallback, commands))
            else:
                self.cbManager.AddCallback(commands)

        if mode == 'HSV':
            self.currentHSV = list(currentColor)
            self.currentRGB = list(ToRGB(currentColor))
            self.currentHEX = ToHEX(currentColor, mode='HSV')

        elif mode == 'RGB':
            self.currentRGB = list(currentColor)
            self.currentHSV = list(ToHSV(currentColor))
            self.currentHEX = ToHEX(currentColor, mode='RGB')

        elif mode == 'HEX':
            self.currentRGB = ToHEX(currentColor, mode='RGB')
            self.currentHSV = ToHEX(currentColor, mode='HSV')
            self.currentHEX = currentColor
        else:
            print('mode not recognized mode set to RGB')
        self.createColorEditor()

    def createColorEditor(self):
        # The chooserFrame containinsg the colorwheel and the value scale
        chooserFrame = tkinter.Frame(self.editFrame)
        # Create a Tkinter Scale widget bound a callback : self.scale_cb
        self.vScale = tkinter.Scale(
            chooserFrame,
            from_=1.0,
            to_=0.0,
            orient='vertical',
            resolution=0.01,
        )
        ##                                     command = self.scale_cb)
        if self.immediate:
            self.vScale.configure(command=self.scale_cb)
        else:
            self.vScale.bind('<ButtonRelease-1>', self.scaleUp_cb)

        # pack the scale to be on the left side of the colorwheel
        self.vScale.pack(side='right', padx=5, pady=5, expand=1, fill='both')
        self.vScale.set(1.0)

        # Create the colorWheel Frame
        wheelFrame = tkinter.Frame(chooserFrame, relief='ridge', borderwidth=1)
        # Pack the ColorWheel
        wheelFrame.pack(side='left', pady=5, padx=10, fill='both', expand=1)
        # Create the ColorWheel

        # to silent an error report from pychecker
        self.cw = ColorWheel(wheelFrame, None, self.colorWidget_cb,
                             self.immediate)
        #self.cw = ColorWheel(wheelFrame,title=None,
        #                     callback=self.colorWidget_cb,
        #                     immediate=self.immediate)

        self.cw.set(self.currentRGB, mode='RGB', trigger=0)
        # Bind the colorwidget to a callback function self.colorWidget_cb
        #self.cw.callback = self.colorWidget_cb
        # Pack the chooserFrame
        chooserFrame.pack(expand=1, fill='both')

        bottomFrame = tkinter.Frame(self.editFrame)
        #The preview frame will contain the frame to show the choosen color
        previewFrame = tkinter.Frame(bottomFrame)
        previewFrame.pack(side='left', fill='both', expand=1)
        preview = tkinter.Frame(previewFrame, )
        bg = self.currentHEX
        self.chip = tkinter.Frame(previewFrame,
                                  borderwidth=3,
                                  width=50,
                                  height=30,
                                  bg=bg,
                                  relief='ridge')
        # Pack the chipFrame
        self.chip.pack(fill='both', expand=1)

        #The entriesFrame will contain all the entryFields
        entriesFrame = tkinter.Frame(bottomFrame)
        entriesOption = {
            'labelpos': 'w',
            'validate': {
                'validator': 'real',
                'min': 0.0,
                'max': 1.0
            },
            'entry_width': 4,
        }

        # the hsvFrame will contain the H,S,V entryFields
        hsvFrame = tkinter.Frame(entriesFrame)

        entriesOption['label_text'] = 'H'
        entriesOption['value'] = "%4.2f" % self.currentHSV[0]
        entriesOption['command'] = self.hVal_cb
        self.hVal = Pmw.EntryField(*(hsvFrame, ), **entriesOption)
        self.hVal.pack(side='left')

        entriesOption['label_text'] = 'S'
        entriesOption['value'] = "%4.2f" % self.currentHSV[1]
        entriesOption['command'] = self.sVal_cb
        self.sVal = Pmw.EntryField(*(hsvFrame, ), **entriesOption)
        self.sVal.pack(side='left')

        entriesOption['label_text'] = 'V'
        entriesOption['value'] = "%4.2f" % self.currentHSV[2]
        entriesOption['command'] = self.vVal_cb
        self.vVal = Pmw.EntryField(*(hsvFrame, ), **entriesOption)
        self.vVal.pack(side='left')

        hsvFrame.pack(padx=4, pady=4, fill='both', expand=1)

        rgbFrame = tkinter.Frame(entriesFrame)
        # RGB entries
        entriesOption['label_text'] = 'R'
        entriesOption['value'] = "%4.2f" % self.currentRGB[0]
        entriesOption['command'] = self.rVal_cb
        self.rVal = Pmw.EntryField(*(rgbFrame, ), **entriesOption)
        self.rVal.pack(side='left')

        entriesOption['label_text'] = 'G'
        entriesOption['value'] = "%4.2f" % self.currentRGB[1]
        entriesOption['command'] = self.gVal_cb
        self.gVal = Pmw.EntryField(*(rgbFrame, ), **entriesOption)
        self.gVal.pack(side='left')

        entriesOption['label_text'] = 'B'
        entriesOption['value'] = "%4.2f" % self.currentRGB[2]
        entriesOption['command'] = self.bVal_cb
        self.bVal = Pmw.EntryField(*(rgbFrame, ), **entriesOption)
        self.bVal.pack(side='left')
        rgbFrame.pack(padx=4, pady=4, fill='both', expand=1)

        hexFrame = tkinter.Frame(entriesFrame)
        entriesOption['label_text'] = 'Hex triplet'
        entriesOption['value'] = self.currentHEX
        entriesOption['command'] = self.hexVal_cb
        del entriesOption['validate']
        entriesOption['entry_width'] = 8
        #entriesOption['validate']='alphanumeric'
        self.hexVal = Pmw.EntryField(*(hexFrame, ), **entriesOption)
        self.hexVal.pack(padx=4, pady=4, side='left')
        hexFrame.pack(fill='both', expand=1)

        entriesFrame.pack(side='right', fill='both', expand=1)
        bottomFrame.pack(side='bottom', fill='both', expand=1)

    ###############################################################
    ####           COLOR CHOOSER UTILITY FUNCTIONs             ####
    ###############################################################
    #def caluculate(self):

    def set(self, color, mode='RGB', trigger=1):
        """Set the current color"""
        #assert len(color)==3
        assert mode in ['HSV', 'RGB', 'HEX']
        self.mode = mode
        if mode == 'HSV':
            newRGB = [float("%4.2f" % x) for x in ToRGB(color)]
        elif mode == 'HEX':
            newRGB = ToRGB(color, mode='HEX')
        else:
            newRGB = color
        if newRGB != self.currentRGB:
            self.updateWidgetsColor(newRGB)
            if trigger == 1 and self.immediate and self.cbManager.callbacks:
                self.cbManager.CallCallbacks(self.currentRGB)

    def get(self, mode='RGB'):
        assert mode in ['RGB', 'HSV', 'HEX']
        self.mode = mode
        if mode == 'RGB':
            return self.currentRGB
        elif mode == 'HSV':
            return self.currentHSV
        elif mode == 'HEX':
            col = ToHEX(self.currentRGB, mode='HEX')
            return col

    def pack(self, *args, **kw):
        self.editFrame.pack(*args, **kw)

    def pack_forget(self, *args, **kw):
        self.editFrame.pack_forget(*args, **kw)

    def grid(self, *args, **kw):
        self.editFrame.grid(*args, **kw)

    def grid_forget(self, *args, **kw):
        self.editFrame.grid_forget(*args, **kw)

    ###############################################################
    ####               WIDGETS CALLBACK FUNCTIONS              ####
    ###############################################################

    def colorWidget_cb(self, rgbcolor):
        # Do this test because updateCurrent is called after the set
        # cw.
        # if color is different from current color then update chip
        color = list(ToHSV(rgbcolor))[:]
        color[2] = float(self.vScale.get())
        newrgb = list(ToRGB(color))
        if newrgb != self.currentRGB:
            self.updateWidgetsColor(newrgb, who='cw')

    def scale_cb(self, val):
        if self.afterID is not None:
            self.vScale.after_cancel(self.afterID)
            self.afterID = None
        else:
            self.afterID = self.vScale.after(17, self.scaleImm_cb, val)

    def scaleImm_cb(self, val):
        newHSV = [float(self.hVal.get()), float(self.sVal.get()), float(val)]
        if newHSV != self.currentHSV:
            self.updateWidgetsColor(ToRGB(newHSV), who='scale')

    def scaleUp_cb(self, event=None):
        val = float(self.vScale.get())
        newHSV = [float(self.hVal.get()), float(self.sVal.get()), float(val)]
        if newHSV != self.currentHSV:
            self.updateWidgetsColor(ToRGB(newHSV), who='scale')

    def hVal_cb(self):
        val = float(self.hVal.get())
        newColor = self.currentHSV
        newColor[0] = val
        newHSV = [float("%4.2f" % x) for x in newColor]
        if (not (float(self.vVal.get())==0.00 or \
                (float(self.sVal.get())==0 and float(self.vVal.get())==1.0))):
            self.updateWidgetsColor(ToRGB(newHSV), who='h')

    def sVal_cb(self):
        val = float(self.sVal.get())
        newColor = list(ToHSV(self.currentRGB[:]))
        newColor[1] = val
        newHSV = [float("%4.2f" % x) for x in newColor]
        if (not float(self.vVal.get()) == 0) and newHSV != self.currentHSV:
            self.updateWidgetsColor(ToRGB(newHSV), who='s')

    def vVal_cb(self):
        newColor = [
            float(self.hVal.get()),
            float(self.sVal.get()),
            float(self.vVal.get())
        ]
        newHSV = [float("%4.2f" % x) for x in newColor]
        if newHSV != self.currentHSV:
            self.updateWidgetsColor(ToRGB(newHSV), who='v')

    def rVal_cb(self):
        val = float(self.rVal.get())
        newColor = self.currentRGB[:]
        newColor[0] = val
        newRGB = [float("%4.2f" % x) for x in newColor]
        if newRGB != self.currentRGB:
            self.updateWidgetsColor(newRGB, who='r')

    def gVal_cb(self):
        val = float(self.gVal.get())
        newColor = self.currentRGB[:]
        newColor[1] = val
        newRGB = [float("%4.2f" % x) for x in newColor]
        if newRGB != self.currentRGB:
            self.updateWidgetsColor(newRGB, who='g')

    def bVal_cb(self):
        val = float(self.bVal.get())
        newColor = self.currentRGB[:]
        newColor[2] = val
        newRGB = [float("%4.2f" % x) for x in newColor]
        if newRGB != self.currentRGB:
            self.updateWidgetsColor(newRGB, who='b')

    def hexVal_cb(self):
        val = self.hexVal.get()
        if val[0] != '#' or len(val) != 7:
            val = self.currentHEX
        newRGB = ToRGB(val, 'HEX')
        if newRGB != self.currentRGB:
            self.updateWidgetsColor(newRGB, who='hex')

    ###############################################################
    ####               WIDGETS UPDATE FUNCTIONS                ####
    ###############################################################
    def updateWidgetsColor(self, rgbcolor, who='set', trigger=1):
        oldRGB = list(self.currentRGB)
        self.currentRGB = [float("%4.2f" % x) for x in rgbcolor]
        # If newcolor is the same than old color nothing to update.
        if oldRGB == self.currentRGB: return
        hsvcolor = ToHSV(rgbcolor[:])
        self.currentHSV = [float("%4.2f" % x) for x in hsvcolor]
        self.currentHEX = ToHEX(self.currentRGB)
        # Update the preview chip
        self.chip.configure(bg=self.currentHEX)

        # ColorWidget:
        cwColor = self.cw.get(mode='RGB')
        newRGB = [float("%4.2f" % x) for x in cwColor]
        if newRGB != self.currentRGB and not who in ['v', 'scale']:
            self.cw.set(self.currentRGB, mode='RGB', trigger=0)

        # Value Scale:
        scaleCol = self.vScale.get()
        if scaleCol != self.currentHSV[2]:
            self.vScale.set(self.currentHSV[2])

        # H Entry:
        h = float(self.hVal.get())
        hCol = float("%4.2f" % h)
        if hCol != self.currentHSV[0] and not who in ['v', 'scale']:
            self.hVal.setentry(self.currentHSV[0])

        # S Entry:
        s = float(self.sVal.get())
        sCol = float("%4.2f" % s)
        if sCol != self.currentHSV[1] and self.currentHSV[2] !=0 \
           and not who in ['v', 'scale']:
            self.sVal.setentry(self.currentHSV[1])

        # V Entry:
        v = float(self.vVal.get())
        vCol = float("%4.2f" % v)
        if vCol != self.currentHSV[2] and self.currentHSV[2] != 0:
            self.vVal.setentry(self.currentHSV[2])

        # R Entry:
        r = float(self.rVal.get())
        rCol = float("%4.2f" % r)
        if rCol != self.currentRGB[0]:
            self.rVal.setentry(self.currentRGB[0])
        # G Entry:
        g = float(self.gVal.get())
        gCol = float("%4.2f" % g)
        if gCol != self.currentRGB[1]:
            self.gVal.setentry(self.currentRGB[1])

        # B Entry:
        b = float(self.bVal.get())
        bCol = float("%4.2f" % b)
        if bCol != self.currentRGB[2]:
            self.bVal.setentry(self.currentRGB[2])

        # Hex Entry:
        hexCol = self.hexVal.get()
        if hexCol != self.currentHEX:
            self.hexVal.setentry(self.currentHEX)

        # This might depend of the mode. ?
        if trigger == 1 and self.immediate and self.cbManager.callbacks:
            self.cbManager.CallCallbacks(self.currentRGB)
Beispiel #18
0
class xyzGUI(Tkinter.Frame):

    """ 
    """
    def __init__(self, master=None, name='XYZ',callback=None,
                 callbackX=None, widthX=100, heightX=26, wheelPadX=4,
                 labcfgX={'text':None}, widthY=100, heightY=26, wheelPadY=4,
                 labcfgY={'text':None}, callbackY=None, widthZ=100,
                 heightZ=26, wheelPadZ=4, callbackZ=None,
                 labcfgZ={'text':None}, **kw):


        self.callback = callback   # user specified callback
        self.name=name               # title inside canvas

        self.widthX=widthX
        self.heightX=heightX
        self.wheelPadX=wheelPadX
        self.labcfgX=labcfgX
        self.widthY=widthY
        self.heightY=heightY
        self.wheelPadY=wheelPadY
        self.labcfgY=labcfgY
        self.widthZ=widthZ
        self.heightZ=heightZ
        self.wheelPadZ=wheelPadZ
        self.labcfgZ=labcfgZ

	Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self)

        self.callbacks = CallbackManager() # object to manage callback
                                        # functions. They get called with the
                                        # current value as an argument

        self.frame = Tkinter.Frame(self, relief = 'sunken', borderwidth=5)
        self.frame.pack(expand=1, fill='x')
        self.createEntries(self.frame)

        if self.callback:
            self.callbacks.AddCallback(self.callback)

   
    def createEntries(self, master):
        self.f = Tkinter.Frame(master)
	self.f.grid(column=1, rowspan=3)

        self.thumbx = ThumbWheel(master=self.f, width=self.widthX,
                                 height=self.heightX, labcfg=self.labcfgX,
                                 wheelPad=self.wheelPadX)
        self.thumbx.callbacks.AddCallback(self.thumbx_cb)
        self.thumbx.grid(row=0, column=0)

        self.thumby = ThumbWheel(master=self.f, width=self.widthY,
                                 height=self.heightY, labcfg=self.labcfgY,
                                 wheelPad=self.wheelPadY)
        self.thumby.callbacks.AddCallback(self.thumby_cb)
        self.thumby.grid(row=1, column=0)

        self.thumbz = ThumbWheel(master=self.f, width=self.widthZ,
                                 height=self.heightZ, labcfg=self.labcfgZ,
                                 wheelPad=self.wheelPadZ)
        self.thumbz.callbacks.AddCallback(self.thumbz_cb)
        self.thumbz.grid(row=2, column=0)

        self.f.pack(side='top', expand=1)


    def thumbx_cb(self, events=None):
        self.callbacks.CallCallbacks(self.thumbx.value)


    def thumby_cb(self, events=None):
        self.callbacks.CallCallbacks(self.thumby.value)


    def thumbz_cb(self, events=None):
        self.callbacks.CallCallbacks(self.thumbz.value)


    def set(self, x, y, z):
        # called from outside
        self.thumbx.setValue(x)
        self.thumby.setValue(y)
        self.thumbz.setValue(z)


 #####################################################################
 # the 'configure' methods:
 #####################################################################

    def configure(self, **kw):
        for key,value in kw.items():
            # the 'set parameter' callbacks
            if key=='labcfgX': self.setLabel(value,'x')
            elif key=='labcfgY': self.setLabel(value,'y')
            elif key=='labcfgZ': self.setLabel(value,'z')

            elif key=='continuousX': self.setContinuous(value,'x')
            elif key=='continuousY': self.setContinuous(value,'y')
            elif key=='continuousZ': self.setContinuous(value,'z')

            elif key=='precisionX': self.setPrecision(value,'x')
            elif key=='precisionY': self.setPrecision(value,'y')
            elif key=='precisionZ': self.setPrecision(value,'z')

            elif key=='typeX': self.setType(value,'x')
            elif key=='typeY': self.setType(value,'y')
            elif key=='typeZ': self.setType(value,'z')

            elif key=='minX': self.setMin(value,'x')
            elif key=='minY': self.setMin(value,'y')
            elif key=='minZ': self.setMin(value,'z')

            elif key=='maxX': self.setMax(value,'x')
            elif key=='maxY': self.setMax(value,'y')
            elif key=='maxZ': self.setMax(value,'z')

            elif key=='oneTurnX': self.setOneTurn(value,'x')
            elif key=='oneTurnY': self.setOneTurn(value,'y')
            elif key=='oneTurnZ': self.setOneTurn(value,'z')

            elif key=='showLabelX': self.setShowLabel(value,'x')
            elif key=='showLabelY': self.setShowLabel(value,'y')
            elif key=='showLabelZ': self.setShowLabel(value,'z')

            elif key=='incrementX': self.setIncrement(value,'x')
            elif key=='incrementY': self.setIncrement(value,'y')
            elif key=='incrementZ': self.setIncrement(value,'z')

            ####################################################

            elif key=='lockTypeX': self.lockType(value,'x')
            elif key=='lockTypeY': self.lockType(value,'y')
            elif key=='lockTypeZ': self.lockType(value,'z')

            elif key=='lockMinX': self.lockMin(value,'x')
            elif key=='lockMinY': self.lockMin(value,'y')
            elif key=='lockMinZ': self.lockMin(value,'z')

            elif key=='lockBMinX': self.lockBMin(value,'x')
            elif key=='lockBMinY': self.lockBMin(value,'y')
            elif key=='lockBMinZ': self.lockBMin(value,'z')

            elif key=='lockMaxX': self.lockMax(value,'x')
            elif key=='lockMaxY': self.lockMax(value,'y')
            elif key=='lockMaxZ': self.lockMax(value,'z')

            elif key=='lockBMaxX': self.lockBMax(value,'x')
            elif key=='lockBMaxY': self.lockBMax(value,'y')
            elif key=='lockBMaxZ': self.lockBMax(value,'z')

            elif key=='lockIncrementX': self.lockIncrement(value,'x')
            elif key=='lockIncrementY': self.lockIncrement(value,'y')
            elif key=='lockIncrementZ': self.lockIncrement(value,'z')

            elif key=='lockBIncrementX': self.lockBIncrement(value,'x')
            elif key=='lockBIncrementY': self.lockBIncrement(value,'y')
            elif key=='lockBIncrementZ': self.lockBIncrement(value,'z')

            elif key=='lockPrecisionX': self.lockPrecision(value,'x')
            elif key=='lockPrecisionY': self.lockPrecision(value,'y')
            elif key=='lockPrecisionZ': self.lockPrecision(value,'z')

            elif key=='lockShowLabelX': self.lockShowLabel(value,'x')
            elif key=='lockShowLabelY': self.lockShowLabel(value,'y')
            elif key=='lockShowLabelZ': self.lockShowLabel(value,'z')

            elif key=='lockValueX': self.lockValue(value,'x')
            elif key=='lockValueY': self.lockValue(value,'y')
            elif key=='lockValueZ': self.lockValue(value,'z')

            elif key=='lockContinuousX': self.lockContinuous(value,'x')
            elif key=='lockContinuousY': self.lockContinuous(value,'y')
            elif key=='lockContinuousZ': self.lockContinuous(value,'z')

            elif key=='lockOneTurnX': self.lockOneTurn(value,'x')
            elif key=='lockOneTurnY': self.lockOneTurn(value,'y')
            elif key=='lockOneTurnZ': self.lockOneTurn(value,'z')


    def setLabel(self, label, mode):
        if mode == 'x':
            self.thumbx.setLabel(label)
        elif mode == 'y':
            self.thumby.setLabel(label)
        elif mode == 'z':
            self.thumbz.setLabel(label)


    def setContinuous(self, value, mode):
        if mode == 'x':
            self.thumbx.setContinuous(value)
        elif mode == 'y':
            self.thumby.setContinuous(value)
        elif mode == 'z':
            self.thumbz.setContinuous(value)


    def setPrecision(self, value, mode):
        if mode == 'x':
            self.thumbx.setPrecision(value)
        elif mode == 'y':
            self.thumby.setPrecision(value)
        elif mode == 'z':
            self.thumbz.setPrecision(value)


    def setType(self, type, mode):
        if type == 'int': type = int
        else: type = float

        if mode == 'x':
            self.thumbx.setType(type)
        elif mode == 'y':
            self.thumby.setType(type)
        elif mode == 'z':
            self.thumbz.setType(type)


    def setMin(self, value, mode):
        if mode == 'x':
            self.thumbx.setMin(value)
        elif mode == 'y':
            self.thumby.setMin(value)
        elif mode == 'z':
            self.thumbz.setMin(value)


    def setMax(self, value, mode):
        if mode == 'x':
            self.thumbx.setMax(value)
        elif mode == 'y':
            self.thumby.setMax(value)
        elif mode == 'z':
            self.thumbz.setMax(value)


    def setOneTurn(self, value, mode):
        if mode == 'x':
            self.thumbx.setOneTurn(value)
        elif mode == 'y':
            self.thumby.setOneTurn(value)
        elif mode == 'z':
            self.thumbz.setOneTurn(value)


    def setShowLabel(self, value, mode):
        if mode == 'x':
            self.thumbx.setShowLabel(value)
        if mode == 'y':
            self.thumby.setShowLabel(value)
        if mode == 'z':
            self.thumbz.setShowLabel(value)
            

    def setIncrement(self, value, mode):
        if mode == 'x':
            self.thumbx.setIncrement(value)
        if mode == 'y':
            self.thumby.setIncrement(value)
        if mode == 'z':
            self.thumbz.setIncrement(value)



 #####################################################################
 # the 'lock' methods:
 #####################################################################


    def lockType(self, value, mode):
        if mode == 'x':
            self.thumbx.lockTypeCB(value)
        if mode == 'y':
            self.thumby.lockTypeCB(value)
        if mode == 'z':
            self.thumbz.lockTypeCB(value)


    def lockMin(self, value, mode):
        if mode == 'x':
            self.thumbx.lockMinCB(value)
        if mode == 'y':
            self.thumby.lockMinCB(value)
        if mode == 'z':
            self.thumbz.lockMinCB(value)


    def lockBMin(self, value, mode):
        if mode == 'x':
            self.thumbx.lockBMinCB(value)
        if mode == 'y':
            self.thumby.lockBMinCB(value)
        if mode == 'z':
            self.thumbz.lockBMinCB(value)


    def lockMax(self, value, mode):
        if mode == 'x':
            self.thumbx.lockMaxCB(value)
        if mode == 'y':
            self.thumby.lockMaxCB(value)
        if mode == 'z':
            self.thumbz.lockMaxCB(value)


    def lockBMax(self, value, mode):
        if mode == 'x':
            self.thumbx.lockBMaxCB(value)
        if mode == 'y':
            self.thumby.lockBMaxCB(value)
        if mode == 'z':
            self.thumbz.lockBMaxCB(value)


    def lockIncrement(self, value, mode):
        if mode == 'x':
            self.thumbx.lockIncrementCB(value)
        if mode == 'y':
            self.thumby.lockIncrementCB(value)
        if mode == 'z':
            self.thumbz.lockIncrementCB(value)


    def lockBIncrement(self, value, mode):
        if mode == 'x':
            self.thumbx.lockBIncrementCB(value)
        if mode == 'y':
            self.thumby.lockBIncrementCB(value)
        if mode == 'z':
            self.thumbz.lockBIncrementCB(value)


    def lockPrecision(self, value, mode):
        if mode == 'x':
            self.thumbx.lockPrecisionCB(value)
        if mode == 'y':
            self.thumby.lockPrecisionCB(value)
        if mode == 'z':
            self.thumbz.lockPrecisionCB(value)


    def lockShowLabel(self, value, mode):
        if mode == 'x':
            self.thumbx.lockShowLabelCB(value)
        if mode == 'y':
            self.thumby.lockShowLabelCB(value)
        if mode == 'z':
            self.thumbz.lockShowLabelCB(value)


    def lockValue(self, value, mode):
        if mode == 'x':
            self.thumbx.lockValueCB(value)
        if mode == 'y':
            self.thumby.lockValueCB(value)
        if mode == 'z':
            self.thumbz.lockValueCB(value)


    def lockContinuous(self, value, mode):
        if mode == 'x':
            self.thumbx.lockContinuousCB(value)
        if mode == 'y':
            self.thumby.lockContinuousCB(value)
        if mode == 'z':
            self.thumbz.lockContinuousCB(value)


    def lockOneTurn(self, value, mode):
        if mode == 'x':
            self.thumbx.lockOneTurnCB(value)
        if mode == 'y':
            self.thumby.lockOneTurnCB(value)
        if mode == 'z':
            self.thumbz.lockOneTurnCB(value)
Beispiel #19
0
class ColorWheel:
    def __init__(self, master, title=None, callback=None, immediate=1):
        if not master:
            master = tkinter.Toplevel()

        if title is not None:
            master.title(title)

        f = self.frame = tkinter.Frame(master)
        path = __import__('mglutil').__path__
        iconfile = os.path.join(path[0], 'gui/BasicWidgets/Tk/cw.ppm')
        self.iconfile = iconfile
        self.cwim = tkinter.PhotoImage(file=iconfile, master=master)
        self.width = self.cwim.width()
        self.height = self.cwim.height()
        self.cwcanvas = tkinter.Canvas(
            f,
            width=self.width,
            height=self.height,  ###relief='sunken',
            borderwidth=3)
        self.cwcanvas.create_image(3, 3, anchor=tkinter.NW, image=self.cwim)
        self.cwcanvas.pack()
        self.frame.pack()

        #self.callback = None
        self.cbManager = CallbackManager()
        if callback:
            if type(callback) in [ListType, TupleType]:
                list(map(self.cbManager.AddCallback, callback))
            else:
                self.cbManager.AddCallback(callback)
        self.afterID = None
        self.immediate = immediate
        self.x = 0
        self.y = 0
        self.radius = 55
        cx = self.cx = self.width / 2 + 3
        cy = self.cy = self.height / 2 + 3

        self.cursor = self.cwcanvas.create_line(cx - 3, cy - 3, cx - 3, cy + 3,
                                                cx + 3, cy + 3, cx + 3, cy - 3,
                                                cx - 3, cy - 3)

        self.hsvColor = [1., 1., 1.]

        self.cwcanvas.bind('<ButtonPress-1>', self.mouse1Down)
        #self.cursor = self.cwcanvas.create_line(cx, cy, cx-55, cy)

    def _MoveCursor(self, x, y, trigger=1):
        # find the saturation based on distance
        s = math.sqrt(x * x + y * y) / self.radius
        if s > 1.0:
            x = x / s
            y = y / s
            s = 1.0

        # now find the hue based on the angle
        if x or y:
            angle = math.atan2(y, x)
            if angle < 0.0:
                angle = angle + (2. * math.pi)
            h = 1. - angle / (2.0 * math.pi)
        else:
            h = 0
        # check if redraw and callback are needed
        if self.hsvColor[0] != h or self.hsvColor[1] != s:
            if trigger == 1:
                self.hsvColor[0] = h
                self.hsvColor[1] = s
            cx = self.cx + x
            cy = self.cy + y
            self.cwcanvas.coords(self.cursor, cx - 3, cy - 3, cx - 3, cy + 3,
                                 cx + 3, cy + 3, cx + 3, cy - 3, cx - 3,
                                 cy - 3)

            if self.cbManager.callbacks:
                self.cbManager.CallCallbacks(self.get('RGB'))

    def mouse1Down(self, event=None):
        self.cwcanvas.bind('<B1-Motion>', self.mouse1Move)
        self.cwcanvas.bind('<ButtonRelease-1>', self.mouse1Up)
        self._MoveCursor(event.x - self.cx, event.y - self.cy)

    def mouse1Move(self, event=None):
        if self.immediate:
            if self.afterID is not None:
                self.cwcanvas.after_cancel(self.afterID)
                self.afterID = None
            else:
                self.afterID = self.cwcanvas.after(15, self._MoveCursor,
                                                   event.x - self.cx,
                                                   event.y - self.cy)

        else:
            self._MoveCursor(event.x - self.cx, event.y - self.cy, trigger=0)

    def mouse1Up(self, event=None):
        self._MoveCursor(event.x - self.cx, event.y - self.cy)
        self.cwcanvas.unbind('<B1-Motion>')
        self.cwcanvas.unbind('<ButtonRelease-1>')

    def get(self, mode='HSV'):
        """Get the current color"""
        if mode == 'RGB':
            rgb = ToRGB(self.hsvColor)
            #return OneColor(rgb)
            return rgb

        elif mode == 'HSV':
            #return OneColor(self.hsvColor)
            return self.hsvColor

        elif mode == 'HEX':
            col = numpy.array(ToRGB(self.hsvColor[:]), 'f') * 255
            return ToHEX(col)

    def set(self, color, mode='HSV', trigger=1):
        """Set the current color"""
        assert len(color) == 3
        #color = OneColor(color)
        if mode == 'RGB': color = ToHSV(color[:])
        self.hsvColor = list(color[:])

        # update cursor
        rad = self.hsvColor[1] * self.radius
        angle = 2.0 * math.pi * (1. - self.hsvColor[0])
        cx = self.cx + int(rad * math.cos(angle))
        cy = self.cy + int(rad * math.sin(angle))
        self.cwcanvas.coords(self.cursor, cx - 3, cy - 3, cx - 3, cy + 3,
                             cx + 3, cy + 3, cx + 3, cy - 3, cx - 3, cy - 3)

        if trigger == 1 and self.immediate and self.cbManager.callbacks:
            self.cbManager.CallCallbacks(self.get('RGB'))
Beispiel #20
0
class ContourSpectrum(Tkinter.Frame):
    """This class implements a ContourSpectrum widget.
it is fully a copy/paste from Dial
"""
    def __init__(self,
                 master=None,
                 type='float',
                 labCfg={
                     'fg': 'black',
                     'side': 'left',
                     'text': None
                 },
                 min=None,
                 max=None,
                 showLabel=1,
                 value=0.0,
                 continuous=1,
                 precision=2,
                 callback=None,
                 lockMin=0,
                 lockBMin=0,
                 lockMax=0,
                 lockBMax=0,
                 lockPrecision=0,
                 lockShowLabel=0,
                 lockValue=0,
                 lockType=0,
                 lockContinuous=0,
                 signatures=None,
                 **kw):

        Tkinter.Frame.__init__(self, master)
        Tkinter.Pack.config(self)

        self.callbacks = CallbackManager()  # object to manage callback
        # functions. They get called with the
        # current value as an argument

        # initialize various attributes with default values
        self.height = 100  # widget height
        self.width = 256  # widget height
        self.widthMinusOne = self.width - 1

        self.min = 0  # minimum value
        self.max = 1  # maximum value
        self.range = self.max - self.min

        self.precision = 2  # decimal places
        self.minOld = 0.  # used to store old values
        self.maxOld = 0.
        self.size = 50  # defines widget size
        self.offsetValue = 0.  # used to set increment correctly
        self.lab = None  # label
        self.callback = None  # user specified callback
        self.opPanel = None  # option panel widget
        self.value = 0.0  # current value of widget
        self.oldValue = 0.0  # old value of widget
        self.showLabel = 1  # turn on to display label on
        self.continuous = 1  # set to 1 to call callbacks at
        # each value change, else gets called
        # on button release event

        self.labCfg = labCfg  # Tkinter Label options
        self.labelFont = (ensureFontCase('helvetica'), 14, 'bold'
                          )  # label font
        self.labelColor = 'yellow'  # label color
        self.canvas = None  # the canvas to create the widget in

        self.lockMin = lockMin  # lock<X> vars are used in self.lock()
        self.lockMax = lockMax  # to lock/unlock entries in optionpanel
        self.lockBMin = lockBMin
        self.lockBMax = lockBMax
        self.lockPrecision = 0
        self.lockShowLabel = lockShowLabel
        self.lockValue = lockValue
        self.lockType = lockType
        self.lockContinuous = lockContinuous

        # configure with user-defined values
        self.setCallback(callback)
        self.setContinuous(continuous)

        self.setType(type)
        self.setPrecision(precision)
        self.setMin(min)
        self.setMax(max)
        self.setShowLabel(showLabel)
        self.setValue(value)
        self.setLabel(self.labCfg)

        if master is None:
            master = Tkinter.Toplevel()

        self.master = master  # widget master

        self.createCanvas(master)

        Tkinter.Widget.bind(self.canvas, "<ButtonPress-1>", self.mouseDown)
        Tkinter.Widget.bind(self.canvas, "<B1-Motion>", self.mouseMove)
        Tkinter.Widget.bind(self.canvas, "<ButtonRelease-1>", self.mouseUp)

        # create cursor
        self.cursorTk = self.canvas.create_line(0, 0, 0, 0, tags=['cursor'])

        self.increment = 0.0
        self.incrementOld = 0.
        self.lockIncrement = 0
        self.lockBIncrement = 0
        self.oneTurn = 360.
        self.lockOneTurn = 0
        self.opPanel = OptionsPanel(master=self, title="Slider graph Options")

        self.signatures = None  # Signature objects fro isocontouring lib
        self.sigData = []  # list of (x,y) values arrays for each signature
        self.maxFun = []  # max Y value in each signature
        self.minFun = []  # min Y value in each signature
        self.yratios = []  # normalization factors
        self.colors = ['red', 'green', 'blue', 'orange']
        self.tkLines = []  # list of Tkids for lines
        if signatures:
            self.setSignatures(signatures)

    def setCallback(self, cb):
        """Set widget callback. Must be callable function. Callback is called
every time the widget value is set/modified"""

        assert cb is None or callable(cb) or type(cb) is types.ListType,\
               "Illegal callback: must be either None or callable, or list. Got %s"%cb
        if cb is None: return
        elif type(cb) is types.ListType:
            for func in cb:
                assert callable(
                    func), "Illegal callback must be callable. Got %s" % func
                self.callbacks.AddCallback(func)
        else:
            self.callbacks.AddCallback(cb)
        self.callback = cb

    def toggleOptPanel(self, event=None):
        if self.opPanel.flag:
            self.opPanel.Dismiss_cb()
        else:
            if not hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.displayPanel(create=1)
            else:
                self.opPanel.displayPanel(create=0)

    def mouseDown(self, event):
        # remember where the mouse went down
        #self.lastx = event.x
        #self.lasty = event.y
        self.setXcursor(event.x)

    def mouseUp(self, event):
        # call callbacks if not in continuous mode
        if not self.continuous:
            self.callbacks.CallCallbacks(self.opPanel.valInput.get())
        if self.showLabel == 2:
            # no widget labels on mouse release
            self.canvas.itemconfigure(self.labelId2, text='')
            self.canvas.itemconfigure(self.labelId, text='')

    def mouseMove(self, event):
        # move the cursor
        self.setXcursor(event.x)
        #self.lastx = event.x

    def printLabel(self):
        if self.canvas is None:
            return
        self.canvas.itemconfigure(self.labelId2,
                                  text=self.labelFormat % self.value)  #newVal)
        self.canvas.itemconfigure(self.labelId,
                                  text=self.labelFormat % self.value)  #newVal)

    def drawCursor(self, x):
        if self.canvas:
            self.canvas.coords(self.cursorTk, x, 0, x, self.height)

    def get(self):
        return self.type(self.value)

    def setXcursor(self, x, update=1, force=0):
        """ x is a cursor position in pixel between 1 and self.width
"""
        if x < 1:
            x = 1
        if x > self.width:
            x = self.width

        self.drawCursor(x)

        # the mouse return position from 1 to self.width (x=0 is not drawn)
        # we need cursor position from 0 (so last x is self.width-1)
        x = x - 1

        if self.range is not None:
            self.value = self.min + x * self.range / float(self.widthMinusOne)

        newVal = self.get()

        if self.continuous or force:
            if update and self.oldValue != newVal or force:
                self.oldValue = newVal
                self.callbacks.CallCallbacks(newVal)
            if self.showLabel == 2:
                self.printLabel()
        else:
            if self.showLabel == 2:
                self.printLabel()

        if self.showLabel == 1:
            self.printLabel()
        if self.opPanel:
            self.opPanel.valInput.set(self.labelFormat % newVal)

    def set(self, x, update=1, force=0):
        """ x is a value between self.min and self.max
"""
        #print "set ContourSpectrum"
        if self.range is not None:
            xcursor = (x - self.min) * float(self.widthMinusOne) / self.range
            xcursor = xcursor + 1
            self.drawCursor(xcursor)
            self.setXcursor(xcursor, update, force)

    def createCanvas(self, master):
        self.frame = Tkinter.Frame(self, borderwidth=3, relief='sunken')
        self.canvas = Tkinter.Canvas(self.frame,
                                     width=self.width,
                                     height=self.height)
        self.xm = 25
        self.ym = 25
        self.labelId2 = self.canvas.create_text(self.xm + 2,
                                                self.ym + 2,
                                                fill='black',
                                                justify='center',
                                                text='',
                                                font=self.labelFont)
        self.labelId = self.canvas.create_text(self.xm,
                                               self.ym,
                                               fill=self.labelColor,
                                               justify='center',
                                               text='',
                                               font=self.labelFont)

        # pack em up
        self.canvas.pack(side=Tkinter.TOP)
        self.frame.pack(expand=1, fill='x')
        self.toggleWidgetLabel(self.showLabel)

    def toggleWidgetLabel(self, val):
        if val == 0:
            # no widget labels
            self.showLabel = 0
            self.canvas.itemconfigure(self.labelId2, text='')
            self.canvas.itemconfigure(self.labelId, text='')

        if val == 1:
            # show always widget labels
            self.showLabel = 1
            self.printLabel()

        if val == 2:
            # show widget labels only when mouse moves
            self.showLabel = 2
            self.canvas.itemconfigure(self.labelId2, text='')
            self.canvas.itemconfigure(self.labelId, text='')

    def setValue(self, val):
        #print "setValue"
        assert type(val) in [types.IntType, types.FloatType],\
               "Illegal type for value: expected %s or %s, got %s"%(
                   type(1), type(1.0), type(val) )

        # setValue does NOT call a callback!
        if self.min is not None and val < self.min:
            val = self.min
        if self.max is not None and val > self.max:
            val = self.max
        self.value = self.type(val)
        self.offsetValue = self.value
        self.oldValue = self.value

        #print "setValue ContourSpectrum"
        if self.range is not None:
            xcursor = (val - self.min) * float(self.widthMinusOne) / self.range
            xcursor = xcursor + 1
            self.drawCursor(xcursor)

        if self.showLabel == 1:
            self.printLabel()
        if self.opPanel:
            self.opPanel.valInput.set(self.labelFormat % self.value)

    def setLabel(self, labCfg):
        self.labCfg = labCfg

        text = labCfg.get('text', None)
        if text is None or text == '':
            return

        d = {}
        for k, w in self.labCfg.items():
            if k == 'side': continue
            else: d[k] = w
        if not 'side' in self.labCfg.keys():
            self.labCfg['side'] = 'left'

        if not self.lab:
            self.lab = Tkinter.Label(self, d)
            self.lab.pack(side=self.labCfg['side'])
            self.lab.bind("<Button-3>", self.toggleOptPanel)
        else:
            self.lab.configure(text)

#####################################################################
# the 'configure' methods:
#####################################################################

    def configure(self, **kw):
        for key, value in kw.items():
            # the 'set' parameter callbacks
            if key == 'labCfg': self.setLabel(value)
            elif key == 'type': self.setType(value)
            elif key == 'min': self.setMin(value)
            elif key == 'max': self.setMax(value)
            elif key == 'precision': self.setPrecision(value)
            elif key == 'showLabel': self.setShowLabel(value)
            elif key == 'continuous':
                self.setContinuous(value)

                # the 'lock' entries callbacks
            elif key == 'lockType':
                self.lockTypeCB(value)
            elif key == 'lockMin':
                self.lockMinCB(value)
            elif key == 'lockBMin':
                self.lockBMinCB(value)
            elif key == 'lockMax':
                self.lockMaxCB(value)
            elif key == 'lockBMax':
                self.lockBMaxCB(value)
            elif key == 'lockPrecision':
                self.lockPrecisionCB(value)
            elif key == 'lockShowLabel':
                self.lockShowLabelCB(value)
            elif key == 'lockValue':
                self.lockValueCB(value)
            elif key == 'lockContinuous':
                self.lockContinuousCB(value)

    def setType(self, Type):

        assert type(Type) in [types.StringType, types.TypeType],\
               "Illegal type for datatype. Expected %s or %s, got %s"%(
                   type('a'), type(type), type(Type) )

        if type(Type) == type(""):  # type str
            assert Type in ('int','float'),\
            "Illegal type descriptor. Expected 'int' or 'float', got '%s'"%Type
            self.type = eval(Type)
        else:
            self.type = Type

        if self.type == int:
            self.labelFormat = "%d"
            self.int_value = self.value
        else:
            self.labelFormat = "%." + str(self.precision) + "f"

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togIntFloat']['widget']
            if self.type == int:
                w.setvalue('int')
            elif self.type == 'float':
                w.setvalue('float')

        if self.opPanel:
            self.opPanel.updateDisplay()

        # and update the printed label
        if self.canvas and self.showLabel == 1:
            self.printLabel()

    def setMin(self, min):
        if min is not None:
            assert type(min) in [types.IntType, types.FloatType,
                                 numpy.int, numpy.int8, numpy.int16,
                                 numpy.int32, numpy.int64,
                                 numpy.uint, numpy.uint8, numpy.uint16,
                                 numpy.uint32, numpy.uint64,
                                 numpy.float, numpy.float32, numpy.float64],\
                 "Illegal type for minimum. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(min) )

            if self.max and min > self.max:
                min = self.max

            self.min = self.type(min)

            if self.showLabel == 1:
                self.printLabel()

            if self.value < self.min:
                self.set(self.min)

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.minInput.set(self.labelFormat % self.min)

                self.opPanel.toggleMin.set(1)
                self.opPanel.min_entry.configure(state='normal', fg='gray0')
            self.minOld = self.min

        else:
            self.min = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleMin.set(0)
                self.opPanel.min_entry.configure(state='disabled', fg='gray40')

        if self.min is not None and self.max is not None:
            self.range = float(self.max - self.min)
        else:
            self.range = None

    def setMax(self, max):
        if max is not None:
            assert type(max) in [types.IntType, types.FloatType,
                                 numpy.int, numpy.int8, numpy.int16,
                                 numpy.int32, numpy.int64,
                                 numpy.uint, numpy.uint8, numpy.uint16,
                                 numpy.uint32, numpy.uint64,
                                 numpy.float, numpy.float32, numpy.float64],\
                 "Illegal type for maximum. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(max) )

            if self.min and max < self.min:
                max = self.min

            self.max = self.type(max)

            if self.showLabel == 1:
                self.printLabel()

            if self.value > self.max:
                self.set(self.max)

            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.maxInput.set(self.labelFormat % self.max)

                self.opPanel.toggleMax.set(1)
                self.opPanel.max_entry.configure(state='normal', fg='gray0')
            self.maxOld = self.max

        else:
            self.max = None
            if hasattr(self.opPanel, 'optionsForm'):
                self.opPanel.toggleMax.set(0)
                self.opPanel.max_entry.configure(state='disabled', fg='gray40')

        if self.min is not None and self.max is not None:
            self.range = float(self.max - self.min)
        else:
            self.range = None

    def setPrecision(self, val):
        assert type(val) in [types.IntType, types.FloatType,
                                 numpy.int, numpy.float32],\
               "Illegal type for precision. Expected type %s or %s, got %s"%(
                     type(0), type(0.0), type(val) )
        val = int(val)

        if val > 10:
            val = 10
        if val < 1:
            val = 1
        self.precision = val

        if self.type == float:
            self.labelFormat = "%." + str(self.precision) + "f"
        else:
            self.labelFormat = "%d"

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['selPrec']['widget']
            w.setvalue(val)

        if self.opPanel:
            self.opPanel.updateDisplay()

        # and update the printed label
        if self.canvas and self.showLabel == 1:
            self.printLabel()

    def setContinuous(self, cont):
        """ cont can be None, 0 or 1 """

        assert cont in [None, 0, 1],\
             "Illegal value for continuous: expected None, 0 or 1, got %s"%cont

        if cont != 1:
            cont = None
        self.continuous = cont
        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togCont']['widget']
            if cont:
                w.setvalue('on')  #i=1
            else:
                w.setvalue('off')  #i=0

        if self.opPanel:
            self.opPanel.updateDisplay()

    def setShowLabel(self, val):
        """Show label can be 0, 1 or 2
0: no label
1: label is always shown
2: show label only when value changes"""

        assert val in [0,1,2],\
               "Illegal value for showLabel. Expected 0, 1 or 2, got %s"%val

        if val != 0 and val != 1 and val != 2:
            print "Illegal value. Must be 0, 1 or 2"
            return
        self.showLabel = val
        self.toggleWidgetLabel(val)

        if hasattr(self.opPanel, 'optionsForm'):
            w = self.opPanel.idf.entryByName['togLabel']['widget']
            if self.showLabel == 0:
                label = 'never'
            elif self.showLabel == 1:
                label = 'always'
            elif self.showLabel == 2:
                label = 'move'
            w.setvalue(label)

        if self.opPanel:
            self.opPanel.updateDisplay()

#####################################################################
# the 'lock' methods:
#####################################################################

    def lockTypeCB(self, mode):
        if mode != 0: mode = 1
        self.lockType = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockMinCB(self, mode):  #min entry field
        if mode != 0: mode = 1
        self.lockMin = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBMinCB(self, mode):  # min checkbutton
        if mode != 0: mode = 1
        self.lockBMin = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockMaxCB(self, mode):  # max entry field
        if mode != 0: mode = 1
        self.lockMax = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockBMaxCB(self, mode):  # max checkbutton
        if mode != 0: mode = 1
        self.lockBMax = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockPrecisionCB(self, mode):
        if mode != 0: mode = 1
        self.lockPrecision = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockShowLabelCB(self, mode):
        if mode != 0: mode = 1
        self.lockShowLabel = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockValueCB(self, mode):
        if mode != 0: mode = 1
        self.lockValue = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def lockContinuousCB(self, mode):
        if mode != 0: mode = 1
        self.lockContinuous = mode
        if hasattr(self.opPanel, 'optionsForm'):
            self.opPanel.lockUnlockDisplay()

    def setSignatures(self, signatures):
        self.signatures = signatures
        self.sigData = []

        # get the values
        self.maxFun = []
        self.minFun = []
        for s in self.signatures:
            x = Numeric.zeros((s.nval, ), 'f')
            s.getFx(x)

            self.minix = mini = min(x)
            if (isinstance(mini, Numeric.ArrayType)) and (mini.shape == ()):
                mini = mini[0]

            maxi = max(x)
            if (isinstance(maxi, Numeric.ArrayType)) and (maxi.shape == ()):
                maxi = maxi[0]

            self.rangex = range = maxi - mini
            if range != 0:
                x = (((x - mini) / range) * self.widthMinusOne).astype('i')

            y = Numeric.zeros((s.nval, ), 'f')
            s.getFy(y)
            self.sigData.append((x, y))
            self.maxFun.append(max(y))
            self.minFun.append(min(y))

        self.setMin(mini)
        self.setMax(maxi)

        # iso value with hightest value in first function
        if len(self.sigData):
            ind = list(self.sigData[0][1]).index(max(self.sigData[0][1]))
            self.setXcursor(ind)
        else:
            self.setXcursor(0.0)

        self.drawSignatures()

    def drawSignatures(self):
        # compute normalization factors
        self.yratios = []
        maxi = max(self.maxFun)
        for i in range(4):
            h = self.height - 1.
            if maxi != 0 and self.maxFun[i] != 0:
                self.yratios.append((h / maxi) * (maxi / self.maxFun[i]))
            else:
                self.yratios.append(0)

        for l in self.tkLines:
            self.canvas.delete(l)

        for i, f in enumerate(self.sigData):
            coords = []
            for x, y in zip(f[0], f[1]):
                coords.append(x)
                coords.append(self.height - y * self.yratios[i])
            self.tkLines.append(
                apply(self.canvas.create_line, coords,
                      {'fill': self.colors[i]}))