# Sketch - A Python-based interactive drawing program
# Copyright (C) 1997, 1998, 2001 by Bernhard Herzog
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from types import StringType,TupleType,FunctionType
from Sketch import Publisher
from Sketch.const import CHANGED,SELECTION
from Sketch.warn import warn,warn_tb,INTERNAL
#
# Command Class
#
class Command(Publisher):
def __init__(self, cmd_class, object):
self.cmd_class = cmd_class
self.object = object
def __getattr__(self, attr):
try:
return getattr(self.cmd_class, attr)
except AttributeError:
if attr == 'button_name':
return self.menu_name
raise AttributeError, attr
def get_method(self, path):
if callable(path):
return path
method = self.object
if type(path) != TupleType:
path = (path,)
for name in path:
method = getattr(method, name)
return method
def Invoke(self, args = ()):
if type(args) != TupleType:
args = (args,)
try:
apply(self.get_method(self.command), self.args + args)
except:
warn_tb(INTERNAL)
def Update(self):
# XXX: bitmaps and key_strokes should probably be also changeable
changed = self.set_name(self.get_name())
changed = self.set_sensitive(self.get_sensitive()) or changed
changed = self.set_value(self.get_value()) or changed
if changed:
self.issue(CHANGED)
def get_name(self):
if self.name_cb:
method = self.get_method(self.name_cb)
if method:
return method()
return self.menu_name
def set_name(self, menu_name = None):
changed = self.menu_name != menu_name
if changed:
self.menu_name = menu_name
return changed
def get_sensitive(self):
#print 'get_sensitive', self
if self.sensitive_cb:
method = self.get_method(self.sensitive_cb)
if method:
return method()
else:
warn(INTERNAL, 'no method for sensitive_cb (%s)',
self.sensitive_cb)
return 0
return 1
def set_sensitive(self, sensitive):
changed = self.sensitive != sensitive
if changed:
self.sensitive = sensitive
return changed
def get_value(self):
if self.value_cb:
method = self.get_method(self.value_cb)
if method:
return method()
return self.value
def set_value(self, value):
changed = self.value != value
if changed:
self.value = value
return changed
def GetKeystroke(self):
return self.key_stroke
def GetValue(self):
return self.value
def IsOn(self):
return self.value == self.value_on
def InContext(self):
return 1
def set_bitmap(self, bitmap):
if bitmap:
changed = self.bitmap != bitmap
self.bitmap = bitmap
return changed
return 0
def __repr__(self):
return 'Command: %s' % self.name
class CommandClass:
cmd_class = Command
# default attributes
menu_name = '???'
bitmap = None
key_stroke = None
name_cb = None
sensitive_cb = None
sensitive = 1
value_cb = None
value = 0
value_on = 1
value_off = 0
is_command = 1
is_check = 0
invoke_with_keystroke = 0
callable_attributes = ('name_cb', 'sensitive_cb', 'value_cb')
def __init__(self, name, command, subscribe_to = None, args = (),
is_check = 0, **rest):
self.name = name
self.command = command
self.subscribe_to = subscribe_to
if type(args) != TupleType:
self.args = (args,)
else:
self.args = args
for key, value in rest.items():
setattr(self, key, value)
if is_check:
self.is_check = 1
self.is_command = 0
def InstantiateFor(self, object):
cmd = self.cmd_class(self, object)
if self.subscribe_to:
if type(self.subscribe_to) == TupleType:
attrs = self.subscribe_to[:-1]
for attr in attrs:
object = getattr(object, attr)
subscribe_to = self.subscribe_to[-1]
else:
subscribe_to = self.subscribe_to
object.Subscribe(subscribe_to, cmd.Update)
return cmd
def __repr__(self):
return 'CommandClass: %s' % self.name
class ObjectCommand(Command):
def get_method(self, path):
if type(path) == type(""):
return self.object.document.GetObjectMethod(self.object_class,path)
return Command.get_method(self, path)
def Invoke(self, args = ()):
if type(args) != TupleType:
args = (args,)
try:
apply(self.object.document.CallObjectMethod,
(self.object_class, self.menu_name, self.command) \
+ self.args + args)
except:
warn_tb(INTERNAL)
def get_sensitive(self):
if self.object.document.CurrentObjectCompatible(self.object_class):
return Command.get_sensitive(self)
return 0
def GetKeystroke(self):
return self.key_stroke
def GetValue(self):
return self.value
def InContext(self):
return self.object.document.CurrentObjectCompatible(self.object_class)
def __repr__(self):
return 'ObjectCommand: %s' % self.name
class ObjectCommandClass(CommandClass):
cmd_class = ObjectCommand
object_class = None
def SetClass(self, aclass):
if self.object_class is None:
self.object_class = aclass
#
#
#
class Commands:
def Update(self):
for item in self.__dict__.values():
item.Update()
def __getitem__(self, key):
return getattr(self, key)
def Get(self, name):
try:
return getattr(self, name)
except AttributeError:
for item in self.__dict__.values():
if item.__class__ == Commands:
cmd = item.Get(name)
if cmd:
return cmd
else:
return None
#
#
#
class Keymap:
def __init__(self):
self.map = {}
def AddCommand(self, command):
key_stroke = command.GetKeystroke()
if key_stroke:
if type(key_stroke) == StringType:
key_stroke = (key_stroke,)
for stroke in key_stroke:
if self.map.has_key(stroke):
# XXX: should be user visible if keybindings can be
# changed by user
warn(INTERNAL, 'Warning: Binding %s to %s replaces %s',
command.name, stroke, self.map[stroke].name)
self.map[stroke] = command
def MapKeystroke(self, stroke):
if self.map.has_key(stroke):
return self.map[stroke]
#
#
#
def AddCmd(list, name, menu_name, method = None, **kw):
if type(name) == FunctionType:
name = name.func_name
if method is None:
method = name
elif type(method) == FunctionType:
method = method.func_name
kw['menu_name'] = menu_name
kw['subscribe_to'] = SELECTION
cmd = apply(ObjectCommandClass, (name, method), kw)
list.append(cmd)
|