示例#1
0
class AnimPlayer(Player, geomsChooser):
    """ provide a player to display/undisplay DejaVu object
    in a cylce making a animation.

    viewer: DejaVu viewer
    height,width are the property of the player gui
    startFrame: frame to begin
    endFrame: last frame to display
    stepSize: step between new frame
    playMode:                  #playMode options:
                               #   0   play once and stop
                               #   1   play continuously in 1 direction
                               #   2   play once in 2 directions
                               #   3   play continuously in 2 directions
    titleStr: title of the gui windows
    counter: gui with a counter on or not
    gui: #1 show the player gui
         #0 player gui not display
    framerate =15.             # number of frame per second to be display
    """
    def __init__(self,
                 viewer,
                 master=None,
                 root=None,
                 height=80,
                 width=200,
                 currentFrameIndex=0,
                 startFrame=0,
                 endFrame=0,
                 maxFrame=0,
                 stepSize=1,
                 playMode=1,
                 titleStr='AnimPlayer',
                 counter=1,
                 gui=1,
                 framerate=15.):

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

        # viewer from which we get the geom to animate
        self.viewer = viewer
        # frame list, is a list of geom .
        # each frame is made of n DejaVu object to be display
        # it a list of tuple, each tuple is a {} and []
        # {} is: {'objname':['geom1','geom2'],'objname':['geom1','geom2']}
        # [] is list of DejaVu object per frame
        self.framelist = []

        Player.__init__(self,
                        master=master,
                        root=root,
                        height=height,
                        width=width,
                        currentFrameIndex=currentFrameIndex,
                        startFrame=startFrame,
                        endFrame=endFrame,
                        maxFrame=maxFrame,
                        stepSize=stepSize,
                        playMode=playMode,
                        titleStr=titleStr,
                        counter=counter,
                        gui=gui,
                        framerate=framerate)

    def nextFrame(self, id):
        """ id: index number of the frame to display.
        undisplay object from previous frame, display object
        of new frame.
        """
        if not self.framelist: return
        id = int(id)
        if id >= len(self.framelist): return

        i = self.currentFrameIndex
        ## undisplay previous object
        frame = self.framelist[i]
        for obj in frame[1]:
            obj.Set(visible=0, redo=0)

        if self.hasCounter and self.gui:
            self.form.ent2.delete(0, 'end')
            self.form.ent2.insert(0, str(id))

        ## display new frame
        currentframe = self.framelist[id]
        for obj in currentframe[1]:
            obj.Set(visible=1, redo=0)

        self.viewer.deleteOpenglList()
        self.viewer.Redraw()
        self.currentFrameIndex = id

#####################################################################
#### Animation Setting the frame

    def SetAnim_cb(self):
        self.showForm()

    def showForm(self):
        """create formdescr for setAnim
        form to set the animation:
        each frame is a list of geom to display
        """

        entryFrame = []
        for i in range(len(self.framelist)):
            val = 'frame_' + str(i)
            entryFrame.append((val, ))

        if not hasattr(self, 'form_Setanim'):
            ifd = InputFormDescr(title="SetAnimation")
            ifd.append({
                'widgetType': ListChooser,
                'name': 'availableGeom',
                'tooltip': 'geom available in viewer',
                'wcfg': {
                    'mode': 'extended',
                    'lbwcfg': {
                        'exportselection': 1
                    },
                    'command': [(self.toggleExpansion, '<Double-Button-1>')],
                    'commandEvent': None,
                    'title': 'availableGeom'
                },
                'gridcfg': {
                    'row': 0,
                    'column': 0,
                    'sticky': 'wens',
                    'rowspan': 3
                }
            })
            ifd.append({
                'name': 'newframe',
                'widgetType': Tkinter.Button,
                'tooltip': """ Add an empty frame to the animation""",
                'wcfg': {
                    'text': 'NewFrame',
                    'command': self.addframe_cb
                },
                'gridcfg': {
                    'row': 0,
                    'column': 1,
                    'rowspan': 1
                }
            })

            ifd.append({
                'name': 'add',
                'widgetType': Tkinter.Button,
                'tooltip': """ Add the selected geom to selected frame""",
                'wcfg': {
                    'text': 'AddGeom',
                    'command': self.add_cb
                },
                'gridcfg': {
                    'row': 1,
                    'column': 1,
                    'rowspan': 1
                }
            })

            ifd.append({
                'name': 'geomtoload',
                'widgetType': ListChooser,
                'tooltip': """list of frame  the user chose to
                        apply to the pattern""",
                'wcfg': {
                    'entries': entryFrame,
                    'mode': 'extended',
                    'lbwcfg': {
                        'exportselection': 0
                    },
                    'title': 'Frame(geom) to be display'
                },
                'gridcfg': {
                    'sticky': 'we',
                    'row': 0,
                    'column': 2,
                    'rowspan': 3
                }
            })
            ifd.append({
                'name': 'remove',
                'widgetType': Tkinter.Button,
                'tooltip': """ Remove the selected entry from the
                        commands to be applied to the object when loaded in the application""",
                'wcfg': {
                    'text': 'REMOVE',
                    'width': 10,
                    'command': self.remove_cb
                },
                'gridcfg': {
                    'sticky': 'we',
                    'row': 0,
                    'column': 3
                }
            })

            ifd.append({
                'name': 'oneup',
                'widgetType': Tkinter.Button,
                'tooltip': """Move the selected entry up one entry""",
                'wcfg': {
                    'text': 'Move up',
                    'width': 10,
                    'command': self.moveup_cb
                },
                'gridcfg': {
                    'sticky': 'we',
                    'row': 1,
                    'column': 3
                }
            })

            ifd.append({
                'name': 'onedown',
                'widgetType': Tkinter.Button,
                'tooltip': """Move the selected entry down one entry""",
                'wcfg': {
                    'text': 'Move down',
                    'width': 10,
                    'command': self.movedown_cb
                },
                'gridcfg': {
                    'sticky': 'we',
                    'row': 2,
                    'column': 3
                }
            })

            self.form_Setanim = InputForm(self.master,
                                          None,
                                          descr=ifd,
                                          scrolledFrame=0)

            self.lc = self.form_Setanim.descr.entryByName['availableGeom'][
                'widget']
            self.lc2 = self.form_Setanim.descr.entryByName['geomtoload'][
                'widget']
            self.addObject(self.viewer.rootObject, None)
            val = self.form_Setanim.go()
            if val:
                self.assign()
                self.form_Setanim.withdraw()
        else:
            self.form_Setanim.deiconify()
            val = self.form_Setanim.go()
            if val:
                self.assign()
                self.form_Setanim.withdraw()

    def deleteAnim(self):
        """ Delete all frame from the player list."""

        self.Stop_cb()
        self.startFrame = 0
        self.endFrame = -1
        self.maxFrame = 0
        self.targetFrame = self.endFrame
        self.target = self.endFrame
        self.currentFrameIndex = 0

    def assign(self, list=None):
        """ assign the animation.
        framelist ; list of {}
        return a list of obj for each frame
        """
        self.deleteAnim()
        AllObjects = self.viewer.rootObject.AllObjects()
        if list:
            self.framelist = []
            for f in list:
                self.framelist.append((f, []))
        print "assign"
        print "self.framelist", self.framelist
        for frame in self.framelist:
            geomDic = frame[0]
            Namelist = []
            for parents in geomDic.keys():
                parentlist = filter(lambda x, name=parents: x.name == name,
                                    AllObjects)
                obj = parentlist[0]
                childrens = geomDic[obj.name]
                if len(childrens) > 0:
                    for namegeom in childrens:
                        child = filter(lambda x, name=namegeom: x.name == name,
                                       obj.children)[0]
                        if child.children != []:
                            for c in child.children:
                                frame[1].append(c)
                        else:
                            frame[1].append(child)
                else:
                    frame[1].append(obj)

            self.endFrame = self.endFrame + 1
            self.maxFrame = self.maxFrame + 1
            self.targetFrame = self.endFrame
            self.target = self.endFrame

    def movedown_cb(self):
        """ move entry one down """
        sel = self.lc2.get()
        index = self.lc2.getInd()
        if not sel: return
        sel = sel[0]
        if string.find(sel, "frame") < 0: return
        # get frame Index
        frameInd = int(string.split(sel, '_')[1])
        currentframe = self.framelist[frameInd]
        if (frameInd + 1) >= len(self.framelist): return
        # select next Frame.
        nextframe = self.framelist[frameInd + 1]
        # move current frame one down in list
        self.framelist[frameInd] = nextframe
        self.framelist[frameInd + 1] = currentframe
        self.updatelistchooser(self.framelist)

    def moveup_cb(self):
        """ move entry one up """
        sel = self.lc2.get()
        index = self.lc2.getInd()
        if not sel: return
        sel = sel[0]
        if string.find(sel, "frame") < 0: return
        # get frame Index
        frameInd = int(string.split(sel, '_')[1])
        currentframe = self.framelist[frameInd]
        if (frameInd - 1) < 0: return
        # select previous Frame
        prevframe = self.framelist[frameInd - 1]
        # move current frame one up in list
        self.framelist[frameInd] = prevframe
        self.framelist[frameInd - 1] = currentframe
        self.updatelistchooser(self.framelist)

    def addframe_cb(self):
        """ add a new frame entry"""
        frame = ({}, [])
        nb = len(self.framelist)
        #frame.number = nbframe
        value = 'frame_' + str(nb)
        self.framelist.append(frame)
        self.lc2.deselect(0, last='end')
        self.lc2.insert('end', value)
        self.lc2.select('end')

    def add_cb(self):
        listgeom = []
        # get the frame index to add new geom
        if len(self.lc2.entries) > 0:
            ind = self.lc2.getInd()
            if len(ind) == 0: return  # no entry selected so create a new frame
            # get geom name to load
            o = map(int, self.lc.lb.curselection())
            for Ind in o:
                fullName = self.getFullName(Ind)
                listgeom.append(fullName)
            # get frame instance
            for index in ind:
                value = self.lc2.entries[index][0]
                if string.find(value, "frame") < 0: return
                frameInd = int(string.split(value, '_')[1])
                frameGeom = self.framelist[frameInd][0]
                for geom in listgeom:
                    # strip the root
                    l = string.split(geom, '|')
                    if not frameGeom.has_key(l[1]):
                        frameGeom[l[1]] = []
                    for i in l[2:]:
                        if not (i in frameGeom[l[1]]):
                            frameGeom[l[1]].append(i)

            self.updatelistchooser(self.framelist)
        else:
            return

    def updatelistchooser(self, entry):
        """ update what is display in the list chooser """
        # save current selection
        sel = self.lc2.get()
        # remove current entry
        self.lc2.clear()
        prefix = '~'
        prefix2 = '~~'
        nb = 0
        for e in entry:
            v = 'frame_' + str(nb)
            nb = nb + 1
            # listchooser entry has to be a tuple(value,comment)
            self.lc2.add((v, ))
            for mol in e[0].keys():
                self.lc2.add((prefix + mol, ))
                for geom in e[0][mol]:
                    self.lc2.add((prefix2 + geom, ))
        # select the entry save as sel
        # keep the entry selected after the update
        for i in sel:
            self.lc2.select((i, ))

    def findFramefromGeomInd(self, index):
        """ return the frame number from  which the geom was selected """
        for i in range(index + 1):
            value = self.lc2.entries[index - i][0]
            if string.find(value, "frame") >= 0:
                frameInd = int(string.split(value, '_')[1])
                lcInd = index - i
                return (frameInd, lcInd)
        return 0

    def findParentGeom(self, index):
        """ find the parent value name from a geom ~~
        go up to find first value with onley ~ """
        parent = None
        for i in range(index + 1):
            parent = self.lc2.entries[index - i][0]
            if parent[0] == '~' and parent[1] != '~':
                parent = parent[1:]
                return parent
        return None

    def removeEntryGeom(self, value, index):
        """ the geom entry in the listchooser"""
        # first find from which frame we need to remove geom
        val = self.findFramefromGeomInd(index)
        if val:
            frameInd = val[0]
            lcInd = val[1]
            if value[1] == '~':
                parent = self.findParentGeom(index)
                if parent:
                    listgeom = self.framelist[frameInd][0][parent]
                    rindex = listgeom.index(value[2:])
                    del listgeom[rindex]

            elif self.framelist[frameInd][0].has_key(value[1:]):
                del self.framelist[frameInd][0][value[1:]]

            self.updatelistchooser(self.framelist)

    def removeEntryFrame(self, value, index):
        """ remove the frame entry in the listchooser"""
        # delete frame from framelist
        frameInd = int(string.split(value, '_')[1])
        del self.framelist[frameInd]
        # Update list chooser
        self.updatelistchooser(self.framelist)

    def remove_cb(self):
        """ remove entry in litschooser (geomtoload)"""
        selindex = self.lc2.getInd()
        for index in selindex:
            value = self.lc2.entries[index][0]
            if string.find(value, "frame") >= 0:
                self.removeEntryFrame(value, index)
            elif value[0] == '~':
                self.removeEntryGeom(value, index)
示例#2
0
class Recorder(Tkinter.Frame):
    """Implements GUI for recording movie clips( *.mpg)"""
    def __init__(self,
                 master=None,
                 height=80,
                 width=100,
                 title="Video recorder",
                 icondir=None,
                 filetypes=[("MPG", ".mpg")],
                 fileName=None,
                 camera=None,
                 gui=True):
        self.ifd = None
        self.form = None
        self.paramForm = None
        self.ifd2 = None
        self.fileName = fileName

        self.autoPauseDelay = 1  # auto pause after 1 second
        self.pauseLength = 30
        self.cameraw = 0
        self.camerah = 0
        self.camera = weakref.ref(camera)
        if self.camera():
            self.cameraw = camera.width
            self.camerah = camera.height

        if not icondir:
            icondir = findFilePath('icons', 'mglutil.gui.BasicWidgets.Tk')
        self.stopIcon = Tkinter.PhotoImage(file=os.path.join(
            icondir, "stop3.gif"),
                                           master=master)
        self.pauseIcon = Tkinter.PhotoImage(file=os.path.join(
            icondir, "stop2.gif"),
                                            master=master)
        self.recordIcon = Tkinter.PhotoImage(file=os.path.join(
            icondir, "record.gif"),
                                             master=master)
        self.record1Icon = Tkinter.PhotoImage(file=os.path.join(
            icondir, "record1.gif"),
                                              master=master)
        self.chmodIcon = Tkinter.PhotoImage(file=os.path.join(
            icondir, 'chmod.gif'),
                                            master=master)
        self.closeIcon = Tkinter.PhotoImage(file=os.path.join(
            icondir, 'close.gif'),
                                            master=master)
        self.fileTypes = filetypes
        if gui:
            self.RecVar = Tkinter.IntVar()
            self.RecVar.set(0)
            self.PauseVar = Tkinter.IntVar()
            self.PauseVar.set(0)
            form = self.buildForm(master=master,
                                  title=title,
                                  height=height,
                                  width=width)
            form.deiconify()

    def buildForm(self, master=None, width=100, height=80, title=None):
        if self.form:
            self.form.deiconify()
            self.createKeyBindings()
            return
        self.master = master
        ifd = self.ifd = InputFormDescr(title=title)
        ifd.append({
            'name': 'fileopen',
            'widgetType': Tkinter.Button,
            'tooltip': "Opens file browser",
            'wcfg': {
                'text': "Save As:",
                'command': self.browseFile,
                'width': 0,
                'height': 0,
            },
            'gridcfg': {
                'sticky': 'w',
                'column': 0
            }
        })
        ifd.append({
            'name': 'filename',
            'widgetType': Pmw.EntryField,
            'tooltip': "type filename",
            'gridcfg': {
                'sticky': 'w',
                #'columnspan': 3},
                'columnspan': 2,
                'row': -1
            },
            'wcfg': {
                'command': self.getFileName,
                #'label_text':'Save As',
                'entry_width': 12,
                'value': self.fileName,
                #'labelpos':'w'}})
            }
        })

        ## ifd.append({'name':'fileopen',
        ##                     'widgetType':Tkinter.Button,
        ##                     'tooltip': "Open file browser",
        ##                     'wcfg':{'text':"...",
        ##                             'command': self.browseFile,
        ##                             'width': 0, 'height': 0,},
        ##                     'gridcfg':{'sticky':'w', 'column':2, 'row':-1}
        ##                     })
        ifd.append({
            'name': 'recordB',
            'widgetType': Tkinter.Checkbutton,
            'tooltip': 'start/stop recording',
            'wcfg': {
                'variable': self.RecVar,
                'bd': 2,
                'image': self.record1Icon,
                'width': self.record1Icon.width(),
                'height': self.record1Icon.height(),
                'indicatoron': 0,
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1
            },
            'command': self.record_cb
        })

        ifd.append({
            'name': 'pauseB',
            'widgetType': Tkinter.Checkbutton,
            'tooltip': 'pause/start recording',
            'wcfg': {
                'variable': self.PauseVar,
                'bd': 2,
                'image': self.pauseIcon,
                'width': self.pauseIcon.width(),
                'height': self.pauseIcon.height(),
                'indicatoron': 0,
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1
            },
            'command': self.pause_cb
        })

        ifd.append({
            'name': 'stopB',
            'widgetType': Tkinter.Button,
            'tooltip': 'stop recording',
            'wcfg': {
                'bd': 2,
                'image': self.stopIcon,
                'width': self.stopIcon.width(),
                'height': self.stopIcon.height(),
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1
            },
            'command': self.stop_cb
        })

        ##         ifd.append({'name': 'recordB',
        ##                     'widgetType': Tkinter.Button,
        ##                     'tooltip':'start/pause recording',
        ##                     'wcfg':{'bd':4,
        ##                             'image':self.recordIcon,
        ##                             'width':self.recordIcon.width(),
        ##                             'height':self.recordIcon.height()
        ##                             },
        ##                     'gridcfg':{'sticky':'nesw','row':-1},
        ##                     'command':self.record_cb})

        ##         ifd.append({'name': 'pauseB',
        ##                     'widgetType': Tkinter.Button,
        ##                     'tooltip':'pause recording',
        ##                     'wcfg':{'bd':4,
        ##                             'image':self.pauseIcon,
        ##                             'width':self.pauseIcon.width(),
        ##                             'height':self.pauseIcon.height()
        ##                             },
        ##                     'gridcfg':{'sticky':'nesw', 'row':-1},
        ##                     'command':self.pause_cb})

        ##         ifd.append({'name': 'modeB',
        ##                     'widgetType': Tkinter.Button,
        ##                     'text':'Change Mode',
        ##                     'tooltip':'opens panel to change video parameters',
        ##                     'wcfg':{'bd':4,
        ##                             'image':self.chmodIcon,
        ##                             'width':self.chmodIcon.width(),
        ##                             'height':self.chmodIcon.height()
        ##                             },
        ##                     'gridcfg':{'sticky':'nesw','row':-1},
        ##                     'command':self.setparams_cb })

        ##         ifd.append({'name': 'closeB',
        ##             'widgetType': Tkinter.Button,
        ##             'text':'Close',
        ##             'tooltip':'closes video recorder',
        ##             'wcfg':{'bd':2,
        ##                     'image':self.closeIcon,
        ##                     'width':self.closeIcon.width(),
        ##                     'height':self.closeIcon.height(),
        ##                     },
        ##             'gridcfg':{'sticky':'nesw','row':-1},
        ##             'command':self.close_cb})
        form = self.form = InputForm(self.master,
                                     None,
                                     descr=ifd,
                                     modal=0,
                                     blocking=0,
                                     closeWithWindow=1,
                                     onDestroy=self.close_cb)
        self.createKeyBindings()
        return form

    def getFileName(self):
        """ Get file name from the input form's entry field."""
        if self.ifd:
            name = self.ifd.entryByName['filename']['widget'].get()
            if name:
                if self.fileName != name:
                    self.fileName = name

    def browseFile(self):
        """Opens file browser."""

        fileDir = None
        if self.fileName:
            if path.exists(self.fileName):
                fileDir = path.dirname(path.realpath(self.fileName))
            else:
                fileDir = os.getcwd()
        file = tkFileDialog.asksaveasfilename(filetypes=self.fileTypes,
                                              initialdir=fileDir,
                                              initialfile=None,
                                              title="Save file")
        if file:
            if self.fileName != file:
                self.fileName = file
                self.ifd.entryByName['filename']['widget'].setentry(file)

    def record_cb(self):

        #get the value of the Record checkbutton
        val = self.RecVar.get()
        if val:  #checked
            self.getFileName()
            res = 1
            if self.camera:
                if self.camera().videoRecordingStatus == "stopped":
                    #kw = {'filename':self.fileName, 'width':self.cameraw, 'hight':self.camerah,
                    #      'autoPauseDelay': self.autoPauseDelay,'pauseLength':self.pauseLength}
                    #kw = {'filename':self.fileName }
                    #apply(self.setVideoParams, (), kw)
                    if os.path.exists(self.fileName):
                        # ask the user if he wants to overwrite the existing file
                        from Dialog import Dialog
                        d = Dialog(
                            None, {
                                'title':
                                'File exisits',
                                'text':
                                'File "%s" already exists.'
                                ' Do you want to overwrite it ?' %
                                self.fileName,
                                'bitmap':
                                'warning',
                                'default':
                                1,
                                'strings': ('Yes', 'No')
                            })
                        ans = d.num
                        if ans == 1:  #no
                            self.RecVar.set(0)
                            return
                    res = self.setVideoParams(filename=self.fileName)
                if res:
                    #print "record_cb: recording"
                    self.camera().start()
            if self.ifd:
                b = self.ifd.entryByName['recordB']['widget']
                if res:
                    b.config(image=self.recordIcon)
                    pauseval = self.PauseVar.get()
                    if pauseval:
                        self.PauseVar.set(0)  #uncheck the Pause checkbutton
        else:  #unchecked
            if self.camera:
                #print "record_cb: stop recording"
                self.stop_cb()

    def stop_cb(self):
        #print "stop_cb"
        if self.camera:
            if not self.camera().videoRecordingStatus == 'stopped':
                #print "stop recording"
                self.camera().stop()
            if self.ifd:
                recval = self.RecVar.get()
                if recval:
                    self.RecVar.set(0)  #uncheck the Record checkbutton
                pauseval = self.PauseVar.get()
                if pauseval:
                    self.PauseVar.set(0)  #uncheck the Pause checkbutton
                b = self.ifd.entryByName['recordB']['widget']
                b.config(image=self.record1Icon)

    def pause_cb(self):
        #print "pause_cb"
        val = self.PauseVar.get()
        if self.camera:
            camerastatus = self.camera().videoRecordingStatus
            if val:  # the Pause button is checked
                if camerastatus == 'recording':
                    #print "pause recording"
                    self.camera().pause()
                    #if self.ifd:
                    #b = self.ifd.entryByName['recordB']['widget']
                    #b.config(command = self.record_cb, image=self.recordIcon)
            else:  # the Pause button is unchecked
                if camerastatus == 'paused':
                    #print "start recording after pause"
                    self.record_cb()

    def spacePress_cb(self, event):
        if self.camera:
            camerastatus = self.camera().videoRecordingStatus
            if camerastatus == "stopped" or camerastatus == "paused":
                self.RecVar.set(1)
                self.record_cb()
            elif camerastatus == "recording":
                self.PauseVar.set(1)
                self.pause_cb()

    def setparams_cb(self):
        """Opens a panel to set Video Parameters"""
        if self.paramForm:
            self.paramForm.deiconify()
            return
        self.ifd2 = ifd2 = InputFormDescr(title="Set video options")
        ifd2.append({
            'widgetType': Pmw.EntryField,
            'tooltip': 'Set camera width',
            'name': 'cameraw',
            'gridcfg': {
                'sticky': 'w',
                'columnspan': 2
            },
            'wcfg': {  #'command': self.setCameraWidth_cb,
                'label_text': 'width:',
                'entry_width': 10,
                'validate': {
                    'validator': 'real',
                    'min': 0
                },
                'value': str(self.cameraw),
                'labelpos': 'w'
            }
        })

        ifd2.append({
            'widgetType': Pmw.EntryField,
            'name': 'camerah',
            'tooltip': 'Set camera height',
            'gridcfg': {
                'sticky': 'w',
                'columnspan': 2
            },
            'wcfg': {  #'command': self.setCameraHeight_cb,
                'label_text': 'height',
                'entry_width': 10,
                'validate': {
                    'validator': 'real',
                    'min': 0
                },
                'value': str(self.camerah),
                'labelpos': 'w'
            }
        })
        ifd2.append({
            'name': 'autoPause',
            'wtype': ThumbWheel,
            'widgetType': ThumbWheel,
            'tooltip': 'set auto pause delay (seconds)',
            'wcfg': {
                'labCfg': {
                    'fg': 'black',
                    'side': 'left',
                    'text': 'AutoPause Delay'
                },
                'showLabel': 1,
                'width': 100,
                'min': 0,
                'value': self.autoPauseDelay,
                'oneTurn': 100,
                'type': 'int',
                'increment': 1,
                #'callback':self.setAutoPauseDelay_cb,
                'canvascfg': {
                    'bg': 'red'
                },
                'continuous': 0,
                'wheelPad': 1,
                'height': 15
            },
            'gridcfg': {
                'sticky': 'nesw',
                'columnspan': 2
            }
        })
        ifd2.append({
            'name': 'pauseLength',
            'wtype': ThumbWheel,
            'widgetType': ThumbWheel,
            'tooltip':
            'set number of frames to be added when\nrecording resumes after autopause',
            'wcfg': {
                'labCfg': {
                    'fg': 'black',
                    'side': 'left',
                    'text': 'AutoPause Length'
                },
                'showLabel': 1,
                'width': 100,
                'min': 0,
                'value': self.pauseLength,
                'oneTurn': 100,
                'type': 'int',
                'increment': 1,
                #'callback':self.setPauseLength_cb,
                'canvascfg': {
                    'bg': 'red'
                },
                'continuous': 0,
                'wheelPad': 1,
                'height': 15
            },
            'gridcfg': {
                'sticky': 'nesw',
                'columnspan': 2
            }
        })
        ifd2.append({
            'name': 'okB',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Apply',
                'command': self.apply_cb,
            },
            'gridcfg': {
                'sticky': 'nesw'
            }
        })
        ifd2.append({
            'name': 'cancelB',
            'widgetType': Tkinter.Button,
            'wcfg': {
                'text': 'Cancel',
                'command': self.cancel_cb,
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1,
                'column': 1
            }
        })
        self.paramForm = InputForm(self.master,
                                   None,
                                   descr=ifd2,
                                   modal=0,
                                   blocking=0)
        self.paramForm.deiconify()

        return self.paramForm

    def setCameraWidth_cb(self):
        """ 'Width' entry field callback of the video parameters form ."""
        w = int(self.ifd2.entryByName['cameraw']['widget'].get())
        if w != self.cameraw:
            self.cameraw = w

    def setCameraHeight_cb(self):
        """'Height' entry field callback of the video parameters form ."""
        h = int(self.ifd2.entryByName['camerah']['widget'].get())
        if h != self.camerah:
            self.camerah = h

    def setAutoPauseDelay_cb(self, val):
        """Callback of the autoPause thumbwheel widget (video parameters input form). """
        #print val
        d = int(val)
        if d != self.autoPauseDelay:
            self.autoPauseDelay = d

    def setPauseLength_cb(self, val):
        """Callback of the pauseLength thumbwheel widget (video parameters input form). """
        #print val
        l = int(val)
        if l != self.pauseLength:
            self.pauseLength = l

    def apply_cb(self):
        """Apply button callback of the video parameters input form."""
        kw = {}
        ebn = self.ifd2.entryByName
        w = float(ebn['cameraw']['widget'].get())
        if w != self.cameraw:
            self.cameraw = w
        kw['width'] = w
        h = float(ebn['camerah']['widget'].get())
        if h != self.camerah:
            self.camerah = h
        kw['height'] = h

        d = ebn['autoPause']['widget'].get()
        if d != self.autoPauseDelay:
            self.autoPauseDelay = d
        kw["autoPauseDelay"] = d

        l = ebn['pauseLength']['widget'].get()
        if l != self.pauseLength:
            self.pauseLength = l
        kw['pauseLength'] = l

        #apply(self.setVideoParams, (), kw)
        self.cancel_cb()

    def setVideoParams(self, **kw):
        """ Uses Recordable Camera methods to set file name and other video parameters"""
        #print kw
        if self.camera:
            filename = kw.get('filename')
            if filename:
                try:
                    self.camera().setVideoOutputFile(filename)
                except IOError:
                    button = tkMessageBox.showerror(
                        "IOError",
                        message="Could not open file %s\nfor writing a movie."
                        % filename,
                        parent=self.master)
                    return False
            ## params = {}
##             w = kw.get('width')
##             if w is not None:
##                 params['width'] = w
##             h = kw.get('height')
##             if h is not None:
##                 params['height']= h
##             pl = kw.get('pauseLength')
##             if pl is not None:
##                 params['pauseLength'] = pl
##             apd = kw.get('autoPauseDelay')
##             if apd is not None:
##                 params['autoPauseDelay'] = apd
##             if len(params):
##                 apply(self.camera().setVideoParameters, (), params)

#use default parameters for now
            self.camera().setVideoParameters()
            return True

    def createKeyBindings(self):
        self.master.bind('<KeyPress-space>', self.spacePress_cb)

    def removeKeyBindings(self):
        self.master.unbind('<KeyPress-space>')

    def cancel_cb(self):
        self.paramForm.withdraw()

    def close_cb(self, event=None):
        if hasattr(self, 'form'):
            self.form.withdraw()
        self.removeKeyBindings()
示例#3
0
class Player(Tkinter.Frame):
    """Widget to play sequence of frames.
    The GUI allows to specify direction and speed of playback.

    the nextFrame(number) methoid should be overridden and define how
    this player plays the animation
    
    the root constructor argument can be a Tkinter container in which to
    embde the control panel.
    
    required attributes:
        currentFrameIndex = 0
        startFrame = 0
        endFrame = 0
        maxFrame = 0
        stepSize = 1
        target = endFrame           #determines direction of play
        increment = 1               #implements decrementing vs incrementing
                                    #  in getNextFrameIndex
        playMode = 0                #playMode options:
                                    #   0   play once and stop
                                    #   1   play continuously in 1 direction
                                    #   2   play once in 2 directions
                                    #   3   play continuously in 2 directions
        framerate =15.              # number of frame per second to be display
        hasSlider = False           #adds Tkinter Scale Widget if True

    customization attributes:
        buttonMask is a dictionary that provides a button name as a key and
        a boolean as a value. For each button in the GUI if the name appears
        in self.buttonMask and the value is False the button willnot be
        addded. This only works when form2 is true. slider and counter
        are handle by the hasSlider and coutner keyword arguments

    required methods:
    #play methods:
        play                           #play according to play mode
        getNextFrameIndex              #returns index of next frame to
                                        play according to current index
                                        and playMode
        nextFrame                      #actually display the nextFrame
                                        ??possibly update widgets???

    #methods to regulate play
        Play_cb                        #play according to playMode
        PlayRev_cb                     #play backwards  
        FastForward_cb()               #play foward at max speed
        FastReverse_cb()               #play reverse at max speed
        Stop_cb                        #stop current play
        ?Pause_cb                      #stop at current frame??
        ?Loop_cb                       #???????


    #methods to set Frame to a specific frame
        SetState_cb                    #counter callback for random access
        GoToStart_cb                   #set to current startFrame
        GoToEnd_cb                     #set to current endFrame
        ?setCurrentFrameIndex          #set currentframe index???


    #methods for player gui
        showGUI                        #show the gui
        buildForm2                     #opens image-based gui
        buildForm                      #opens text-based gui
        Close_cb                       #withdraws gui

    #methods for pmw counter
        custom_validate                #used by pmw to check entry
        custom_counter                 #used by pmw for counter


    #methods for changing playMode
        SetMode_cb                     #opens playModeForm
        setPlayMode_cb                 #sets playMode, sets delay,
                                          startFrame, endFrame 
                                          AND closes playModeForm
        cancelPlayMode_cb              #closes playModeForm w/out changes

        #methods for end points:
            setStartFrame()            #set startFrame
            setEndFrame()              #set endFrame
            setStepSize()              #sets increment, def=1
        additional methods:
    """

    def __init__(
        self,
        master=None,
        root=None,
        height=80,
        width=200,
        currentFrameIndex=0,
        startFrame=0,
        endFrame=0,
        maxFrame=0,
        stepSize=1,
        playMode=0,
        ##afterDelay=50,
        titleStr="Player",
        gotoStartfile="go_to_start.gif",
        gotoEndfile="go_to_end.gif",
        ff_revfile="ff_rev.gif",
        ff_fwdfile="ff_fwd.gif",
        stopfile="stop.gif",
        playfile="play_fwd.gif",
        playRevfile="play_rev.gif",
        chmodfile="chmod.gif",
        closefile="close.gif",
        iconpath=None,
        counter=1,
        form2=1,
        gui=1,
        framerate=15.0,
        hasSlider=False,
        buttonMask=None,
    ):

        # frame rate in fps
        self.framerate = framerate
        self.gui = gui
        self.currentFrameIndex = currentFrameIndex
        self.startFrame = startFrame
        self.endFrame = endFrame
        self.targetFrame = self.endFrame
        self.maxFrame = maxFrame
        if not maxFrame:
            self.maxFrame = endFrame
        self.stepSize = stepSize
        # used for play once in 2 directions
        self.oneDirection = 0
        self.increment = 1
        self.target = self.endFrame
        self.hasSlider = hasSlider
        # used to coordinate switching icons
        # playMode options:
        #   0   play once and stop
        #   1   play continuously in 1 direction
        #   2   play once in 2 directions and stop
        #   3   play continuously in 2 directions
        self.playMode = playMode
        ### replace by framerate
        # amt of time to sleep
        # self.delay = delay

        # amt of time for after
        # self.afterDelay = afterDelay

        self.afterID = None
        self.stop = 1
        self.hasCounter = 0
        # gui variable
        # self.master = master
        # self.root = root
        self.form2 = form2
        self.hasCounter = counter

        if buttonMask is None:
            self.buttonMask = {}
            # self.buttonMask provides a button name as a key and a boolean
            # as a value. For each button in the GUI if the name appears in
            # self.buttonMask and the value is False the button willnot be
            # addded
        else:
            self.buttonMask = buttonMask

        if gui:
            self.showGUI(master=master, root=root, titleStr=titleStr, height=height, width=width, iconpath=iconpath)

        # make sure we have a master as we will call master.update in play()
        if hasattr(master, "update"):
            self.masterForUpdate = self.master
        else:
            self.masterForUpdate = self.root

    def showGUI(
        self,
        master=None,
        root=None,
        width=200,
        height=80,
        titleStr="player",
        gotoStartfile="go_to_start.gif",
        gotoEndfile="go_to_end.gif",
        ff_revfile="ff_rev.gif",
        ff_fwdfile="ff_fwd.gif",
        stopfile="stop.gif",
        playfile="play_fwd.gif",
        playRevfile="play_rev.gif",
        chmodfile="chmod.gif",
        closefile="close.gif",
        iconpath=None,
    ):
        """ function to display the player gui."""

        if hasattr(self, "form"):
            if hasattr(self.form, "deiconify"):
                self.form.deiconify()
                return
        self.master = master
        self.root = root

        if not self.form2:
            self.form = self.buildForm(titleStr)  # pass some arguments here
            self.form2 = 0
        else:
            if iconpath is None:
                iconpath = ("mglutil.gui.BasicWidgets.Tk", "icons")
            ICONDIR = findFilePath(iconpath[1], iconpath[0])
            # if findFilePath failed, already returned
            gotoStartfile = os.path.join(ICONDIR, gotoStartfile)
            gotoEndfile = os.path.join(ICONDIR, gotoEndfile)
            ff_revfile = os.path.join(ICONDIR, ff_revfile)
            ff_fwdfile = os.path.join(ICONDIR, ff_fwdfile)
            stopfile = os.path.join(ICONDIR, stopfile)
            playfile = os.path.join(ICONDIR, playfile)
            playRevfile = os.path.join(ICONDIR, playRevfile)
            chmodfile = os.path.join(ICONDIR, chmodfile)
            closefile = os.path.join(ICONDIR, closefile)
            recordfile = os.path.join(ICONDIR, "record.gif")
            record1file = os.path.join(ICONDIR, "record1.gif")

            self.gotoStartIcon = Tkinter.PhotoImage(file=gotoStartfile, master=master)
            self.gotoEndIcon = Tkinter.PhotoImage(file=gotoEndfile, master=master)
            self.ff_revIcon = Tkinter.PhotoImage(file=ff_revfile, master=master)
            self.ff_fwdIcon = Tkinter.PhotoImage(file=ff_fwdfile, master=master)
            self.stopIcon = Tkinter.PhotoImage(file=stopfile, master=master)
            self.playIcon = Tkinter.PhotoImage(file=playfile, master=master)
            self.playRevIcon = Tkinter.PhotoImage(file=playRevfile, master=master)
            self.recIcon = Tkinter.PhotoImage(file=recordfile, master=master)
            self.rec1Icon = Tkinter.PhotoImage(file=record1file, master=master)
            self.chmodIcon = Tkinter.PhotoImage(file=chmodfile, master=master)
            self.closeIcon = Tkinter.PhotoImage(file=closefile, master=master)
            self.form = self.buildForm2(titleStr)  # pass some argument here

    # play methods:
    # play, waitTime, getNextFrameIndex, nextFrame
    def play(self, framerate, event=None):
        t1 = time.time()  # previous frame time
        timestamp = 1.0 / framerate  # rate to update frame
        self.stop = 0
        ind = self.currentFrameIndex

        # if player at the end we resume from begining
        if ind >= self.endFrame:
            self.GoToStart_cb()

        while not self.stop:  # this has to be more complex
            if self.stop:
                print "play stopped!"
                break

            # do something different here if ff_fwd or ff_rev
            if self.gui:
                # self.afterID = self.master.after(self.afterDelay, self.waitTime)
                self.masterForUpdate.update()

            t2 = time.time()  # current time
            t = t2 - t1  # time difference between current frame and previous

            if framerate > -1 and t < timestamp:
                pass
            else:
                id = self.getNextFrameIndex(self.currentFrameIndex)
                if id == None:
                    self.stop = 1
                    if self.gui:
                        self.Stop_cb()
                        break
                self.nextFrame(id)  # maybe set entry then call nextFrame??
                self.currentFrameIndex = id
                t1 = t2

    def getNextFrameIndex(self, index):
        newFrame = index + self.increment * self.stepSize
        # check if  newFrame in current range:
        #       if incrementing, has to be <=self.endFrame
        #       if decrementing, has to be >=self.startFrame
        #   NB: incPos indicates whether currently incrementing or decrementing
        # FORCE newFrame into range
        incPos = self.increment > 0
        if incPos and newFrame > self.endFrame:
            newFrame = self.endFrame
        elif not incPos and newFrame < self.startFrame:
            newFrame = self.startFrame
        # check whether reached current targetFrame
        #       if so, action depends on current playMode
        mode = self.playMode
        if index == self.targetFrame:
            # playModes 0 and 2 are play once and stop (in 1 or 2 directions)
            if not mode % 2:
                if mode == 0:
                    # None means stop
                    return None
                else:
                    # play once in 2 directions
                    #   check whether already reached halfway pt
                    if self.oneDirection:
                        return None
                    self.oneDirection = 1
                    # to reverse direction:
                    #   toggle increment
                    self.increment = -1 * self.increment
                    #   toggle targetFrame
                    if self.targetFrame == self.endFrame:
                        self.targetFrame = self.startFrame
                    else:
                        self.targetFrame = self.endFrame
                    return newFrame
            elif self.playMode == 1:
                # play continuously in 1 direction
                # toggle targetFrame to the opposite end
                if self.targetFrame == self.endFrame:
                    return self.startFrame
                else:
                    return self.endFrame
            elif self.playMode == 3:
                # loop continuously in 2 directions
                #   toggle increment
                self.increment = -1 * self.increment
                newFrame = self.targetFrame + self.stepSize * self.increment
                #   toggle targetFrame
                if self.targetFrame == self.endFrame:
                    self.targetFrame = self.startFrame
                else:
                    self.targetFrame = self.endFrame
                return newFrame
        return newFrame

    ##     def waitTime(self):
    ##         self.afterID = None
    ##         t1 = time.time()
    ##         delta = time.time() - t1
    ##         #curBut is either play or playRev button
    ##         hasCurBut = hasattr(self, 'curBut')
    ##         while delta < self.delay:
    ##             if hasCurBut:
    ##                 self.curBut.config(bg='red')
    ##             self.master.update()
    ##             time.sleep(self.delay/100)
    ##             delta = time.time() - t1
    ##         if hasCurBut:
    ##             self.curBut.config(bg='white')
    ##         if self.afterID is not None and hasCurBut:
    ##             self.curBut.after_cancel(self.afterID)
    ##             self.afterID = self.curBut.after(self.afterDelay, self.waitTime)

    def nextFrame(self, id):
        ##pass #must be overriden
        id = int(id)
        if id == self.currentFrameIndex:
            return
        if self.hasCounter and self.gui:
            self.form.ent2.delete(0, "end")
            self.form.ent2.insert(0, str(id))
            if self.hasSlider:
                self.form.ifd.entryByName["slider"]["widget"].set(id)
        print "playing ", id
        self.currentFrameIndex = int(id)

    # methods to call play
    # Play_cb, PlayRev_cb, FastForward_cb, FastReverse_cb
    # Stop_cb and possibly Pause_cb, Loop_cb
    def startRecording_cb(self, event=None):
        pass

    def stopRecording_cb(self, event=None):
        pass

    def Play_cb(self, framerate=None, event=None):
        # print 'Play_cb'
        self.form.ifd.entryByName["playB"]["widget"].grab_release()
        # this is a new call to Play_cb
        if framerate == None:
            framerate = self.framerate
        self.stop = 0
        self.oneDirection = 0
        self.targetFrame = self.endFrame
        self.increment = 1
        # print 'currentFrameIndex=', self.currentFrameIndex
        # possibly currently playing reverse
        if hasattr(self, "curBut") and self.curBut == self.form.playRevB:
            if self.form2:
                self.curBut.config(command=self.oldCmd, image=self.oldImage, bg="white")
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
        self.oldTT = self.form.playTT
        self.oldTTtext = "play forward according to current play mode"
        self.curBut = self.form.playB
        self.oldCmd = self.Play_cb
        self.oldImage = self.playIcon
        self.oldText = "Play"
        if self.form2:
            self.curBut.config(command=self.Stop_cb, image=self.stopIcon)
        else:
            self.curBut.config(command=self.Stop_cb, text="Stop")
        self.oldTT.bind(self.curBut, "stop play")
        # self.master.update()
        self.play(framerate)
        self.stopRecording_cb()

    def PlayRev_cb(self, framerate=None, event=None):
        # figure out current number and then play backwards
        # print 'currentFrameIndex=', self.currentFrameIndex
        self.form.ifd.entryByName["playRevB"]["widget"].grab_release()
        if framerate == None:
            framerate = self.framerate
        self.increment = -1
        self.targetFrame = self.startFrame
        self.oneDirection = 0
        self.stop = 0
        # possibly currently playing
        if hasattr(self, "curBut") and self.curBut == self.form.playB:
            if self.form2:
                self.curBut.config(command=self.oldCmd, image=self.oldImage, bg="white")
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
        self.oldTT = self.form.playRevTT
        self.oldTTtext = "play reverse according to current play mode"
        self.curBut = self.form.playRevB
        self.oldCmd = self.PlayRev_cb
        self.oldImage = self.playRevIcon
        self.oldText = "Play Reverse"
        if self.form2:
            self.curBut.config(command=self.Stop_cb, image=self.stopIcon)
        else:
            self.curBut.config(command=self.Stop_cb, text="Stop")
        self.oldTT.bind(self.curBut, "stop play")
        self.play(framerate)

    def FastReverse_cb(self, event=None):
        # print 'FastReverse'
        # framerate = self.framerate * 2
        self.oneDirection = 0
        self.PlayRev_cb(framerate=-1)  # framerate)

    def FastForward_cb(self, event=None):
        # print 'FastForward'
        self.oneDirection = 0
        # framerate = self.framerate * 2
        self.Play_cb(framerate=-1)

    def Stop_cb(self, event=None):
        self.stop = 1
        if hasattr(self, "curBut"):
            if self.form2:
                self.curBut.config(command=self.oldCmd, image=self.oldImage)
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
                # FIX THIS!!!!
                # DECIDE if stop means reset to start or not
                # self.nextFrame(self.startFrame)
            self.oldTT.bind(self.curBut, self.oldTTtext)

        self.stopRecording_cb()

        # FIX THIS: does this go here?  or in nextFrame
        # clean up form
        # if self.hasCounter:
        #    self.form.ent2.delete(0,'end')
        #    self.form.ent2.insert(0, str(self.currentFrameIndex))

    # these may be superfluous: called by original form
    def PlayReturn_cb(self, event=None):
        # print 'PlayReturn_cb'
        # this should be superfluous
        self.playMode = 3
        self.Play_cb()

    def Loop_cb(self, event=None):
        # print 'Loop_cb'
        # this should be superfluous
        self.playMode = 3
        self.Play_cb()

    def Pause_cb(self, event=None):
        self.stop = 1

    # methods to set Frame to a specific frame
    # SetState_cb, GoToStart_cb, GoToEnd_cb, setCurrentFrameIndex
    def SetState_cb(self, event=None):
        # do nothing if no counter
        if self.hasCounter:
            index = self.form.counter.get()
            self.nextFrame(index)

    def GoToStart_cb(self, event=None):
        # print "GoToStart_cb", self.startFrame, self.currentFrameIndex
        # self.currentFrameIndex = self.startFrame
        self.oneDirection = 0
        self.nextFrame(self.startFrame)

    def GoToEnd_cb(self, event=None):
        # print 'GoToEnd'
        self.oneDirection = 0
        # self.currentFrameIndex = self.endFrame
        self.nextFrame(self.endFrame)

    def setCurrentFrameIndex(self, index):
        # print 'setting currentFrameIndex to', index
        self.currentFrameIndex = index

    # methods for player gui
    def Close_cb(self, event=None):
        self.stop = 1
        if hasattr(self, "form"):
            self.form.withdraw()

    def SetAnim_cb(self):
        """ function to be overwritten.
        Use to call a functoin to set the animatiom frame."""

        return

    def buildForm2(self, titleStr):
        self.stop = 1
        if hasattr(self, "form"):
            if hasattr(self.form, "deiconify"):
                self.form.deiconify()
                return
        maxval = self.endFrame
        ifd = InputFormDescr(title=titleStr)

        if self.buttonMask.get("gotoStartB", None) is not False:
            ifd.append(
                {
                    "name": "gotoStartB",
                    "widgetType": Tkinter.Button,
                    #'text':'gotoStart',
                    "tooltip": "sets frame to current startFrame",
                    "wcfg": {
                        "bd": 4,
                        "image": self.gotoStartIcon,
                        "width": self.gotoStartIcon.width(),
                        "height": self.gotoStartIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw"},
                    "command": self.GoToStart_cb,
                }
            )

        if self.buttonMask.get("fastReverseB", None) is not False:
            ifd.append(
                {
                    "name": "fastReverseB",
                    "widgetType": Tkinter.Button,
                    #'text':'fastReverse',
                    "tooltip": "play reverse as fast as possible",
                    "wcfg": {
                        "bd": 4,
                        "image": self.ff_revIcon,
                        "width": self.ff_revIcon.width(),
                        "height": self.ff_revIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 1},
                    "command": self.FastReverse_cb,
                }
            )

        if self.buttonMask.get("playRevB", None) is not False:
            ifd.append(
                {
                    "name": "playRevB",
                    "widgetType": Tkinter.Button,
                    #'text':'Play Reverse',
                    "tooltip": "play reverse according to current play mode",
                    "wcfg": {
                        "bd": 4,
                        "image": self.playRevIcon,
                        "width": self.playRevIcon.width(),
                        "height": self.playRevIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 2},
                    "command": self.PlayRev_cb,
                }
            )

            if self.hasCounter:
                ifd.append(
                    {
                        "widgetType": Pmw.Counter,
                        "name": "statesCounter",
                        "required": 1,
                        "tooltip": "used to show frames via random access",
                        "wcfg": {  #'labelpos': 'n,
                            #'label_text':'conformation:  ',
                            "autorepeat": 0,
                            "entryfield_value": self.startFrame,
                            #'entryfield_value':self.idList[0],
                            "datatype": self.custom_counter,
                            "entry_width": 3,
                            "entryfield_validate": self.custom_validate,
                        },
                        "gridcfg": {"sticky": "nesw", "row": -1, "column": 3, "columnspan": 2},
                    }
                )

        if self.buttonMask.get("playB", None) is not False:
            ifd.append(
                {
                    "name": "playB",
                    "widgetType": Tkinter.Button,
                    #'text':'Play',
                    "tooltip": "play forward according to current play mode",
                    "wcfg": {
                        "bd": 4,
                        "image": self.playIcon,
                        "width": self.playIcon.width(),
                        "height": self.playIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 5},
                    "command": self.Play_cb,
                }
            )

        if self.buttonMask.get("fastForwardB", None) is not False:
            ifd.append(
                {
                    "name": "fastForwardB",
                    "widgetType": Tkinter.Button,
                    #'text':'fastForward',
                    "tooltip": "play as fast as possible",
                    "wcfg": {
                        "bd": 4,
                        "image": self.ff_fwdIcon,
                        "width": self.ff_fwdIcon.width(),
                        "height": self.ff_fwdIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 6},
                    "command": self.FastForward_cb,
                }
            )

        if self.buttonMask.get("gotoEndB", None) is not False:
            ifd.append(
                {
                    "name": "gotoEndB",
                    "widgetType": Tkinter.Button,
                    #'text':'gotoEnd',
                    "tooltip": "sets frame to current endFrame",
                    "wcfg": {
                        "bd": 4,
                        "image": self.gotoEndIcon,
                        "width": self.gotoEndIcon.width(),
                        "height": self.gotoEndIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 7},
                    "command": self.GoToEnd_cb,
                }
            )

        if self.buttonMask.get("modeB", None) is not False:
            ifd.append(
                {
                    "name": "modeB",
                    "widgetType": Tkinter.Button,
                    "text": "Change Mode",
                    "tooltip": "opens panel to change play options",
                    "wcfg": {
                        "bd": 4,
                        "image": self.chmodIcon,
                        "width": self.chmodIcon.width(),
                        "height": self.chmodIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 8},
                    "command": self.SetMode_cb,
                }
            )

        if pymediaFound and self.buttonMask.get("recordB", None) is not False:
            ifd.append(
                {
                    "name": "recordB",
                    "widgetType": Tkinter.Checkbutton,
                    "text": "Record",
                    "tooltip": "record an mpeg movie into movie_####.mpg",
                    "defaultValue": 0,
                    "wcfg": {
                        "bd": 4,
                        "variable": Tkinter.IntVar(),
                        "image": self.recIcon,
                        "width": self.recIcon.width(),
                        "height": self.recIcon.height(),
                        "indicatoron": 0,
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 9},
                    "command": self.startRecording_cb,
                }
            )

        if self.buttonMask.get("setanimB", None) is not False:
            ifd.append(
                {
                    "name": "setanimB",
                    "widgetType": Tkinter.Button,
                    "text": "SetAnim",
                    "tooltip": "Set Animation",
                    "wcfg": {"bd": 4},
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 10},
                    "command": self.SetAnim_cb,
                }
            )

        if self.buttonMask.get("closeB", None) is not False:
            ifd.append(
                {
                    "name": "closeB",
                    "widgetType": Tkinter.Button,
                    "text": "Close",
                    "tooltip": "closes player",
                    "wcfg": {
                        "bd": 4,
                        "image": self.closeIcon,
                        "width": self.closeIcon.width(),
                        "height": self.closeIcon.height(),
                    },
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 11},
                    #'gridcfg':{'sticky':'nesw', 'columnspan':2},
                    "command": self.Close_cb,
                }
            )

        if self.hasSlider:
            ifd.append(
                {
                    "name": "slider",
                    "widgetType": Tkinter.Scale,
                    "wcfg": {"orient": "horizontal", "from_": self.startFrame, "to": self.maxFrame, "showvalue": False},
                    "gridcfg": {"sticky": "nesw", "row": 1, "column": 0, "columnspan": 12},
                    "command": self.nextFrame,
                }
            )
        # form = self.vf.getUserInput(ifd, modal=0,blocking=0)
        form = InputForm(self.master, self.root, descr=ifd, modal=0, blocking=0, closeWithWindow=1)
        form.ifd = ifd
        form.playB = form.ifd.entryByName["playB"]["widget"]
        form.playRevB = form.ifd.entryByName["playRevB"]["widget"]
        # set up link to balloon help which needs to change, also
        form.playTT = form.ifd.entryByName["playB"]["balloon"]
        form.playRevTT = form.ifd.entryByName["playRevB"]["balloon"]
        if self.hasCounter:
            ctr = ifd.entryByName["statesCounter"]["widget"]
            entF = ctr.component("entryfield")
            form.ent2 = entF._entryFieldEntry
            da = ctr.component("downarrow")
            ua = ctr.component("uparrow")
            for item in [da, ua]:
                item.bind("<ButtonPress-1>", self.SetState_cb, "+")
            form.ent2.bind("<Return>", self.SetState_cb, "+")
            form.counter = form.ifd.entryByName["statesCounter"]["widget"]
        if self.hasSlider:
            slider = form.ifd.entryByName["slider"]["widget"]
            slider.set(self.currentFrameIndex)
        # print 'returning form'
        return form

    def buildForm(self, titleStr):
        # ??FIX THIS:
        self.stop = 1
        if hasattr(self, "form"):
            self.form.deiconify()
            return
        maxval = self.endFrame
        ifd = InputFormDescr(title=titleStr)
        if self.hasCounter:
            ifd.append(
                {
                    "widgetType": Pmw.Counter,
                    "name": "statesCounter",
                    "required": 1,
                    "tooltip": "used to show frames via random access",
                    "wcfg": {  #'labelpos': 'n,
                        #'label_text':'conformation:  ',
                        "autorepeat": 0,
                        "entryfield_value": self.startFrame,
                        #'entryfield_value':self.idList[0],
                        "datatype": self.custom_counter,
                        "entry_width": 9,
                        "entryfield_validate": self.custom_validate,
                    },
                    "gridcfg": {"sticky": "nesw", "columnspan": 2},
                }
            )
        ifd.append(
            {
                "name": "playB",
                "widgetType": Tkinter.Button,
                "text": "Play",
                "tooltip": "play sequence according to current play mode",
                "wcfg": {"bd": 4},
                "gridcfg": {"sticky": "nesw", "columnspan": 1},
                "command": self.Play_cb,
            }
        )
        ifd.append(
            {
                "name": "playRevB",
                "widgetType": Tkinter.Button,
                "text": "Play Reverse",
                "wcfg": {"bd": 4},
                "gridcfg": {"sticky": "nesw", "row": -1, "column": 1},
                "command": self.PlayRev_cb,
            }
        )
        ifd.append(
            {
                "name": "playTB",
                "widgetType": Tkinter.Button,
                "text": "Play+Return",
                "wcfg": {"bd": 4},
                "gridcfg": {"sticky": "nesw", "columnspan": 1},
                "command": self.PlayReturn_cb,
            }
        )
        ifd.append(
            {
                "name": "loopB",
                "widgetType": Tkinter.Button,
                "text": "Loop",
                "wcfg": {"bd": 4},
                "gridcfg": {"sticky": "nesw", "row": -1, "column": 1},
                "command": self.Loop_cb,
            }
        )
        ifd.append(
            {
                "name": "stopB",
                "widgetType": Tkinter.Button,
                "text": "Stop",
                "tooltip": "stop play",
                "wcfg": {"bd": 4},
                "gridcfg": {"sticky": "nesw"},
                "command": self.Stop_cb,
            }
        )
        # add fastforward, fastrewind, thumbwheel for speed
        ifd.append(
            {
                "name": "pauseB",
                "widgetType": Tkinter.Button,
                "text": "Pause",
                "wcfg": {"bd": 4},
                "gridcfg": {"sticky": "nesw", "row": -1, "column": 1},
                "command": self.Pause_cb,
            }
        )

        ifd.append(
            {
                "name": "closeB",
                "widgetType": Tkinter.Button,
                "text": "Close",
                "wcfg": {"bd": 4},
                #'gridcfg':{'sticky':'nesw','row':-1, 'column':1},
                "gridcfg": {"sticky": "nesw", "columnspan": 2},
                "command": self.Close_cb,
            }
        )
        form = InputForm(self.master, self.root, descr=ifd, modal=0, blocking=0, closeWithWindow=1)
        form.ifd = ifd
        if self.hasCounter:
            ctr = ifd.entryByName["statesCounter"]["widget"]
            entF = ctr.component("entryfield")
            form.ent2 = entF._entryFieldEntry
            da = ctr.component("downarrow")
            ua = ctr.component("uparrow")
            for item in [da, ua]:
                item.bind("<ButtonPress-1>", self.SetState_cb, "+")
            form.ent2.bind("<Return>", self.SetState_cb, "+")
            form.counter = form.ifd.entryByName["statesCounter"]["widget"]
        form.stopB = form.ifd.entryByName["stopB"]["widget"]
        form.playB = form.ifd.entryByName["playB"]["widget"]
        form.playRevB = form.ifd.entryByName["playRevB"]["widget"]
        # print 'returning form1'
        self.form = form
        return form

    # methods for changing playMode
    def SetMode_cb(self, event=None):
        # print 'SetMode'
        # playMode options:
        #   0   play once and stop
        #   1   play continuously in 1 direction
        #   2   play once in 2 directions
        #   3   play continuously in 2 directions
        # play framerate is frame/per second
        if not hasattr(self, "playModeForm"):
            self.playModeList = [
                "once and stop",
                "continuously in 1 direction",
                "once in 2 directions",
                "continuously in 2 directions",
            ]
            ifd2 = InputFormDescr(title="Set Play Mode")

            ifd2.append(
                {
                    "name": "playModeLabel",
                    "widgetType": Tkinter.Label,
                    "wcfg": {"text": "play mode options:", "font": (ensureFontCase("helvetica"), 12, "bold")},
                    "gridcfg": {"sticky": "w"},
                }
            )

            ifd2.append(
                {
                    "name": "playMode",
                    "widgetType": Tkinter.Radiobutton,
                    "defaultValue": self.playModeList[self.playMode],
                    "listtext": self.playModeList,
                    "gridcfg": {"sticky": "w"},
                }
            )

            ifd2.append(
                {
                    "name": "framerateTW",
                    "widgetType": ThumbWheel,
                    "tooltip": """Framerate to enforce during playback""",
                    "gridcfg": {"sticky": "we"},
                    "wcfg": {
                        "value": self.framerate,
                        "oneTurn": 100.0,
                        "type": "float",
                        "continuous": True,
                        "wheelPad": 2,
                        "width": 145,
                        "height": 18,
                        "labCfg": {"text": "framerate:  "},
                    },
                }
            )

            ifd2.append(
                {
                    "name": "startFrameTW",
                    "widgetType": ThumbWheel,
                    "tooltip": """First frame used in playback""",
                    "gridcfg": {"sticky": "we"},
                    "wcfg": {
                        "value": self.startFrame,
                        "oneTurn": 100,
                        "type": "int",
                        "continuous": True,
                        "wheelPad": 2,
                        "width": 145,
                        "height": 18,
                        "labCfg": {"text": "start frame: "},
                    },
                }
            )

            ifd2.append(
                {
                    "name": "endFrameTW",
                    "widgetType": ThumbWheel,
                    "tooltip": """Last frame used in playback""",
                    "gridcfg": {"sticky": "we"},
                    "wcfg": {
                        "value": self.endFrame,
                        "oneTurn": 100,
                        "type": "int",
                        "continuous": True,
                        "wheelPad": 2,
                        "width": 145,
                        "height": 18,
                        "labCfg": {"text": " end frame: "},
                    },
                }
            )

            ifd2.append(
                {
                    "name": "stepSizeTW",
                    "widgetType": ThumbWheel,
                    "tooltip": """???""",
                    "gridcfg": {"sticky": "we"},
                    "wcfg": {
                        "value": self.stepSize,
                        "oneTurn": 100,
                        "type": "int",
                        "continuous": True,
                        "wheelPad": 2,
                        "width": 145,
                        "height": 18,
                        "labCfg": {"text": " step size:  "},
                    },
                }
            )

            ifd2.append(
                {
                    "name": "acceptB",
                    "widgetType": Tkinter.Button,
                    "wcfg": {"text": "ok", "command": self.setPlayMode_cb},
                    "gridcfg": {"sticky": "nesw"},
                }
            )

            ifd2.append(
                {
                    "name": "cancelB",
                    "widgetType": Tkinter.Button,
                    "wcfg": {"text": "cancel", "command": self.cancelPlayMode_cb},
                    "gridcfg": {"sticky": "nesw", "row": -1, "column": 1},
                }
            )
            if self.master is None:
                master = self.root
            else:
                master = Tkinter.Toplevel()
            self.playModeForm = InputForm(master, None, descr=ifd2, modal=0, blocking=0)
            self.playModeVar = self.playModeForm.descr.entryByName["playMode"]["variable"]
            self.framerateWidget = self.playModeForm.descr.entryByName["framerateTW"]["widget"]
            self.startFrameWidget = self.playModeForm.descr.entryByName["startFrameTW"]["widget"]
            self.endFrameWidget = self.playModeForm.descr.entryByName["endFrameTW"]["widget"]
            self.stepSizeWidget = self.playModeForm.descr.entryByName["stepSizeTW"]["widget"]
        else:
            self.playModeForm.deiconify()

    def setPlayMode_cb(self, event=None):
        curVal = self.playModeVar.get()
        self.playMode = self.playModeList.index(curVal)
        # print 'setting playMode to ', curVal
        self.framerate = round(self.framerateWidget.get(), 4)
        # print 'setting self.framerate ->', self.framerate
        self.timestamp = 1.0 / self.framerate

        self.startFrame = self.startFrameWidget.get()
        self.endFrame = self.endFrameWidget.get()
        self.stepSize = self.stepSizeWidget.get()
        self.cancelPlayMode_cb()
        self.oneDirection = 0

    def cancelPlayMode_cb(self, event=None):
        self.playModeForm.withdraw()

    # methods for counter
    def custom_validate(self, text):
        # print 'in custom_validate, text=', text
        if not len(text):
            return -1

        if text in ["start", "end"]:
            return 1

        tt = int(text)
        okList = range(self.startFrame, self.endFrame + 1)
        if tt in okList:
            return 1
        else:
            return -1

    def custom_counter(self, text, factor, increment, **kw):
        # text is current content of entry
        # factor is 1 for increment and -1 for decrement
        # increment is value of increment megawidget option
        ###if not text in self.idList:
        ###raise ValueError, text + ' not in current idList'
        # check whether ind+factor is in range
        newval = self.currentFrameIndex + factor
        # print 'newval=', newval
        if newval < 0 or newval > self.endFrame:
            # print 'custom_counter returning ', text
            return text
        else:
            # print 'custom_counter returning ', newval
            return newval
示例#4
0
class geomsChooser:
    def __init__(self, viewer):

        #ViewerGUI(viewer,8,2)
        # the viewe where the geoms are display (for us: pmv or DejaVu)
        if viewer is None:
            return
        self.viewer = viewer
        geomDic = {}
        dpyList = None
        self.assignGeom = [geomDic, dpyList]

    def toggleExpansion(self, event):
        # get a 0-based index into list of names
        o = self.lc.lb.nearest(event.y)
        fullName = self.getFullName(o)
        #obj = self.objectByName(self.olist.get(o))
        obj = self.viewer.FindObjectByName(fullName)
        if obj:
            childGeoms = obj.AllObjects()
            if len(childGeoms) == 1:  # this geoemtry has no children
                return
            else:  # this geometry has children
                if obj.isExpandedInObjectList: self.collapse(obj)
                else: self.expand(obj)

    def expand(self, object):
        # object is a geometry
        if object.isExpandedInObjectList: return
        object.isExpandedInObjectList = 1
        geoms = object.children
        ind = self.objectIndex(object) + 1
        c = self.countParents(object) + 1
        prefix = '~' * c
        for i in range(len(geoms)):
            g = geoms[i]
            if g == object: continue
            if not g.listed: continue
            if len(g.vertexSet) == 0 and len(g.children) == 0: continue
            self.lc.insert(ind, prefix + g.name)
            ind = ind + 1

    def collapse(self, object):
        # object is a geometry, we recursively collapse the sub-tree
        object.isExpandedInObjectList = 0

        # delete the names from the bject list widget
        nbChildren = self.countDecendentsInWidget(object)
        ind = self.objectIndex(object) + 1
        for i in range(ind, ind + nbChildren):
            self.lc.lb.delete(ind)
        # toggle isExpandedInObjectList for all descendents
        for child in object.AllObjects():
            if child.listed:
                child.isExpandedInObjectList = 0

    def countDecendentsInWidget(self, object):
        # object is a geometry, we count and return the number of
        # decendents shown in widget
        ind = self.objectIndex(object)
        allNames = self.lc.lb.get(0, 'end')
        nbTild = string.count(allNames[ind], '~') + 1
        # count children in widget
        nbChildren = 0
        for i in range(ind + 1, len(allNames)):
            nbt = string.count(allNames[i], '~')
            if nbt >= nbTild:
                nbChildren = nbChildren + 1
            else:
                break
        return nbChildren

    def getFullName(self, ind):
        # strip the leading ~
        allNames = self.lc.lb.get(0, 'end')
        nbTild = string.count(allNames[ind], '~')
        fullName = allNames[ind][nbTild:]
        for i in range(ind - 1, -1, -1):
            nbt, name = self.lstripChar(allNames[i], '~')
            if nbt >= nbTild: continue
            nbTild = nbt
            fullName = name + '|' + fullName
        return fullName

    def objectIndex(self, object):
        # object is a geometry and we find this object's index in the list of
        # names displayed in te widget. If the ibecjt is not shown we
        # return -1
        l = self.lc.lb.get(0, 'end')
        for i in range(len(l)):
            indent, n = self.lstripChar(l[i], '~')
            if n == object.name: break
        if i == len(l): return -1
        else: return i

    def lstripChar(self, name, char):
        n = string.count(name, '~')
        return n, name[n:]

    def countParents(self, object):
        c = 0
        while object.parent:
            c = c + 1
            object = object.parent
        return c

    def addObject(self, obj, parent):
        if not obj.listed: return
        if not parent:
            self.lc.insert(0, obj.name)
            self.lc.select(obj.name)
        else:
            if not parent.isExpandedInObjectList: return

            i = self.objectIndex(parent)
            if i == -1: return
            c = self.countParents(obj)
            prefix = '~' * c
            name = prefix + obj.name
            # now we need to skip all children already there
            l = self.lc.lb.get(0, 'end')
            while 1:
                i = i + 1
                if i == len(l): break
                if self.lc.get(i)[:c] != prefix: break

            self.lc.insert(i, name)

    def getFullNameList(self, name, list, dic):
        """ get the list of fullName from geomDic """

        for p in dic.keys():
            name1 = name + '|' + p
            if dic[p] != {}:
                list = self.getFullNameList(name1, list, dic[p])
            else:
                list.append(name1)

        return list

    def getDpyList(self, objects):
        """function to obtain a display list for any object in DejaVu"""
        from opengltk.OpenGL import GL
        # Draw build a display function that contains global coloring,
        # transformation nd all global GL properties of this objects.
        # we cannot use the object's display list that does not contains this
        # info
        #if len(objects) == 1 and objects[0].dpyList:
        #    return objects[0].dpyList
        # transparent object need to be drawn last

        # reorder object so transparent object drawn last
        transparent = []
        opaque = []
        for obj in objects:
            if obj.transparent:  #obj.isTransparent():
                transparent.append(obj)
            else:
                opaque.append(obj)
        objlist = opaque + transparent

        lNewList = GL.glGenLists(1)
        #print "lNewList geomsChooser.getDpyList", lNewList, self.name
        dpyList = (lNewList,
                   self.viewer.currentCamera.tk.call(
                       self.viewer.currentCamera._w, 'contexttag'))

        camera = self.mv.GUI.VIEWER.currentCamera
        camera.Activate()

        GL.glNewList(dpyList, GL.GL_COMPILE)
        #print "geomChooser 208", GL.glGetIntegerv(GL.GL_LIST_INDEX)
        for obj in objlist:
            if obj.immediateRendering:  # or obj.hasChildWithImmediateRendering:
                camera.drawMode = 5
                camera.Draw(obj)
            else:
                camera.drawMode = 2
                camera.drawTransparentObjects = 0
                camera.hasTransparentObjects = 0
                # draw opaque object
                for m in obj.instanceMatricesFortran:
                    GL.glPushMatrix()
                    GL.glMultMatrixf(m)
                    if len(obj.children):
                        map(camera.Draw, obj.children)
                    else:
                        camera.Draw(obj)
                    GL.glPopMatrix()

                # draw transparent children of object
                if camera.hasTransparentObjects:
                    camera.drawTransparentObjects = 1
                    for m in obj.instanceMatricesFortran:
                        GL.glPushMatrix()
                        GL.glMultMatrixf(m)
                        map(camera.Draw, obj.children)
                        GL.glPopMatrix()
                # draw transparent object that do not have children
                if obj.isTransparent() and not len(obj.children):
                    camera.drawTransparentObjects = 1
                    for m in obj.instanceMatricesFortran:
                        GL.glPushMatrix()
                        GL.glMultMatrixf(m)
                        camera.Draw(obj)
                        GL.glPopMatrix()

        GL.glEndList()
        return dpyList

    def buildForm(self):
        ifd = InputFormDescr(title=self.ftitle)
        ifd.append({
            'widgetType': ListChooser,
            'name': 'availableGeom',
            'tooltip': 'geom available in viewer',
            'wcfg': {
                'mode': 'extended',
                'lbwcfg': {
                    'exportselection': 1
                },
                'command': [(self.toggleExpansion, '<Double-Button-1>')],
                'commandEvent': None,
                'title': 'availableGeom'
            },
            'gridcfg': {
                'row': 0,
                'column': 0,
                'sticky': 'wens',
                'rowspan': 3
            }
        })

        ifd.append({
            'name': 'add',
            'widgetType': Tkinter.Button,
            'tooltip': """ Add the selected geom to selected frame""",
            'wcfg': {
                'text': '>>',
                'command': self.add_cb
            },
            'gridcfg': {
                'row': 1,
                'column': 1,
                'rowspan': 1
            }
        })

        ifd.append({
            'name': 'remove',
            'widgetType': Tkinter.Button,
            'tooltip': """ remove the selected geom to selected """,
            'wcfg': {
                'text': '<<',
                'command': self.remove_cb
            },
            'gridcfg': {
                'row': 2,
                'column': 1,
                'rowspan': 1
            }
        })

        ifd.append({
            'name': 'toload',
            'widgetType': ListChooser,
            'tooltip': """list of geom  the user chose to
                    apply to the pattern""",
            'wcfg': {
                'mode': 'extended',
                'lbwcfg': {
                    'exportselection': 0
                },
                'title': self.lc2title
            },
            'gridcfg': {
                'sticky': 'we',
                'row': 0,
                'column': 2,
                'rowspan': 3
            }
        })
        ifd.append({
            'name': 'clear',
            'widgetType': Tkinter.Button,
            'tooltip': """ Clear entry """,
            'wcfg': {
                'text': 'Clear',
                'width': 10,
                'command': self.clear_cb
            },
            'gridcfg': {
                'sticky': 'we',
                'row': 0,
                'column': 3
            }
        })
        ifd.append({
            'name': 'remove',
            'widgetType': Tkinter.Button,
            'tooltip': """ remove the selected geom to selected """,
            'wcfg': {
                'text': '<<',
                'command': self.remove_cb
            },
            'gridcfg': {
                'row': 2,
                'column': 1,
                'rowspan': 1
            }
        })
        return ifd

    def showForm(self, master, geomDic=None, func=None):
        """create formdescr for setGeoms
        geomDic = a dict of Geom 
        """
        # assign a func so we can log it in Pmv
        # func is a Pmv command
        if func:
            self.assign_func = func

        if geomDic:
            self.assignGeom[0] = geomDic

        if hasattr(self, 'form'):
            if self.guiOn:
                return
            else:
                self.update_lc2()
                self.form.deiconify()
                val = self.form.go()

                if val:
                    geomDic = self.assignGeom[0]
                    self.assign_func(geomDic)
                    self.form.withdraw()
        else:
            if not master:
                master = Tkinter.Toplevel()
                master.title('GeomChooser')
            else:
                master = master

            ifd = self.buildForm()
            self.form = InputForm(master,
                                  None,
                                  descr=ifd,
                                  scrolledFrame=0,
                                  cancelCfg={'command': self.cancel_cb})

            self.lc = self.form.descr.entryByName['availableGeom']['widget']
            self.lc2 = self.form.descr.entryByName['toload']['widget']
            self.addObject(self.viewer.rootObject, None)
            self.update_lc2()
            val = self.form.go()
            if val:
                geomDic = self.assignGeom[0]
                self.assign_func(geomDic)
                self.form.withdraw()

    def cancel_cb(self, event=None, func=None):
        """ close setup animation form without setting anything"""
        if hasattr(self, 'geomDicCopy'):
            self.patDic = self.patDicCopy.copy()

    def add_cb(self):
        lgeom = []
        geomDic = self.assignGeom[0]
        # get geom name to load
        o = map(int, self.lc.lb.curselection())
        for Ind in o:
            fullName = self.getFullName(Ind)
            obj = self.viewer.FindObjectByName(fullName)
            # strip the root
            l = string.split(fullName, '|')[1:]
            for i in range(len(l)):
                if i == 0:
                    if not geomDic.has_key(l[i]):
                        dic = geomDic[l[i]] = {}
                    else:
                        dic = geomDic[l[i]]
                else:
                    if not dic.has_key(l[i]):
                        dic[l[i]] = {}

                    dic = dic[l[i]]

        self.update_lc2()

    def insertValue(self, ind, prefix, dic):
        """ insert Value of a dictionnary in the listchooser2"""
        for key in dic.keys():
            if dic[key] == {}:
                ind = ind + 1
                self.lc2.insert(ind, prefix + key)
            else:
                ind = ind + 1
                self.lc2.insert(ind, prefix + key)
                p = prefix + '~'
                ind = self.insertValue(ind, p, dic[key])
        return ind

    def update_lc2(self):
        """ update listchooser entries display"""

        # save current entry selected
        sel = self.lc2.get()
        prefix = '~'
        self.lc2.clear()
        ind = 0
        geomDic = self.assignGeom[0]
        ind = self.insertValue(ind, prefix, geomDic)

        # select the entry save as sel
        # keep the entry selected after the update
        for i in sel:
            self.lc2.select((i, ))

    def findParentMol(self, index):
        """ find the parent value name from a geom ~~
        go up to find first value with onley ~ """
        parent = None
        for i in range(index + 1):
            parent = self.lc2.entries[index - i][0]
            if parent[0] == '~' and parent[1] != '~':
                parent = parent[1:]
                return parent
        return None

    def remove_cb(self):
        """ remove entry in litschooser (geomtoload)"""
        geomDic = self.assignGeom[0]
        selindex = self.lc2.getInd()
        for index in selindex:
            value = self.lc2.entries[index][0]

            if value[1] == '~':
                mol = self.findParentMol(index)
                rindex = geomDic[mol].index(value[2:])
                del geomDic[mol][rindex]
            else:
                mol = value[1:]
                del geomDic[mol]
        self.update_lc2()

    def clear_cb(self):
        """ clear all entry """
        self.lc2.clear()
        if self.assignGeom:
            self.assignGeom[0] = {}  # geomDic
            self.assignGeom[1] = None  # dpyList
class Player(Tkinter.Frame):
    """Widget to play sequence of frames, with GUI to specify direction and speed.
    required attributes:
        currentFrameIndex = 0
        startFrame = 0
        endFrame = 0
        maxFrame = 0
        stepSize = 1
        target = endFrame           #determines direction of play
        increment = 1               #implements decrementing vs incrementing
                                    #  in getNextFrameIndex
        playMode = 0                #playMode options:
                                    #   0   play once and stop
                                    #   1   play continuously in 1 direction
                                    #   2   play once in 2 directions
                                    #   3   play continuously in 2 directions
        framerate =15.              # number of frame per second to be display
        hasSlider = False           #adds Tkinter Scale Widget if True

    required methods:
    #play methods:
        play                           #play according to play mode
        getNextFrameIndex              #returns index of next frame to
                                        play according to current index
                                        and playMode
        nextFrame                      #actually display the nextFrame
                                        ??possibly update widgets???

    #methods to regulate play
        Play_cb                        #play according to playMode
        PlayRev_cb                     #play backwards  
        FastForward_cb()               #play foward at max speed
        FastReverse_cb()               #play reverse at max speed
        Stop_cb                        #stop current play
        ?Pause_cb                      #stop at current frame??
        ?Loop_cb                       #???????


    #methods to set Frame to a specific frame
        SetState_cb                    #counter callback for random access
        GoToStart_cb                   #set to current startFrame
        GoToEnd_cb                     #set to current endFrame
        ?setCurrentFrameIndex          #set currentframe index???


    #methods for player gui
        showGUI                        #show the gui
        buildForm2                     #opens image-based gui
        buildForm                      #opens text-based gui
        Close_cb                       #withdraws gui

    #methods for pmw counter
        custom_validate                #used by pmw to check entry
        custom_counter                 #used by pmw for counter


    #methods for changing playMode
        SetMode_cb                     #opens playModeForm
        setPlayMode_cb                 #sets playMode, sets delay,
                                          startFrame, endFrame 
                                          AND closes playModeForm
        cancelPlayMode_cb              #closes playModeForm w/out changes

        #methods for end points:
            setStartFrame()            #set startFrame
            setEndFrame()              #set endFrame
            setStepSize()              #sets increment, def=1
        additional methods:
        



    """

    def __init__(self, master=None, root=None,
                        height=80,width=200,
                        currentFrameIndex=0,
                        startFrame=0, 
                        endFrame=0,
                        maxFrame=0,
                        stepSize=1, 
                        playMode=0,
                        ##afterDelay=50,
                        titleStr='Player',
                        gotoStartfile = 'go_to_start.gif',
                        gotoEndfile = 'go_to_end.gif',
                        ff_revfile = 'ff_rev.gif',
                        ff_fwdfile = 'ff_fwd.gif',
                        stopfile = 'stop.gif',
                        playfile = 'play_fwd.gif',
                        playRevfile = 'play_rev.gif',
                        chmodfile = 'chmod.gif',
                        closefile = 'close.gif',
                        iconpath = None,
                        counter = 1,
                        form2=1,gui=1,framerate=15., hasSlider=False):

        # frame rate in fps
        self.framerate = framerate 
        self.gui = gui
        self.currentFrameIndex = currentFrameIndex
        self.startFrame = startFrame
        self.endFrame = endFrame
        self.targetFrame = self.endFrame
        self.maxFrame = maxFrame
        if not maxFrame:
            self.maxFrame = endFrame
        self.stepSize = stepSize
        #used for play once in 2 directions
        self.oneDirection = 0
        self.increment = 1
        self.target = self.endFrame
        self.hasSlider = hasSlider
        #used to coordinate switching icons
        #playMode options:
        #   0   play once and stop
        #   1   play continuously in 1 direction
        #   2   play once in 2 directions and stop
        #   3   play continuously in 2 directions
        self.playMode = playMode
        ### replace by framerate
        #amt of time to sleep
        #self.delay = delay


        #amt of time for after
        #self.afterDelay = afterDelay

        self.afterID = None
        self.stop = 1
        self.hasCounter = 0
        # gui variable
        #self.master = master
        #self.root = root
        self.form2 = form2
        self.hasCounter = counter

        if gui:
            self.showGUI(master=master,root=root,
                         titleStr=titleStr,height=height,
                         width=width,iconpath=iconpath)


    def showGUI(self,master=None,root=None,
                width=200,height=80,titleStr='player',
                gotoStartfile = 'go_to_start.gif',
                gotoEndfile = 'go_to_end.gif',
                ff_revfile = 'ff_rev.gif',
                ff_fwdfile = 'ff_fwd.gif',
                stopfile = 'stop.gif',
                playfile = 'play_fwd.gif',
                playRevfile = 'play_rev.gif',
                chmodfile = 'chmod.gif',
                closefile = 'close.gif',iconpath=None):
        """ function to display the player gui."""

        if hasattr(self, 'form'):
	    if hasattr(self.form, "deiconify"):
                self.form.deiconify()
                return   
        self.master=master
        self.root=root

        if not self.form2:
            self.form = self.buildForm(titleStr)  # pass some arguments here
            self.form2=0
        else:
            if iconpath is None:
                iconpath = ('mglutil.gui.BasicWidgets.Tk','icons')
            ICONDIR = findFilePath(iconpath[1], iconpath[0])
            #if findFilePath failed, already returned
            gotoStartfile = os.path.join(ICONDIR,gotoStartfile)
            gotoEndfile = os.path.join(ICONDIR,gotoEndfile)
            ff_revfile = os.path.join(ICONDIR,ff_revfile)
            ff_fwdfile = os.path.join(ICONDIR,ff_fwdfile)
            stopfile = os.path.join(ICONDIR,stopfile)
            playfile = os.path.join(ICONDIR,playfile)
            playRevfile = os.path.join(ICONDIR,playRevfile)
            chmodfile = os.path.join(ICONDIR,chmodfile)
            closefile = os.path.join(ICONDIR,closefile)
            
            self.gotoStartIcon = Tkinter.PhotoImage(file=gotoStartfile, master=master)
            self.gotoEndIcon = Tkinter.PhotoImage(file=gotoEndfile, master=master)
            self.ff_revIcon = Tkinter.PhotoImage(file=ff_revfile, master=master)
            self.ff_fwdIcon = Tkinter.PhotoImage(file=ff_fwdfile, master=master)
            self.stopIcon = Tkinter.PhotoImage(file=stopfile, master=master)
            self.playIcon = Tkinter.PhotoImage(file=playfile, master=master)
            self.playRevIcon = Tkinter.PhotoImage(file=playRevfile, master=master)
            self.chmodIcon = Tkinter.PhotoImage(file=chmodfile, master=master)
            self.closeIcon = Tkinter.PhotoImage(file=closefile, master=master)
            self.form = self.buildForm2(titleStr)  # pass some argument here

    #play methods:
    # play, waitTime, getNextFrameIndex, nextFrame
    def play(self, framerate,event=None):
        t1=  time.time() # previous frame time
        timestamp = 1./framerate # rate to update frame
        self.stop = 0
        ind = self.currentFrameIndex

        
        while not self.stop: #this has to be more complex
            if self.stop: 
                print 'play stopped!'
                break
            
            #do something different here if ff_fwd or ff_rev
            if self.gui:
                #self.afterID = self.master.after(self.afterDelay, self.waitTime)
                self.master.update()

            t2 = time.time()  # current time
            t = t2 -t1        # time difference between current frame and previous
    
            if (t < timestamp):
                pass
            else:
                id = self.getNextFrameIndex(self.currentFrameIndex)
                if id==None:
                    self.stop = 1
                    if self.gui:
                        self.Stop_cb()
                        break
                self.nextFrame(id) #maybe set entry then call nextFrame??
                self.currentFrameIndex = id
                t1 = t2
            
    def getNextFrameIndex(self, index):
        newFrame = index + self.increment*self.stepSize
        # check if  newFrame in current range:
        #       if incrementing, has to be <=self.endFrame
        #       if decrementing, has to be >=self.startFrame
        #   NB: incPos indicates whether currently incrementing or decrementing
        # FORCE newFrame into range 
        incPos = self.increment>0
        if incPos and newFrame>self.endFrame:
            newFrame = self.endFrame
        elif not incPos and newFrame<self.startFrame:
            newFrame = self.startFrame
        # check whether reached current targetFrame
        #       if so, action depends on current playMode 
        mode = self.playMode
        if index==self.targetFrame:
            # playModes 0 and 2 are play once and stop (in 1 or 2 directions)
            if not mode%2:
                if mode==0:
                    # None means stop
                    return None
                else:
                    # play once in 2 directions
                    #   check whether already reached halfway pt
                    if self.oneDirection:
                        return None
                    self.oneDirection = 1
                    # to reverse direction:
                    #   toggle increment
                    self.increment = -1 * self.increment
                    #   toggle targetFrame
                    if self.targetFrame==self.endFrame:
                        self.targetFrame = self.startFrame
                    else:
                        self.targetFrame = self.endFrame
                    return newFrame
            elif self.playMode==1:
                # play continuously in 1 direction
                # toggle targetFrame to the opposite end
                if self.targetFrame==self.endFrame:
                    return self.startFrame
                else:
                    return self.endFrame
            elif self.playMode==3:
                # loop continuously in 2 directions
                #   toggle increment
                self.increment = -1 * self.increment
                newFrame = self.targetFrame + self.stepSize * self.increment
                #   toggle targetFrame
                if self.targetFrame==self.endFrame:
                    self.targetFrame = self.startFrame
                else:
                    self.targetFrame = self.endFrame
                return newFrame
        return newFrame


##     def waitTime(self):
##         self.afterID = None
##         t1 = time.time()
##         delta = time.time() - t1
##         #curBut is either play or playRev button
##         hasCurBut = hasattr(self, 'curBut')
##         while delta < self.delay:
##             if hasCurBut:
##                 self.curBut.config(bg='red')
##             self.master.update()
##             time.sleep(self.delay/100)
##             delta = time.time() - t1
##         if hasCurBut:
##             self.curBut.config(bg='white')
##         if self.afterID is not None and hasCurBut:
##             self.curBut.after_cancel(self.afterID)
##             self.afterID = self.curBut.after(self.afterDelay, self.waitTime)
        

    def nextFrame(self, id):
        ##pass #must be overwritten
        id = int(id)
        if id == self.currentFrameIndex: return        
        if self.hasCounter and self.gui:
            self.form.ent2.delete(0,'end')
            self.form.ent2.insert(0, str(id))
            if self.hasSlider:
                self.form.ifd.entryByName['slider']['widget'].set(id)
        print 'playing ', id
        self.currentFrameIndex = int(id)


    #methods to call play
    #Play_cb, PlayRev_cb, FastForward_cb, FastReverse_cb
    #Stop_cb and possibly Pause_cb, Loop_cb

    def Play_cb(self, framerate=None,event=None):
        #print 'Play_cb'
        self.form.ifd.entryByName['playB']['widget'].grab_release()
        #this is a new call to Play_cb
        if framerate == None:
            framerate =self.framerate
        self.stop = 0
        self.oneDirection = 0
        self.targetFrame = self.endFrame
        self.increment = 1
        #print 'currentFrameIndex=', self.currentFrameIndex
        #possibly currently playing reverse
        if hasattr(self,'curBut') and self.curBut==self.form.playRevB:
            if self.form2:
                self.curBut.config(command=self.oldCmd,
                        image=self.oldImage,bg='white')
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
        self.oldTT = self.form.playTT
        self.oldTTtext = 'play forward according to current play mode'
        self.curBut = self.form.playB
        self.oldCmd = self.Play_cb
        self.oldImage = self.playIcon
        self.oldText = 'Play'
        if self.form2:
            self.curBut.config(command=self.Stop_cb, image=self.stopIcon)
        else:
            self.curBut.config(command=self.Stop_cb, text='Stop')
        self.oldTT.bind(self.curBut,'stop play')
        #self.master.update()
        self.play(framerate)


    def PlayRev_cb(self, framerate=None,event=None):
        #figure out current number and then play backwards
        #print 'currentFrameIndex=', self.currentFrameIndex
        self.form.ifd.entryByName['playRevB']['widget'].grab_release()
        if framerate == None:
            framerate=self.framerate
        self.increment = -1
        self.targetFrame = self.startFrame
        self.oneDirection = 0
        self.stop = 0
        #possibly currently playing 
        if hasattr(self,'curBut') and self.curBut==self.form.playB:
            if self.form2:
                self.curBut.config(command=self.oldCmd, 
                        image=self.oldImage,bg='white')
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
        self.oldTT = self.form.playRevTT
        self.oldTTtext = 'play reverse according to current play mode'
        self.curBut = self.form.playRevB
        self.oldCmd = self.PlayRev_cb
        self.oldImage = self.playRevIcon
        self.oldText = 'Play Reverse'
        if self.form2:
            self.curBut.config(command=self.Stop_cb, image=self.stopIcon)
        else:
            self.curBut.config(command=self.Stop_cb, text='Stop')
        self.oldTT.bind(self.curBut,'stop play')
        self.play(framerate)

    def FastReverse_cb(self, event=None):
        #print 'FastReverse'
        framerate = self.framerate * 2
        self.oneDirection = 0
        self.PlayRev_cb(framerate=framerate)
        

    def FastForward_cb(self, event=None):
        #print 'FastForward'
        self.oneDirection = 0
        framerate = self.framerate * 2
        self.Play_cb(framerate=framerate)
        


    def Stop_cb(self, event=None):
        self.stop = 1
        if hasattr(self, 'curBut'):
            if self.form2:
                self.curBut.config(command=self.oldCmd, image=self.oldImage)
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
                #FIX THIS!!!!
                #DECIDE if stop means reset to start or not
                self.nextFrame(self.startFrame)
            self.oldTT.bind(self.curBut,self.oldTTtext)
        #FIX THIS: does this go here?  or in nextFrame
        #clean up form
        #if self.hasCounter:
        #    self.form.ent2.delete(0,'end')
        #    self.form.ent2.insert(0, str(self.currentFrameIndex))


    #these may be superfluous: called by original form
    def PlayReturn_cb(self, event=None):
        #print 'PlayReturn_cb'
        #this should be superfluous
        self.playMode = 3
        self.Play_cb()


    def Loop_cb(self, event=None):
        #print 'Loop_cb'
        #this should be superfluous
        self.playMode = 3
        self.Play_cb()


    def Pause_cb(self, event=None):
        self.stop = 1


    #methods to set Frame to a specific frame
    #SetState_cb, GoToStart_cb, GoToEnd_cb, setCurrentFrameIndex
    def SetState_cb(self,  event=None):
        #do nothing if no counter
        if self.hasCounter:
            index = self.form.counter.get()
            self.nextFrame(index)


    def GoToStart_cb(self, event=None):
        #print 'GoToStart'
        #self.currentFrameIndex = self.startFrame
        self.oneDirection = 0
        self.nextFrame(self.startFrame)


    def GoToEnd_cb(self, event=None):
        #print 'GoToEnd'
        self.oneDirection = 0
        #self.currentFrameIndex = self.endFrame
        self.nextFrame(self.endFrame)


    def setCurrentFrameIndex(self, index):
        #print 'setting currentFrameIndex to', index
        self.currentFrameIndex = index 


    #methods for player gui
    def Close_cb(self, event=None):
        self.stop = 1
        if hasattr(self,'form'):
            self.form.withdraw()
    def SetAnim_cb(self):
        """ function to be overwritten.
        Use to call a functoin to set the animatiom frame."""

        return

    def buildForm2(self, titleStr):
        self.stop = 1
        if hasattr(self, 'form'):
            if hasattr(self.form, 'deiconify'):
                self.form.deiconify()
                return
        maxval = self.endFrame
        ifd = InputFormDescr(title=titleStr)
        ifd.append({'name': 'gotoStartB',
            'widgetType': Tkinter.Button,
            #'text':'gotoStart',
            'tooltip':'sets frame to current startFrame',
            'wcfg':{'bd':4,
                    'image':self.gotoStartIcon,
                    'width':self.gotoStartIcon.width(),
                    'height':self.gotoStartIcon.height()
            },
            'gridcfg':{'sticky':'nesw'},
            'command':self.GoToStart_cb})
        ifd.append({'name': 'fastReverseB',
            'widgetType': Tkinter.Button,
            #'text':'fastReverse',
            'tooltip':'play reverse as fast as possible',
            'wcfg':{'bd':4,
                    'image':self.ff_revIcon,
                    'width':self.ff_revIcon.width(),
                    'height':self.ff_revIcon.height()
            },
            'gridcfg':{'sticky':'nesw', 'row':-1, 'column':1},
            'command':self.FastReverse_cb})
        ifd.append({'name': 'playRevB',
            'widgetType': Tkinter.Button,
            #'text':'Play Reverse',
            'tooltip':'play reverse according to current play mode',
            'wcfg':{'bd':4,
                    'image':self.playRevIcon,
                    'width':self.playRevIcon.width(),
                    'height':self.playRevIcon.height()},
            'gridcfg':{'sticky':'nesw','row':-1, 'column':2},
            'command':self.PlayRev_cb})
        if self.hasCounter:
            ifd.append({'widgetType':Pmw.Counter,
                    'name':'statesCounter',
                    'required':1,
                    'tooltip':'used to show frames via random access',
                    'wcfg':{#'labelpos': 'n,
                         #'label_text':'conformation:  ',
                        'autorepeat':0,
                        'entryfield_value':self.startFrame,
                        #'entryfield_value':self.idList[0],
                        'datatype': self.custom_counter,
                        'entry_width':3,
                        'entryfield_validate': self.custom_validate },
                     'gridcfg':{'sticky':'nesw', 'row':-1, 'column':3,'columnspan':2}})
        ifd.append({'name': 'playB',
            'widgetType': Tkinter.Button,
            #'text':'Play',
            'tooltip':'play forward according to current play mode',
            'wcfg':{'bd':4,
                    'image':self.playIcon,
                    'width':self.playIcon.width(),
                    'height':self.playIcon.height()
            },
            'gridcfg':{'sticky':'nesw', 'row':-1, 'column':5},
            'command':self.Play_cb})
        ifd.append({'name': 'fastForwardB',
            'widgetType': Tkinter.Button,
            #'text':'fastForward',
            'tooltip':'play as fast as possible',
            'wcfg':{'bd':4,
                    'image': self.ff_fwdIcon,
                    'width':self.ff_fwdIcon.width(),
                    'height':self.ff_fwdIcon.height()
                    },
            'gridcfg':{'sticky':'nesw','row':-1, 'column':6},
            'command':self.FastForward_cb})
        ifd.append({'name': 'gotoEndB',
            'widgetType': Tkinter.Button,
            #'text':'gotoEnd',
            'tooltip':'sets frame to current endFrame',
            'wcfg':{'bd':4,
                    'image':self.gotoEndIcon,
                    'width':self.gotoEndIcon.width(),
                    'height':self.gotoEndIcon.height()
            },
            'gridcfg':{'sticky':'nesw','row':-1, 'column':7},
            'command':self.GoToEnd_cb})
        ifd.append({'name': 'modeB',
            'widgetType': Tkinter.Button,
            'text':'Change Mode',
            'tooltip':'opens panel to change play options',
            'wcfg':{'bd':4,
                    'image':self.chmodIcon,
                    'width':self.chmodIcon.width(),
                    'height':self.chmodIcon.height()
                    },
            'gridcfg':{'sticky':'nesw','row':-1, 'column':8},
            'command':self.SetMode_cb})

        ifd.append({'name': 'setanimB',
            'widgetType': Tkinter.Button,
            'text':'SetAnim',
            'tooltip':'Set Animation',
            'wcfg':{'bd':4},
            'gridcfg':{'sticky':'nesw','row':-1, 'column':9},
            'command':self.SetAnim_cb})
        
        ifd.append({'name': 'closeB',
            'widgetType': Tkinter.Button,
            'text':'Close',
            'tooltip':'closes player',
            'wcfg':{'bd':4,
                    'image':self.closeIcon,
                    'width':self.closeIcon.width(),
                    'height':self.closeIcon.height(),
                    },
            'gridcfg':{'sticky':'nesw','row':-1, 'column':10},
            #'gridcfg':{'sticky':'nesw', 'columnspan':2},
            'command':self.Close_cb})
        if self.hasSlider:
            ifd.append({'name': 'slider',
                'widgetType': Tkinter.Scale,
                'wcfg':{'orient':'horizontal',
                        'from_':self.startFrame,
                        'to':self.maxFrame,
                        'showvalue':False},
                'gridcfg':{'sticky':'nesw','row':1, 'column':0, 'columnspan':11},
                'command':self.nextFrame
                })        
        #form = self.vf.getUserInput(ifd, modal=0,blocking=0)
        form = InputForm(self.master, self.root,
                         descr = ifd,
                         modal = 0, blocking = 0,
                         closeWithWindow=1)
        form.ifd = ifd
        form.playB = form.ifd.entryByName['playB']['widget']
        form.playRevB = form.ifd.entryByName['playRevB']['widget']
        #set up link to balloon help which needs to change, also
        form.playTT = form.ifd.entryByName['playB']['balloon']
        form.playRevTT = form.ifd.entryByName['playRevB']['balloon']
        if self.hasCounter:
            ctr = ifd.entryByName['statesCounter']['widget']
            entF = ctr.component('entryfield')
            form.ent2 = entF._entryFieldEntry
            da = ctr.component('downarrow')
            ua = ctr.component('uparrow')
            for item in [da,ua]:
                item.bind('<ButtonPress-1>', self.SetState_cb, '+')
            form.ent2.bind('<Return>', self.SetState_cb, '+')
            form.counter = form.ifd.entryByName['statesCounter']['widget']
        #print 'returning form'
        return form


    def buildForm(self, titleStr):
        #??FIX THIS:
        self.stop = 1
        if hasattr(self, 'form'):
            self.form.deiconify()
            return
        maxval = self.endFrame
        ifd = InputFormDescr(title=titleStr)
        if self.hasCounter:
            ifd.append({'widgetType':Pmw.Counter,
                    'name':'statesCounter',
                    'required':1,
                    'tooltip':'used to show frames via random access',
                    'wcfg':{#'labelpos': 'n,
                         #'label_text':'conformation:  ',
                        'autorepeat':0,
                        'entryfield_value':self.startFrame,
                        #'entryfield_value':self.idList[0],
                        'datatype': self.custom_counter,
                        'entry_width':9,
                        'entryfield_validate': self.custom_validate },
                     'gridcfg':{'sticky':'nesw', 'columnspan':2}})
        ifd.append({'name': 'playB',
            'widgetType': Tkinter.Button,
            'text':'Play',
            'tooltip':'play sequence according to current play mode',
            'wcfg':{'bd':4},
            'gridcfg':{'sticky':'nesw','columnspan':1},
            'command':self.Play_cb})
        ifd.append({'name': 'playRevB',
            'widgetType': Tkinter.Button,
            'text':'Play Reverse',
            'wcfg':{'bd':4},
            'gridcfg':{'sticky':'nesw','row':-1, 'column':1},
            'command':self.PlayRev_cb})
        ifd.append({'name': 'playTB',
            'widgetType': Tkinter.Button,
            'text':'Play+Return',
            'wcfg':{'bd':4},
            'gridcfg':{'sticky':'nesw','columnspan':1},
            'command':self.PlayReturn_cb})
        ifd.append({'name': 'loopB',
            'widgetType': Tkinter.Button,
            'text':'Loop',
            'wcfg':{'bd':4},
            'gridcfg':{'sticky':'nesw','row':-1, 'column':1},
            'command':self.Loop_cb})
        ifd.append({'name': 'stopB',
            'widgetType': Tkinter.Button,
            'text':'Stop',
            'tooltip':'stop play',
            'wcfg':{'bd':4,
                    },
            'gridcfg':{'sticky':'nesw'},
            'command':self.Stop_cb})
        #add fastforward, fastrewind, thumbwheel for speed
        ifd.append({'name': 'pauseB',
            'widgetType': Tkinter.Button,
            'text':'Pause',
            'wcfg':{'bd':4},
            'gridcfg':{'sticky':'nesw','row':-1, 'column':1},
            'command':self.Pause_cb})

        ifd.append({'name': 'closeB',
            'widgetType': Tkinter.Button,
            'text':'Close',
            'wcfg':{'bd':4},
            #'gridcfg':{'sticky':'nesw','row':-1, 'column':1},
            'gridcfg':{'sticky':'nesw', 'columnspan':2},
            'command':self.Close_cb})
        form = InputForm(self.master, self.root,
                         descr = ifd, modal = 0,
                         blocking = 0,closeWithWindow=1)
        form.ifd = ifd
        if self.hasCounter:
            ctr = ifd.entryByName['statesCounter']['widget']
            entF = ctr.component('entryfield')
            form.ent2 = entF._entryFieldEntry
            da = ctr.component('downarrow')
            ua = ctr.component('uparrow')
            for item in [da,ua]:
                item.bind('<ButtonPress-1>', self.SetState_cb, '+')
            form.ent2.bind('<Return>', self.SetState_cb, '+')
            form.counter = form.ifd.entryByName['statesCounter']['widget']
        form.stopB = form.ifd.entryByName['stopB']['widget']
        form.playB = form.ifd.entryByName['playB']['widget']
        form.playRevB = form.ifd.entryByName['playRevB']['widget']
        #print 'returning form1'
        self.form = form
        return form


    #methods for changing playMode
    def SetMode_cb(self, event=None):
        #print 'SetMode'
        #playMode options:
        #   0   play once and stop
        #   1   play continuously in 1 direction
        #   2   play once in 2 directions
        #   3   play continuously in 2 directions
        #play framerate is frame/per second
        if not hasattr(self, 'playModeForm'):
            self.playModeList=[ 'once and stop', 
                                'continuously in 1 direction',
                                'once in 2 directions', 
                                'continuously in 2 directions']
            ifd2 = InputFormDescr(title='Set Play Mode')    
            ifd2.append( {'name': 'playModeLabel',
                    'widgetType':Tkinter.Label,
                    'wcfg':{'text':'play mode options:', 
                        'font':(ensureFontCase('helvetica'),12,'bold')},
                    'gridcfg':{'sticky':'w'}})
            ifd2.append({'name':'playMode',
                        'widgetType': Tkinter.Radiobutton,
                        'defaultValue': self.playModeList[self.playMode],
                        'listtext':self.playModeList,
                        'gridcfg':{'sticky':'w'}})
            ifd2.append( {'name': 'framerateLabel',
                    'widgetType':Tkinter.Label,
                    'wcfg':{'text':'framerate:',
                        'font':(ensureFontCase('helvetica'),12,'bold')},
                    'gridcfg':{'sticky':'w'}})
            ifd2.append({'name': 'framerateTW',
                    'wtype':ThumbWheel,
                    'widgetType':ThumbWheel,
                    'wcfg':{
                        'labcfg':{
                            'fg':'black',
                            'side':'left',
                            'text':'       '
                            },
                        'showLabel':1, 'width':100,
                        'min':0,
                        'max':100,
                        'lockBMin':1,
                        'lockBMax':0,
                        'lockBIncrement':1,
                        'value':self.framerate,
                        'oneTurn':100,
                        'type':'float',
                        'increment':.1,
                        'canvascfg':{'bg':'red'},
                        'wheelLabcfg1':{'font':(ensureFontCase('times'),14,'bold')},
                        'wheelLabcfg2':{'font':(ensureFontCase('times'),14,'bold')},
                        'continuous':1, 'wheelPad':1, 'height':20},
                    'gridcfg':{'sticky':'nesw'}})

            ifd2.append( {'name': 'startFrameLabel',
                    'widgetType':Tkinter.Label,
                    'wcfg':{'text':'start frame:',
                        'font':(ensureFontCase('helvetica'),12,'bold')},
                    'gridcfg':{'sticky':'w'}})
            ifd2.append({'name': 'startFrameTW',
                    'wtype':ThumbWheel,
                    'widgetType':ThumbWheel,
                    'wcfg':{
                        'labcfg':{
                            'fg':'black',
                            'side':'left',
                            'text':'       '
                            },
                        'showLabel':1, 'width':100,
                        'min':0,
                        'max':self.endFrame,
                        'lockBMin':0,
                        'lockBMax':1,
                        'lockBIncrement':1,
                        'value':self.startFrame,
                        'oneTurn':10,
                        'type':'int',
                        'increment':1,
                        'canvascfg':{'bg':'green'},
                        'wheelLabcfg1':{'font':(ensureFontCase('times'),14,'bold')},
                        'wheelLabcfg2':{'font':(ensureFontCase('times'),14,'bold')},
                        'continuous':1, 'wheelPad':1, 'height':20},
                    'gridcfg':{'sticky':'nesw'}})
            ifd2.append( {'name': 'endFrameLabel',
                    'widgetType':Tkinter.Label,
                    'wcfg':{'text':'end frame:',
                        'font':(ensureFontCase('helvetica'),12,'bold')},
                    'gridcfg':{'sticky':'w'}})
            ifd2.append({'name': 'endFrameTW',
                    'wtype':ThumbWheel,
                    'widgetType':ThumbWheel,
                    'wcfg':{
                        'labcfg':{
                            'fg':'black',
                            'side':'left',
                            'text':'       '
                            },
                        'showLabel':1, 'width':100,
                        'min':self.startFrame,
                        'max':self.maxFrame,
                        'lockBMin':1,
                        'lockBMax':0,
                        'lockBIncrement':1,
                        'value':self.endFrame,
                        'oneTurn':10,
                        'type':'int',
                        'increment':1,
                        'canvascfg':{'bg':'green'},
                        'wheelLabcfg1':{'font':(ensureFontCase('times'),14,'bold')},
                        'wheelLabcfg2':{'font':(ensureFontCase('times'),14,'bold')},
                        'continuous':1, 'wheelPad':1, 'height':20},
                    'gridcfg':{'sticky':'nesw'}})
            ifd2.append( {'name': 'stepSizeLabel',
                    'widgetType':Tkinter.Label,
                    'wcfg':{'text':'step size:',
                        'font':(ensureFontCase('helvetica'),12,'bold')},
                    'gridcfg':{'sticky':'w'}})
            ifd2.append({'name': 'stepSizeTW',
                    'wtype':ThumbWheel,
                    'widgetType':ThumbWheel,
                    'wcfg':{
                        'labcfg':{
                            'fg':'black',
                            'side':'left',
                            'text':'       '
                            },
                        'showLabel':1, 'width':100,
                        'min':1,
                        'max':1000,
                        'lockBMin':1,
                        'lockBMax':0,
                        'lockBIncrement':1,
                        'value':self.stepSize,
                        'oneTurn':10,
                        'type':'int',
                        'increment':1,
                        'canvascfg':{'bg':'blue'},
                        'wheelLabcfg1':{'font':(ensureFontCase('times'),14,'bold')},
                        'wheelLabcfg2':{'font':(ensureFontCase('times'),14,'bold')},
                        'continuous':1, 'wheelPad':1, 'height':20},
                    'gridcfg':{'sticky':'nesw'}})
            ifd2.append({'name':'acceptB',
                        'widgetType': Tkinter.Button,
                        'wcfg':{
                            'text': 'ok',
                            'command': self.setPlayMode_cb,
                        },
                        'gridcfg':{'sticky':'nesw'}})
            ifd2.append({'name':'cancelB',
                        'widgetType': Tkinter.Button,
                        'wcfg':{
                            'text': 'cancel',
                            'command': self.cancelPlayMode_cb,
                        },
                        'gridcfg':{'sticky':'nesw', 'row':-1, 'column':1}})
            self.playModeForm = InputForm(self.master, self.root,
                        descr = ifd2,
                        modal = 0, blocking = 0)
            self.playModeVar = self.playModeForm.descr.entryByName['playMode']['variable']
            self.framerateWidget = self.playModeForm.descr.entryByName['framerateTW']['widget']
            self.startFrameWidget = self.playModeForm.descr.entryByName['startFrameTW']['widget']
            self.endFrameWidget = self.playModeForm.descr.entryByName['endFrameTW']['widget']
            self.stepSizeWidget = self.playModeForm.descr.entryByName['stepSizeTW']['widget']
        else:
            self.playModeForm.deiconify()
        

    def setPlayMode_cb(self, event=None):
        curVal = self.playModeVar.get()
        self.playMode = self.playModeList.index(curVal)
        #print 'setting playMode to ', curVal
        self.framerate = round(self.framerateWidget.get(),4)
        #print 'setting self.framerate ->', self.framerate
        self.timestamp= 1./self.framerate

        self.startFrame = self.startFrameWidget.get()
        self.endFrame = self.endFrameWidget.get()
        self.stepSize = self.stepSizeWidget.get()
        self.cancelPlayMode_cb()
        self.oneDirection = 0
        

    def cancelPlayMode_cb(self, event=None):
        self.playModeForm.withdraw()


    #methods for counter
    def custom_validate(self, text):
        #print 'in custom_validate, text=', text, ':', text in self.idList
        if not len(text):
            
            return -1
        tt = int(text)
        okList = range(self.startFrame, self.endFrame+1)
        if tt in okList:
            return 1
        else:
            return -1


    def custom_counter(self, text, factor, increment, **kw):
        # text is current content of entry
        # factor is 1 for increment and -1 for decrement
        # increment is value of increment megawidget option
        ###if not text in self.idList:
            ###raise ValueError, text + ' not in current idList'
        #check whether ind+factor is in range
        newval = self.currentFrameIndex + factor
        #print 'newval=', newval
        if newval<0 or newval>self.endFrame:
            #print 'returning ', text
            return text
        else:
            #print 'returning ', self.idList[newval]
            return newval
示例#6
0
class Player(Tkinter.Frame):
    """Widget to play sequence of frames.
    The GUI allows to specify direction and speed of playback.

    the nextFrame(number) methoid should be overridden and define how
    this player plays the animation
    
    the root constructor argument can be a Tkinter container in which to
    embde the control panel.
    
    required attributes:
        currentFrameIndex = 0
        startFrame = 0
        endFrame = 0
        maxFrame = 0
        stepSize = 1
        target = endFrame           #determines direction of play
        increment = 1               #implements decrementing vs incrementing
                                    #  in getNextFrameIndex
        playMode = 0                #playMode options:
                                    #   0   play once and stop
                                    #   1   play continuously in 1 direction
                                    #   2   play once in 2 directions
                                    #   3   play continuously in 2 directions
        framerate =15.              # number of frame per second to be display
        hasSlider = False           #adds Tkinter Scale Widget if True

    customization attributes:
        buttonMask is a dictionary that provides a button name as a key and
        a boolean as a value. For each button in the GUI if the name appears
        in self.buttonMask and the value is False the button willnot be
        addded. This only works when form2 is true. slider and counter
        are handle by the hasSlider and coutner keyword arguments

    required methods:
    #play methods:
        play                           #play according to play mode
        getNextFrameIndex              #returns index of next frame to
                                        play according to current index
                                        and playMode
        nextFrame                      #actually display the nextFrame
                                        ??possibly update widgets???

    #methods to regulate play
        Play_cb                        #play according to playMode
        PlayRev_cb                     #play backwards  
        FastForward_cb()               #play foward at max speed
        FastReverse_cb()               #play reverse at max speed
        Stop_cb                        #stop current play
        ?Pause_cb                      #stop at current frame??
        ?Loop_cb                       #???????


    #methods to set Frame to a specific frame
        SetState_cb                    #counter callback for random access
        GoToStart_cb                   #set to current startFrame
        GoToEnd_cb                     #set to current endFrame
        ?setCurrentFrameIndex          #set currentframe index???


    #methods for player gui
        showGUI                        #show the gui
        buildForm2                     #opens image-based gui
        buildForm                      #opens text-based gui
        Close_cb                       #withdraws gui

    #methods for pmw counter
        custom_validate                #used by pmw to check entry
        custom_counter                 #used by pmw for counter


    #methods for changing playMode
        SetMode_cb                     #opens playModeForm
        setPlayMode_cb                 #sets playMode, sets delay,
                                          startFrame, endFrame 
                                          AND closes playModeForm
        cancelPlayMode_cb              #closes playModeForm w/out changes

        #methods for end points:
            setStartFrame()            #set startFrame
            setEndFrame()              #set endFrame
            setStepSize()              #sets increment, def=1
        additional methods:
    """
    def __init__(
            self,
            master=None,
            root=None,
            height=80,
            width=200,
            currentFrameIndex=0,
            startFrame=0,
            endFrame=0,
            maxFrame=0,
            stepSize=1,
            playMode=0,
            ##afterDelay=50,
            titleStr='Player',
            gotoStartfile='go_to_start.gif',
            gotoEndfile='go_to_end.gif',
            ff_revfile='ff_rev.gif',
            ff_fwdfile='ff_fwd.gif',
            stopfile='stop.gif',
            playfile='play_fwd.gif',
            playRevfile='play_rev.gif',
            chmodfile='chmod.gif',
            closefile='close.gif',
            iconpath=None,
            counter=1,
            form2=1,
            gui=1,
            framerate=15.,
            hasSlider=False,
            buttonMask=None):

        # frame rate in fps
        self.framerate = framerate
        self.gui = gui
        self.currentFrameIndex = currentFrameIndex
        self.startFrame = startFrame
        self.endFrame = endFrame
        self.targetFrame = self.endFrame
        self.maxFrame = maxFrame
        if not maxFrame:
            self.maxFrame = endFrame
        self.stepSize = stepSize
        #used for play once in 2 directions
        self.oneDirection = 0
        self.increment = 1
        self.target = self.endFrame
        self.hasSlider = hasSlider
        #used to coordinate switching icons
        #playMode options:
        #   0   play once and stop
        #   1   play continuously in 1 direction
        #   2   play once in 2 directions and stop
        #   3   play continuously in 2 directions
        self.playMode = playMode
        ### replace by framerate
        #amt of time to sleep
        #self.delay = delay

        #amt of time for after
        #self.afterDelay = afterDelay

        self.afterID = None
        self.stop = 1
        self.hasCounter = 0
        # gui variable
        #self.master = master
        #self.root = root
        self.form2 = form2
        self.hasCounter = counter

        if buttonMask is None:
            self.buttonMask = {}
            # self.buttonMask provides a button name as a key and a boolean
            # as a value. For each button in the GUI if the name appears in
            # self.buttonMask and the value is False the button willnot be
            # addded
        else:
            self.buttonMask = buttonMask

        if gui:
            self.showGUI(master=master,
                         root=root,
                         titleStr=titleStr,
                         height=height,
                         width=width,
                         iconpath=iconpath)

        # make sure we have a master as we will call master.update in play()
        if hasattr(master, 'update'):
            self.masterForUpdate = self.master
        else:
            self.masterForUpdate = self.root

    def showGUI(self,
                master=None,
                root=None,
                width=200,
                height=80,
                titleStr='player',
                gotoStartfile='go_to_start.gif',
                gotoEndfile='go_to_end.gif',
                ff_revfile='ff_rev.gif',
                ff_fwdfile='ff_fwd.gif',
                stopfile='stop.gif',
                playfile='play_fwd.gif',
                playRevfile='play_rev.gif',
                chmodfile='chmod.gif',
                closefile='close.gif',
                iconpath=None):
        """ function to display the player gui."""

        if hasattr(self, 'form'):
            if hasattr(self.form, "deiconify"):
                self.form.deiconify()
                return
        self.master = master
        self.root = root

        if not self.form2:
            self.form = self.buildForm(titleStr)  # pass some arguments here
            self.form2 = 0
        else:
            if iconpath is None:
                iconpath = ('mglutil.gui.BasicWidgets.Tk', 'icons')
            ICONDIR = findFilePath(iconpath[1], iconpath[0])
            #if findFilePath failed, already returned
            gotoStartfile = os.path.join(ICONDIR, gotoStartfile)
            gotoEndfile = os.path.join(ICONDIR, gotoEndfile)
            ff_revfile = os.path.join(ICONDIR, ff_revfile)
            ff_fwdfile = os.path.join(ICONDIR, ff_fwdfile)
            stopfile = os.path.join(ICONDIR, stopfile)
            playfile = os.path.join(ICONDIR, playfile)
            playRevfile = os.path.join(ICONDIR, playRevfile)
            chmodfile = os.path.join(ICONDIR, chmodfile)
            closefile = os.path.join(ICONDIR, closefile)
            recordfile = os.path.join(ICONDIR, "record.gif")
            record1file = os.path.join(ICONDIR, "record1.gif")

            self.gotoStartIcon = Tkinter.PhotoImage(file=gotoStartfile,
                                                    master=master)
            self.gotoEndIcon = Tkinter.PhotoImage(file=gotoEndfile,
                                                  master=master)
            self.ff_revIcon = Tkinter.PhotoImage(file=ff_revfile,
                                                 master=master)
            self.ff_fwdIcon = Tkinter.PhotoImage(file=ff_fwdfile,
                                                 master=master)
            self.stopIcon = Tkinter.PhotoImage(file=stopfile, master=master)
            self.playIcon = Tkinter.PhotoImage(file=playfile, master=master)
            self.playRevIcon = Tkinter.PhotoImage(file=playRevfile,
                                                  master=master)
            self.recIcon = Tkinter.PhotoImage(file=recordfile, master=master)
            self.rec1Icon = Tkinter.PhotoImage(file=record1file, master=master)
            self.chmodIcon = Tkinter.PhotoImage(file=chmodfile, master=master)
            self.closeIcon = Tkinter.PhotoImage(file=closefile, master=master)
            self.form = self.buildForm2(titleStr)  # pass some argument here

    #play methods:
    # play, waitTime, getNextFrameIndex, nextFrame
    def play(self, framerate, event=None):
        t1 = time.time()  # previous frame time
        timestamp = 1. / framerate  # rate to update frame
        self.stop = 0
        ind = self.currentFrameIndex

        # if player at the end we resume from begining
        if ind >= self.endFrame:
            self.GoToStart_cb()

        while not self.stop:  #this has to be more complex
            if self.stop:
                print 'play stopped!'
                break

            #do something different here if ff_fwd or ff_rev
            if self.gui:
                #self.afterID = self.master.after(self.afterDelay, self.waitTime)
                self.masterForUpdate.update()

            t2 = time.time()  # current time
            t = t2 - t1  # time difference between current frame and previous

            if framerate > -1 and t < timestamp:
                pass
            else:
                id = self.getNextFrameIndex(self.currentFrameIndex)
                if id == None:
                    self.stop = 1
                    if self.gui:
                        self.Stop_cb()
                        break
                self.nextFrame(id)  #maybe set entry then call nextFrame??
                self.currentFrameIndex = id
                t1 = t2

    def getNextFrameIndex(self, index):
        newFrame = index + self.increment * self.stepSize
        # check if  newFrame in current range:
        #       if incrementing, has to be <=self.endFrame
        #       if decrementing, has to be >=self.startFrame
        #   NB: incPos indicates whether currently incrementing or decrementing
        # FORCE newFrame into range
        incPos = self.increment > 0
        if incPos and newFrame > self.endFrame:
            newFrame = self.endFrame
        elif not incPos and newFrame < self.startFrame:
            newFrame = self.startFrame
        # check whether reached current targetFrame
        #       if so, action depends on current playMode
        mode = self.playMode
        if index == self.targetFrame:
            # playModes 0 and 2 are play once and stop (in 1 or 2 directions)
            if not mode % 2:
                if mode == 0:
                    # None means stop
                    return None
                else:
                    # play once in 2 directions
                    #   check whether already reached halfway pt
                    if self.oneDirection:
                        return None
                    self.oneDirection = 1
                    # to reverse direction:
                    #   toggle increment
                    self.increment = -1 * self.increment
                    #   toggle targetFrame
                    if self.targetFrame == self.endFrame:
                        self.targetFrame = self.startFrame
                    else:
                        self.targetFrame = self.endFrame
                    return newFrame
            elif self.playMode == 1:
                # play continuously in 1 direction
                # toggle targetFrame to the opposite end
                if self.targetFrame == self.endFrame:
                    return self.startFrame
                else:
                    return self.endFrame
            elif self.playMode == 3:
                # loop continuously in 2 directions
                #   toggle increment
                self.increment = -1 * self.increment
                newFrame = self.targetFrame + self.stepSize * self.increment
                #   toggle targetFrame
                if self.targetFrame == self.endFrame:
                    self.targetFrame = self.startFrame
                else:
                    self.targetFrame = self.endFrame
                return newFrame
        return newFrame


##     def waitTime(self):
##         self.afterID = None
##         t1 = time.time()
##         delta = time.time() - t1
##         #curBut is either play or playRev button
##         hasCurBut = hasattr(self, 'curBut')
##         while delta < self.delay:
##             if hasCurBut:
##                 self.curBut.config(bg='red')
##             self.master.update()
##             time.sleep(self.delay/100)
##             delta = time.time() - t1
##         if hasCurBut:
##             self.curBut.config(bg='white')
##         if self.afterID is not None and hasCurBut:
##             self.curBut.after_cancel(self.afterID)
##             self.afterID = self.curBut.after(self.afterDelay, self.waitTime)

    def nextFrame(self, id):
        ##pass #must be overriden
        id = int(id)
        if id == self.currentFrameIndex: return
        if self.hasCounter and self.gui:
            self.form.ent2.delete(0, 'end')
            self.form.ent2.insert(0, str(id))
            if self.hasSlider:
                self.form.ifd.entryByName['slider']['widget'].set(id)
        print 'playing ', id
        self.currentFrameIndex = int(id)

    #methods to call play
    #Play_cb, PlayRev_cb, FastForward_cb, FastReverse_cb
    #Stop_cb and possibly Pause_cb, Loop_cb
    def startRecording_cb(self, event=None):
        pass

    def stopRecording_cb(self, event=None):
        pass

    def Play_cb(self, framerate=None, event=None):
        #print 'Play_cb'
        self.form.ifd.entryByName['playB']['widget'].grab_release()
        #this is a new call to Play_cb
        if framerate == None:
            framerate = self.framerate
        self.stop = 0
        self.oneDirection = 0
        self.targetFrame = self.endFrame
        self.increment = 1
        #print 'currentFrameIndex=', self.currentFrameIndex
        #possibly currently playing reverse
        if hasattr(self, 'curBut') and self.curBut == self.form.playRevB:
            if self.form2:
                self.curBut.config(command=self.oldCmd,
                                   image=self.oldImage,
                                   bg='white')
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
        self.oldTT = self.form.playTT
        self.oldTTtext = 'play forward according to current play mode'
        self.curBut = self.form.playB
        self.oldCmd = self.Play_cb
        self.oldImage = self.playIcon
        self.oldText = 'Play'
        if self.form2:
            self.curBut.config(command=self.Stop_cb, image=self.stopIcon)
        else:
            self.curBut.config(command=self.Stop_cb, text='Stop')
        self.oldTT.bind(self.curBut, 'stop play')
        #self.master.update()
        self.play(framerate)
        self.stopRecording_cb()

    def PlayRev_cb(self, framerate=None, event=None):
        #figure out current number and then play backwards
        #print 'currentFrameIndex=', self.currentFrameIndex
        self.form.ifd.entryByName['playRevB']['widget'].grab_release()
        if framerate == None:
            framerate = self.framerate
        self.increment = -1
        self.targetFrame = self.startFrame
        self.oneDirection = 0
        self.stop = 0
        #possibly currently playing
        if hasattr(self, 'curBut') and self.curBut == self.form.playB:
            if self.form2:
                self.curBut.config(command=self.oldCmd,
                                   image=self.oldImage,
                                   bg='white')
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
        self.oldTT = self.form.playRevTT
        self.oldTTtext = 'play reverse according to current play mode'
        self.curBut = self.form.playRevB
        self.oldCmd = self.PlayRev_cb
        self.oldImage = self.playRevIcon
        self.oldText = 'Play Reverse'
        if self.form2:
            self.curBut.config(command=self.Stop_cb, image=self.stopIcon)
        else:
            self.curBut.config(command=self.Stop_cb, text='Stop')
        self.oldTT.bind(self.curBut, 'stop play')
        self.play(framerate)

    def FastReverse_cb(self, event=None):
        #print 'FastReverse'
        #framerate = self.framerate * 2
        self.oneDirection = 0
        self.PlayRev_cb(framerate=-1)  #framerate)

    def FastForward_cb(self, event=None):
        #print 'FastForward'
        self.oneDirection = 0
        #framerate = self.framerate * 2
        self.Play_cb(framerate=-1)

    def Stop_cb(self, event=None):
        self.stop = 1
        if hasattr(self, 'curBut'):
            if self.form2:
                self.curBut.config(command=self.oldCmd, image=self.oldImage)
            else:
                self.curBut.config(command=self.oldCmd, text=self.oldText)
                #FIX THIS!!!!
                #DECIDE if stop means reset to start or not
                #self.nextFrame(self.startFrame)
            self.oldTT.bind(self.curBut, self.oldTTtext)

        self.stopRecording_cb()

        #FIX THIS: does this go here?  or in nextFrame
        #clean up form
        #if self.hasCounter:
        #    self.form.ent2.delete(0,'end')
        #    self.form.ent2.insert(0, str(self.currentFrameIndex))

    #these may be superfluous: called by original form
    def PlayReturn_cb(self, event=None):
        #print 'PlayReturn_cb'
        #this should be superfluous
        self.playMode = 3
        self.Play_cb()

    def Loop_cb(self, event=None):
        #print 'Loop_cb'
        #this should be superfluous
        self.playMode = 3
        self.Play_cb()

    def Pause_cb(self, event=None):
        self.stop = 1

    #methods to set Frame to a specific frame
    #SetState_cb, GoToStart_cb, GoToEnd_cb, setCurrentFrameIndex
    def SetState_cb(self, event=None):
        #do nothing if no counter
        if self.hasCounter:
            index = self.form.counter.get()
            self.nextFrame(index)

    def GoToStart_cb(self, event=None):
        #print "GoToStart_cb", self.startFrame, self.currentFrameIndex
        #self.currentFrameIndex = self.startFrame
        self.oneDirection = 0
        self.nextFrame(self.startFrame)

    def GoToEnd_cb(self, event=None):
        #print 'GoToEnd'
        self.oneDirection = 0
        #self.currentFrameIndex = self.endFrame
        self.nextFrame(self.endFrame)

    def setCurrentFrameIndex(self, index):
        #print 'setting currentFrameIndex to', index
        self.currentFrameIndex = index

    #methods for player gui
    def Close_cb(self, event=None):
        self.stop = 1
        if hasattr(self, 'form'):
            self.form.withdraw()

    def SetAnim_cb(self):
        """ function to be overwritten.
        Use to call a functoin to set the animatiom frame."""

        return

    def buildForm2(self, titleStr):
        self.stop = 1
        if hasattr(self, 'form'):
            if hasattr(self.form, 'deiconify'):
                self.form.deiconify()
                return
        maxval = self.endFrame
        ifd = InputFormDescr(title=titleStr)

        if self.buttonMask.get('gotoStartB', None) is not False:
            ifd.append({
                'name': 'gotoStartB',
                'widgetType': Tkinter.Button,
                #'text':'gotoStart',
                'tooltip': 'sets frame to current startFrame',
                'wcfg': {
                    'bd': 4,
                    'image': self.gotoStartIcon,
                    'width': self.gotoStartIcon.width(),
                    'height': self.gotoStartIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw'
                },
                'command': self.GoToStart_cb
            })

        if self.buttonMask.get('fastReverseB', None) is not False:
            ifd.append({
                'name': 'fastReverseB',
                'widgetType': Tkinter.Button,
                #'text':'fastReverse',
                'tooltip': 'play reverse as fast as possible',
                'wcfg': {
                    'bd': 4,
                    'image': self.ff_revIcon,
                    'width': self.ff_revIcon.width(),
                    'height': self.ff_revIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 1
                },
                'command': self.FastReverse_cb
            })

        if self.buttonMask.get('playRevB', None) is not False:
            ifd.append({
                'name': 'playRevB',
                'widgetType': Tkinter.Button,
                #'text':'Play Reverse',
                'tooltip': 'play reverse according to current play mode',
                'wcfg': {
                    'bd': 4,
                    'image': self.playRevIcon,
                    'width': self.playRevIcon.width(),
                    'height': self.playRevIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 2
                },
                'command': self.PlayRev_cb
            })

            if self.hasCounter:
                ifd.append({
                    'widgetType': Pmw.Counter,
                    'name': 'statesCounter',
                    'required': 1,
                    'tooltip': 'used to show frames via random access',
                    'wcfg': {  #'labelpos': 'n,
                        #'label_text':'conformation:  ',
                        'autorepeat': 0,
                        'entryfield_value': self.startFrame,
                        #'entryfield_value':self.idList[0],
                        'datatype': self.custom_counter,
                        'entry_width': 3,
                        'entryfield_validate': self.custom_validate
                    },
                    'gridcfg': {
                        'sticky': 'nesw',
                        'row': -1,
                        'column': 3,
                        'columnspan': 2
                    }
                })

        if self.buttonMask.get('playB', None) is not False:
            ifd.append({
                'name': 'playB',
                'widgetType': Tkinter.Button,
                #'text':'Play',
                'tooltip': 'play forward according to current play mode',
                'wcfg': {
                    'bd': 4,
                    'image': self.playIcon,
                    'width': self.playIcon.width(),
                    'height': self.playIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 5
                },
                'command': self.Play_cb
            })

        if self.buttonMask.get('fastForwardB', None) is not False:
            ifd.append({
                'name': 'fastForwardB',
                'widgetType': Tkinter.Button,
                #'text':'fastForward',
                'tooltip': 'play as fast as possible',
                'wcfg': {
                    'bd': 4,
                    'image': self.ff_fwdIcon,
                    'width': self.ff_fwdIcon.width(),
                    'height': self.ff_fwdIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 6
                },
                'command': self.FastForward_cb
            })

        if self.buttonMask.get('gotoEndB', None) is not False:
            ifd.append({
                'name': 'gotoEndB',
                'widgetType': Tkinter.Button,
                #'text':'gotoEnd',
                'tooltip': 'sets frame to current endFrame',
                'wcfg': {
                    'bd': 4,
                    'image': self.gotoEndIcon,
                    'width': self.gotoEndIcon.width(),
                    'height': self.gotoEndIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 7
                },
                'command': self.GoToEnd_cb
            })

        if self.buttonMask.get('modeB', None) is not False:
            ifd.append({
                'name': 'modeB',
                'widgetType': Tkinter.Button,
                'text': 'Change Mode',
                'tooltip': 'opens panel to change play options',
                'wcfg': {
                    'bd': 4,
                    'image': self.chmodIcon,
                    'width': self.chmodIcon.width(),
                    'height': self.chmodIcon.height()
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 8
                },
                'command': self.SetMode_cb
            })

        if pymediaFound and self.buttonMask.get('recordB', None) is not False:
            ifd.append({
                'name': 'recordB',
                'widgetType': Tkinter.Checkbutton,
                'text': 'Record',
                'tooltip': 'record an mpeg movie into movie.mpeg',
                'defaultValue': 0,
                'wcfg': {
                    'bd': 4,
                    'variable': Tkinter.IntVar(),
                    'image': self.recIcon,
                    'width': self.recIcon.width(),
                    'height': self.recIcon.height(),
                    'indicatoron': 0,
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 9
                },
                'command': self.startRecording_cb
            })

        if self.buttonMask.get('setanimB', None) is not False:
            ifd.append({
                'name': 'setanimB',
                'widgetType': Tkinter.Button,
                'text': 'SetAnim',
                'tooltip': 'Set Animation',
                'wcfg': {
                    'bd': 4
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 10
                },
                'command': self.SetAnim_cb
            })

        if self.buttonMask.get('closeB', None) is not False:
            ifd.append({
                'name': 'closeB',
                'widgetType': Tkinter.Button,
                'text': 'Close',
                'tooltip': 'closes player',
                'wcfg': {
                    'bd': 4,
                    'image': self.closeIcon,
                    'width': self.closeIcon.width(),
                    'height': self.closeIcon.height(),
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 11
                },
                #'gridcfg':{'sticky':'nesw', 'columnspan':2},
                'command': self.Close_cb
            })

        if self.hasSlider:
            ifd.append({
                'name': 'slider',
                'widgetType': Tkinter.Scale,
                'wcfg': {
                    'orient': 'horizontal',
                    'from_': self.startFrame,
                    'to': self.maxFrame,
                    'showvalue': False
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': 1,
                    'column': 0,
                    'columnspan': 12
                },
                'command': self.nextFrame
            })
        #form = self.vf.getUserInput(ifd, modal=0,blocking=0)
        form = InputForm(self.master,
                         self.root,
                         descr=ifd,
                         modal=0,
                         blocking=0,
                         closeWithWindow=1)
        form.ifd = ifd
        form.playB = form.ifd.entryByName['playB']['widget']
        form.playRevB = form.ifd.entryByName['playRevB']['widget']
        #set up link to balloon help which needs to change, also
        form.playTT = form.ifd.entryByName['playB']['balloon']
        form.playRevTT = form.ifd.entryByName['playRevB']['balloon']
        if self.hasCounter:
            ctr = ifd.entryByName['statesCounter']['widget']
            entF = ctr.component('entryfield')
            form.ent2 = entF._entryFieldEntry
            da = ctr.component('downarrow')
            ua = ctr.component('uparrow')
            for item in [da, ua]:
                item.bind('<ButtonPress-1>', self.SetState_cb, '+')
            form.ent2.bind('<Return>', self.SetState_cb, '+')
            form.counter = form.ifd.entryByName['statesCounter']['widget']
        if self.hasSlider:
            slider = form.ifd.entryByName['slider']['widget']
            slider.set(self.currentFrameIndex)
        #print 'returning form'
        return form

    def buildForm(self, titleStr):
        #??FIX THIS:
        self.stop = 1
        if hasattr(self, 'form'):
            self.form.deiconify()
            return
        maxval = self.endFrame
        ifd = InputFormDescr(title=titleStr)
        if self.hasCounter:
            ifd.append({
                'widgetType': Pmw.Counter,
                'name': 'statesCounter',
                'required': 1,
                'tooltip': 'used to show frames via random access',
                'wcfg': {  #'labelpos': 'n,
                    #'label_text':'conformation:  ',
                    'autorepeat': 0,
                    'entryfield_value': self.startFrame,
                    #'entryfield_value':self.idList[0],
                    'datatype': self.custom_counter,
                    'entry_width': 9,
                    'entryfield_validate': self.custom_validate
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'columnspan': 2
                }
            })
        ifd.append({
            'name': 'playB',
            'widgetType': Tkinter.Button,
            'text': 'Play',
            'tooltip': 'play sequence according to current play mode',
            'wcfg': {
                'bd': 4
            },
            'gridcfg': {
                'sticky': 'nesw',
                'columnspan': 1
            },
            'command': self.Play_cb
        })
        ifd.append({
            'name': 'playRevB',
            'widgetType': Tkinter.Button,
            'text': 'Play Reverse',
            'wcfg': {
                'bd': 4
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1,
                'column': 1
            },
            'command': self.PlayRev_cb
        })
        ifd.append({
            'name': 'playTB',
            'widgetType': Tkinter.Button,
            'text': 'Play+Return',
            'wcfg': {
                'bd': 4
            },
            'gridcfg': {
                'sticky': 'nesw',
                'columnspan': 1
            },
            'command': self.PlayReturn_cb
        })
        ifd.append({
            'name': 'loopB',
            'widgetType': Tkinter.Button,
            'text': 'Loop',
            'wcfg': {
                'bd': 4
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1,
                'column': 1
            },
            'command': self.Loop_cb
        })
        ifd.append({
            'name': 'stopB',
            'widgetType': Tkinter.Button,
            'text': 'Stop',
            'tooltip': 'stop play',
            'wcfg': {
                'bd': 4,
            },
            'gridcfg': {
                'sticky': 'nesw'
            },
            'command': self.Stop_cb
        })
        #add fastforward, fastrewind, thumbwheel for speed
        ifd.append({
            'name': 'pauseB',
            'widgetType': Tkinter.Button,
            'text': 'Pause',
            'wcfg': {
                'bd': 4
            },
            'gridcfg': {
                'sticky': 'nesw',
                'row': -1,
                'column': 1
            },
            'command': self.Pause_cb
        })

        ifd.append({
            'name': 'closeB',
            'widgetType': Tkinter.Button,
            'text': 'Close',
            'wcfg': {
                'bd': 4
            },
            #'gridcfg':{'sticky':'nesw','row':-1, 'column':1},
            'gridcfg': {
                'sticky': 'nesw',
                'columnspan': 2
            },
            'command': self.Close_cb
        })
        form = InputForm(self.master,
                         self.root,
                         descr=ifd,
                         modal=0,
                         blocking=0,
                         closeWithWindow=1)
        form.ifd = ifd
        if self.hasCounter:
            ctr = ifd.entryByName['statesCounter']['widget']
            entF = ctr.component('entryfield')
            form.ent2 = entF._entryFieldEntry
            da = ctr.component('downarrow')
            ua = ctr.component('uparrow')
            for item in [da, ua]:
                item.bind('<ButtonPress-1>', self.SetState_cb, '+')
            form.ent2.bind('<Return>', self.SetState_cb, '+')
            form.counter = form.ifd.entryByName['statesCounter']['widget']
        form.stopB = form.ifd.entryByName['stopB']['widget']
        form.playB = form.ifd.entryByName['playB']['widget']
        form.playRevB = form.ifd.entryByName['playRevB']['widget']
        #print 'returning form1'
        self.form = form
        return form

    #methods for changing playMode
    def SetMode_cb(self, event=None):
        #print 'SetMode'
        #playMode options:
        #   0   play once and stop
        #   1   play continuously in 1 direction
        #   2   play once in 2 directions
        #   3   play continuously in 2 directions
        #play framerate is frame/per second
        if not hasattr(self, 'playModeForm'):
            self.playModeList = [
                'once and stop', 'continuously in 1 direction',
                'once in 2 directions', 'continuously in 2 directions'
            ]
            ifd2 = InputFormDescr(title='Set Play Mode')

            ifd2.append({
                'name': 'playModeLabel',
                'widgetType': Tkinter.Label,
                'wcfg': {
                    'text': 'play mode options:',
                    'font': (ensureFontCase('helvetica'), 12, 'bold')
                },
                'gridcfg': {
                    'sticky': 'w'
                }
            })

            ifd2.append({
                'name': 'playMode',
                'widgetType': Tkinter.Radiobutton,
                'defaultValue': self.playModeList[self.playMode],
                'listtext': self.playModeList,
                'gridcfg': {
                    'sticky': 'w'
                }
            })

            ifd2.append({
                'name': 'framerateTW',
                'widgetType': ThumbWheel,
                'tooltip': """Framerate to enforce during playback""",
                'gridcfg': {
                    'sticky': 'we'
                },
                'wcfg': {
                    'value': self.framerate,
                    'oneTurn': 100.,
                    'type': 'float',
                    'continuous': True,
                    'wheelPad': 2,
                    'width': 145,
                    'height': 18,
                    'labCfg': {
                        'text': 'framerate:  '
                    },
                },
            })

            ifd2.append({
                'name': 'startFrameTW',
                'widgetType': ThumbWheel,
                'tooltip': """First frame used in playback""",
                'gridcfg': {
                    'sticky': 'we'
                },
                'wcfg': {
                    'value': self.startFrame,
                    'oneTurn': 100,
                    'type': 'int',
                    'continuous': True,
                    'wheelPad': 2,
                    'width': 145,
                    'height': 18,
                    'labCfg': {
                        'text': 'start frame: '
                    },
                },
            })

            ifd2.append({
                'name': 'endFrameTW',
                'widgetType': ThumbWheel,
                'tooltip': """Last frame used in playback""",
                'gridcfg': {
                    'sticky': 'we'
                },
                'wcfg': {
                    'value': self.endFrame,
                    'oneTurn': 100,
                    'type': 'int',
                    'continuous': True,
                    'wheelPad': 2,
                    'width': 145,
                    'height': 18,
                    'labCfg': {
                        'text': ' end frame: '
                    },
                },
            })

            ifd2.append({
                'name': 'stepSizeTW',
                'widgetType': ThumbWheel,
                'tooltip': """???""",
                'gridcfg': {
                    'sticky': 'we'
                },
                'wcfg': {
                    'value': self.stepSize,
                    'oneTurn': 100,
                    'type': 'int',
                    'continuous': True,
                    'wheelPad': 2,
                    'width': 145,
                    'height': 18,
                    'labCfg': {
                        'text': ' step size:  '
                    },
                },
            })

            ifd2.append({
                'name': 'acceptB',
                'widgetType': Tkinter.Button,
                'wcfg': {
                    'text': 'ok',
                    'command': self.setPlayMode_cb,
                },
                'gridcfg': {
                    'sticky': 'nesw'
                }
            })

            ifd2.append({
                'name': 'cancelB',
                'widgetType': Tkinter.Button,
                'wcfg': {
                    'text': 'cancel',
                    'command': self.cancelPlayMode_cb,
                },
                'gridcfg': {
                    'sticky': 'nesw',
                    'row': -1,
                    'column': 1
                }
            })
            if self.master is None:
                master = self.root
            else:
                master = Tkinter.Toplevel()
            self.playModeForm = InputForm(master,
                                          None,
                                          descr=ifd2,
                                          modal=0,
                                          blocking=0)
            self.playModeVar = self.playModeForm.descr.entryByName['playMode'][
                'variable']
            self.framerateWidget = self.playModeForm.descr.entryByName[
                'framerateTW']['widget']
            self.startFrameWidget = self.playModeForm.descr.entryByName[
                'startFrameTW']['widget']
            self.endFrameWidget = self.playModeForm.descr.entryByName[
                'endFrameTW']['widget']
            self.stepSizeWidget = self.playModeForm.descr.entryByName[
                'stepSizeTW']['widget']
        else:
            self.playModeForm.deiconify()

    def setPlayMode_cb(self, event=None):
        curVal = self.playModeVar.get()
        self.playMode = self.playModeList.index(curVal)
        #print 'setting playMode to ', curVal
        self.framerate = round(self.framerateWidget.get(), 4)
        #print 'setting self.framerate ->', self.framerate
        self.timestamp = 1. / self.framerate

        self.startFrame = self.startFrameWidget.get()
        self.endFrame = self.endFrameWidget.get()
        self.stepSize = self.stepSizeWidget.get()
        self.cancelPlayMode_cb()
        self.oneDirection = 0

    def cancelPlayMode_cb(self, event=None):
        self.playModeForm.withdraw()

    #methods for counter
    def custom_validate(self, text):
        #print 'in custom_validate, text=', text
        if not len(text):
            return -1

        if text in ['start', 'end']:
            return 1

        tt = int(text)
        okList = range(self.startFrame, self.endFrame + 1)
        if tt in okList:
            return 1
        else:
            return -1

    def custom_counter(self, text, factor, increment, **kw):
        # text is current content of entry
        # factor is 1 for increment and -1 for decrement
        # increment is value of increment megawidget option
        ###if not text in self.idList:
        ###raise ValueError, text + ' not in current idList'
        #check whether ind+factor is in range
        newval = self.currentFrameIndex + factor
        #print 'newval=', newval
        if newval < 0 or newval > self.endFrame:
            #print 'custom_counter returning ', text
            return text
        else:
            #print 'custom_counter returning ', newval
            return newval
class AnimPlayer(Player,geomsChooser):
    """ provide a player to display/undisplay DejaVu object
    in a cylce making a animation.

    viewer: DejaVu viewer
    height,width are the property of the player gui
    startFrame: frame to begin
    endFrame: last frame to display
    stepSize: step between new frame
    playMode:                  #playMode options:
                               #   0   play once and stop
                               #   1   play continuously in 1 direction
                               #   2   play once in 2 directions
                               #   3   play continuously in 2 directions
    titleStr: title of the gui windows
    counter: gui with a counter on or not
    gui: #1 show the player gui
         #0 player gui not display
    framerate =15.             # number of frame per second to be display
    """


    def __init__(self,viewer, master=None, root=None,
                 height=80,width=200,
                 currentFrameIndex=0,
                 startFrame=0, 
                 endFrame=0,
                 maxFrame=0,
                 stepSize=1, 
                 playMode=1,
                 titleStr='AnimPlayer',
                 counter = 1,
                 gui=1,framerate=15.):

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

        # viewer from which we get the geom to animate
        self.viewer = viewer
        # frame list, is a list of geom .
        # each frame is made of n DejaVu object to be display
        # it a list of tuple, each tuple is a {} and []
        # {} is: {'objname':['geom1','geom2'],'objname':['geom1','geom2']}
        # [] is list of DejaVu object per frame
        self.framelist=[]

        Player.__init__(self, master=master,root=root,height=height,
                        width=width,currentFrameIndex=currentFrameIndex,
                        startFrame=startFrame,endFrame=endFrame,
                        maxFrame=maxFrame,stepSize=stepSize,
                        playMode=playMode,titleStr=titleStr,counter=counter,
                        gui=gui,framerate=framerate)

    def nextFrame(self, id):
        """ id: index number of the frame to display.
        undisplay object from previous frame, display object
        of new frame.
        """
        if not self.framelist:return
        id = int(id)
        if id >=len(self.framelist):return

        i = self.currentFrameIndex
        ## undisplay previous object
        frame = self.framelist[i]
        for obj in frame[1]:
            obj.Set(visible=0,redo=0)
            
        if self.hasCounter and self.gui:
            self.form.ent2.delete(0,'end')
            self.form.ent2.insert(0, str(id))

        ## display new frame
        currentframe = self.framelist[id]
        for obj in currentframe[1]:
            obj.Set(visible=1,redo=0)
        
        self.viewer.deleteOpenglList()
	self.viewer.Redraw()
        self.currentFrameIndex = id

#####################################################################
#### Animation Setting the frame

    def SetAnim_cb(self):
        self.showForm()
        
    def showForm(self):
        """create formdescr for setAnim
        form to set the animation:
        each frame is a list of geom to display
        """

        entryFrame = []
        for i in range(len(self.framelist)):
            val = 'frame_'+str(i)
            entryFrame.append((val,))
        
        if not hasattr(self,'form_Setanim'):
            ifd = InputFormDescr(title="SetAnimation")
            ifd.append({'widgetType':ListChooser,
                        'name':'availableGeom',
                        'tooltip':'geom available in viewer',
                        'wcfg':{'mode':'extended',
                                'lbwcfg':{'exportselection':1},
                                'command':[(self.toggleExpansion,'<Double-Button-1>')],
                                'commandEvent':None,
                                'title':'availableGeom'},
                        
                        'gridcfg':{'row':0,'column':0,
                                   'sticky':'wens','rowspan':3}})
            ifd.append({'name':'newframe',
                        'widgetType':Tkinter.Button,
                        'tooltip':""" Add an empty frame to the animation""",
                        'wcfg':{'text':'NewFrame','command':self.addframe_cb},
                        'gridcfg':{'row':0,'column':1,'rowspan':1 }})
            
            ifd.append({'name':'add',
                        'widgetType':Tkinter.Button,
                        'tooltip':""" Add the selected geom to selected frame""",
                        'wcfg':{'text':'AddGeom','command':self.add_cb},
                        'gridcfg':{'row':1,'column':1,'rowspan':1 }})
            
            ifd.append({'name':'geomtoload',
                        'widgetType':ListChooser,
                        'tooltip':"""list of frame  the user chose to
                        apply to the pattern""",
                        'wcfg':{'entries':entryFrame,
                                'mode':'extended',
                                'lbwcfg':{'exportselection':0},
                                'title':'Frame(geom) to be display'},
                        'gridcfg':{'sticky':'we', 
                                   'row':0, 'column':2,'rowspan':3}})
            ifd.append({'name':'remove',
                        'widgetType':Tkinter.Button,
                        'tooltip':""" Remove the selected entry from the
                        commands to be applied to the object when loaded in the application""",
                        'wcfg':{'text':'REMOVE','width':10,
                                'command':self.remove_cb},
                        'gridcfg':{'sticky':'we','row':0, 'column':3}})
            
            ifd.append({'name':'oneup',
                        'widgetType':Tkinter.Button,
                        'tooltip':"""Move the selected entry up one entry""",
                        'wcfg':{'text':'Move up','width':10,
                                'command':self.moveup_cb},
                        'gridcfg':{'sticky':'we','row':1,'column':3}})
            
            ifd.append({'name':'onedown',
                        'widgetType':Tkinter.Button,
                        'tooltip':"""Move the selected entry down one entry""",
                        'wcfg':{'text':'Move down','width':10,
                                'command':self.movedown_cb},
                        'gridcfg':{'sticky':'we','row':2,'column':3}})

            self.form_Setanim = InputForm(self.master,None,descr=ifd,
                                  scrolledFrame=0)
            
            
            self.lc = self.form_Setanim.descr.entryByName['availableGeom']['widget']
            self.lc2 = self.form_Setanim.descr.entryByName['geomtoload']['widget']
            self.addObject(self.viewer.rootObject,None)
            val = self.form_Setanim.go()
            if val:
                self.assign()
                self.form_Setanim.withdraw()
        else:
            self.form_Setanim.deiconify()
            val = self.form_Setanim.go()
            if val:
                self.assign()
                self.form_Setanim.withdraw()
                
    def deleteAnim(self):
        """ Delete all frame from the player list."""

        self.Stop_cb()
        self.startFrame=0
        self.endFrame = -1
        self.maxFrame = 0
        self.targetFrame = self.endFrame
        self.target = self.endFrame
        self.currentFrameIndex =0


    def assign(self,list=None):
        """ assign the animation.
        framelist ; list of {}
        return a list of obj for each frame
        """
        self.deleteAnim()
        AllObjects = self.viewer.rootObject.AllObjects()
        if list :
            self.framelist=[]
            for f in list:
                self.framelist.append((f,[]))
        print "assign"
        print "self.framelist",self.framelist
        for frame in self.framelist:
            geomDic = frame[0]
            Namelist=[]
            for parents in geomDic.keys():
                parentlist = filter(lambda x, name=parents:x.name == name,AllObjects)
                obj = parentlist[0]
                childrens = geomDic[obj.name]
                if len(childrens) > 0:
                    for namegeom in childrens:
                        child = filter(lambda x,
                                       name=namegeom:x.name == name,
                                       obj.children)[0]
                        if child.children != []:
                            for c in child.children:
                                frame[1].append(c)
                        else:
                            frame[1].append(child)
                else:
                    frame[1].append(obj)

            self.endFrame = self.endFrame +1
            self.maxFrame = self.maxFrame +1
            self.targetFrame = self.endFrame
            self.target = self.endFrame


    def movedown_cb(self):
        """ move entry one down """
        sel = self.lc2.get()
        index = self.lc2.getInd()
        if not sel: return
        sel = sel[0]
        if string.find(sel,"frame") < 0: return
        # get frame Index
        frameInd = int(string.split(sel,'_')[1])
        currentframe = self.framelist[frameInd]
        if (frameInd + 1) >= len(self.framelist):return
        # select next Frame.
        nextframe = self.framelist[frameInd+1]
        # move current frame one down in list
        self.framelist[frameInd] =nextframe
        self.framelist[frameInd+1] =currentframe
        self.updatelistchooser(self.framelist)

    def moveup_cb(self):
        """ move entry one up """
        sel = self.lc2.get()
        index = self.lc2.getInd()
        if not sel: return
        sel = sel[0]
        if string.find(sel,"frame") < 0: return
        # get frame Index
        frameInd = int(string.split(sel,'_')[1])
        currentframe=self.framelist[frameInd]
        if (frameInd - 1) <  0 :return
        # select previous Frame
        prevframe = self.framelist[frameInd-1]
        # move current frame one up in list
        self.framelist[frameInd] =prevframe
        self.framelist[frameInd-1] =currentframe
        self.updatelistchooser(self.framelist)
        
    def addframe_cb(self):
        """ add a new frame entry"""
        frame = ({},[])
        nb = len(self.framelist)
        #frame.number = nbframe 
        value = 'frame_'+ str(nb)
        self.framelist.append(frame)
        self.lc2.deselect(0,last='end')
        self.lc2.insert('end',value)
        self.lc2.select('end')

    def add_cb(self):
        listgeom=[]
        # get the frame index to add new geom
        if len(self.lc2.entries)>0:
            ind = self.lc2.getInd()
            if len(ind) ==0:return # no entry selected so create a new frame
            # get geom name to load
            o = map(int,self.lc.lb.curselection())
            for Ind in o:
                    fullName = self.getFullName(Ind)
                    listgeom.append(fullName)
            # get frame instance
            for index in ind:
                value = self.lc2.entries[index][0]
                if string.find(value,"frame") < 0: return
                frameInd = int(string.split(value,'_')[1])
                frameGeom = self.framelist[frameInd][0]
                for geom in listgeom:
                    # strip the root
                    l = string.split(geom,'|')
                    if not frameGeom.has_key(l[1]):
                        frameGeom[l[1]]=[]
                    for i in l[2:]:
                        if not( i in frameGeom[l[1]]):
                            frameGeom[l[1]].append(i)

            self.updatelistchooser(self.framelist)
        else:
            return
        
    def updatelistchooser(self,entry):
        """ update what is display in the list chooser """
        # save current selection
        sel  = self.lc2.get()
        # remove current entry
        self.lc2.clear()
        prefix = '~'
        prefix2 = '~~'
        nb= 0
        for e in entry:
            v = 'frame_'+str(nb)
            nb = nb+1
            # listchooser entry has to be a tuple(value,comment)
            self.lc2.add((v,))
            for mol in e[0].keys():
                self.lc2.add((prefix+mol,))
                for geom in e[0][mol]:
                    self.lc2.add((prefix2+geom,))
        # select the entry save as sel
        # keep the entry selected after the update
        for i in sel:
            self.lc2.select((i,))


    def findFramefromGeomInd(self,index):
        """ return the frame number from  which the geom was selected """
        for i in range(index+1):
            value = self.lc2.entries[index-i][0]
            if string.find(value,"frame") >= 0:
                frameInd =  int(string.split(value,'_')[1])
                lcInd = index -i
                return (frameInd,lcInd)
        return 0
    
    def findParentGeom(self,index):
        """ find the parent value name from a geom ~~
        go up to find first value with onley ~ """
        parent = None
        for i in range(index+1):
            parent = self.lc2.entries[index -i][0]
            if parent[0] == '~' and parent[1] !='~':
                parent = parent[1:]
                return parent
        return  None
    
    def removeEntryGeom(self,value,index):
        """ the geom entry in the listchooser"""
        # first find from which frame we need to remove geom
        val = self.findFramefromGeomInd(index)
        if val:
            frameInd =val[0]
            lcInd = val[1]
            if value[1] == '~':
                parent = self.findParentGeom(index)
                if parent:
                    listgeom = self.framelist[frameInd][0][parent]
                    rindex = listgeom.index(value[2:])
                    del listgeom[rindex]
                
            elif self.framelist[frameInd][0].has_key(value[1:]):
                del self.framelist[frameInd][0][value[1:]]
            
            self.updatelistchooser(self.framelist)
            
    def removeEntryFrame(self,value,index):
        """ remove the frame entry in the listchooser"""
        # delete frame from framelist
        frameInd = int(string.split(value,'_')[1])
        del self.framelist[frameInd]
        # Update list chooser
        self.updatelistchooser(self.framelist)
        
    def remove_cb(self):
        """ remove entry in litschooser (geomtoload)"""
        selindex = self.lc2.getInd()
        for index in selindex:
            value = self.lc2.entries[index][0]
            if string.find(value,"frame") >= 0:
                self.removeEntryFrame(value,index)
            elif value[0] == '~':
                self.removeEntryGeom(value,index)
class geomsChooser:

    def __init__(self,viewer):

        #ViewerGUI(viewer,8,2)
        # the viewe where the geoms are display (for us: pmv or DejaVu)
        if viewer is None:
            return
        self.viewer = viewer
        geomDic = {}
        dpyList = None
        self.assignGeom =[geomDic,dpyList]

 
    def toggleExpansion(self, event):
        # get a 0-based index into list of names
	o = self.lc.lb.nearest(event.y)
        fullName = self.getFullName(o)
	#obj = self.objectByName(self.olist.get(o))
        obj = self.viewer.FindObjectByName(fullName)
	if obj:
            childGeoms = obj.AllObjects()
            if len(childGeoms)==1:  # this geoemtry has no children
                return
            else: # this geometry has children
                if obj.isExpandedInObjectList: self.collapse(obj)
                else: self.expand(obj)

    def expand(self, object):
        # object is a geometry
        if object.isExpandedInObjectList: return
        object.isExpandedInObjectList = 1
        geoms = object.children
        ind = self.objectIndex(object) + 1
        c = self.countParents(object) + 1
        prefix = '~'*c
        for i in range(len(geoms)):
            g = geoms[i]
            if g==object: continue
            if not g.listed: continue
            if len(g.vertexSet) == 0 and len(g.children)==0:continue
            self.lc.insert(ind, prefix + g.name)
            ind = ind + 1

            
    def collapse(self, object):
        # object is a geometry, we recursively collapse the sub-tree
        object.isExpandedInObjectList = 0

        # delete the names from the bject list widget
        nbChildren = self.countDecendentsInWidget(object)
        ind = self.objectIndex(object) + 1
        for i in range(ind, ind+nbChildren):
            self.lc.lb.delete(ind)
        # toggle isExpandedInObjectList for all descendents
        for child in object.AllObjects():
            if child.listed:
                child.isExpandedInObjectList = 0

    def countDecendentsInWidget(self, object):
        # object is a geometry, we count and return the number of 
        # decendents shown in widget
        ind = self.objectIndex(object)
        allNames = self.lc.lb.get(0,'end')
        nbTild = string.count(allNames[ind],'~')+1
        # count children in widget
        nbChildren = 0
        for i in range(ind+1, len(allNames)):
            nbt = string.count(allNames[i],'~')
            if nbt >= nbTild:
                nbChildren = nbChildren + 1
            else:
                break
        return nbChildren

        
    def getFullName(self, ind):
        # strip the leading ~
        allNames = self.lc.lb.get(0,'end')
        nbTild = string.count(allNames[ind],'~')
        fullName = allNames[ind][nbTild:]
        for i in range(ind-1, -1, -1):
            nbt, name = self.lstripChar(allNames[i], '~')
            if nbt >= nbTild: continue
            nbTild = nbt
            fullName = name + '|' + fullName
        return fullName

    def objectIndex(self, object):
        # object is a geometry and we find this object's index in the list of
        # names displayed in te widget. If the ibecjt is not shown we
        # return -1
        l = self.lc.lb.get(0,'end')
        for i in range(len(l)):
            indent, n = self.lstripChar(l[i], '~')
            if n==object.name: break
        if i==len(l): return -1
        else: return i

    def lstripChar(self, name, char):
	n = string.count(name,'~')
	return n, name[ n : ]

    def countParents(self, object):
	c = 0
	while object.parent:
	    c = c+1
	    object = object.parent
	return c

    def addObject(self, obj, parent):
        if not obj.listed: return
	if not parent:
	    self.lc.insert(0,obj.name)
	    self.lc.select(obj.name)
	else:
            if not parent.isExpandedInObjectList: return
                
            i = self.objectIndex(parent)
	    if i==-1: return
	    c = self.countParents(obj)
            prefix = '~'*c
	    name = prefix + obj.name
            # now we need to skip all children already there
            l = self.lc.lb.get(0,'end')
            while 1:
                i = i + 1
                if i==len(l): break
                if self.lc.get(i)[:c]!=prefix: break

	    self.lc.insert(i, name)

    def getFullNameList(self,name,list,dic):
        """ get the list of fullName from geomDic """

        for p in dic.keys():
            name1 = name +'|'+p
            if dic[p] != {}:
                list = self.getFullNameList(name1,list,dic[p])
            else:
                list.append(name1)
                
        return list
    

    def getDpyList(self,objects):
        """function to obtain a display list for any object in DejaVu"""
        from opengltk.OpenGL import GL
        # Draw build a display function that contains global coloring,
        # transformation nd all global GL properties of this objects.
        # we cannot use the object's display list that does not contains this
        # info
        #if len(objects) == 1 and objects[0].dpyList:
        #    return objects[0].dpyList
        # transparent object need to be drawn last

        # reorder object so transparent object drawn last
        transparent =[]
        opaque = []
        for obj in objects:
            if obj.transparent: #obj.isTransparent():
                transparent.append(obj)
            else:
                opaque.append(obj)
        objlist = opaque + transparent
        
        lNewList = GL.glGenLists(1)
        #print "lNewList geomsChooser.getDpyList", lNewList, self.name
        dpyList = ( lNewList,
                   self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag')
                  )

        camera = self.mv.GUI.VIEWER.currentCamera
        camera.Activate()

        GL.glNewList(dpyList, GL.GL_COMPILE)
        #print "geomChooser 208", GL.glGetIntegerv(GL.GL_LIST_INDEX)
        for obj in objlist:
            if obj.immediateRendering: # or obj.hasChildWithImmediateRendering:
                camera.drawMode=5
                camera.Draw(obj)
            else:
                camera.drawMode=2
                camera.drawTransparentObjects = 0
                camera.hasTransparentObjects = 0
                # draw opaque object
                for m in obj.instanceMatricesFortran:
                    GL.glPushMatrix()
                    GL.glMultMatrixf(m)
                    if len(obj.children):
                        map( camera.Draw, obj.children)
                    else:
                        camera.Draw(obj)
                    GL.glPopMatrix()
                
                # draw transparent children of object
                if camera.hasTransparentObjects:
                    camera.drawTransparentObjects = 1
                    for m in obj.instanceMatricesFortran:
                        GL.glPushMatrix()
                        GL.glMultMatrixf(m)
                        map( camera.Draw, obj.children)
                        GL.glPopMatrix()
                # draw transparent object that do not have children
                if obj.isTransparent() and not len(obj.children):
                    camera.drawTransparentObjects =1
                    for m in obj.instanceMatricesFortran:
                        GL.glPushMatrix()
                        GL.glMultMatrixf(m)
                        camera.Draw(obj)
                        GL.glPopMatrix()
                    

        GL.glEndList()    
        return dpyList

    def buildForm(self):
        ifd = InputFormDescr(title=self.ftitle)
        ifd.append({'widgetType':ListChooser,
                    'name':'availableGeom',
                    'tooltip':'geom available in viewer',
                    'wcfg':{'mode':'extended',
                            'lbwcfg':{'exportselection':1},
                            'command':[(self.toggleExpansion,'<Double-Button-1>')],
                            'commandEvent':None,
                            'title':'availableGeom'},
                    
                    'gridcfg':{'row':0,'column':0,
                               'sticky':'wens','rowspan':3}})
        
        ifd.append({'name':'add',
                    'widgetType':Tkinter.Button,
                    'tooltip':""" Add the selected geom to selected frame""",
                    'wcfg':{'text':'>>','command':self.add_cb},
                    'gridcfg':{'row':1,'column':1,'rowspan':1 }})
        
        ifd.append({'name':'remove',
                    'widgetType':Tkinter.Button,
                    'tooltip':""" remove the selected geom to selected """,
                    'wcfg':{'text':'<<','command':self.remove_cb},
                    'gridcfg':{'row':2,'column':1,'rowspan':1 }})
            
        ifd.append({'name':'toload',
                    'widgetType':ListChooser,
                    'tooltip':"""list of geom  the user chose to
                    apply to the pattern""",
                    'wcfg':{
            'mode':'extended',
            'lbwcfg':{'exportselection':0},
            'title':self.lc2title},
                    'gridcfg':{'sticky':'we', 
                               'row':0, 'column':2,'rowspan':3}})
        ifd.append({'name':'clear',
                    'widgetType':Tkinter.Button,
                    'tooltip':""" Clear entry """,
                    'wcfg':{'text':'Clear','width':10,
                            'command':self.clear_cb},
                    'gridcfg':{'sticky':'we','row':0, 'column':3}})
        ifd.append({'name':'remove',
                    'widgetType':Tkinter.Button,
                    'tooltip':""" remove the selected geom to selected """,
                    'wcfg':{'text':'<<','command':self.remove_cb},
                    'gridcfg':{'row':2,'column':1,'rowspan':1 }})
        return ifd
        
    def showForm(self,master,geomDic=None,func=None):
        """create formdescr for setGeoms
        geomDic = a dict of Geom 
        """
        # assign a func so we can log it in Pmv
        # func is a Pmv command
        if func:
            self.assign_func = func
            
        if geomDic:
            self.assignGeom[0]=geomDic
            
        if hasattr(self,'form'):
            if self.guiOn:
                return
            else:
                self.update_lc2()
                self.form.deiconify()
                val = self.form.go()
               
                if val:
                    geomDic =self.assignGeom[0] 
                    self.assign_func(geomDic)
                    self.form.withdraw()
        else:
            if not master:
                master = Tkinter.Toplevel()
                master.title('GeomChooser')
            else:
                master = master

            ifd = self.buildForm()
            self.form = InputForm(master,None,descr=ifd,
                                  scrolledFrame=0,
                                  cancelCfg={'command':self.cancel_cb})
                
            self.lc = self.form.descr.entryByName['availableGeom']['widget']
            self.lc2 = self.form.descr.entryByName['toload']['widget']
            self.addObject(self.viewer.rootObject,None)
            self.update_lc2()
            val = self.form.go()
            if val:
                geomDic =self.assignGeom[0] 
                self.assign_func(geomDic)
                self.form.withdraw()
                
    def cancel_cb(self,event = None, func=None):
        """ close setup animation form without setting anything"""
        if hasattr(self,'geomDicCopy'):
            self.patDic = self.patDicCopy.copy()
        
    def add_cb(self):
        lgeom=[]
        geomDic = self.assignGeom[0]
        # get geom name to load
        o = map(int,self.lc.lb.curselection())
        for Ind in o:
            fullName = self.getFullName(Ind)
            obj = self.viewer.FindObjectByName(fullName)
            # strip the root
            l = string.split(fullName,'|')[1:]
            for i in range(len(l)):
                if i==0:
                    if not geomDic.has_key(l[i]):
                        dic = geomDic[l[i]]={}
                    else:
                        dic = geomDic[l[i]]
                else:
                    if not dic.has_key(l[i]):
                        dic[l[i]]={}
                        
                    dic = dic[l[i]]
            
        self.update_lc2()

    def insertValue(self,ind,prefix,dic):
        """ insert Value of a dictionnary in the listchooser2"""
        for key in dic.keys():
            if dic[key] == {}:
                ind = ind+1
                self.lc2.insert(ind, prefix+key)
            else:
                ind =ind +1
                self.lc2.insert(ind, prefix+key)
                p = prefix + '~'
                ind=self.insertValue(ind,p,dic[key])
        return ind
        
    def update_lc2(self):
        """ update listchooser entries display"""

        # save current entry selected
        sel  = self.lc2.get()
        prefix = '~'
        self.lc2.clear()
        ind = 0
        geomDic = self.assignGeom[0]
        ind = self.insertValue(ind,prefix,geomDic)

        # select the entry save as sel
        # keep the entry selected after the update
        for i in sel:
            self.lc2.select((i,))

    def findParentMol(self,index):
        """ find the parent value name from a geom ~~
        go up to find first value with onley ~ """
        parent = None
        for i in range(index+1):
            parent = self.lc2.entries[index -i][0]
            if parent[0] == '~' and parent[1] !='~':
                parent = parent[1:]
                return parent
        return  None
         
    def remove_cb(self):
        """ remove entry in litschooser (geomtoload)"""
        geomDic = self.assignGeom[0]
        selindex = self.lc2.getInd()
        for index in selindex:
            value = self.lc2.entries[index][0]
           
            if value[1] == '~':
                mol = self.findParentMol(index)
                rindex = geomDic[mol].index(value[2:])
                del geomDic[mol][rindex]
            else:
                mol = value[1:]
                del geomDic[mol]
        self.update_lc2()

    def clear_cb(self):
        """ clear all entry """
        self.lc2.clear()
        if  self.assignGeom:
            self.assignGeom[0] = {} # geomDic
            self.assignGeom[1] = None # dpyList