| """Switchboard class. | 
 |  | 
 | This class is used to coordinate updates among all Viewers.  Every Viewer must | 
 | conform to the following interface: | 
 |  | 
 |     - it must include a method called update_yourself() which takes three | 
 |       arguments; the red, green, and blue values of the selected color. | 
 |  | 
 |     - When a Viewer selects a color and wishes to update all other Views, it | 
 |       should call update_views() on the Switchboard object.  Note that the | 
 |       Viewer typically does *not* update itself before calling update_views(), | 
 |       since this would cause it to get updated twice. | 
 |  | 
 | Optionally, Viewers can also implement: | 
 |  | 
 |     - save_options() which takes an optiondb (a dictionary).  Store into this | 
 |       dictionary any values the Viewer wants to save in the persistent | 
 |       ~/.pynche file.  This dictionary is saved using marshal.  The namespace | 
 |       for the keys is ad-hoc; make sure you don't clobber some other Viewer's | 
 |       keys! | 
 |  | 
 |     - withdraw() which takes no arguments.  This is called when Pynche is | 
 |       unmapped.  All Viewers should implement this. | 
 |  | 
 |     - colordb_changed() which takes a single argument, an instance of | 
 |       ColorDB.  This is called whenever the color name database is changed and | 
 |       gives a chance for the Viewers to do something on those events.  See | 
 |       ListViewer for details. | 
 |  | 
 | External Viewers are found dynamically.  Viewer modules should have names such | 
 | as FooViewer.py.  If such a named module has a module global variable called | 
 | ADDTOVIEW and this variable is true, the Viewer will be added dynamically to | 
 | the `View' menu.  ADDTOVIEW contains a string which is used as the menu item | 
 | to display the Viewer (one kludge: if the string contains a `%', this is used | 
 | to indicate that the next character will get an underline in the menu, | 
 | otherwise the first character is underlined). | 
 |  | 
 | FooViewer.py should contain a class called FooViewer, and its constructor | 
 | should take two arguments, an instance of Switchboard, and optionally a Tk | 
 | master window. | 
 |  | 
 | """ | 
 |  | 
 | import sys | 
 | from types import DictType | 
 | import marshal | 
 |  | 
 |  | 
 |  | 
 | class Switchboard: | 
 |     def __init__(self, initfile): | 
 |         self.__initfile = initfile | 
 |         self.__colordb = None | 
 |         self.__optiondb = {} | 
 |         self.__views = [] | 
 |         self.__red = 0 | 
 |         self.__green = 0 | 
 |         self.__blue = 0 | 
 |         self.__canceled = 0 | 
 |         # read the initialization file | 
 |         fp = None | 
 |         if initfile: | 
 |             try: | 
 |                 try: | 
 |                     fp = open(initfile) | 
 |                     self.__optiondb = marshal.load(fp) | 
 |                     if not isinstance(self.__optiondb, DictType): | 
 |                         print('Problem reading options from file:', initfile, file=sys.stderr) | 
 |                         self.__optiondb = {} | 
 |                 except (IOError, EOFError, ValueError): | 
 |                     pass | 
 |             finally: | 
 |                 if fp: | 
 |                     fp.close() | 
 |  | 
 |     def add_view(self, view): | 
 |         self.__views.append(view) | 
 |  | 
 |     def update_views(self, red, green, blue): | 
 |         self.__red = red | 
 |         self.__green = green | 
 |         self.__blue = blue | 
 |         for v in self.__views: | 
 |             v.update_yourself(red, green, blue) | 
 |  | 
 |     def update_views_current(self): | 
 |         self.update_views(self.__red, self.__green, self.__blue) | 
 |  | 
 |     def current_rgb(self): | 
 |         return self.__red, self.__green, self.__blue | 
 |  | 
 |     def colordb(self): | 
 |         return self.__colordb | 
 |  | 
 |     def set_colordb(self, colordb): | 
 |         self.__colordb = colordb | 
 |         for v in self.__views: | 
 |             if hasattr(v, 'colordb_changed'): | 
 |                 v.colordb_changed(colordb) | 
 |         self.update_views_current() | 
 |  | 
 |     def optiondb(self): | 
 |         return self.__optiondb | 
 |  | 
 |     def save_views(self): | 
 |         # save the current color | 
 |         self.__optiondb['RED'] = self.__red | 
 |         self.__optiondb['GREEN'] = self.__green | 
 |         self.__optiondb['BLUE'] = self.__blue | 
 |         for v in self.__views: | 
 |             if hasattr(v, 'save_options'): | 
 |                 v.save_options(self.__optiondb) | 
 |         # save the name of the file used for the color database.  we'll try to | 
 |         # load this first. | 
 |         self.__optiondb['DBFILE'] = self.__colordb.filename() | 
 |         fp = None | 
 |         try: | 
 |             try: | 
 |                 fp = open(self.__initfile, 'w') | 
 |             except IOError: | 
 |                 print('Cannot write options to file:', \ | 
 |                       self.__initfile, file=sys.stderr) | 
 |             else: | 
 |                 marshal.dump(self.__optiondb, fp) | 
 |         finally: | 
 |             if fp: | 
 |                 fp.close() | 
 |  | 
 |     def withdraw_views(self): | 
 |         for v in self.__views: | 
 |             if hasattr(v, 'withdraw'): | 
 |                 v.withdraw() | 
 |  | 
 |     def canceled(self, flag=1): | 
 |         self.__canceled = flag | 
 |  | 
 |     def canceled_p(self): | 
 |         return self.__canceled |