| """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 >> sys.stderr, \ | |
| 'Problem reading options from file:', initfile | |
| 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 >> sys.stderr, 'Cannot write options to file:', \ | |
| self.__initfile | |
| 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 |