VisionEgg.GUI

Package VisionEgg :: Module GUI |
[frames] | no frames]

# Source Code for Module VisionEgg.GUI

      1  # The Vision Egg: GUI
      2  #
      3  # Copyright (C) 2001-2003 Andrew Straw.
      4  # Copyright (C) 2008 California Institute of Technology
      5  #
      6  # URL: <http://www.visionegg.org/>
      7  #
      8  # Distributed under the terms of the GNU Lesser General Public License
      9  # (LGPL). See LICENSE.TXT that came with this file.
     10
     11  """
     12  Graphical user interface classes and functions.
     13
     14  """
     15
     16  import VisionEgg
     17
     18  ####################################################################
     19  #
     20  #        Import all the necessary packages
     21  #
     22  ####################################################################
     23
     24
     25  import logging                              # available in Python 2.3
     26
     27  import VisionEgg
     28  import os
     29  import sys
     30
     31 -class _delay_import_error:
     32      """Defer import errors until they cause problems."""
     33 -    def __init__(self,orig_traceback):
     34          self.orig_traceback = orig_traceback
     35 -    def __getattr__(self,name):
     36          raise self.orig_traceback # ImportError deferred from earlier failure
     37
     38  try:
     39      import Tkinter
     40  except ImportError, x: # don't fail on this until it becomes a problem...
     41      Tkinter = _delay_import_error(x)
     42
     43  try:
     44      import tkMessageBox
     45  except ImportError, x: # don't fail on this until it becomes a problem...
     46      tkMessageBox = _delay_import_error(x)
     47
     48  try:
     49      import tkFileDialog
     50  except ImportError, x: # don't fail on this until it becomes a problem...
     51      tkFileDialog = _delay_import_error(x)
     52
     53 -def showexception(exc_type, exc_value, traceback_str):
     54      # private subclass of Tkinter.Frame
     55      class ShowExceptionFrame(Tkinter.Frame):
     56          """A window that shows a string and has a quit button."""
     57          def __init__(self,master,exc_type, exc_value, traceback_str):
     58              VisionEgg.config._Tkinter_used = True
     59              Tkinter.Frame.__init__(self,master,borderwidth=20)
     60              title="Vision Egg: exception caught"
     61              first_str = "An unhandled exception was caught."
     62              type_value_str = "%s: %s"%(str(exc_type),str(exc_value))
     63
     64              frame = self
     65
     66              top = frame.winfo_toplevel()
     67              top.title(title)
     68              top.protocol("WM_DELETE_WINDOW",self.close_window)
     69
     70              Tkinter.Label(frame,text=first_str).pack()
     71              Tkinter.Label(frame,text=type_value_str).pack()
     72              if traceback_str:
     73                  Tkinter.Label(frame,text="Traceback (most recent call last):").pack()
     74                  Tkinter.Label(frame,text=traceback_str).pack()
     75
     76              b = Tkinter.Button(frame,text="OK",command=self.close_window)
     77              b.pack()
     78              b.focus_set()
     79              b.grab_set()
     80              b.bind('<Return>',self.close_window)
     81
     82          def close_window(self,dummy_arg=None):
     83              self.quit()
     84      # create instance of class
     85      parent = Tkinter._default_root
     86      if parent:
     87          top = Tkinter.Toplevel(parent)
     88          top.transient(parent)
     89      else:
     90          top = None
     91      f = ShowExceptionFrame(top, exc_type, exc_value, traceback_str)
     92      f.pack()
     93      f.mainloop()
     94      f.winfo_toplevel().destroy()
     95
     96 -class AppWindow(Tkinter.Frame):
     97      """A GUI Window that can be subclassed for a main application window"""
     98 -    def __init__(self,master=None,idle_func=lambda: None,**cnf):
     99          VisionEgg.config._Tkinter_used = True
    100          Tkinter.Frame.__init__(self,master,**cnf)
    101          self.winfo_toplevel().title('Vision Egg')
    102
    103          self.info_frame = InfoFrame(self)
    104          self.info_frame.pack()
    105
    106          self.idle_func = idle_func
    107          self.after(1,self.idle) # register idle function with Tkinter
    108
    109 -    def idle(self):
    110          self.idle_func()
    111          self.after(1,self.idle) # (re)register idle function with Tkinter
    112
    113 -class ProgressBar(Tkinter.Frame):
    114 -    def __init__(self, master=None, orientation="horizontal",
    115                   min=0, max=100, width=100, height=18,
    116                   doLabel=1, fillColor="LightSteelBlue1", background="gray",
    117                   labelColor="black", labelFont="Helvetica",
    118                   labelText="", labelFormat="%d%%",
    119                   value=50, **cnf):
    120          Tkinter.Frame.__init__(self,master)
    121          # preserve various values
    122          self.master=master
    123          self.orientation=orientation
    124          self.min=min
    125          self.max=max
    126          self.width=width
    127          self.height=height
    128          self.doLabel=doLabel
    129          self.fillColor=fillColor
    130          self.labelFont= labelFont
    131          self.labelColor=labelColor
    132          self.background=background
    133          self.labelText=labelText
    134          self.labelFormat=labelFormat
    135          self.value=value
    136          self.canvas=Tkinter.Canvas(self, height=height, width=width, bd=0,
    137                                      highlightthickness=0, background=background)
    138          self.scale=self.canvas.create_rectangle(0, 0, width, height,
    139                                                  fill=fillColor)
    140          self.label=self.canvas.create_text(self.canvas.winfo_reqwidth() / 2,
    141                                             height / 2, text=labelText,
    142                                             anchor="c", fill=labelColor,
    143                                             font=self.labelFont)
    144          self.update()
    145          self.canvas.pack(side='top', fill='x', expand='no')
    146
    147 -    def updateProgress(self, newValue, newMax=None):
    148          if newMax:
    149              self.max = newMax
    150          self.value = newValue
    151          self.update()
    152
    153 -    def update(self):
    154          # Trim the values to be between min and max
    155          value=self.value
    156          if value > self.max:
    157              value = self.max
    158          if value < self.min:
    159              value = self.min
    160          # Adjust the rectangle
    161          if self.orientation == "horizontal":
    162              self.canvas.coords(self.scale, 0, 0,
    163                float(value) / self.max * self.width, self.height)
    164          else:
    165              self.canvas.coords(self.scale, 0,
    166                                 self.height - (float(value) /
    167                                                self.max*self.height),
    168                                 self.width, self.height)
    169          # Now update the colors
    170          self.canvas.itemconfig(self.scale, fill=self.fillColor)
    171          self.canvas.itemconfig(self.label, fill=self.labelColor)
    172          # And update the label
    173          if self.doLabel:
    174              if value:
    175                  if value >= 0:
    176                      pvalue = int((float(value) / float(self.max)) *
    177                                     100.0)
    178                  else:
    179                      pvalue = 0
    180                  self.canvas.itemconfig(self.label, text=self.labelFormat
    181                                           % pvalue)
    182              else:
    183                  self.canvas.itemconfig(self.label, text='')
    184          else:
    185              self.canvas.itemconfig(self.label, text=self.labelFormat %
    186                                     self.labelText)
    187          self.canvas.update_idletasks()
    188
    189 -class GraphicsConfigurationWindow(Tkinter.Frame):
    190      """Graphics Configuration Window"""
    191 -    def __init__(self,master=None,**cnf):
    192          VisionEgg.config._Tkinter_used = True
    193          Tkinter.Frame.__init__(self,master,**cnf)
    194          self.winfo_toplevel().title('Vision Egg - Graphics configuration')
    195          self.pack()
    196
    197          self.clicked_ok = 0 # So we can distinguish between clicking OK and closing the window
    198
    199          row = 0
    200          Tkinter.Label(self,
    201                        text="Vision Egg - Graphics configuration",
    202                        font=("Helvetica",14,"bold")).grid(row=row,columnspan=2)
    203          row += 1
    204
    205          ################## begin topframe ##############################
    206
    207          topframe = Tkinter.Frame(self)
    208          topframe.grid(row=row,column=0,columnspan=2)
    209          topframe_row = 0
    210
    211          Tkinter.Label(topframe,
    212                        text=self.format_string("The default value for these variables and the presence of this dialog window can be controlled via the Vision Egg config file. If this file exists in the Vision Egg user directory, that file is used.  Otherwise, the configuration file found in the Vision Egg system directory is used."),
    213                        ).grid(row=topframe_row,column=1,columnspan=2,sticky=Tkinter.W)
    214          topframe_row += 1
    215
    216          try:
    217              import _imaging, _imagingtk
    218              import ImageFile, ImageFileIO, BmpImagePlugin, JpegImagePlugin
    219              import Image,ImageTk
    220              im = Image.open(os.path.join(VisionEgg.config.VISIONEGG_SYSTEM_DIR,'data','visionegg.bmp'))
    221              self.tk_im=ImageTk.PhotoImage(im)
    222              Tkinter.Label(topframe,image=self.tk_im).grid(row=0,rowspan=topframe_row,column=0)
    223          except Exception,x:
    224              logger = logging.getLogger('VisionEgg.GUI')
    225              logger.info("No Vision Egg logo :( because of error while "
    226                          "trying to display image in "
    227                          "GUI.GraphicsConfigurationWindow: %s: "
    228                          "%s"%(str(x.__class__),str(x)))
    229
    230          ################## end topframe ##############################
    231
    232          row += 1
    233
    234          ################## begin file_frame ##############################
    235
    236          file_frame = Tkinter.Frame(self)
    237          file_frame.grid(row=row,columnspan=2,sticky=Tkinter.W+Tkinter.E,pady=5)
    238
    239          # Script name and location
    240          file_row = 0
    241          Tkinter.Label(file_frame,
    242                        text="This script:").grid(row=file_row,column=0,sticky=Tkinter.E)
    243          Tkinter.Label(file_frame,
    244                        text="%s"%(os.path.abspath(sys.argv[0]),)).grid(row=file_row,column=1,sticky=Tkinter.W)
    245          file_row += 1
    246          # Vision Egg system dir
    247          Tkinter.Label(file_frame,
    248                        text="Vision Egg system directory:").grid(row=file_row,column=0,sticky=Tkinter.E)
    249          Tkinter.Label(file_frame,
    250                        text="%s"%(os.path.abspath(VisionEgg.config.VISIONEGG_SYSTEM_DIR),)).grid(row=file_row,column=1,sticky=Tkinter.W)
    251          file_row += 1
    252
    253          # Vision Egg user dir
    254          Tkinter.Label(file_frame,
    255                        text="Vision Egg user directory:").grid(row=file_row,column=0,sticky=Tkinter.E)
    256          Tkinter.Label(file_frame,
    257                        text="%s"%(os.path.abspath(VisionEgg.config.VISIONEGG_USER_DIR),)).grid(row=file_row,column=1,sticky=Tkinter.W)
    258          file_row += 1
    259
    260          # Config file
    261          Tkinter.Label(file_frame,
    262                        text="Config file location:").grid(row=file_row,column=0,sticky=Tkinter.E)
    263          if VisionEgg.config.VISIONEGG_CONFIG_FILE:
    264              Tkinter.Label(file_frame,
    265                            text="%s"%(os.path.abspath(VisionEgg.config.VISIONEGG_CONFIG_FILE),)).grid(row=file_row,column=1,sticky=Tkinter.W)
    266          else:
    267              Tkinter.Label(file_frame,
    268                            text="(None)").grid(row=file_row,column=1,sticky=Tkinter.W)
    269          file_row += 1
    270
    271          # Log file location
    272          Tkinter.Label(file_frame,
    273                        text="Log file location:").grid(row=file_row,column=0,sticky=Tkinter.E)
    274          if VisionEgg.config.VISIONEGG_LOG_FILE:
    275              Tkinter.Label(file_frame,
    276                            text="%s"%(os.path.abspath(VisionEgg.config.VISIONEGG_LOG_FILE),)).grid(row=file_row,column=1,sticky=Tkinter.W)
    277          else:
    278              Tkinter.Label(file_frame,
    279                            text="(stderr console)").grid(row=file_row,column=1,sticky=Tkinter.W)
    280
    281          ################## end file_frame ##############################
    282
    283          row += 1
    284
    285          ################## begin cf ##############################
    286
    287          cf = Tkinter.Frame(self)
    288          cf.grid(row=row,column=0,padx=10)
    289
    290          cf_row = 0
    291          # Fullscreen
    292          self.fullscreen = Tkinter.BooleanVar()
    293          self.fullscreen.set(VisionEgg.config.VISIONEGG_FULLSCREEN)
    294          Tkinter.Checkbutton(cf,
    295                              text='Fullscreen',
    296                              variable=self.fullscreen,
    297                              relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    298
    299          cf_row += 1
    300          self.synclync_present = Tkinter.BooleanVar()
    301          self.synclync_present.set(VisionEgg.config.SYNCLYNC_PRESENT)
    302          try:
    303              import synclync
    304              self.show_synclync_option = 1
    305          except:
    306              self.show_synclync_option = 0
    307
    308          if self.show_synclync_option:
    309              Tkinter.Checkbutton(cf,
    310                                  text='SyncLync device present',
    311                                  variable=self.synclync_present,
    312                                  relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    313
    314
    315          cf_row += 1
    316          # Maximum priority
    317          self.maxpriority = Tkinter.BooleanVar()
    318          self.maxpriority.set(VisionEgg.config.VISIONEGG_MAXPRIORITY)
    319
    320          Tkinter.Checkbutton(cf,
    321                              text='Maximum priority (use with caution)',
    322                              variable=self.maxpriority,
    323                              relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    324          cf_row += 1
    325
    326          if sys.platform=='darwin':
    327              # Only used on darwin platform
    328              self.darwin_conventional = Tkinter.IntVar()
    329              self.darwin_conventional.set(VisionEgg.config.VISIONEGG_DARWIN_MAXPRIORITY_CONVENTIONAL_NOT_REALTIME)
    330              self.darwin_priority = Tkinter.StringVar()
    331              self.darwin_priority.set(str(VisionEgg.config.VISIONEGG_DARWIN_CONVENTIONAL_PRIORITY))
    332              self.darwin_realtime_period_denom = Tkinter.StringVar()
    333              self.darwin_realtime_period_denom.set(str(VisionEgg.config.VISIONEGG_DARWIN_REALTIME_PERIOD_DENOM))
    334              self.darwin_realtime_computation_denom = Tkinter.StringVar()
    335              self.darwin_realtime_computation_denom.set(str(VisionEgg.config.VISIONEGG_DARWIN_REALTIME_COMPUTATION_DENOM))
    336              self.darwin_realtime_constraint_denom = Tkinter.StringVar()
    337              self.darwin_realtime_constraint_denom.set(str(VisionEgg.config.VISIONEGG_DARWIN_REALTIME_CONSTRAINT_DENOM))
    338              self.darwin_realtime_preemptible = Tkinter.BooleanVar()
    339              self.darwin_realtime_preemptible.set(not VisionEgg.config.VISIONEGG_DARWIN_REALTIME_PREEMPTIBLE)
    340              Tkinter.Button(cf,text="Maximum priority options...",
    341                             command=self.darwin_maxpriority_tune).grid(row=cf_row,column=0)
    342              cf_row += 1
    343
    344          # Sync swap
    345          self.sync_swap = Tkinter.BooleanVar()
    346          self.sync_swap.set(VisionEgg.config.VISIONEGG_SYNC_SWAP)
    347          Tkinter.Checkbutton(cf,
    348                              text='Attempt vsync',
    349                              variable=self.sync_swap,
    350                              relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    351          cf_row += 1
    352
    353          # Frameless window
    354          self.frameless = Tkinter.BooleanVar()
    355          self.frameless.set(VisionEgg.config.VISIONEGG_FRAMELESS_WINDOW)
    356          Tkinter.Checkbutton(cf,
    357                              text='No frame around window',
    358                              variable=self.frameless,
    359                              relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    360          cf_row += 1
    361
    362          # Hide mouse
    363          self.mouse_visible = Tkinter.BooleanVar()
    364          self.mouse_visible.set(not VisionEgg.config.VISIONEGG_HIDE_MOUSE)
    365          Tkinter.Checkbutton(cf,
    366                              text='Mouse cursor visible',
    367                              variable=self.mouse_visible,
    368                              relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    369          cf_row += 1
    370
    371          # Stereo
    372          self.stereo = Tkinter.BooleanVar()
    373          self.stereo.set(VisionEgg.config.VISIONEGG_REQUEST_STEREO)
    374          Tkinter.Checkbutton(cf,
    375                              text='Stereo',
    376                              variable=self.stereo,
    377                              relief=Tkinter.FLAT).grid(row=cf_row,column=0,sticky=Tkinter.W)
    378          cf_row += 1
    379
    380          if sys.platform == 'darwin':
    381              if sys.version == '2.2 (#11, Jan  6 2002, 01:00:42) \n[GCC 2.95.2 19991024 (release)]':
    382                  if Tkinter.TkVersion == 8.4:
    383                      # The Tk in Bob Ippolito's kitchensink distro had
    384                      # a bug in Checkbutton
    385                      Tkinter.Label(cf,text="If you want to check any buttons\n(Mac OS X Tk 8.4a4 bug workaround):").grid(row=cf_row,column=0)
    386                      cf_row += 1
    387                      Tkinter.Button(cf,text="PRESS ME FIRST").grid(row=cf_row,column=0)
    388                      cf_row += 1
    389
    390          ################## end cf ##############################
    391
    392          ################## begin entry_frame ###################
    393
    394          entry_frame = Tkinter.Frame(self)
    395          entry_frame.grid(row=row,column=1,padx=10,sticky="n")
    396          row += 1
    397          ef_row = 0
    398
    399          # frame rate
    400          Tkinter.Label(entry_frame,text="What will your monitor refresh's rate be (Hz):").grid(row=ef_row,column=0,sticky=Tkinter.E)
    401          self.frame_rate = Tkinter.StringVar()
    402          self.frame_rate.set("%s"%str(VisionEgg.config.VISIONEGG_MONITOR_REFRESH_HZ))
    403          Tkinter.Entry(entry_frame,textvariable=self.frame_rate).grid(row=ef_row,column=1,sticky=Tkinter.W)
    404          ef_row += 1
    405
    406          # width
    407          Tkinter.Label(entry_frame,text="Window width (pixels):").grid(row=ef_row,column=0,sticky=Tkinter.E)
    408          self.width = Tkinter.StringVar()
    409          self.width.set("%s"%str(VisionEgg.config.VISIONEGG_SCREEN_W))
    410          Tkinter.Entry(entry_frame,textvariable=self.width).grid(row=ef_row,column=1,sticky=Tkinter.W)
    411          ef_row += 1
    412
    413          # height
    414          Tkinter.Label(entry_frame,text="Window height (pixels):").grid(row=ef_row,column=0,sticky=Tkinter.E)
    415          self.height = Tkinter.StringVar()
    416          self.height.set("%s"%str(VisionEgg.config.VISIONEGG_SCREEN_H))
    417          Tkinter.Entry(entry_frame,textvariable=self.height).grid(row=ef_row,column=1,sticky=Tkinter.W)
    418          ef_row += 1
    419
    420          # color depth
    421          Tkinter.Label(entry_frame,text="Requested total color depth (bits per pixel):").grid(row=ef_row,column=0,sticky=Tkinter.E)
    422          self.color_depth = Tkinter.StringVar()
    423          self.color_depth.set(str(VisionEgg.config.VISIONEGG_PREFERRED_BPP))
    424          Tkinter.Entry(entry_frame,textvariable=self.color_depth).grid(row=ef_row,column=1,sticky=Tkinter.W)
    425          ef_row += 1
    426
    427          # red depth
    428          Tkinter.Label(entry_frame,text="Requested red bits per pixel:").grid(row=ef_row,column=0,sticky=Tkinter.E)
    429          self.red_depth = Tkinter.StringVar()
    430          self.red_depth.set(str(VisionEgg.config.VISIONEGG_REQUEST_RED_BITS))
    431          Tkinter.Entry(entry_frame,textvariable=self.red_depth).grid(row=ef_row,column=1,sticky=Tkinter.W)
    432          ef_row += 1
    433
    434          # green depth
    435          Tkinter.Label(entry_frame,text="Requested green bits per pixel:").grid(row=ef_row,column=0,sticky=Tkinter.E)
    436          self.green_depth = Tkinter.StringVar()
    437          self.green_depth.set(str(VisionEgg.config.VISIONEGG_REQUEST_GREEN_BITS))
    438          Tkinter.Entry(entry_frame,textvariable=self.green_depth).grid(row=ef_row,column=1,sticky=Tkinter.W)
    439          ef_row += 1
    440
    441          # blue depth
    442          Tkinter.Label(entry_frame,text="Requested blue bits per pixel:").grid(row=ef_row,column=0,sticky=Tkinter.E)
    443          self.blue_depth = Tkinter.StringVar()
    444          self.blue_depth.set(str(VisionEgg.config.VISIONEGG_REQUEST_BLUE_BITS))
    445          Tkinter.Entry(entry_frame,textvariable=self.blue_depth).grid(row=ef_row,column=1,sticky=Tkinter.W)
    446          ef_row += 1
    447
    448          # alpha depth
    449          Tkinter.Label(entry_frame,text="Requested alpha bits per pixel:").grid(row=ef_row,column=0,sticky=Tkinter.E)
    450          self.alpha_depth = Tkinter.StringVar()
    451          self.alpha_depth.set(str(VisionEgg.config.VISIONEGG_REQUEST_ALPHA_BITS))
    452          Tkinter.Entry(entry_frame,textvariable=self.alpha_depth).grid(row=ef_row,column=1,sticky=Tkinter.W)
    453          ef_row += 1
    454
    455          ################## end entry_frame ###################
    456
    457          ################## gamma_frame ###################
    458
    459          # gamma stuff
    460          row += 1
    461          gamma_frame = Tkinter.Frame(self)
    462          gamma_frame.grid(row=row,columnspan=2,sticky="we")
    463          self.gamma_source = Tkinter.StringVar()
    464          self.gamma_source.set(str(VisionEgg.config.VISIONEGG_GAMMA_SOURCE).lower()) # can be 'none', 'invert', or 'file'
    465          Tkinter.Label(gamma_frame,
    466                        text="Gamma:").grid(row=0,column=0)
    467          Tkinter.Radiobutton(gamma_frame,
    468                              text="Native",
    469                              value="none",
    470                              variable = self.gamma_source).grid(row=0,column=1,padx=1)
    471          Tkinter.Radiobutton(gamma_frame,
    472                              text="Quick",
    473                              value="invert",
    474                              variable = self.gamma_source).grid(row=0,column=2)
    475          Tkinter.Label(gamma_frame,
    476                        text="R:").grid(row=0,column=3)
    477          self.gamma_invert_red = Tkinter.DoubleVar()
    478          self.gamma_invert_red.set( VisionEgg.config.VISIONEGG_GAMMA_INVERT_RED )
    479          Tkinter.Entry(gamma_frame,
    480                        textvariable=self.gamma_invert_red,
    481                        width=3).grid(row=0,column=4)
    482          Tkinter.Label(gamma_frame,
    483                        text="G:").grid(row=0,column=5)
    484          self.gamma_invert_green = Tkinter.DoubleVar()
    485          self.gamma_invert_green.set( VisionEgg.config.VISIONEGG_GAMMA_INVERT_GREEN )
    486          Tkinter.Entry(gamma_frame,
    487                        textvariable=self.gamma_invert_green,
    488                        width=3).grid(row=0,column=6)
    489          Tkinter.Label(gamma_frame,
    490                        text="B:").grid(row=0,column=7)
    491          self.gamma_invert_blue = Tkinter.DoubleVar()
    492          self.gamma_invert_blue.set( VisionEgg.config.VISIONEGG_GAMMA_INVERT_BLUE )
    493          Tkinter.Entry(gamma_frame,
    494                        textvariable=self.gamma_invert_blue,
    495                        width=3).grid(row=0,column=8)
    496          Tkinter.Radiobutton(gamma_frame,
    497                              text="Custom:",
    498                              value="file",
    499                              variable = self.gamma_source).grid(row=0,column=9)
    500          self.gamma_file = Tkinter.StringVar()
    501          if os.path.isfile(VisionEgg.config.VISIONEGG_GAMMA_FILE):
    502              self.gamma_file.set( VisionEgg.config.VISIONEGG_GAMMA_FILE )
    503          else:
    504              self.gamma_file.set("")
    505          Tkinter.Entry(gamma_frame,
    506                        textvariable=self.gamma_file,
    507                        width=15).grid(row=0,column=10)
    508          Tkinter.Button(gamma_frame,
    509                         command=self.set_gamma_file,
    510                         text="Set...").grid(row=0,column=11)
    511
    512          ################## end gamma_frame ###################
    513
    514          row += 1
    515          bf = Tkinter.Frame(self)
    516          bf.grid(row=row,columnspan=2,sticky=Tkinter.W+Tkinter.E)
    517
    518          # Save settings to config file
    519          b = Tkinter.Button(bf,text="Save current settings to config file",command=self.save)
    520          b.grid(row=0,column=0,padx=20)
    521          b.bind('<Return>',self.start)
    522
    523          # Start button
    524          b2 = Tkinter.Button(bf,text="ok",command=self.start)
    525          b2.grid(row=0,column=1,padx=20)
    526          b2.focus_force()
    527          b2.bind('<Return>',self.start)
    528
    529          # Raise our application on darwin
    530          if sys.platform == 'darwin':
    531              try:
    532                  # from Jack Jansen email 20 April 2003
    533                  # WMAvailable() returns true if you can use the window
    534                  # manager, and as a side #effect it raises the
    535                  # application to the foreground.
    536                  import MacOS
    537                  if not MacOS.WMAvailable():
    538                      raise "Cannot reach the window manager"
    539              except:
    540                  pass
    541
    542 -    def set_gamma_file(self,dummy_arg=None):
    543          filename = tkFileDialog.askopenfilename(
    544              parent=self,
    545              defaultextension=".ve_gamma",
    546              filetypes=[('Configuration file','*.ve_gamma')],
    547              initialdir=VisionEgg.config.VISIONEGG_USER_DIR)
    548          if not filename:
    549              return
    550          self.gamma_file.set(filename)
    551
    552 -    def format_string(self,in_str):
    553          # This probably a slow way to do things, but it works!
    554          min_line_length = 60
    555          in_list = in_str.split()
    556          out_str = ""
    557          cur_line = ""
    558          for word in in_list:
    559              cur_line = cur_line + word + " "
    560              if len(cur_line) > min_line_length:
    561                  out_str = out_str + cur_line[:-1] + "\n"
    562                  cur_line = "    "
    563          out_str = out_str + cur_line + "\n"
    564          return out_str
    565
    566 -    def darwin_maxpriority_tune(self):
    567          class DarwinFineTuneDialog(ToplevelDialog):
    568              def __init__(self,parent,**cnf):
    569                  # Bugs in Tk 8.4a4 for Darwin seem to prevent use of "grid" in this dialog
    570                  ToplevelDialog.__init__(self,**cnf)
    571                  self.title("Fine tune maximum priority")
    572                  f = Tkinter.Frame(self)
    573                  f.pack(expand=1,fill=Tkinter.BOTH,ipadx=2,ipady=2)
    574                  row = 0
    575                  Tkinter.Label(f,
    576                                text=parent.format_string(
    577
    578                      """This information is used by the Vision Egg when
    579                      in "maximum priority" mode.  These values fine
    580                      tune this behavior on the Mac OS X ("darwin")
    581                      platform. For conventional priority, the valid
    582                      values range from -20 (highest priority) to 20
    583                      (worst priority).  In the realtime settings, the
    584                      numerical values represent a fraction of the total
    585                      cycles available on the computer. For more
    586                      information, please refer to
    587                      http://developer.apple.com/ techpubs/ macosx/
    588                      Darwin/ General/ KernelProgramming/ scheduler/
    589                      Using_Mach__pplications.html Hint: Try the
    590                      realtime task method with the framerate as the
    591                      denominator.  """
    592
    593                      )).grid(row=row,columnspan=4,column=0)
    594                  row = 1
    595  #                Tkinter.Checkbutton(f,text="Use conventional priority",variable=parent.darwin_conventional).grid(row=row,column=0,columnspan=4)
    596                  row = 2
    597  #                Tkinter.Label(f,text="Conventional priority settings").grid(row=row,column=0,columnspan=2)
    598                  Tkinter.Radiobutton(f,
    599                                text="Conventional priority method",
    600                                variable=parent.darwin_conventional,
    601                                value=1).grid(row=row,column=0,columnspan=2)
    602                  row += 1
    603                  Tkinter.Label(f,text="Priority").grid(row=row,column=0,sticky=Tkinter.E)
    604                  Tkinter.Entry(f,textvariable=parent.darwin_priority).grid(row=row,column=1,sticky=Tkinter.W)
    605                  row = 2
    606                  Tkinter.Radiobutton(f,
    607                                text="Realtime task method",
    608                                variable=parent.darwin_conventional,
    609                                value=0).grid(row=row,column=2,columnspan=2)
    610  #                Tkinter.Label(f,text="Realtime settings").grid(row=row,column=2,columnspan=2)
    611                  row += 1
    612                  Tkinter.Label(f,text="Realtime period denominator").grid(row=row,column=2,sticky=Tkinter.E)
    613                  Tkinter.Entry(f,textvariable=parent.darwin_realtime_period_denom).grid(row=row,column=3,sticky=Tkinter.W)
    614                  row += 1
    615                  Tkinter.Label(f,text="Realtime computation denominator").grid(row=row,column=2,sticky=Tkinter.E)
    616                  Tkinter.Entry(f,textvariable=parent.darwin_realtime_computation_denom).grid(row=row,column=3,sticky=Tkinter.W)
    617                  row += 1
    618                  Tkinter.Label(f,text="Realtime constraint denominator").grid(row=row,column=2,sticky=Tkinter.E)
    619                  Tkinter.Entry(f,textvariable=parent.darwin_realtime_constraint_denom).grid(row=row,column=3,sticky=Tkinter.W)
    620                  row += 1
    621                  Tkinter.Checkbutton(f,text="Do not preempt",variable=parent.darwin_realtime_preemptible).grid(row=row,column=2,columnspan=2)
    622                  row += 1
    623                  Tkinter.Button(f, text="ok",command=self.ok).grid(row=row,column=0,columnspan=4)
    624                  self.wait_window(self)
    625
    626              def ok(self):
    627                  self.destroy()
    628
    629          DarwinFineTuneDialog(parent=self)
    630
    631 -    def _set_config_values(self):
    632          VisionEgg.config.VISIONEGG_MONITOR_REFRESH_HZ = float(self.frame_rate.get())
    633          VisionEgg.config.VISIONEGG_FULLSCREEN = self.fullscreen.get()
    634          VisionEgg.config.VISIONEGG_GAMMA_SOURCE = self.gamma_source.get()
    635          VisionEgg.config.VISIONEGG_GAMMA_INVERT_RED = self.gamma_invert_red.get()
    636          VisionEgg.config.VISIONEGG_GAMMA_INVERT_GREEN = self.gamma_invert_green.get()
    637          VisionEgg.config.VISIONEGG_GAMMA_INVERT_BLUE = self.gamma_invert_blue.get()
    638          VisionEgg.config.VISIONEGG_GAMMA_FILE = self.gamma_file.get()
    639          VisionEgg.config.VISIONEGG_MAXPRIORITY = self.maxpriority.get()
    640          VisionEgg.config.VISIONEGG_SYNC_SWAP = self.sync_swap.get()
    641          VisionEgg.config.VISIONEGG_FRAMELESS_WINDOW = self.frameless.get()
    642          VisionEgg.config.VISIONEGG_HIDE_MOUSE = not self.mouse_visible.get()
    643          VisionEgg.config.VISIONEGG_REQUEST_STEREO = self.stereo.get()
    644          VisionEgg.config.VISIONEGG_SCREEN_W = int(self.width.get())
    645          VisionEgg.config.VISIONEGG_SCREEN_H = int(self.height.get())
    646          VisionEgg.config.VISIONEGG_PREFERRED_BPP = int(self.color_depth.get())
    647          VisionEgg.config.VISIONEGG_REQUEST_RED_BITS = int(self.red_depth.get())
    648          VisionEgg.config.VISIONEGG_REQUEST_GREEN_BITS = int(self.green_depth.get())
    649          VisionEgg.config.VISIONEGG_REQUEST_BLUE_BITS = int(self.blue_depth.get())
    650          VisionEgg.config.VISIONEGG_REQUEST_ALPHA_BITS = int(self.alpha_depth.get())
    651
    652          if sys.platform=='darwin':
    653              # Only used on darwin platform
    654              VisionEgg.config.VISIONEGG_DARWIN_MAXPRIORITY_CONVENTIONAL_NOT_REALTIME = self.darwin_conventional.get()
    655              VisionEgg.config.VISIONEGG_DARWIN_CONVENTIONAL_PRIORITY = int(self.darwin_priority.get())
    656              VisionEgg.config.VISIONEGG_DARWIN_REALTIME_PERIOD_DENOM = int(self.darwin_realtime_period_denom.get())
    657              VisionEgg.config.VISIONEGG_DARWIN_REALTIME_COMPUTATION_DENOM = int(self.darwin_realtime_computation_denom.get())
    658              VisionEgg.config.VISIONEGG_DARWIN_REALTIME_CONSTRAINT_DENOM = int(self.darwin_realtime_constraint_denom.get())
    659              VisionEgg.config.VISIONEGG_DARWIN_REALTIME_PREEMPTIBLE = int(not self.darwin_realtime_preemptible.get())
    660
    661          if self.show_synclync_option:
    662              VisionEgg.config.SYNCLYNC_PRESENT = self.synclync_present.get()
    663
    664 -    def save(self,dummy_arg=None):
    665          self._set_config_values()
    666          try:
    667              VisionEgg.Configuration.save_settings()
    668          except IOError, x:
    669              try:
    670                  import tkMessageBox
    671                  if str(x).find('Permission denied') != -1:
    672                      tkMessageBox.showerror(title="Permission denied",
    673                                             message="Permission denied when trying to save settings.\n\nTry making a copy of the config file in the Vision Egg user directory %s and making sure you have write permission."%(os.path.abspath(VisionEgg.config.VISIONEGG_USER_DIR),))
    674              except:
    675                  raise x
    676
    677 -    def start(self,dummy_arg=None):
    678          self.clicked_ok = 1
    679          self._set_config_values()
    680          for child in self.children.values():
    681              child.destroy()
    682          Tkinter.Tk.destroy(self.master) # OK, now close myself
    683
    684 -class InfoFrame(Tkinter.Frame):
    685 -    def __init__(self,master=None,**cnf):
    686          VisionEgg.config._Tkinter_used = True
    687          Tkinter.Frame.__init__(self,master,**cnf)
    688
    689          Tkinter.Label(self,text="Vision Egg information:").pack()
    690          self.sub_frame = Tkinter.Frame(self,relief=Tkinter.GROOVE)
    691          self.sub_frame.pack()
    692          self.update()
    693
    694 -    def update(self):
    695          for child in self.sub_frame.children.values():
    696              child.destroy()
    697          if VisionEgg.config.VISIONEGG_FULLSCREEN:
    698              Tkinter.Label(self.sub_frame,text="fullscreen mode").pack()
    699          else:
    700              Tkinter.Label(self.sub_frame,text="window mode").pack()
    701  ##        if VisionEgg.config.VISIONEGG_TEXTURE_COMPRESSION:
    702  ##            Tkinter.Label(self.sub_frame,text="Texture compression on").pack()
    703  ##        else:
    704  ##            Tkinter.Label(self.sub_frame,text="Texture compression off").pack()
    705
    706          #Tkinter.Button(self.sub_frame,text="Update information",command=self.update).pack()
    707
    708 -class ToplevelDialog(Tkinter.Toplevel):
    709      """Base class for a dialog that runs on the top level."""
    710 -    def __init__(self,**kw):
    711          VisionEgg.config._Tkinter_used = True
    712          Tkinter.Toplevel.__init__(self,**kw)
    713          self.transient(self)
    714
    715 -    def destroy(self):
    716          Tkinter.Toplevel.destroy(self)
    717
    718 -class GetKeypressDialog(ToplevelDialog):
    719      """Open a dialog box which returns when a valid key is pressed.
    720
    721      Arguments are:
    722      master - a Tkinter widget (defaults to None)
    723      title - a string for the title bar of the widget
    724      text - a string to display as the text in the body of the dialog
    725      key_list - a list of acceptable keys, e.g. ['q','1','2','<Return>']
    726
    727      The following example will print whatever character was pressed:
    728      d = GetKeypressDialog(key_list=['q','1','2','<Return>','<Escape>'])
    729      print d.result
    730
    731      The implementation is somewhat obscure because a new Tk/Tcl
    732      interpreter may be created if this Dialog is called with no
    733      master widget."""
    734 -    def __init__(self,
    735                   title="Press a key",
    736                   text="Press a key",
    737                   key_list=[],
    738                   **kw):
    739
    740          ToplevelDialog.__init__(self,**kw)
    741          self.title(title)
    742          self.result = None
    743
    744          # The dialog box body
    745          Tkinter.Label(self.frame, text=text).pack()
    746
    747          for key in key_list:
    748              self.bind(key,self.keypress)
    749          self.wait_window(self)
    750
    751 -    def keypress(self,tkinter_event):
    752          self.result = tkinter_event.keysym
    753          self.destroy()
    754