*** empty log message ***

git-svn-id: file:///Users/arjan/backup/gaphor/trunk/gaphor@200 a8418922-720d-0410-834f-a69b97ada669
This commit is contained in:
Arjan Molenaar 2003-05-19 17:37:52 +00:00
parent 668fd5aad6
commit 135c2cb684
12 changed files with 215 additions and 167 deletions

View File

@ -1,3 +1,13 @@
2002-05-19 Arjan Molenaar <arjanmolenaar@hetnet.nl>
* gaphor/diagram/actor.py, modelelement.py, diagramitem.py:
make ActorItem kinda work...
2002-05-03 Arjan Molenaar <arjanmolenaar@hetnet.nl>
* updated doc/UML2.gaphor to third release of UML 2.0 proposal.
* did lots of other updates.
2002-05-03 Arjan Molenaar <arjanmolenaar@hetnet.nl>
* all files: Implementing UML2 data model based on the data

File diff suppressed because one or more lines are too long

View File

@ -63,8 +63,7 @@ class Diagram(Namespace, PackageableElement):
"""Create a new canvas item on the canvas. It is created with
a unique ID and it is attached to the diagram's root item."""
assert issubclass(type, diacanvas.CanvasItem)
obj = type()
obj.set_property('id', uniqueid.generate_id())
obj = type(uniqueid.generate_id())
obj.set_property('parent', self.canvas.root)
return obj

View File

@ -18,6 +18,7 @@ Each property type (association, attribute and enumeration) has three specific
methods:
_get(): return the value
_set(value): set the value or add it to a list
(_set2(value): used by association, used to set bi-directional ass.)
_del(value=None): delete the value. 'value' is used to tell which value
is to be removed (in case of associations with
multiplicity > 1).
@ -192,7 +193,7 @@ class association(umlproperty):
def load(self, obj, value):
if not isinstance(value, self.type):
raise AttributeError, 'Value should be of type %s' % self.type.__name__
self.__set(obj, value)
self._set2(obj, value)
def __str__(self):
if self.lower == self.upper:
@ -222,7 +223,7 @@ class association(umlproperty):
old = self._get(obj)
if old:
self.__delete__(obj, old)
self.__set(obj, value)
self._set2(obj, value)
# Set opposite side:
if self.opposite:
getattr(self.type, self.opposite)._set(value, obj)
@ -255,10 +256,10 @@ class association(umlproperty):
#print '_set', self, obj, value
if not isinstance(value, self.type):
raise AttributeError, 'Value should be of type %s' % self.type.__name__
self.__set(obj, value)
self._set2(obj, value)
self.notify(obj)
def __set(self, obj, value):
def _set2(self, obj, value):
"""Real setter, avoid doing the assertion check twice."""
if self.upper > 1:
if value in self._get(obj):

View File

@ -21,8 +21,8 @@ class ActorItem(ModelElementItem):
'', 0.0, 10000.0,
1, gobject.PARAM_READWRITE),
}
def __init__(self):
ModelElementItem.__init__(self)
def __init__(self, id=None):
ModelElementItem.__init__(self, id)
self.set(height=(ActorItem.HEAD + ActorItem.NECK + ActorItem.BODY + ActorItem.ARM),
width=(ActorItem.ARM * 2),
min_height=(ActorItem.HEAD + ActorItem.NECK + ActorItem.BODY + ActorItem.ARM),
@ -47,6 +47,12 @@ class ActorItem(ModelElementItem):
self.__name.set(font=font, multiline=0,
alignment=pango.ALIGN_CENTER)
self.__name.connect('text_changed', self.on_text_changed)
self.connect('notify::subject', ActorItem.on_subject_notify)
self.subject_name_changed_id = 0
def save (self, save_func):
ModelElementItem.save(self, save_func)
self.save_property(save_func, 'name-width')
def do_set_property (self, pspec, value):
#print 'Actor: Trying to set property', pspec.name, value
@ -61,22 +67,24 @@ class ActorItem(ModelElementItem):
else:
return ModelElementItem.do_get_property (self, pspec)
def _set_subject(self, subject):
ModelElementItem._set_subject(self, subject)
def on_subject_notify(self, subject):
"""See DiagramItem.on_subject_changed().
"""
if self.subject_name_changed_id:
self.disconnect(self.subject_name_changed_id)
if self.subject:
self.subject_name_changed_id = self.subject.connect('name', self.on_subject_name_changed)
self.__name.set(text=self.subject and self.subject.name or '')
self.request_update()
# def save (self, store):
# ModelElementItem.save(self, store)
# store.save_property('name-width')
def on_subject_name_changed(self, name):
self.__name.set(text=self.subject.name)
def save (self, save_func):
ModelElementItem.save(self, save_func)
self.save_property(save_func, 'name-width')
def on_text_changed(self, text_item, text):
if text != self.subject.name:
self.subject.name = text
# def load(self, name, value):
# ModelElementItem.load(self, store)
# self.set_property('name-width', eval (store.value('name-width')))
# DiaCanvasItem callbacks:
def on_update(self, affine):
# Center the text:
@ -108,7 +116,7 @@ class ActorItem(ModelElementItem):
(ActorItem.ARM * fx,
(ActorItem.HEAD + ActorItem.NECK + ActorItem.BODY) * fy),
(ActorItem.ARM * 2 * fx, (ActorItem.HEAD + ActorItem.NECK + ActorItem.BODY + ActorItem.ARM) * fy)))
# Update the bounding box:
# update the bounding box:
ulx, uly, lrx, lry = self.bounds
w, h = self.__name.get_property('layout').get_pixel_size()
if w > self.width:
@ -180,14 +188,5 @@ class ActorItem(ModelElementItem):
else:
return -1
def on_subject_update(self, name, old_value, new_value):
if name == 'name':
self.__name.set(text=self.subject.name)
else:
ModelElementItem.on_subject_update(self, name, old_value, new_value)
def on_text_changed(self, text_item, text):
if text != self.subject.name:
self.subject.name = text
gobject.type_register(ActorItem)

View File

@ -1,118 +1,170 @@
# vim:sw=4
# vim:sw=4:et
from gaphor.UML import Presentation
from gaphor.UML import Element, Presentation
from diacanvas import CanvasItem
import gobject
import gaphor.UML.properties.umlproperty
class diagramassociation(gaphor.UML.properties.umlproperty):
"""Specialized association for use in diagram items.
It has the same interface as the association property defined in
gaphor/UML/properties.py, but delegates everything to the GObject property
handlers.
"""
def notify(self, obj):
# notification is done by set_property()
pass
def load(self, value):
pass
def save(self, save_func):
pass
def unlink(self, obj):
obj.set_property(self.name, None)
def _get(self, obj):
return obj.get_property(self.name)
def _set2(self, obj, value):
obj.set_property(self.name, value)
def _del(self, obj, value):
obj.set_property(self.name, None)
class DiagramItem(Presentation):
"""
Basic functionality for all model elements (lines and elements!).
"""Basic functionality for all model elements (lines and elements!).
This class contains common functionallity for model elements and
relationships.
It provides an interface similar to UML.Element for connecting and
disconnecting signals.
This class is not very useful on its own. It functions as a base class
for more concrete subclasses:
class ModelElement(diacanvas.CanvasElement, DiagramItem):
...
"""
signal_prototype = ('__unlink__', gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
(gobject.TYPE_STRING,))
def __init__(self):
self.__subject = None
self.connect ('notify::parent', DiagramItem.on_parent_notify)
# Prototype for signals emited by UML.Element
signal_prototype = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING,))
# Override the original subject as defined in UML.Presentation:
subject = diagramassociation('subject', Element, upper=1, opposite='presentation')
def __init__(self, id=None):
Presentation.__init__(self, id)
self.saved_subject = None
self.handler_to_id = { }
self.connect('notify::parent', DiagramItem.on_parent_notify)
self.connect('__unlink__', self.on_unlink)
# UML.Element interface used by properties:
def unlink(self):
"""Send the unlink signal and remove itself from the canvas
"""
self.emit('__unlink__', '__unlink__')
def on_unlink(self, signal_name):
if self.parent:
self.parent.remove(self)
def connect(self, name, handler, *args):
return CanvasItem.connect(self, name, handler, *args)
"""Let UML.Element specific signals be handled by the Element and
other signals by CanvasItem.
"""
id = CanvasItem.connect(self, name, handler, *args)
key = (handler,) + args
ids = self.handler_to_id.get(key)
if not ids:
self.handler_to_id[key] = (id,)
else:
self.handler_to_id[key] = ids + (id,)
return id
def disconnect(self, handler_or_id, *args):
if type(handler_or_id) == type(1):
CanvasItem.disconnect(self, id)
else:
Presentation.disconnect(self, handler_or_id, *args)
"""Call GObject.disconnect() or UML.Element.disconnect() depending
on if handler_or_id is an id or a method.
"""
if type(handler_or_id) == type(1):
try:
ids = self.handler_to_id[(handler_or_id,) + args]
except KeyError, e:
print e
else:
for id in ids:
CanvasItem.disconnect(self, id)
else:
CanvasItem.disconnect(self, handler_or_id)
def emit(self, name, *args):
"""Emit a signal, handle the __unlink__ signals the same way
gaphor.UML.Element does (signal name as first argument for callbacks)
"""
if name == '__unlink__':
CanvasItem.emit('__unlink__', '__unlink__')
else:
CanvasItem.emit('__unlink__', *args)
def notify(self, name):
"""Emit a signal with as first argument the signal's name.
"""
self.emit(name, name)
def get_subject(self, x=None, y=None):
"""Get the subject that is represented by this diagram item.
A (x,y) coordinate can be given (relative to the item) so a
diagram item can return another subject that the default when the
mouse pointer is on a specific place over the item."""
return self.__subject
def set_subject(self, subject):
"""Set a subject."""
self.set_property('subject', subject)
#self._set_subject(subject)
# Define subject property:
# subject = property(get_subject, set_subject, None, 'Subject')
"""Get the subject that is represented by this diagram item.
A (x,y) coordinate can be given (relative to the item) so a
diagram item can return another subject that the default when the
mouse pointer is on a specific place over the item.
"""
return self.subject
def has_capability(self, capability):
"""Returns the availability of an diagram item specific capability.
This kinda works the same way as capabilities on windows."""
return False
This kinda works the same way as capabilities on windows.
"""
return False
def save_property(self, save_func, name):
'''Save a property, this is a shorthand method.'''
save_func(name, self.get_property(name))
"""Save a property, this is a shorthand method.
"""
save_func(name, self.get_property(name))
def on_parent_notify (self, parent):
if self.__subject:
if self.parent:
self.__subject.add_presentation (self)
else:
self.__subject.remove_presentation (self)
if self.parent and self.subject:
self.saved_subject = self.subject
del self.subject[self]
elif not self.parent and self.saved_subject:
self.subject = self.saved_subject
self.saved_subject = None
def on_subject_update (self, name, old_value, new_value):
pass
def _set_subject(self, subject):
"""Real (protected) set_subject method. Should be called by
do_set_property(), in the sub-classes.
"""
if subject is not self.__subject:
if self.__subject:
self.__subject.disconnect(self.on_subject_update)
self.__subject.remove_presentation(self)
self.__subject = subject
if subject:
subject.add_presentation(self)
subject.connect(self.on_subject_update)
# def on_subject_changed(self, name):
# pass
# DiaCanvasItem callbacks
def _on_glue(self, handle, wx, wy, parent):
if handle.owner.allow_connect_handle (handle, self):
#print self.__class__.__name__, 'Glueing allowed.'
return parent.on_glue (self, handle, wx, wy)
#else:
#print self.__class__.__name__, 'Glueing NOT allowed.'
# Dummy value with large distance value
return None
def _on_glue(self, handle, wx, wy, parent_class):
if handle.owner.allow_connect_handle (handle, self):
#print self.__class__.__name__, 'Glueing allowed.'
return parent_class.on_glue (self, handle, wx, wy)
#else:
#print self.__class__.__name__, 'Glueing NOT allowed.'
# Dummy value with large distance value
return None
def _on_connect_handle (self, handle, parent):
if handle.owner.allow_connect_handle (handle, self):
#print self.__class__.__name__, 'Connection allowed.'
ret = parent.on_connect_handle (self, handle)
if ret != 0:
handle.owner.confirm_connect_handle(handle)
return ret
#else:
#print self.__class__.__name__, 'Connection NOT allowed.'
return 0
def _on_connect_handle (self, handle, parent_class):
if handle.owner.allow_connect_handle (handle, self):
#print self.__class__.__name__, 'Connection allowed.'
ret = parent_class.on_connect_handle (self, handle)
if ret != 0:
handle.owner.confirm_connect_handle(handle)
return ret
#else:
#print self.__class__.__name__, 'Connection NOT allowed.'
return 0
def _on_disconnect_handle (self, handle, parent):
if handle.owner.allow_disconnect_handle (handle):
#print self.__class__.__name__, 'Disconnecting allowed.'
ret = parent.on_disconnect_handle (self, handle)
if ret != 0:
handle.owner.confirm_disconnect_handle(handle, self)
return ret
#else:
#print self.__class__.__name__, 'Disconnecting NOT allowed.'
return 0
def _on_disconnect_handle (self, handle, parent_class):
if handle.owner.allow_disconnect_handle (handle):
#print self.__class__.__name__, 'Disconnecting allowed.'
ret = parent_class.on_disconnect_handle (self, handle)
if ret != 0:
handle.owner.confirm_disconnect_handle(handle, self)
return ret
#else:
#print self.__class__.__name__, 'Disconnecting NOT allowed.'
return 0

View File

@ -16,9 +16,6 @@ __date__ = '$date$'
class ModelElementItem (diacanvas.CanvasElement, diacanvas.CanvasAbstractGroup, DiagramItem):
__gproperties__ = {
'id': (gobject.TYPE_PYOBJECT, 'id',
'Identification number of the canvas item',
gobject.PARAM_READWRITE),
'subject': (gobject.TYPE_PYOBJECT, 'subject',
'subject held by the model element',
gobject.PARAM_READWRITE),
@ -27,15 +24,16 @@ class ModelElementItem (diacanvas.CanvasElement, diacanvas.CanvasAbstractGroup,
1, gobject.PARAM_READWRITE),
}
def __init__(self):
__gsignals__ = { '__unlink__': DiagramItem.signal_prototype,
'__relink__': DiagramItem.signal_prototype
}
def __init__(self, id=None):
self.__gobject_init__()
#diacanvas.CanvasElement.__init__(self)
DiagramItem.__init__(self)
DiagramItem.__init__(self, id)
self.auto_resize = 0
self.__id = -1
def set_id(self, value):
self.__id = value
self._subject = None
def save(self, save_func):
self.save_property(save_func, 'affine')
@ -49,7 +47,7 @@ class ModelElementItem (diacanvas.CanvasElement, diacanvas.CanvasAbstractGroup,
#if name == 'subject':
#self.set_property('subject', store.reference('subject')[0])
if name == 'subject':
self.set_property(name, value)
self._subject = value
else:
#log.debug('Setting unknown property "%s" -> "%s"' % (name, value))
self.set_property(name, eval(value))
@ -58,26 +56,37 @@ class ModelElementItem (diacanvas.CanvasElement, diacanvas.CanvasAbstractGroup,
pass
def do_set_property(self, pspec, value):
if pspec.name == 'id':
self.__id = value
elif pspec.name == 'subject':
if pspec.name == 'subject':
#print 'Setting subject:', value
self._set_subject(value)
# property is preserved by self.subject's property
if value is not self._subject:
self.preserve_property('subject')
if self._subject:
self._subject.disconnect('__unlink__', self.__on_unlink, obj, value)
s = self._subject
self._subject = value
if len(s.presentation) == 0:
s.unlink()
if value:
value.connect('__unlink__', self.__on_unlink, obj, value)
elif pspec.name == 'auto-resize':
self.preserve_property('auto-resize')
self.auto_resize = value
else:
raise AttributeError, 'Unknown property %s' % pspec.name
def do_get_property(self, pspec):
if pspec.name == 'id':
return self.__id
elif pspec.name == 'subject':
return self.subject
if pspec.name == 'subject':
return self._subject
elif pspec.name == 'auto-resize':
return self.auto_resize
else:
raise AttributeError, 'Unknown property %s' % pspec.name
# Ensure we call the right connect functions:
connect = DiagramItem.connect
disconnect = DiagramItem.disconnect
# DiaCanvasItem callbacks
def on_glue(self, handle, wx, wy):
return self._on_glue(handle, wx, wy, diacanvas.CanvasElement)
@ -88,18 +97,7 @@ class ModelElementItem (diacanvas.CanvasElement, diacanvas.CanvasAbstractGroup,
def on_disconnect_handle(self, handle):
return self._on_disconnect_handle(handle, diacanvas.CanvasElement)
def on_subject_update(self, name, old_value, new_value):
if name == '__unlink__':
#self.set_property('subject', None)
if self.parent:
self.parent.remove(self)
else:
DiagramItem.on_subject_update(self, name, old_value, new_value)
gobject.type_register(ModelElementItem)
diacanvas.set_callbacks(ModelElementItem)
diacanvas.set_groupable(ModelElementItem)
if __name__ == '__main__':
me = ModelElementItem()
print me, me.__gtype__

View File

@ -20,7 +20,7 @@ class PlacementTool(diacanvas.PlacementTool):
subject = elemfact.create(self.subject_class)
item.set_property ('subject', subject)
if isinstance(subject, UML.Namespace):
subject.namespace = view.get_diagram().namespace
subject.package = view.get_diagram().namespace
if self.properties and len(self.properties) > 0:
try:

View File

@ -122,7 +122,7 @@ class AssociationPlacementCommand(PlacementCommand):
def __init__(self):
PlacementCommand.__init__(self)
self._name = 'Association'
self._class = diagram.AssociationItem
#self._class = diagram.AssociationItem
CommandInfo(name='InsertAssociation', _label='_Association', context='diagram.menu',
_tip='Create a new Association', pixname='gaphor-association',

View File

@ -26,7 +26,7 @@ class DiagramWindow(AbstractWindow):
self.__diagram = diagram
if self.get_state() == AbstractWindow.STATE_ACTIVE:
self.get_window().set_title(diagram.name or 'NoName')
self.__view.set_diagram(dia)
self.__view.set_diagram(diagram)
if diagram:
diagram.canvas.set_property ('allow_undo', 1)
diagram.connect(('name', '__unlink__'), self.__on_diagram_event)

View File

@ -1,2 +1,2 @@
python setup.py run
python setup.py run "$@"

View File

@ -3,10 +3,10 @@ from gaphor.UML.umllex import *
from gaphor.UML.umllex import property_pat, operation_pat, parameter_pat
# Add some extra associations that have to be added to the model:
Parameter.typeValue = association('typeValue', ValueSpecification, upper=1, composite=True)
Parameter.taggedValue = association('taggedValue', ValueSpecification, upper=1, composite=True)
Property.typeValue = association('typeValue', ValueSpecification, upper=1, composite=True)
Property.taggedValue = association('taggedValue', ValueSpecification, upper=1, composite=True)
#Parameter.typeValue = association('typeValue', ValueSpecification, upper=1, composite=True)
#Parameter.taggedValue = association('taggedValue', ValueSpecification, upper=1, composite=True)
#Property.typeValue = association('typeValue', ValueSpecification, upper=1, composite=True)
#Property.taggedValue = association('taggedValue', ValueSpecification, upper=1, composite=True)
def dump_prop(prop):
m = property_pat.match(prop)