1"""Switchboard class. 2 3This class is used to coordinate updates among all Viewers. Every Viewer must 4conform 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 14Optionally, 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 30External Viewers are found dynamically. Viewer modules should have names such 31as FooViewer.py. If such a named module has a module global variable called 32ADDTOVIEW and this variable is true, the Viewer will be added dynamically to 33the `View' menu. ADDTOVIEW contains a string which is used as the menu item 34to display the Viewer (one kludge: if the string contains a `%', this is used 35to indicate that the next character will get an underline in the menu, 36otherwise the first character is underlined). 37 38FooViewer.py should contain a class called FooViewer, and its constructor 39should take two arguments, an instance of Switchboard, and optionally a Tk 40master window. 41 42""" 43 44import sys 45from types import DictType 46import marshal 47 48 49 50class Switchboard: 51 def __init__(self, initfile): 52 self.__initfile = initfile 53 self.__colordb = None 54 self.__optiondb = {} 55 self.__views = [] 56 self.__red = 0 57 self.__green = 0 58 self.__blue = 0 59 self.__canceled = 0 60 # read the initialization file 61 fp = None 62 if initfile: 63 try: 64 try: 65 fp = open(initfile) 66 self.__optiondb = marshal.load(fp) 67 if not isinstance(self.__optiondb, DictType): 68 print >> sys.stderr, \ 69 'Problem reading options from file:', initfile 70 self.__optiondb = {} 71 except (IOError, EOFError, ValueError): 72 pass 73 finally: 74 if fp: 75 fp.close() 76 77 def add_view(self, view): 78 self.__views.append(view) 79 80 def update_views(self, red, green, blue): 81 self.__red = red 82 self.__green = green 83 self.__blue = blue 84 for v in self.__views: 85 v.update_yourself(red, green, blue) 86 87 def update_views_current(self): 88 self.update_views(self.__red, self.__green, self.__blue) 89 90 def current_rgb(self): 91 return self.__red, self.__green, self.__blue 92 93 def colordb(self): 94 return self.__colordb 95 96 def set_colordb(self, colordb): 97 self.__colordb = colordb 98 for v in self.__views: 99 if hasattr(v, 'colordb_changed'): 100 v.colordb_changed(colordb) 101 self.update_views_current() 102 103 def optiondb(self): 104 return self.__optiondb 105 106 def save_views(self): 107 # save the current color 108 self.__optiondb['RED'] = self.__red 109 self.__optiondb['GREEN'] = self.__green 110 self.__optiondb['BLUE'] = self.__blue 111 for v in self.__views: 112 if hasattr(v, 'save_options'): 113 v.save_options(self.__optiondb) 114 # save the name of the file used for the color database. we'll try to 115 # load this first. 116 self.__optiondb['DBFILE'] = self.__colordb.filename() 117 fp = None 118 try: 119 try: 120 fp = open(self.__initfile, 'w') 121 except IOError: 122 print >> sys.stderr, 'Cannot write options to file:', \ 123 self.__initfile 124 else: 125 marshal.dump(self.__optiondb, fp) 126 finally: 127 if fp: 128 fp.close() 129 130 def withdraw_views(self): 131 for v in self.__views: 132 if hasattr(v, 'withdraw'): 133 v.withdraw() 134 135 def canceled(self, flag=1): 136 self.__canceled = flag 137 138 def canceled_p(self): 139 return self.__canceled 140