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