Home | History | Annotate | Download | only in pynche
      1 """Switchboard class.
      2 
      3 This class is used to coordinate updates among all Viewers.  Every Viewer must
      4 conform to the following interface:
      5 
      6     - it must include a method called update_yourself() which takes three
      7       arguments; the red, green, and blue values of the selected color.
      8 
      9     - When a Viewer selects a color and wishes to update all other Views, it
     10       should call update_views() on the Switchboard object.  Note that the
     11       Viewer typically does *not* update itself before calling update_views(),
     12       since this would cause it to get updated twice.
     13 
     14 Optionally, Viewers can also implement:
     15 
     16     - save_options() which takes an optiondb (a dictionary).  Store into this
     17       dictionary any values the Viewer wants to save in the persistent
     18       ~/.pynche file.  This dictionary is saved using marshal.  The namespace
     19       for the keys is ad-hoc; make sure you don't clobber some other Viewer's
     20       keys!
     21 
     22     - withdraw() which takes no arguments.  This is called when Pynche is
     23       unmapped.  All Viewers should implement this.
     24 
     25     - colordb_changed() which takes a single argument, an instance of
     26       ColorDB.  This is called whenever the color name database is changed and
     27       gives a chance for the Viewers to do something on those events.  See
     28       ListViewer for details.
     29 
     30 External Viewers are found dynamically.  Viewer modules should have names such
     31 as FooViewer.py.  If such a named module has a module global variable called
     32 ADDTOVIEW and this variable is true, the Viewer will be added dynamically to
     33 the `View' menu.  ADDTOVIEW contains a string which is used as the menu item
     34 to display the Viewer (one kludge: if the string contains a `%', this is used
     35 to indicate that the next character will get an underline in the menu,
     36 otherwise the first character is underlined).
     37 
     38 FooViewer.py should contain a class called FooViewer, and its constructor
     39 should take two arguments, an instance of Switchboard, and optionally a Tk
     40 master window.
     41 
     42 """
     43 
     44 import sys
     45 from types import DictType
     46 import marshal
     47 
     48 
     49 
     51 class Switchboard:
     52     def __init__(self, initfile):
     53         self.__initfile = initfile
     54         self.__colordb = None
     55         self.__optiondb = {}
     56         self.__views = []
     57         self.__red = 0
     58         self.__green = 0
     59         self.__blue = 0
     60         self.__canceled = 0
     61         # read the initialization file
     62         fp = None
     63         if initfile:
     64             try:
     65                 try:
     66                     fp = open(initfile)
     67                     self.__optiondb = marshal.load(fp)
     68                     if not isinstance(self.__optiondb, DictType):
     69                         print >> sys.stderr, \
     70                               'Problem reading options from file:', initfile
     71                         self.__optiondb = {}
     72                 except (IOError, EOFError, ValueError):
     73                     pass
     74             finally:
     75                 if fp:
     76                     fp.close()
     77 
     78     def add_view(self, view):
     79         self.__views.append(view)
     80 
     81     def update_views(self, red, green, blue):
     82         self.__red = red
     83         self.__green = green
     84         self.__blue = blue
     85         for v in self.__views:
     86             v.update_yourself(red, green, blue)
     87 
     88     def update_views_current(self):
     89         self.update_views(self.__red, self.__green, self.__blue)
     90 
     91     def current_rgb(self):
     92         return self.__red, self.__green, self.__blue
     93 
     94     def colordb(self):
     95         return self.__colordb
     96 
     97     def set_colordb(self, colordb):
     98         self.__colordb = colordb
     99         for v in self.__views:
    100             if hasattr(v, 'colordb_changed'):
    101                 v.colordb_changed(colordb)
    102         self.update_views_current()
    103 
    104     def optiondb(self):
    105         return self.__optiondb
    106 
    107     def save_views(self):
    108         # save the current color
    109         self.__optiondb['RED'] = self.__red
    110         self.__optiondb['GREEN'] = self.__green
    111         self.__optiondb['BLUE'] = self.__blue
    112         for v in self.__views:
    113             if hasattr(v, 'save_options'):
    114                 v.save_options(self.__optiondb)
    115         # save the name of the file used for the color database.  we'll try to
    116         # load this first.
    117         self.__optiondb['DBFILE'] = self.__colordb.filename()
    118         fp = None
    119         try:
    120             try:
    121                 fp = open(self.__initfile, 'w')
    122             except IOError:
    123                 print >> sys.stderr, 'Cannot write options to file:', \
    124                       self.__initfile
    125             else:
    126                 marshal.dump(self.__optiondb, fp)
    127         finally:
    128             if fp:
    129                 fp.close()
    130 
    131     def withdraw_views(self):
    132         for v in self.__views:
    133             if hasattr(v, 'withdraw'):
    134                 v.withdraw()
    135 
    136     def canceled(self, flag=1):
    137         self.__canceled = flag
    138 
    139     def canceled_p(self):
    140         return self.__canceled
    141