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 45import marshal 46 47 48 49class Switchboard: 50 def __init__(self, initfile): 51 self.__initfile = initfile 52 self.__colordb = None 53 self.__optiondb = {} 54 self.__views = [] 55 self.__red = 0 56 self.__green = 0 57 self.__blue = 0 58 self.__canceled = 0 59 # read the initialization file 60 fp = None 61 if initfile: 62 try: 63 try: 64 fp = open(initfile, 'rb') 65 self.__optiondb = marshal.load(fp) 66 if not isinstance(self.__optiondb, dict): 67 print('Problem reading options from file:', initfile, 68 file=sys.stderr) 69 self.__optiondb = {} 70 except (IOError, EOFError, ValueError): 71 pass 72 finally: 73 if fp: 74 fp.close() 75 76 def add_view(self, view): 77 self.__views.append(view) 78 79 def update_views(self, red, green, blue): 80 self.__red = red 81 self.__green = green 82 self.__blue = blue 83 for v in self.__views: 84 v.update_yourself(red, green, blue) 85 86 def update_views_current(self): 87 self.update_views(self.__red, self.__green, self.__blue) 88 89 def current_rgb(self): 90 return self.__red, self.__green, self.__blue 91 92 def colordb(self): 93 return self.__colordb 94 95 def set_colordb(self, colordb): 96 self.__colordb = colordb 97 for v in self.__views: 98 if hasattr(v, 'colordb_changed'): 99 v.colordb_changed(colordb) 100 self.update_views_current() 101 102 def optiondb(self): 103 return self.__optiondb 104 105 def save_views(self): 106 # save the current color 107 self.__optiondb['RED'] = self.__red 108 self.__optiondb['GREEN'] = self.__green 109 self.__optiondb['BLUE'] = self.__blue 110 for v in self.__views: 111 if hasattr(v, 'save_options'): 112 v.save_options(self.__optiondb) 113 # save the name of the file used for the color database. we'll try to 114 # load this first. 115 self.__optiondb['DBFILE'] = self.__colordb.filename() 116 fp = None 117 try: 118 try: 119 fp = open(self.__initfile, 'wb') 120 except IOError: 121 print('Cannot write options to file:', \ 122 self.__initfile, file=sys.stderr) 123 else: 124 marshal.dump(self.__optiondb, fp) 125 finally: 126 if fp: 127 fp.close() 128 129 def withdraw_views(self): 130 for v in self.__views: 131 if hasattr(v, 'withdraw'): 132 v.withdraw() 133 134 def canceled(self, flag=1): 135 self.__canceled = flag 136 137 def canceled_p(self): 138 return self.__canceled 139