Added Zope 3 stuff
Completed xmi export using Kid git-svn-id: file:///Users/arjan/backup/gaphor/trunk/gaphor@610 a8418922-720d-0410-834f-a69b97ada669
This commit is contained in:
parent
e7f98b76fb
commit
0693bcacca
@ -1,3 +1,11 @@
|
||||
2005-10-27 Jeroen Vlootuis <jeroen@vloothuis.net>
|
||||
* Added new object inspector panel at bottom of diagram. This makes use
|
||||
of the Zope 3 component architecture. Therefore Gaphor now depends on
|
||||
Zope 3. This dependency should be diminshed to component and
|
||||
interface. At the moment there is no seperate package for component.
|
||||
|
||||
* Made Kid export handle tagged values.
|
||||
|
||||
2005-10-27 wrobell <wrobell@pld-linux.org>
|
||||
* gaphor/diagram/activitynodes.py: object node has upper bound
|
||||
specification; join node has join specification; initial node naming
|
||||
|
@ -39,14 +39,27 @@ def getLowerAndUpperValuesFromAssociationEnd(end):
|
||||
|
||||
from gaphor.misc.uniqueid import generate_id
|
||||
|
||||
tagDefinitions = []
|
||||
class TaggedValue(object):
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value
|
||||
self.id = generate_id()
|
||||
|
||||
def getTypeRef(self):
|
||||
"""Return a auto generated typeref for use with type definitions."""
|
||||
return self.id+"_typeref"
|
||||
|
||||
typeref = property(getTypeRef)
|
||||
|
||||
def convertTaggedValue(taggedValue):
|
||||
tags = taggedValue.value.split(',')
|
||||
converted = [map(unicode.strip, tag.split("=")) for tag in tags]
|
||||
data = dict(converted)
|
||||
tags = [TaggedValue(key, value) for (key, value) in data.items()]
|
||||
tagDefinitions.extend(tags)
|
||||
return tags
|
||||
|
||||
def getTagDefinitions():
|
||||
items = []
|
||||
for node in elements:
|
||||
if hasattr(node, 'taggedValue'):
|
||||
for tag in node.taggedValue:
|
||||
items.append(tag)
|
||||
return items
|
||||
|
||||
|
||||
?>
|
||||
@ -67,8 +80,6 @@ def getTagDefinitions():
|
||||
xmi.id = 'I48de81cbm106d41f950cmm7f54' name = 'topModel' isSpecification = 'false'
|
||||
isRoot = 'false' isLeaf = 'false' isAbstract = 'false'
|
||||
py:attrs="{'xmi.id':topLevelPackage.id, 'name':topLevelPackage.name}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(topLevelPackage)"/>
|
||||
|
||||
<UML:Classifier.feature py:def="processClassifierFeature(item)">
|
||||
|
||||
@ -85,7 +96,9 @@ def getTagDefinitions():
|
||||
py:for="attribute in [a for a in item.ownedAttribute if a.typeValue]"
|
||||
py:attrs="{'xmi.id':attribute.id, 'name':attribute.name}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(attribute)"/>
|
||||
py:for="taggedValue in convertTaggedValue(attribute.taggedValue)"
|
||||
py:content="processTaggedValue(taggedValue)">
|
||||
</UML:ModelElement.taggedValue>
|
||||
<UML:StructuralFeature.type>
|
||||
<UML:Class xmi.idref = 'I48de81cbm106d41f950cmm7f24'
|
||||
py:attrs="{'xmi.idref':attribute.typeValue.id}"/>
|
||||
@ -126,23 +139,18 @@ def getTagDefinitions():
|
||||
|
||||
</UML:Classifier.feature>
|
||||
|
||||
<UML:ModelElement.taggedValue
|
||||
py:def="processModelElementTaggedValue(node)"
|
||||
py:for="taggedValue in node.taggedValue"
|
||||
py:content="processTaggedValue(taggedValue)">
|
||||
</UML:ModelElement.taggedValue>
|
||||
|
||||
<UML:TagDefinition py:def="processTagDefinition(tagDefinition)"
|
||||
xmi.id = 'I5bd6b6fm106dbda4889mm7f24' name = 'someTag'
|
||||
py:attrs="{'xmi.id':tagDefinition.id+'ref', 'name':tagDefinition.value.split('=')[0]}"
|
||||
py:attrs="{'xmi.id':tagDefinition.typeref, 'name':tagDefinition.name}"
|
||||
isSpecification = 'false'>
|
||||
<UML:TagDefinition.multiplicity>
|
||||
<UML:Multiplicity xmi.id = 'I5bd6b6fm106dbda4889mm7f23'
|
||||
py:attrs="{'xmi.id':tagDefinition.id+'multi'}">
|
||||
py:attrs="{'xmi.id':tagDefinition.typeref+'multi'}">
|
||||
<UML:Multiplicity.range>
|
||||
<UML:MultiplicityRange xmi.id = 'I5bd6b6fm106dbda4889mm7f22' lower = '1'
|
||||
upper = '1'
|
||||
py:attrs="{'xmi.id':tagDefinition.id+'multirange'}"/>
|
||||
py:attrs="{'xmi.id':tagDefinition.typeref+'multirange'}"/>
|
||||
</UML:Multiplicity.range>
|
||||
</UML:Multiplicity>
|
||||
</UML:TagDefinition.multiplicity>
|
||||
@ -153,10 +161,10 @@ def getTagDefinitions():
|
||||
xmi.id = 'I5bd6b6fm106dbda4889mm7f21' isSpecification = 'false'
|
||||
py:attrs="{'xmi.id':taggedValue.id}">
|
||||
<UML:TaggedValue.dataValue
|
||||
py:content="taggedValue.value.split('=')[-1]">someTagValue</UML:TaggedValue.dataValue>
|
||||
py:content="taggedValue.value">someTagValue</UML:TaggedValue.dataValue>
|
||||
<UML:TaggedValue.type>
|
||||
<UML:TagDefinition xmi.idref = 'I5bd6b6fm106dbda4889mm7f24'
|
||||
py:attrs="{'xmi.idref':taggedValue.id+'ref'}"/>
|
||||
py:attrs="{'xmi.idref':taggedValue.typeref}"/>
|
||||
</UML:TaggedValue.type>
|
||||
</UML:TaggedValue>
|
||||
|
||||
@ -178,8 +186,6 @@ def getTagDefinitions():
|
||||
<UML:Generalization py:def="processGeneralization(generalization)"
|
||||
xmi.id = 'I48de81cbm106d41f950cmm7eb4' isSpecification = 'false'
|
||||
py:attrs="{'xmi.id':generalization.id}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(generalization)"/>
|
||||
<UML:Generalization.child>
|
||||
<UML:Class xmi.idref = 'I48de81cbm106d41f950cmm7ec7'
|
||||
py:attrs="{'xmi.idref':generalization.specific.id}"/>
|
||||
@ -195,8 +201,6 @@ def getTagDefinitions():
|
||||
visibility = 'public' isSpecification = 'false' isRoot = 'false' isLeaf = 'false'
|
||||
isAbstract = 'false'
|
||||
py:attrs="{'xmi.id':interface.id, 'name':interface.name}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(interface)"/>
|
||||
<UML:Classifier.feature py:replace="processClassifierFeature(interface)"/>
|
||||
</UML:Interface>
|
||||
|
||||
@ -207,8 +211,6 @@ def getTagDefinitions():
|
||||
isAbstract = 'true' isActive = 'false'
|
||||
py:attrs="{'xmi.id':cls.id, 'name':cls.name,
|
||||
'isAbstract':cls.isAbstract and 'true' or 'false'}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(cls)"/>
|
||||
|
||||
<UML:ModelElement.stereotype py:if="cls.appliedStereotype">
|
||||
<UML:Stereotype xmi.idref = 'I48de81cbm106d41f950cmm7e0c'
|
||||
@ -235,8 +237,6 @@ def getTagDefinitions():
|
||||
visibility = 'public' isSpecification = 'false' isRoot = 'false' isLeaf = 'false'
|
||||
isAbstract = 'false'
|
||||
py:attrs="{'xml.id':stereotype.id, 'name':stereotype.name}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(stereotype)"/>
|
||||
<UML:Stereotype.baseClass py:content="stereotype.ownedAttribute.type.name">Class</UML:Stereotype.baseClass>
|
||||
</UML:Stereotype>
|
||||
|
||||
@ -244,8 +244,6 @@ def getTagDefinitions():
|
||||
xmi.id = 'I48de81cbm106d41f950cmm7e01' name = 'aPackage' visibility = 'public'
|
||||
isSpecification = 'false' isRoot = 'false' isLeaf = 'false' isAbstract = 'false'
|
||||
py:attrs="{'xmi.idref':package.id, 'name':package.name}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(package)"/>
|
||||
<UML:Namespace.ownedElement>
|
||||
<packageContent py:for="item in getPackageChildNodes(package=package)"
|
||||
py:replace="modelProcessNode(item)"/>
|
||||
@ -258,8 +256,6 @@ def getTagDefinitions():
|
||||
xmi.id = 'I48de81cbm106d41f950cmm7d2f' isSpecification = 'false'
|
||||
isRoot = 'false' isLeaf = 'false' isAbstract = 'false'
|
||||
py:attrs="{'xmi.id':association.id, 'name':association.name}">
|
||||
<UML:ModelElement.taggedValue
|
||||
py:replace="processModelElementTaggedValue(association)"/>
|
||||
<UML:Association.connection>
|
||||
<UML:AssociationEnd xmi.id = 'I48de81cbm106d41f950cmm7d35' visibility = 'public'
|
||||
isSpecification = 'false' isNavigable = 'false' ordering = 'unordered' aggregation = 'none'
|
||||
@ -292,7 +288,7 @@ def getTagDefinitions():
|
||||
py:replace="modelProcessNode(item)"/>
|
||||
|
||||
|
||||
<UML:TagDefinition py:for="tagDef in getTagDefinitions()"
|
||||
<UML:TagDefinition py:for="tagDef in tagDefinitions"
|
||||
py:replace="processTagDefinition(tagDef)"/>
|
||||
|
||||
</UML:Namespace.ownedElement>
|
||||
|
@ -8,7 +8,11 @@ from gaphor.diagram import initialize_item
|
||||
|
||||
from feature import FeatureItem
|
||||
|
||||
from zope import interface
|
||||
from gaphor.interfaces import IAttributeView
|
||||
|
||||
class AttributeItem(FeatureItem):
|
||||
interface.implements(IAttributeView)
|
||||
|
||||
popup_menu = FeatureItem.popup_menu + (
|
||||
'EditItem',
|
||||
|
@ -19,6 +19,8 @@ from classifier import ClassifierItem
|
||||
from attribute import AttributeItem
|
||||
from operation import OperationItem
|
||||
|
||||
from gaphor.interfaces import IClassView
|
||||
from zope import interface
|
||||
|
||||
class ClassItem(ClassifierItem, diacanvas.CanvasGroupable):
|
||||
"""This item visualizes a Class instance.
|
||||
@ -29,6 +31,8 @@ class ClassItem(ClassifierItem, diacanvas.CanvasGroupable):
|
||||
Items can be added by callling class.add() and class.remove().
|
||||
This is used to handle CanvasItems, not UML objects!
|
||||
"""
|
||||
interface.implements(IClassView)
|
||||
|
||||
__gproperties__ = {
|
||||
'show-attributes': (gobject.TYPE_BOOLEAN, 'show attributes',
|
||||
'',
|
||||
|
@ -169,7 +169,12 @@ class TextElement(diacanvas.CanvasItem, diacanvas.CanvasEditable, DiagramItem):
|
||||
|
||||
|
||||
|
||||
from zope import interface
|
||||
from gaphor.interfaces import INamedItemView
|
||||
|
||||
class NamedItem(ElementItem, diacanvas.CanvasEditable):
|
||||
interface.implements(INamedItemView)
|
||||
|
||||
__gproperties__ = {
|
||||
'name': (gobject.TYPE_STRING, 'name', '', '', gobject.PARAM_READWRITE)
|
||||
}
|
||||
|
8
gaphor/event.py
Normal file
8
gaphor/event.py
Normal file
@ -0,0 +1,8 @@
|
||||
from zope import interface
|
||||
from gaphor.interfaces import *
|
||||
|
||||
class DiagramItemFocused(object):
|
||||
interface.implements(IDiagramElementReceivedFocus)
|
||||
|
||||
def __init__(self, diagramItem):
|
||||
self.diagramItem = diagramItem
|
57
gaphor/interfaces.py
Normal file
57
gaphor/interfaces.py
Normal file
@ -0,0 +1,57 @@
|
||||
from zope import interface
|
||||
from zope import component
|
||||
class IGaphorAction(interface.Interface):
|
||||
"""Action interface for use in Gaphor"""
|
||||
|
||||
class IMenuAction(interface.Interface):
|
||||
"""An interface to hook up items to."""
|
||||
|
||||
|
||||
class TestAdapter(object):
|
||||
def __init__(self, context):
|
||||
self.context = context
|
||||
|
||||
#component.provideAdapter(
|
||||
#factory=TestAdapter,
|
||||
#adapts=[IGaphorAction],
|
||||
#provides=IZopeMenu,
|
||||
#name="Test adapter name")
|
||||
|
||||
#class TestAdapter2(object):
|
||||
#def __init__(self, context):
|
||||
#self.context = context
|
||||
|
||||
#component.provideAdapter(
|
||||
#factory=TestAdapter2,
|
||||
#adapts=[IGaphorAction],
|
||||
#provides=IZopeMenu,
|
||||
#name="Test adapter 2 name")
|
||||
|
||||
#class TestAction(object):
|
||||
#interface.implements(IGaphorAction)
|
||||
|
||||
class IDiagramElementReceivedFocus(interface.Interface):
|
||||
"""A diagram item received focus"""
|
||||
diagramItem = interface.Attribute("The diagram item that received focus")
|
||||
|
||||
|
||||
class IWidget(interface.Interface):
|
||||
"""A GTK widget"""
|
||||
|
||||
class IDetailsPage(IWidget):
|
||||
"""A property page which can display itself in a notebook"""
|
||||
|
||||
class IDiagramElement(interface.Interface):
|
||||
"""A diagram element"""
|
||||
subject = interface.Attribute("The model element connect to this view")
|
||||
|
||||
class INamedItemView(IDiagramElement):
|
||||
"""A view on an attribute (part of a class, interface etc.)."""
|
||||
|
||||
|
||||
class IClassView(INamedItemView):
|
||||
"""The graphical view on a class."""
|
||||
|
||||
class IAttributeView(INamedItemView):
|
||||
"""A view on an attribute (part of a class, interface etc.)."""
|
||||
|
@ -14,6 +14,9 @@ from gaphor.ui.abstractwindow import AbstractWindow
|
||||
import gaphor.ui.diagramactions
|
||||
import gaphor.diagram.placementactions
|
||||
|
||||
from gaphor.event import DiagramItemFocused
|
||||
from zope import component
|
||||
|
||||
class DiagramTab(object):
|
||||
|
||||
def __init__(self, owning_window):
|
||||
@ -126,6 +129,7 @@ class DiagramTab(object):
|
||||
|
||||
def __on_view_focus_item(self, view, focus_item):
|
||||
self.owning_window.execute_action('ItemFocus')
|
||||
component.handle(DiagramItemFocused(focus_item))
|
||||
|
||||
def __on_view_select_item(self, view, select_item):
|
||||
self.owning_window.execute_action('ItemSelect')
|
||||
|
@ -109,6 +109,7 @@ class NewAction(Action):
|
||||
weave_method(NewAction.execute, ErrorHandlerAspect, message='Could not create a new model.')
|
||||
register_action(NewAction)
|
||||
|
||||
|
||||
class RevertAction(Action):
|
||||
id = 'FileRevert'
|
||||
label = _('_Revert...')
|
||||
|
@ -15,6 +15,11 @@ from gaphor.ui.menufactory import toolbox_to_menu
|
||||
|
||||
# Load actions
|
||||
from gaphor.ui import mainactions, diagramactions
|
||||
from gaphor.ui.objectinspector import ObjectInspector
|
||||
|
||||
|
||||
from gaphor.interfaces import *
|
||||
from zope import component
|
||||
|
||||
class MainWindow(AbstractWindow):
|
||||
"""The main window for the application.
|
||||
@ -122,7 +127,7 @@ class MainWindow(AbstractWindow):
|
||||
_('_Help'), (
|
||||
'Manual',
|
||||
'About',
|
||||
'<HelpSlot>')
|
||||
'<HelpSlot>'),
|
||||
)
|
||||
|
||||
toolbar = ('FileOpen',
|
||||
@ -243,6 +248,7 @@ class MainWindow(AbstractWindow):
|
||||
paned = gtk.HPaned()
|
||||
paned.set_property('position', 160)
|
||||
paned.pack1(vbox)
|
||||
|
||||
notebook = gtk.Notebook()
|
||||
#notebook.popup_enable()
|
||||
notebook.set_scrollable(True)
|
||||
@ -250,7 +256,17 @@ class MainWindow(AbstractWindow):
|
||||
|
||||
notebook.connect_after('switch-page', self.on_notebook_switch_page)
|
||||
|
||||
paned.pack2(notebook)
|
||||
self.objectInspector = ObjectInspector()
|
||||
diagramReceivedFocus = component.adapter(IDiagramElementReceivedFocus)(
|
||||
self.objectInspector)
|
||||
component.provideHandler(diagramReceivedFocus)
|
||||
|
||||
secondPaned = gtk.VPaned()
|
||||
secondPaned.set_property('position', 600)
|
||||
secondPaned.pack1(notebook)
|
||||
secondPaned.pack2(self.objectInspector)
|
||||
secondPaned.show_all()
|
||||
paned.pack2(secondPaned)
|
||||
paned.show_all()
|
||||
|
||||
self.notebook = notebook
|
||||
@ -360,6 +376,7 @@ class MainWindow(AbstractWindow):
|
||||
a Diagram).
|
||||
"""
|
||||
path = self.get_model().path_from_element(element)
|
||||
#log.debug("PATH = %s" % path)
|
||||
# Expand the first row:
|
||||
self.get_tree_view().expand_row(path[:-1], False)
|
||||
# Select the diagram, so it can be opened by the OpenModelElement action
|
||||
|
180
gaphor/ui/objectinspector.py
Normal file
180
gaphor/ui/objectinspector.py
Normal file
@ -0,0 +1,180 @@
|
||||
import gtk
|
||||
from gaphor.interfaces import *
|
||||
from zope import component
|
||||
from gaphor.UML.uml2 import LiteralSpecification
|
||||
|
||||
class TestDiagramElement(object):
|
||||
interface.implements(IDiagramElement)
|
||||
|
||||
class NamedItemPropertyPage(gtk.Table):
|
||||
"""An adapter which works for any named item view.
|
||||
|
||||
It also sets up a table view which can be extended."""
|
||||
def __init__(self, context):
|
||||
super(NamedItemPropertyPage, self).__init__(rows=1, columns=1)
|
||||
|
||||
self.context = context
|
||||
|
||||
self.attach(gtk.Label("Name"), 0, 1, 0, 1, xoptions=gtk.FILL, yoptions=0)
|
||||
nameEntry = gtk.Entry()
|
||||
nameEntry.set_text(context.subject.name or '')
|
||||
nameEntry.connect('changed', self.changeName)
|
||||
self.attach(nameEntry, 1, 2, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0)
|
||||
|
||||
def changeName(self, entry):
|
||||
self.context.subject.name = entry.get_text()
|
||||
|
||||
component.provideAdapter(
|
||||
factory=NamedItemPropertyPage,
|
||||
adapts=[INamedItemView],
|
||||
provides=IDetailsPage,
|
||||
name='Properties')
|
||||
|
||||
|
||||
class PropertyPropertyPage(NamedItemPropertyPage):
|
||||
"""Adapter which shows a property page for a property (attributes etc.)."""
|
||||
|
||||
|
||||
component.provideAdapter(
|
||||
factory=PropertyPropertyPage,
|
||||
adapts=[IAttributeView],
|
||||
provides=IDetailsPage,
|
||||
name='Properties')
|
||||
|
||||
|
||||
class ClassPropertyPage(NamedItemPropertyPage):
|
||||
"""Adapter which shows a property page for a class view."""
|
||||
def __init__(self, context):
|
||||
super(ClassPropertyPage, self).__init__(context)
|
||||
|
||||
# Abstract toggle
|
||||
self.attach(gtk.Label("Abstract"), 0, 1, 1, 2, xoptions=gtk.FILL, yoptions=0)
|
||||
abstractCheckButton = gtk.CheckButton()
|
||||
abstractCheckButton.set_active(context.subject.isAbstract)
|
||||
abstractCheckButton.connect('toggled', self.changeAbstract)
|
||||
self.attach(abstractCheckButton, 1, 2, 1, 2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0)
|
||||
|
||||
# Attributes
|
||||
attributes = gtk.ListStore(str)
|
||||
for attr in context.subject.ownedAttribute:
|
||||
attributes.append([attr.name])
|
||||
attributesTreeView = gtk.TreeView(attributes)
|
||||
attributesTreeView.set_rules_hint(True)
|
||||
|
||||
textRenderer = gtk.CellRendererText()
|
||||
|
||||
attributesColumn = gtk.TreeViewColumn('Attributes', textRenderer, text=0)
|
||||
|
||||
attributesTreeView.append_column(attributesColumn)
|
||||
self.attach(attributesTreeView, 0, 2, 2, 3, xoptions=gtk.FILL|gtk.EXPAND, yoptions=0)
|
||||
|
||||
def changeName(self, entry):
|
||||
self.context.subject.name = entry.get_text()
|
||||
|
||||
def changeAbstract(self, checkButton):
|
||||
self.context.subject.isAbstract=checkButton.get_active()
|
||||
|
||||
|
||||
component.provideAdapter(
|
||||
factory=ClassPropertyPage,
|
||||
adapts=[IClassView],
|
||||
provides=IDetailsPage,
|
||||
name='Properties')
|
||||
|
||||
class TaggedValuePage(gtk.VBox):
|
||||
"""An editor for tagged values associated with elements."""
|
||||
def __init__(self, context):
|
||||
super(TaggedValuePage, self).__init__()
|
||||
self.context = context
|
||||
|
||||
taggedValues = gtk.ListStore(str, str)
|
||||
|
||||
|
||||
for taggedValue in self.context.subject.taggedValue:
|
||||
tag, value = taggedValue.value.split("=")
|
||||
taggedValues.append([tag, value])
|
||||
taggedValues.append(['',''])
|
||||
|
||||
self.taggedValues = taggedValues
|
||||
|
||||
treeView = gtk.TreeView(taggedValues)
|
||||
treeView.set_rules_hint(True)
|
||||
|
||||
tagTextRenderer = gtk.CellRendererText()
|
||||
tagTextRenderer.set_property('editable', True)
|
||||
tagTextRenderer.connect("edited", self.cellEdited, 0)
|
||||
|
||||
valueTextRenderer = gtk.CellRendererText()
|
||||
valueTextRenderer.set_property('editable', True)
|
||||
valueTextRenderer.connect("edited", self.cellEdited, 1)
|
||||
|
||||
tagColumn = gtk.TreeViewColumn('Tag', tagTextRenderer, text=0)
|
||||
treeView.append_column(tagColumn)
|
||||
valueColumn = gtk.TreeViewColumn('Value', valueTextRenderer, text=1)
|
||||
treeView.append_column(valueColumn)
|
||||
|
||||
self.pack_start(treeView)
|
||||
|
||||
def cellEdited(self, cellrenderertext, path, new_text, col):
|
||||
self.taggedValues[path][col]=new_text
|
||||
|
||||
iter = self.taggedValues.get_iter(path)
|
||||
|
||||
if not new_text and not self.taggedValues[path][1-col] and self.isLastRow(self.taggedValues, iter):
|
||||
self.taggedValues.remove(iter)
|
||||
|
||||
# Create a new row to enter next value
|
||||
elif new_text and not self.isLastRow(self.taggedValues, iter):
|
||||
self.taggedValues.append(['',''])
|
||||
|
||||
self.updateTaggedValuesInModel()
|
||||
|
||||
def updateTaggedValuesInModel(self):
|
||||
"""Write the current list out the model."""
|
||||
klass = self.context.subject
|
||||
while klass.taggedValue:
|
||||
klass.taggedValue[0].unlink()
|
||||
for tag, value in self.taggedValues:
|
||||
taggedValue = klass._factory.create(LiteralSpecification)
|
||||
taggedValue.value = "%s=%s"%(tag, value)
|
||||
klass.taggedValue.append(taggedValue)
|
||||
|
||||
def isLastRow(self, model, iter):
|
||||
return bool(model.iter_next(iter))
|
||||
|
||||
|
||||
|
||||
component.provideAdapter(
|
||||
factory=TaggedValuePage,
|
||||
adapts=[INamedItemView],
|
||||
provides=IDetailsPage,
|
||||
name='Tagged values')
|
||||
|
||||
|
||||
class ObjectInspector(gtk.Notebook):
|
||||
def __init__(self):
|
||||
super(ObjectInspector, self).__init__()
|
||||
self.set_scrollable(False)
|
||||
self.set_show_border(True)
|
||||
|
||||
def loadTabsForCurrentItem(self, item):
|
||||
"""Load all tabs that can operate on the given item."""
|
||||
for name, adapter in component.getAdapters(
|
||||
[item,], IDetailsPage):
|
||||
self.prepend_page(adapter, gtk.Label(name))
|
||||
self.show_all()
|
||||
|
||||
def clearAllTabs(self):
|
||||
"""Remove all tabs from the notebook."""
|
||||
[self.remove_page(0) for i in range(self.get_n_pages())]
|
||||
|
||||
def __call__(self, event):
|
||||
"""Called when a diagram item receives focus.
|
||||
|
||||
This reloads all tabs based on the current selection."""
|
||||
diagramItem = event.diagramItem
|
||||
self.clearAllTabs()
|
||||
if diagramItem is None:
|
||||
return
|
||||
self.loadTabsForCurrentItem(diagramItem.item)
|
||||
|
13
setup.py
13
setup.py
@ -371,7 +371,18 @@ setup(name='gaphor',
|
||||
'gaphor.UML',
|
||||
'gaphor.diagram',
|
||||
'gaphor.ui',
|
||||
'gaphor.misc'
|
||||
'gaphor.misc',
|
||||
'zope',
|
||||
'zope.interface',
|
||||
'zope.component.bbb',
|
||||
'zope.component.bbb.tests',
|
||||
'zope.interface.common',
|
||||
'zope.component',
|
||||
'zope.exceptions',
|
||||
'zope.proxy',
|
||||
'zope.deprecation',
|
||||
'zope.testing',
|
||||
|
||||
],
|
||||
# ext_modules=ext_modules,
|
||||
# data files are relative to <prefix>/share/gaphor (see setup.cfg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user