Package nMOLDYN :: Package GUI :: Module Widgets |
[hide private]
[frames] | no frames]

# Source Code for Module nMOLDYN.GUI.Widgets

       1  """This module implements all classes used for the generation of combo widgets.
       2
       3  A combo widget can be defined as a label frame encapsulating several other Tkinter widgets.
       4
       5  Classes:
       6      * ValidatingEntry   : sets up a Tkinter Entry widget that checks its contents whenever it is changed.
       7      * IntegerEntry      : sets up a Tkinter Entry widget that checks that the input is an integer.
       8      * FloatEntry        : sets up a Tkinter Entry widget that checks that the input is a float.
       9      * StringEntry       : sets up a Tkinter Entry widget that checks that the input is a string matching a given pattern.
      10      * ComboLabelEntry   : sets up a combo widget made of a Tkinter Label widget embedded in a Tkinter LabelFrame widget.
      11      * ComboIntegerEntry : sets up a combo widget made of a Tkinter Label widget and IntegerEntry combo widget embedded
      12        in a Tkinter LabelFrame widget.
      13      * ComboFloatEntry   : sets up a combo widget made of a Tkinter Label widget and FloatEntry embedded in a Tkinter
      14        LabelFrame widget.
      15      * ComboStringEntry  : sets up a combo widget made of a Tkinter Label widget and StringEntry embedded in a Tkinter
      16        LabelFrame widget.
      17      * ComboRadiobutton  : sets up a combo widget made of a Tkinter Label widget and a set of Tkinter RadioButton widgets
      18        embedded in a Tkinter LabelFrame widget.
      19      * ComboCheckbutton  : sets up a combo widget made of a Tkinter Label widget and a Tkinter CheckButton widget embedded
      20        in a Tkinter LabelFrame widget.
      21      * ComboOptionMenu   : sets up a combo widget made of a Tkinter Label widget and a Tkinter OptionMenu widget embedded
      22        in a Tkinter LabelFrame widget.
      23      * ComboSpinbox      : sets up a combo widget made of a Tkinter Label widget and a Tkinter Spinbox widget embedded in
      24        a Tkinter LabelFrame widget.
      25      * ComboScale        : sets up a combo widget made of a Tkinter Label widget and a Tkinter Scale widget embedded in
      26        a Tkinter LabelFrame widget.
      27      * ComboButton       : sets up a combo widget made of a Tkinter Button widget and optionnally a Tkinter Entry widget embedded
      28        in a Tkinter LabelFrame widget.
      29      * ComboFileBrowser  : sets up a combo widget made of a Tkinter Label widget, a StringEntry widget and a Tkinter Button
      30        widget for file browsing embedded in a Tkinter LabelFrame widget.
      31      * ComboText         : sets up a combo widget made of a Tkinter Text and a vertical Tkinter Scrollbar widget widget embedded in a
      32        Tkinter LabelFrame widget.
      33      * ComboListbox      : sets up a combo widget made of a Tkinter Listbox widget and a vertical Tkinter Scrollbar widget embedded
      34        in a Tkinter LabelFrame widget.
      35      * StatusBar         : sets up a combo widget made of a Tkinter Scale widget embedded in a Tkinter Frame
      36        widget.
      37
      38
      39  The following classes were adapted from the implementation of Frederic Lundh:
      40      - ValidatingEntry
      41      - IntegerEntry
      42      - FloatEntry
      43  """
      44
      45  # The python distribution modules
      46  import os
      47  import re
      48  import subprocess
      49  import sys
      50  import xml.dom.minidom
      51
      52  # The Tcl/Tk modules
      53  from Tkinter import *
      54  from tkFileDialog import askopenfilename, asksaveasfilename
      55  import tkMessageBox
      56
      57  # The nMOLDYN modules
      58  from nMOLDYN.Core.Error import Error
      59  from nMOLDYN.Core.Logger import LogMessage
      60  from nMOLDYN.Core.Preferences import PREFERENCES
      61  from nMOLDYN.GUI.HTMLReader.tkhtml import tkHTMLViewer
      62  from nMOLDYN.GUI.Tags import tags
      63
      64  # Package path
      65  nmoldyn_package_path = os.path.dirname(os.path.split(__file__)[0])
      66
      67 -class ValidatingEntry(Entry):
      68      """Base class for |IntegerEntry|, |FloatEntry| and |StringEntry| widgets
      69      """
      70
      71 -    def __init__(self, master, contents = '', **kwargs):
      72          """The constructor.
      73
      74          @param master: the parent widget.
      75
      76          @param contents: the contents of the Tkinter Entry widget.
      77          @type contents: string
      78          """
      79
      80          Entry.__init__(self, master, **kwargs)
      81          self.variable = StringVar()
      82          self.variable.trace('w', self.__callback)
      83          self.variable.set(contents)
      84          self._contents = contents
      85
      86          self.config(textvariable = self.variable, bg = 'white')
      87
      88          self.bind('<Return>', lambda event: self.checkValue(event, self.variable.get()))
      89          self.bind('<Tab>', lambda event : self.checkValue(event, self.variable.get()))
      90
      91 -    def __callback(self, *dummy):
      92          contents = self.variable.get()
      93          newContents = self.checkValue(contents = contents)
      94          if newContents is not None:
      95              self._contents = newContents
      96          self.variable.set(self._contents)
      97
      98 -    def checkValue(self, event = None, contents = None):
      99          pass
     100
     101 -    def setValue(self, value):
     102          """Sets the value of the control variable linked to the Tkinter Entry widget.
     103          """
     104
     105          self.variable.set(value)
     106
     107 -    def getValue(self):
     108          """Returns the value of the control variable linked to the Tkinter Entry widget.
     109          """
     110          return self.variable.get()
     111
     112 -class IntegerEntry(ValidatingEntry):
     113      """Sets up a Tkinter Entry widget that accepts only integer values.
     114
     115      @note: subclass of nMOLDYN.GUI.Widgets.ValidatingEntry class.
     116      """
     117
     118 -    def checkValue(self, event = None, contents = None):
     119          """Check that the contents of the Tkinter Entry widget is actually an integer.
     120
     121          @param event: the keyboard event that triggers the checking of the contents of the Tkinter Entry widget.
     122          @type event: a Tkinter.Event object
     123
     124          @param contents: the contents of the Tkinter Entry widget to check.
     125          @type contents: integer
     126          """
     127
     128          if contents == '':
     129              return ''
     130
     131          try:
     132              return int(contents)
     133          except:
     134              return None
     135
     136 -    def setValue(self, value = None):
     137          """Sets the value of the control variable linked to the Tkinter Entry widget.
     138          """
     139
     140          v = self.checkValue(contents = value)
     141          if v is not None:
     142              self.variable.set(v)
     143
     144 -    def getValue(self):
     145          """Returns the value of the control variable linked to the Tkinter Entry widget if it is an integer otherwise
     146          throws an error.
     147          """
     148          try:
     149              return int(self.variable.get())
     150          except ValueError:
     151              raise Error('%s is not an integer' % self.variable.get())
     152
     153 -class FloatEntry(ValidatingEntry):
     154      """Sets up a Tkinter Entry widget that accepts only float values.
     155
     156      @note: subclass of nMOLDYN.GUI.Widgets.ValidatingEntry class.
     157      """
     158
     159 -    def checkValue(self, event = None, contents = None):
     160          """Check that the contents of the Tkinter Entry widget is actually a float.
     161
     162          @param event: the keyboard event that triggers the checking of the contents of the Tkinter Entry widget.
     163          @type event: a Tkinter.Event object
     164
     165          @param contents: the contents of the Tkinter Entry widget to check.
     166          @type contents: float
     167          """
     168
     169          if contents == '':
     170              return ''
     171
     172          try:
     173              return float(contents)
     174          except:
     175              return None
     176
     177 -    def setValue(self, value):
     178          """Sets the value of the control variable linked to the Tkinter Entry widget.
     179          """
     180
     181          v = self.checkValue(contents = value)
     182          if v is not None:
     183              self.variable.set(v)
     184
     185 -    def getValue(self):
     186          """Returns the value of the control variable linked to the Tkinter Entry widget if it is a float otherwise
     187          throws an error.
     188          """
     189          try:
     190              return float(self.variable.get())
     191          except ValueError:
     192              raise Error('%s is not a float' % self.variable.get())
     193
     194 -class StringEntry(ValidatingEntry):
     195      """Sets up a Tkinter Entry widget that accepts only string values.
     196
     197      @note: subclass of nMOLDYN.GUI.Widgets.ValidatingEntry class.
     198      """
     199
     200 -    def __init__(self, master, contents = '', pattern = None, **kwargs):
     201          """The constructor.
     202
     203          @param master: the parent widget.
     204
     205          @param contents: the contents of the Tkinter Entry widget.
     206          @type contents: string
     207
     208          @param pattern: if not None, a string specifying a pattern the contents of the Tkinter Entry widget has to
     209              fulfill.
     210          @type pattern:string
     211          """
     212
     213          self.pattern = pattern
     214          ValidatingEntry.__init__(self, master, contents, **kwargs)
     215
     216 -    def checkValue(self, event = None, contents = None):
     217          """Check that the contents of the Tkinter Entry widget is actually a string that possibly match the
     218          |self.pattern| pattern it is not None..
     219
     220          @param event: the keyboard event that triggers the checking of the contents of the Tkinter Entry widget.
     221          @type event: a Tkinter.Event object
     222
     223          @param contents: the contents of the Tkinter Entry widget to check.
     224          @type contents: string
     225          """
     226          if self.pattern is None:
     227              return contents
     228
     229          if self.variable.get():
     230              if not re.findall(self.pattern, self.variable.get()):
     231                  LogMessage('warning','%s does not math the pattern %s' % (self.variable.get(), self.pattern),['gui'])
     232                  return None
     233              else:
     234                  return contents
     235
     236 -    def getValue(self):
     237          """Returns the value of the control variable linked to the Tkinter Entry widget if it is a string otherwise
     238          throws an error.
     239          """
     240          try:
     241              if self.variable.get():
     242                  return str(self.variable.get())
     243              else:
     244                  return None
     245          except:
     246              raise Error('%s is not a string' % self.variable.get())
     247
     248 -class ComboFrame(LabelFrame):
     249      """Sets up a Tkinter LabelFrame widget.
     250
     251      Some bindings are set by default:
     252          - Tkinter '<Motion>' Event will change the mouse cursor to 'question_arrow' symbol.
     253          - Tkinter '<Leave>' Event will change the mouse cursor to 'arrow' symbol when leaving the widget.
     254          - Tkinter '<Button-1>' Event will give some information about the widget when clicking on it.
     255      """
     256
     257 -    def __init__(self, master, frameLabel = '', tagName = ''):
     258          """The constructor.
     259          """
     260          LabelFrame.__init__(self, master, relief = GROOVE, bd = 2)
     261          self.frameLabel = frameLabel
     262          self.tagName = tagName
     263          if self.frameLabel:
     264              # The label of the LabelFrame is a Label widget.
     265              self.label = Label(self, text = self.frameLabel)
     266              self.config(labelwidget = self.label)
     267              # Some bindings for the Label widget of the LabelFrame.
     268              self.label.bind('<Motion>', lambda event : changeMouseCursor(event,'question_arrow'))
     269              self.label.bind('<Leave>', lambda event : changeMouseCursor(event,'arrow'))
     270              self.label.bind('<Button-1>', informationAboutWidget)
     271
     272 -class ComboLabel(ComboFrame):
     273      """Sets up a combo widget made of a Tkinter Label widget embedded in a Tkinter LabelFrame widget.
     274      """
     275
     276 -    def __init__(self, master, frameLabel = '', tagName = '', contents = ''):
     277          """The constructor.
     278
     279          @param master: the parent widget of the combo widget.
     280
     281          @param frameLabel: the label for the Tkinter LabelFrame widget.
     282          @type frameLabel: string or Tkinter.StringVar object.
     283
     284          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     285          @type tagLabel: string.
     286
     287          @param contents: the contents of the Tkinter Label widget.
     288          @type contents: string
     289          """
     290
     291          # The comboframe is set up.
     292          ComboFrame.__init__(self, master, frameLabel, tagName)
     293
     294          self.labelVar = StringVar()
     295          self.labelVar.set(str(contents))
     296
     297          # The label is set up.
     298          self.label = Label(self, textvariable = self.labelVar, bd = 2, relief = GROOVE, anchor = W, width = len(self.labelVar.get()))
     299          self.label.grid(row = 0, column = 0, sticky = E, padx = 3)
     300
     301 -    def getValue(self):
     302          """Returns the value of the Tkinter Label widget.
     303          """
     304          return self.labelVar.get()
     305
     306 -    def setValue(self, value):
     307          """Returns the value of the Tkinter Label widget.
     308          """
     309          return self.labelVar.set(value)
     310
     311 -class ComboIntegerEntry(ComboFrame):
     312      """Sets up a combo widget made of a Tkinter Label widget and a IntegerEntry widget embedded in a Tkinter LabelFrame
     313      widget.
     314      """
     315
     316 -    def __init__(self, master, frameLabel = '', tagName = '', contents = ''):
     317          """The constructor.
     318
     319          @param master: the parent widget of the combo widget.
     320
     321          @param frameLabel: the label for the Tkinter LabelFrame widget.
     322          @type frameLabel: string or Tkinter.StringVar object.
     323
     324          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     325          @type tagLabel: string.
     326
     327          @param contents: the contents of the IntegerEntry widget.
     328          @type contents: integer
     329          """
     330
     331          # The comboframe is set up.
     332          ComboFrame.__init__(self, master, frameLabel, tagName)
     333
     334          self.entry = IntegerEntry(self, contents, width = 10)
     335          self.entry.grid(row = 0, column = 0, sticky = E, padx = 3)
     336
     337 -    def getValue(self):
     338          """Returns the value of the IntegerEntry widget.
     339          """
     340          return self.entry.getValue()
     341
     342 -    def setValue(self, value):
     343          """Sets the value of the IntegerEntry widget to |value| (integer).
     344
     345          @param value: the contents to insert in the IntegerEntry widget.
     346          @type value: integer
     347          """
     348          self.entry.setValue(value)
     349
     350 -class ComboFloatEntry(ComboFrame):
     351      """Sets up a combo widget made of a Tkinter Label widget and a FloatEntry widget embedded in a Tkinter LabelFrame
     352      widget.
     353      """
     354 -    def __init__(self, master, frameLabel = '', tagName = '', contents = ''):
     355          """The constructor.
     356
     357          @param master: the parent widget of the combo widget.
     358
     359          @param frameLabel: the label for the Tkinter LabelFrame widget.
     360          @type frameLabel: string or Tkinter.StringVar object.
     361
     362          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     363          @type tagLabel: string.
     364
     365          @param contents: the contents of the FloatEntry widget.
     366          @type contents: float
     367          """
     368
     369          # The comboframe is set up.
     370          ComboFrame.__init__(self, master, frameLabel, tagName)
     371
     372          self.entry = FloatEntry(self, contents, width = 10)
     373          self.entry.grid(row = 0, column = 0, sticky = E, padx = 3)
     374
     375 -    def getValue(self):
     376          """Returns the value of the FloatEntry widget.
     377          """
     378          return self.entry.getValue()
     379
     380 -    def setValue(self, value):
     381          """Sets the value of the FloatEntry widget to |value| (float).
     382
     383          @param value: the contents to insert in the FloatEntry widget.
     384          @type value: float
     385          """
     386          self.entry.setValue(value)
     387
     388 -class ComboStringEntry(ComboFrame):
     389      """Sets up a combo widget made of a Tkinter Label widget and a StringEntry widget embedded in a Tkinter LabelFrame
     390      widget.
     391      """
     392 -    def __init__(self, master, frameLabel = '', tagName = '', contents = '', pattern = None):
     393          """The constructor.
     394
     395          @param master: the parent widget of the combo widget.
     396
     397          @param frameLabel: the label for the Tkinter LabelFrame widget.
     398          @type frameLabel: string or Tkinter.StringVar object.
     399
     400          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     401          @type tagLabel: string.
     402
     403          @param contents: the contents of the StringEntry widget.
     404          @type contents: string
     405
     406          @param pattern: if not None, a string specifying a pattern the contents of the Tkinter Entry widget has
     407              to fulfill.
     408          @type pattern:string
     409          """
     410
     411          # The comboframe is set up.
     412          ComboFrame.__init__(self, master, frameLabel, tagName)
     413
     414          self.entry = StringEntry(self, contents, pattern, width = 30)
     415          self.entry.grid(row = 0, column = 0, sticky = E, padx = 3)
     416
     417 -    def getValue(self):
     418          """Returns the value of the StringEntry widget.
     419          """
     420          return self.entry.getValue()
     421
     422 -    def setValue(self, value):
     423          """Sets the value of the StringEntry widget to |value| (string).
     424
     425          @param value: the contents to insert in the StringEntry widget.
     426          @type value: string
     427          """
     428          self.entry.setValue(value)
     429
     430 -class ComboRadiobutton(ComboFrame):
     431      """Sets up a combo widget made of a Tkinter Label widget and a set of Tkinter RadioButton widgets
     432      embedded in a Tkinter LabelFrame widget.
     433      """
     434
     435 -    def __init__(self, master, frameLabel = '', tagName = '', contents = [], default = 0, layout = None):
     436          """The constructor.
     437
     438          @param master: the parent widget of the combo widget.
     439
     440          @param frameLabel: the label for the Tkinter LabelFrame widget.
     441          @type frameLabel: string or Tkinter.StringVar object.
     442
     443          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     444          @type tagLabel: string.
     445
     446          @param contents: a list (string) specifying the names of each Tkinter Radiobutton widget.
     447          @type contents: list
     448
     449          @param default: an integer specifying which Tkinter Radiobutton widget will be switched on by default.
     450          @type default: integer
     451
     452          @param layout: a tuple (integer) of the form (nrows,ncolumns) specifying the way the set of Tkinter Radiobutton widget will be displayed.
     453          @type layout: tuple
     454          """
     455
     456          # The comboframe is set up.
     457          ComboFrame.__init__(self, master, frameLabel, tagName)
     458
     459          # At least one radiobutton must be provided.
     460          if len(contents) == 0:
     461              raise Error('No radiobutton given to set up.')
     462
     463          self.contents = contents
     464          self.radioVar = StringVar()
     465          self.radioVar.set(self.contents[default])
     466
     467          radioFrame = Frame(self)
     468          radioFrame.grid(row = 0, column = 0, sticky = E, padx = 3)
     469
     470          self.radio = []
     471          # If no |layout| argument is given, then build the radiobutton on a single row.
     472          if layout is None:
     473              row = 0
     474              for v in contents:
     475                  self.radio.append(Radiobutton(radioFrame,\
     476                                                text = v,\
     477                                                variable = self.radioVar,\
     478                                                value = v,\
     479                                                width = 14,\
     480                                                justify = LEFT,\
     481                                                anchor = W))
     482                  self.radio[-1].radio.grid(row = row, sticky = W)
     483                  row += 1
     484          else:
     485              nrows, ncols = layout
     486              for r in range(nrows):
     487                  for c in range(ncols):
     488                      ind = r*ncols + c
     489                      if ind < len(contents):
     490                          self.radio.append(Radiobutton(radioFrame,\
     491                                                        text = contents[r*ncols + c],\
     492                                                        variable = self.radioVar,\
     493                                                        value = contents[r*ncols + c],\
     494                                                        width = 14,\
     495                                                        justify = LEFT,\
     496                                                        anchor = W))
     497                          self.radio[-1].grid(row = r, column = c, sticky = W)
     498
     499 -    def getValue(self):
     500          """Returns the value of the control variable linked to the set of Tkinter Radiobutton widgets.
     501          """
     502          return str(self.radioVar.get())
     503
     504 -    def setValue(self, value):
     505          """Sets the value of the control variable linked to the set of Tkinter Radiobutton widgets.
     506
     507          @param value: the value the control variable linked to the set of Tkinter Radiobutton widgets will take.
     508              Must be an element of |self.contents|
     509          @type value: string
     510          """
     511          if value in self.contents:
     512              self.radioVar.set(value)
     513          else:
     514              self.radioVar.set(self.contents[0])
     515
     516 -class ComboCheckbutton(ComboFrame):
     517      """Sets up a combo widget made of a Tkinter Label widget and a set of Tkinter Checkbutton widget
     518      embedded in a Tkinter LabelFrame widget.
     519      """
     520
     521 -    def __init__(self, master, frameLabel = '', tagName = '', contents = '', onvalue = True, offvalue = False, default = False):
     522          """The constructor.
     523
     524          @param master: the parent widget of the combo widget.
     525
     526          @param frameLabel: the label for the Tkinter LabelFrame widget.
     527          @type frameLabel: string or Tkinter.StringVar object.
     528
     529          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     530          @type tagLabel: string.
     531
     532          @param contents: the name of the Tkinter Checkbutton widget.
     533          @type contents: string
     534
     535          @param onvalue: the value of the Tkinter Checkbutton widget when switched on.
     536          @type onvalue: boolean, integer or string
     537
     538          @param offvalue: the value of the Tkinter Checkbutton widget when switched off.
     539          @type offvalue: boolean, integer or string
     540
     541          @param default: a boolean specifying whether the Tkinter Checkbutton widget is switched on (True) or switched off (False)
     542              by default.
     543          @type default: boolean
     544          """
     545
     546          # The comboframe is set up.
     547          ComboFrame.__init__(self, master, frameLabel, tagName, )
     548
     549          checkFrame = Frame(self)
     550          checkFrame.grid(row = 0, column = 0, sticky = E, padx = 3)
     551
     552          self.offvalue = offvalue
     553          self.onvalue = onvalue
     554
     555          if isinstance(self.onvalue, str):
     556              self.checkVar = StringVar()
     557
     558          elif isinstance(self.onvalue, bool):
     559              self.checkVar = BooleanVar()
     560
     561          elif isinstance(self.onvalue, int):
     562              self.checkVar = IntVar()
     563
     564          else:
     565              raise Error('%s can not be used to define the state of a checkbutton.' % onvalue)
     566
     567          if onvalue.__class__ != offvalue.__class__:
     568              raise Error('%s and %s must be of the same class to setup properly the checkbutton.' % (offvalue, onvalue))
     569
     570          if default:
     571              self.checkVar.set(self.onvalue)
     572
     573          else:
     574              self.checkVar.set(self.offvalue)
     575
     576          self.check = Checkbutton(checkFrame,\
     577                                   text = contents,\
     578                                   textvariable = self.checkVar,\
     579                                   variable = self.checkVar,\
     580                                   onvalue = onvalue,\
     581                                   offvalue = offvalue,\
     582                                   width = 8,\
     583                                   justify = LEFT)
     584          self.check.grid(sticky = E)
     585
     586 -    def getValue(self):
     587          """Returns the value of the control variable linked to the Tkinter Checkbutton widget.
     588          """
     589          return self.checkVar.get()
     590
     591 -    def setValue(self, value):
     592          """Sets the value of the control variable linked to the Tkinter Checkbutton widget.
     593
     594          @param value: the value the control variable linked to the Tkinter Checkbutton widget will take.
     595              Must be an element of |self.contents|
     596          @type value: string
     597          """
     598          try:
     599              self.checkVar.set(value)
     600
     601          except:
     602              self.checkVar.set(self.offvalue)
     603
     604 -class ComboOptionMenu(ComboFrame):
     605      """Sets up a combo widget made of a Tkinter Label widget and a Tkinter OptionMenu widget embedded
     606      in a Tkinter LabelFrame widget.
     607      """
     608
     609 -    def __init__(self, master, frameLabel = '', tagName = '', contents = [], default = 0):
     610          """The constructor.
     611
     612          @param master: the parent widget of the combo widget.
     613
     614          @param frameLabel: the label for the Tkinter LabelFrame widget.
     615          @type frameLabel: string or Tkinter.StringVar object.
     616
     617          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     618          @type tagLabel: string.
     619
     620          @param contents: a list (string) specifying the names of for the entries each Tkinter OptionMenu widget.
     621          @type contents: list
     622
     623          @param default: an integer specifying which entry of the Tkinter optionMenu widget will be displayed by default.
     624          @type default: integer
     625          """
     626
     627          # The comboframe is set up.
     628          ComboFrame.__init__(self, master, frameLabel, tagName)
     629
     630          # At least one option must be provided.
     631          if len(contents) == 0:
     632              raise Error('No option given to set up this combowidget.')
     633
     634          # The frame that will host the option menu widget is set up.
     635          optionFrame = Frame(self)
     636          optionFrame.grid(row = 0, column = 1, sticky = E, padx = 3)
     637
     638          self.contents = contents
     639          self.optionVar = StringVar()
     640          self.optionVar.set(self.contents[default])
     641
     642          self.option = OptionMenu(optionFrame, self.optionVar, *contents)
     643          self.option.grid(sticky = E)
     644
     645 -    def getValue(self):
     646          """Returns the value of the control variable linked to the Tkinter OptionMenu widget.
     647          """
     648          return str(self.optionVar.get())
     649
     650 -    def setValue(self, value):
     651          """Sets the value of the control variable linked to the Tkinter OptionMenu widget.
     652
     653          @param value: the value the control variable linked to the Tkinter OptionMenu widget will take.
     654              Must be an element of |self.contents|
     655          @type value: string
     656          """
     657          if value in self.contents:
     658              self.optionVar.set(value)
     659          else:
     660              self.optionVar.set(self.contents[0])
     661
     662 -class ComboSpinbox(ComboFrame):
     663      """Sets up a combo widget made of a Tkinter Label widget and a Tkinter Spinbox widget embedded
     664      in a Tkinter LabelFrame widget.
     665      """
     666
     667 -    def __init__(self, master, frameLabel = '', tagName = '', contents = [], default = 0):
     668          """The constructor.
     669
     670          @param master: the parent widget of the combo widget.
     671
     672          @param frameLabel: the label for the Tkinter LabelFrame widget.
     673          @type frameLabel: string or Tkinter.StringVar object.
     674
     675          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     676          @type tagLabel: string.
     677
     678          @param contents: a tuple (string) specifying the names of for the entries to insert in the Tkinter Spinbox widget.
     679          @type contents: tuple
     680
     681          @param default: an integer specifying which entry of the Tkinter Spinbox widget will be displayed by default.
     682          @type default: integer
     683          """
     684
     685          # The comboframe is set up.
     686          ComboFrame.__init__(self, master, frameLabel, tagName)
     687
     688          # At least one option must be provided.
     689          if len(contents) == 0:
     690              raise Error('No option given to set up this combowidget.')
     691
     692          self.type = type(contents[0])
     693          for v in contents:
     694              if type(v) != self.type:
     695                  self.type = str
     696
     697          # The frame that will host the option menu widget is set up.
     698          spinboxFrame = Frame(self)
     699          spinboxFrame.grid(row = 0, column = 1, sticky = E, padx = 3)
     700
     701          self.contents = contents
     702          self.default = default
     703
     704          self.spinbox = Spinbox(spinboxFrame, values = self.contents, wrap = True, width = 4, bg = 'white')
     705          self.spinbox.grid(sticky = E)
     706
     707          self.setValue(self.contents[self.default])
     708
     709 -    def getValue(self):
     710          """Returns the value of the control variable linked to the Tkinter Spinbox widget.
     711          """
     712          return self.type(self.spinbox.get())
     713
     714 -    def setValue(self, value):
     715          """Sets the value of the control variable linked to the Tkinter Spinbox widget.
     716
     717          @param value: the value the control variable linked to the Tkinter Spinbox widget will take.
     718              Must be an element of |self.contents|
     719          @type value: string
     720          """
     721
     722          if value in self.contents:
     723              v = self.type(self.spinbox.get())
     724              while v != value:
     725                  self.spinbox.invoke('buttonup')
     726                  v = self.type(self.spinbox.get())
     727
     728 -class ComboScale(ComboFrame):
     729      """Sets up a combo widget made of a Tkinter Label widget and a Tkinter Scale widget embedded
     730      in a Tkinter LabelFrame widget.
     731      """
     732
     733 -    def __init__(self, master, frameLabel = '', tagName = '', contents = []):
     734          """The constructor.
     735
     736          @param master: the parent widget of the combo widget.
     737
     738          @param frameLabel: the label for the Tkinter LabelFrame widget.
     739          @type frameLabel: string or Tkinter.StringVar object.
     740
     741          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     742          @type tagLabel: string.
     743
     744          @param contents: a 3 elements list (integer) specifying respectively the first, the last and the resolution values
     745              for the Tkinter Scale widget.
     746          @type contents: list
     747          """
     748
     749          # The comboframe is set up.
     750          ComboFrame.__init__(self, master, frameLabel, tagName)
     751
     752          # At least one option must be provided.
     753          if len(contents) == 0:
     754              raise Error('No values given to set up this combowidget.')
     755
     756          self.from_, self.to, self.resolution = contents
     757
     758          self.scale = Scale(self, from_ = self.from_, to = self.to, resolution = self.resolution, length = 200, orient = HORIZONTAL)
     759          self.scale.grid(row = 0, column = 0, sticky = E, padx = 3)
     760
     761 -    def getValue(self):
     762          """Returns the value of the control variable linked to the Tkinter Scale widget.
     763          """
     764          return self.scale.get()
     765
     766 -    def setValue(self, value):
     767          """Sets the value of the control variable linked to the Tkinter Scale widget.
     768
     769          @param value: the value the Tkinter Scale widget will take.
     770          @type value: integer
     771          """
     772          self.scale.set(value)
     773
     774 -class ComboButton(ComboFrame):
     775      """Sets up a combo widget made of a Tkinter Button widget and optionnally a Tkinter Entry widget embedded
     776      in a Tkinter LabelFrame widget.
     777      """
     778
     779 -    def __init__(self, master, frameLabel = '', tagName = '', contents = '', withEntry = None, command = None):
     780          """The constructor.
     781
     782          @param master: the parent widget of the combo widget.
     783
     784          @param frameLabel: the label for the Tkinter LabelFrame widget.
     785          @type frameLabel: string or Tkinter.StringVar object.
     786
     787          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     788          @type tagLabel: string.
     789
     790          @param contents: string specifying the label of the Tkinter Button widget.
     791          @type contents: string
     792
     793          @param withEntry: if not None, a Tkinter Entry widget will be placed beside the Tkinter Button
     794              with |withEntry| as contents.
     795          @type withEntry: boolean
     796
     797          @param command: the function to call when clicking on the Tkinter Button widget.
     798          @type command: function
     799          """
     800
     801          # The comboframe is set up.
     802          ComboFrame.__init__(self, master, frameLabel, tagName)
     803
     804          self.withEntry = withEntry
     805
     806          self.results = None
     807          self.command = command
     808
     809          if self.withEntry:
     810              # The entry widget is set up.
     811              self.entry = StringEntry(self, self.withEntry, width = 60)
     812              self.entry.grid(row = 0, column = 0, sticky = E)
     813
     814          self.button = Button(self, text = contents, command = self.pushButton, width = 8)
     815          self.button.grid(row = 0, column = 1, sticky = E, padx = 3)
     816
     817 -    def pushButton(self):
     818          """Executes the command linked to the Tkinter Button widget.
     819          """
     820
     821          if self.command is not None:
     822              self.results = self.command()
     823              if self.withEntry:
     824                  self.entry.setValue(str(self.results.getValue()))
     825
     826 -    def getValue(self):
     827          """Returns the output value of the |self.command| function.
     828          """
     829
     830          if self.withEntry:
     831              val = self.entry.getValue()
     832          else:
     833              # Case where |self.results| is instance of a ComboWidget having the getValue method.
     834              try:
     835                  val = self.results.getValue()
     836              except:
     837                  val = self.results
     838
     839          return val
     840
     841 -    def setValue(self):
     842          pass
     843
     844 -class ComboFileBrowser(ComboFrame):
     845      """Sets up a combo widget made of a Tkinter Label widget, a StringEntry widget and a Tkinter Button
     846      widget for file browsing embedded in a Tkinter LabelFrame widget.
     847      """
     848
     849 -    def __init__(self, master, frameLabel = '', tagName = '', contents = '', save = False, command = None, filetypes = []):
     850          """The constructor.
     851
     852          @param master: the parent widget of the combo widget.
     853
     854          @param frameLabel: the label for the Tkinter LabelFrame widget.
     855          @type frameLabel: string or Tkinter.StringVar object.
     856
     857          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     858          @type tagLabel: string.
     859
     860          @param contents: string specifying the contents of the Tkinter Entry widget.
     861          @type contents: string
     862
     863          @param save: boolean specifying whether the file browser is for saving (True) or for loading (False).
     864          @type save: boolean
     865
     866          @param command: the function to call when browsing the file.
     867          @type command: function
     868          """
     869
     870          # The comboframe is set up.
     871          ComboFrame.__init__(self, master, frameLabel, tagName)
     872
     873          self.save = save
     874          self.filetypes = filetypes
     875          self.command = command
     876
     877          # The entry widget is set up.
     878          self.entry = StringEntry(self, contents, width = 60)
     879          self.entry.grid(row = 0, column = 0, sticky = E)
     880
     881          self.button = Button(self, bitmap = "@"+os.path.join(nmoldyn_package_path, 'GUI', 'Images', 'openfile.xbm'), command = self.browse)
     882          self.button.grid(row = 0, column = 1, sticky = E)
     883
     884 -    def browse(self):
     885          """Executes the command linked to the Tkinter Button widget.
     886          """
     887
     888          # No command has been given when the instance of the ComboFileBrowser was created so just launch
     889          # a classical TkFileDialog browser and sets the entry of the Combo FileBrowser to the filename.
     890          if self.command is None:
     891              if self.save:
     892                  filename = asksaveasfilename(parent = self,\
     893                                               title = 'Save file as',\
     894                                               filetypes = self.filetypes,\
     895                                               initialdir = PREFERENCES.outputfile_path)
     896              else:
     897                  filename = askopenfilename(parent = self, title = 'Open file', filetypes = self.filetypes)
     898              self.entry.setValue(filename)
     899          else:
     900              self.command()
     901
     902 -    def getValue(self):
     903          """Returns the value of the StringEntry widget.
     904          """
     905          return self.entry.getValue()
     906
     907 -    def setValue(self, value):
     908          """Sets the value of the StringEntry widget to |value| (string).
     909
     910          @param value: the contents to insert in the StringEntry widget.
     911          @type value: string
     912          """
     913          self.entry.setValue(value)
     914
     915 -class ComboText(ComboFrame):
     916      """Sets up a combo widget made of a Tkinter Text widget and a vertical Tkinter Scrollbar widget embedded in a Tkinter LabelFrame
     917      widget.
     918      """
     919
     920 -    def __init__(self, master = None, frameLabel = '', tagName = '', contents = None):
     921          """The constructor.
     922
     923          @param master: the parent widget of the combo widget.
     924
     925          @param frameLabel: the label for the Tkinter LabelFrame widget.
     926          @type frameLabel: string or Tkinter.StringVar object.
     927
     928          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
     929          @type tagLabel: string.
     930
     931          @param contents: string specifying the contents to insert in the Tkinter Text widget.
     932          @type contents: string
     933          """
     934
     935          # The comboframe is set up.
     936          ComboFrame.__init__(self, master, frameLabel, tagName)
     937
     938          # The text widget and its associated scrollbar.
     939          sb = Scrollbar(self, orient = VERTICAL)
     940          sb.grid(row = 0, column = 1, sticky = NSEW)
     941
     942          self.text = Text(self,\
     943                           state = DISABLED,\
     944                           yscrollcommand = sb.set,\
     945                           bg = 'white')
     946          self.text.grid(row = 0, column = 0, sticky = "NSEW")
     947          sb['command'] = self.text.yview
     948
     949          self.insert(contents = contents)
     950
     951 -    def cleanup(self):
     952          """Deletes the contents of the Tkinter Text widget.
     953          """
     954
     955          self.text.config(state = NORMAL)
     956          self.text.delete('0.0', END)
     957          self.text.config(state = DISABLED)
     958
     959 -    def insert(self, cursor = END, contents = None, tag = None):
     960          """Inserts |contents| text in the Tkinter Text widget.
     961
     962          @param contents: a string specifying the text to insert in the Tkinter Text widget.
     963          @type contents: string
     964
     965          @param tag: if not None, a string specifying the tag name to associate with the inserted text.
     966          @type tag: string
     967          """
     968
     969          # If the contents is None, then do nothing.
     970          if contents is None:
     971              return
     972
     973          # Activate the text widget for writing.
     974          self.text.config(state = NORMAL)
     975
     976          # Insert the contents with a tag eventually.
     977          self.text.insert(cursor, contents, tag)
     978
     979          # Desactivates the text widget for safety reason.
     980          self.text.config(state = DISABLED)
     981
     982 -    def tag(self, pattern, tag):
     983          """Searches and tags all the occurences of a  given pattern.
     984
     985          @param pattern: the pattern to search and tag.
     986          @type pattern: string
     987
     988          @param tag: the tag to associate with |pattern|.
     989          @type tag: string
     990          """
     991
     992          self.patternLength = IntVar()
     993          start = '1.0'
     994          # Loop over all the text widget contents to find all the coocurences of |pattern|.
     995          # Each time an occurence is found, it is tagged with the given tag |tag|.
     996          while 1:
     997              match1 = self.text.search(pattern, index = start, stopindex = END, count = self.patternLength)
     998              # The break condition of the infinite loop. No pattern has been found anymore.
     999              if not match1:
    1000                  break
    1001              match2 = '%s+%sc' % (match1, self.patternLength.get())
    1002              if not self.text.tag_names(match1):
    1003                  self.text.tag_add(tag, match1, match2)
    1004              start = match2
    1005
    1006 -class ComboListbox(ComboFrame):
    1007      """Sets up a combo widget made of a Tkinter Listbox widget and a vertical Tkinter Scrollbar widget embedded in a Tkinter LabelFrame
    1008      widget.
    1009      """
    1010
    1011 -    def __init__(self, master = None, frameLabel = '', tagName = '', contents = []):
    1012          """The constructor.
    1013
    1014          @param master: the parent widget of the combo widget.
    1015
    1016          @param frameLabel: the label for the Tkinter LabelFrame widget.
    1017          @type frameLabel: string or Tkinter.StringVar object.
    1018
    1019          @param tagLabel: the tag used for to document the widget. If set to '', the widget will not be documented.
    1020          @type tagLabel: string.
    1021
    1022          @param contents: a list (string) specifying the items to insert in the Tkinter Listbox widget.
    1023          @type contents: list
    1024          """
    1025
    1026          # The comboframe is set up.
    1027          ComboFrame.__init__(self, master, frameLabel, tagName)
    1028
    1029          # The listbox that will display and its associated scrollbar.
    1030          sb = Scrollbar(self, orient = VERTICAL)
    1031          sb.grid(row = 0, column = 1, sticky = "NSEW")
    1032
    1033          self.lb = Listbox(self, yscrollcommand = sb.set, bg = 'white')
    1034          self.lb.grid(row = 0, column = 0, sticky = "NSEW")
    1035
    1036          sb['command'] = self.lb.yview
    1037          self.lb.bind('<ButtonRelease-1>', self.onListboxEntrySelection)
    1038          self.lb.bind('<Motion>', self.focus)
    1039
    1040          self.insert(contents)
    1041
    1042 -    def focus(self, event):
    1043          """Sets the focus to the Tkinter Listbox widget.
    1044
    1045          @param event: the event triggering the focus.
    1046          @type event: a Tkinter.Event object
    1047          """
    1048          self.lb.focus_set()
    1049
    1050 -    def insert(self, contents = []):
    1051          """Inserts a list of items (string) in the Tkinter Listbox widget.
    1052
    1053          @param contents: a list (string) specifying the items to insert in the Tkinter Listbox widget.
    1054          @type contents: list
    1055          """
    1056
    1057          # Some checkings.
    1058          if not isinstance(contents, (list, tuple, dict)):
    1059              raise Error('The object of type %s cannot be inserted into a listbox.' % contents.__class__.__name__)
    1060
    1061          self.cleanup()
    1062
    1063          # Loop over list to insert in the listbox.
    1064          for c in contents:
    1065              self.lb.insert(END, c)
    1066
    1067 -    def cleanup(self):
    1068          """Deletes all the items of the Tkinter Listbox widget.
    1069          """
    1070
    1071          self.lb.delete(0, END)
    1072
    1073 -    def onListboxEntrySelection(self, event):
    1074          """Updates the selection of the Tkinter Listbox widget when |event| Tkinter Event occurs.
    1075
    1076          @param event: the event triggering the callback.
    1077          @type event: a Tkinter.Event object
    1078          """
    1079          index = self.lb.nearest(event.y)
    1080          if index == -1:
    1081              return
    1082
    1083          if not self.lb.selection_includes(index):
    1084              self.lb.selection_clear(index)
    1085          else:
    1086              self.lb.selection_set(index)
    1087
    1088 -class StatusBar(Frame):
    1089      """Sets up a combo widget made of a Tkinter Scale widget embedded in a Tkinter Frame widget.
    1090      """
    1091
    1092 -    def __init__(self, master = None):
    1093          """The constructor.
    1094
    1095          @param master: the parent widget of the combo widget.
    1096          """
    1097
    1098          Frame.__init__(self, master, bd = 2, relief = RAISED)
    1099
    1100          self.status = Scale(self,\
    1101                              orient = HORIZONTAL,\
    1102                              from_ = 0,\
    1103                              to = 100,\
    1104                              state = DISABLED,\
    1105                              troughcolor = 'red')
    1106
    1107          self.status.grid(row = 0, column = 0, padx = 3, pady = 3)
    1108
    1109 -    def setValue(self, text):
    1110          """Sets the text that will be displayed within the status bar.
    1111
    1112          @param text: the value to display in the Status Bar.
    1113          @type text: string or float
    1114          """
    1115
    1116          self.status.config(state = NORMAL)
    1117          self.status.set(text)
    1118          self.status.config(state = DISABLED)
    1119          self.status.update()
    1120
    1121 -def changeMouseCursor(event, cursor):
    1122      """Changes the mouse cursor aspect.
    1123
    1124      @param event: the event triggering the change of mouse cursor.
    1125      @type event: a Tkinter.Event object
    1126
    1127      @param cursor: the Tkinter name of the mouse cursor.
    1128      @type cursor: string
    1129      """
    1130
    1131      event.widget.config(cursor = cursor)
    1132
    1133 -def loadHelpTree():
    1134      """
    1135      This method will load the XML file that stores the pdf and html links for the help file and store its contents
    1136      into the _helptree nMOLDYN global variables..
    1137      """
    1138      help = xml.dom.minidom.parse(os.path.join(nmoldyn_package_path, 'Doc', 'UsersGuide', 'Hyperlinks.xml'))
    1139
    1140      for node in help.getElementsByTagName('Widget'):
    1141          nodeName = str(node.attributes['id'].value)
    1142          nmoldyn_xml_tree[nodeName] = {'pdf' : None, 'html' : None}
    1143          pdf = node.getElementsByTagName('PDF')[0]
    1144          html = node.getElementsByTagName('HTML')[0]
    1145          nmoldyn_xml_tree[nodeName]['pdf'] = str(pdf.firstChild.data.strip())
    1146          nmoldyn_xml_tree[nodeName]['html'] = str(html.firstChild.data.strip())
    1147
    1148  nmoldyn_xml_tree = {}
    1149  # Load the XML file that stores the PDF and HTML links for the help file.
    1150  loadHelpTree()
    1151
    1152 -def informationAboutWidget(event):
    1153      """Checks the label of the Tkinter LabelFrame of a combo widget and displays the corresponding informations
    1154      documented in nMOLDYN users guide.
    1155
    1156      @param event: the event triggering the request for information about the combo widget.
    1157      @type event: a Tkinter.Event object
    1158      """
    1159
    1160      tagName = event.widget.nametowidget(event.widget.winfo_parent()).tagName
    1161
    1162      if tags.has_key(tagName):
    1163          if PREFERENCES.documentation_style.lower() == 'html':
    1164              url = os.path.join(nmoldyn_package_path, 'Doc', 'UsersGuide', 'HTML', tags[tagName]['html'])
    1165
    1166              top = Toplevel()
    1167              top.title('Information')
    1168
    1169              top.wm_minsize(400, 200)
    1170
    1171              viewer = tkHTMLViewer(top)
    1172              viewer.display(url)
    1173
    1174              top.wait_visibility()
    1175              top.grab_set()
    1176              top.focus_set()
    1177
    1178              top.wait_window(top)
    1179
    1180          elif PREFERENCES.documentation_style.lower() == 'pdf':
    1181              # The name of the users guide pdf file.
    1182              pdfFile = os.path.join(nmoldyn_package_path, 'GUI', 'Documentation', 'UsersGuide', 'PDF', 'nMOLDYN_ug.pdf')
    1183
    1184              if sys.platform == 'win32':
    1185                  try:
    1186                      subprocess.call([PREFERENCES.acroread_path, '/a nameddest=%s' % tags[tagName]['pdf'],  pdfFile])
    1187                  except:
    1188                      os.startfile(pdfFile)
    1189
    1190              elif sys.platform == 'darwin':
    1191                  try:
    1192                      os.system('osascript -e \'tell application "Adobe Reader"\nopen "%s" options "nameddest=%s"\nend tell\'' % (pdfFile, tags[tagName]['pdf']))
    1193                  except:
    1194                      subprocess.call(['open', pdfFile])
    1195
    1196              else:
    1197                  try:
    1198                      subprocess.call([PREFERENCES.acroread_path, '/a nameddest=%s' % tags[tagName]['pdf'], pdfFile])
    1199                  except:
    1200                      LogMessage('warning','Unable to read the file %s\nwith the acrobat reader located in %s.' % (pdfFile, PREFERENCES.acroread_path),['gui'])
    1201                      pass
    1202                  else:
    1203                      return
    1204
    1205      else:
    1206          tkMessageBox.showinfo("nMOLDYN help", "Not documented.")
    1207