1998-10-02 16:20:14 +00:00
|
|
|
"""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. Not that the
|
|
|
|
Viewer typically does *not* update itself before calling update_views(),
|
|
|
|
since this would cause it to get updated twice.
|
1999-04-27 18:53:29 +00:00
|
|
|
|
|
|
|
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.
|
|
|
|
|
1998-10-02 16:20:14 +00:00
|
|
|
"""
|
|
|
|
|
1998-10-22 18:48:01 +00:00
|
|
|
import sys
|
1998-10-20 20:45:46 +00:00
|
|
|
from types import DictType
|
|
|
|
import marshal
|
|
|
|
|
1998-09-28 15:59:21 +00:00
|
|
|
class Switchboard:
|
1999-04-26 23:17:16 +00:00
|
|
|
def __init__(self, initfile):
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
self.__initfile = initfile
|
1999-04-26 23:17:16 +00:00
|
|
|
self.__colordb = None
|
1998-10-20 20:45:46 +00:00
|
|
|
self.__optiondb = {}
|
|
|
|
self.__views = []
|
1998-10-01 16:46:43 +00:00
|
|
|
self.__red = 0
|
|
|
|
self.__green = 0
|
|
|
|
self.__blue = 0
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
self.__canceled = 0
|
1998-10-20 20:45:46 +00:00
|
|
|
# read the initialization file
|
|
|
|
fp = None
|
|
|
|
if initfile:
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
fp = open(initfile)
|
|
|
|
self.__optiondb = marshal.load(fp)
|
|
|
|
if type(self.__optiondb) <> DictType:
|
1998-10-22 18:48:01 +00:00
|
|
|
sys.stderr.write(
|
|
|
|
'Problem reading options from file: %s\n' %
|
|
|
|
initfile)
|
1998-10-20 20:45:46 +00:00
|
|
|
self.__optiondb = {}
|
|
|
|
except (IOError, EOFError):
|
|
|
|
pass
|
|
|
|
finally:
|
|
|
|
if fp:
|
|
|
|
fp.close()
|
1998-09-28 15:59:21 +00:00
|
|
|
|
|
|
|
def add_view(self, view):
|
|
|
|
self.__views.append(view)
|
|
|
|
|
1998-09-28 23:41:12 +00:00
|
|
|
def update_views(self, red, green, blue):
|
1998-10-01 16:46:43 +00:00
|
|
|
self.__red = red
|
|
|
|
self.__green = green
|
|
|
|
self.__blue = blue
|
1998-09-28 15:59:21 +00:00
|
|
|
for v in self.__views:
|
1998-09-28 23:41:12 +00:00
|
|
|
v.update_yourself(red, green, blue)
|
1998-09-29 20:04:19 +00:00
|
|
|
|
1998-10-01 16:46:43 +00:00
|
|
|
def update_views_current(self):
|
|
|
|
self.update_views(self.__red, self.__green, self.__blue)
|
|
|
|
|
1998-10-05 21:14:12 +00:00
|
|
|
def current_rgb(self):
|
|
|
|
return self.__red, self.__green, self.__blue
|
|
|
|
|
1998-09-29 20:04:19 +00:00
|
|
|
def colordb(self):
|
|
|
|
return self.__colordb
|
1998-10-20 20:45:46 +00:00
|
|
|
|
1999-04-26 23:17:16 +00:00
|
|
|
def set_colordb(self, colordb):
|
|
|
|
self.__colordb = colordb
|
1999-04-27 18:53:29 +00:00
|
|
|
for v in self.__views:
|
|
|
|
if hasattr(v, 'colordb_changed'):
|
|
|
|
v.colordb_changed(colordb)
|
|
|
|
self.update_views_current()
|
1999-04-26 23:17:16 +00:00
|
|
|
|
1998-10-20 20:45:46 +00:00
|
|
|
def optiondb(self):
|
|
|
|
return self.__optiondb
|
|
|
|
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
def save_views(self):
|
1998-10-20 20:45:46 +00:00
|
|
|
# save the current color
|
|
|
|
self.__optiondb['RED'] = self.__red
|
|
|
|
self.__optiondb['GREEN'] = self.__green
|
|
|
|
self.__optiondb['BLUE'] = self.__blue
|
|
|
|
for v in self.__views:
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
if hasattr(v, 'save_options'):
|
|
|
|
v.save_options(self.__optiondb)
|
1999-04-26 23:17:16 +00:00
|
|
|
# save the name of the file used for the color database. we'll try to
|
|
|
|
# load this first.
|
|
|
|
self.__optiondb['DBFILE'] = self.__colordb.filename()
|
1998-10-20 20:45:46 +00:00
|
|
|
fp = None
|
|
|
|
try:
|
|
|
|
try:
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
fp = open(self.__initfile, 'w')
|
1998-10-20 20:45:46 +00:00
|
|
|
except IOError:
|
1998-10-22 18:48:01 +00:00
|
|
|
sys.stderr.write('Cannot write options to file: %s\n' %
|
|
|
|
self.__initfile)
|
1998-10-20 20:45:46 +00:00
|
|
|
else:
|
|
|
|
marshal.dump(self.__optiondb, fp)
|
|
|
|
finally:
|
|
|
|
if fp:
|
|
|
|
fp.close()
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
|
|
|
|
def withdraw_views(self):
|
|
|
|
for v in self.__views:
|
|
|
|
if hasattr(v, 'withdraw'):
|
|
|
|
v.withdraw()
|
|
|
|
|
1998-10-22 18:48:01 +00:00
|
|
|
def canceled(self, flag=1):
|
|
|
|
self.__canceled = flag
|
Many changes to support a second mode of operation. Pynche can now be
run either as a standalone application (by running pynche or
pynche.pyw), or as a modal dialog inside another application. This
can be done by importing pyColorChooser and running askcolor(). The
API for this is the same as the tkColorChooser.askcolor() API, namely:
When `Okay' is hit, askcolor() returns ((r, g, b), "name"). When
`Cancel' is hit, askcolor() returns (None, None).
Note the following differences:
1. pyColorChooser.askcolor() takes an optional keyword `master'
which if set tells Pynche to run as a modal dialog. `master'
is a Tkinter parent window. Without the `master' keyword
Pynche runs standalone.
2. in pyColorChooser.askcolor() will return a Tk/X11 color name as
"name" if there is an exact match, otherwise it will return a
color spec, e.g. "#rrggbb". tkColorChooser can't return a
color name.
There are also some UI differences when running standalone vs. modal.
When modal, there is no "File" menu, but instead there are "Okay" and
"Cancel" buttons.
The implementation of all this is a bit of a hack, but it seems to
work moderately well. I'm not guaranteeing the pyColorChooser.Chooser
class has the same semantics as the tkColorChooser.Chooser class.
1998-10-22 03:25:59 +00:00
|
|
|
|
|
|
|
def canceled_p(self):
|
|
|
|
return self.__canceled
|