1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
"""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
|