コード例 #1
0
    def test_braking_big_diamond(self):
        """
        Test diamond shaped dependencies a -> b -> c -> d, a -> b' -> c' -> d
        """
        a = A()
        watcher = EventWatcher(a, self._handler)
        watcher.watch('one.two.one.two')
        #watcher.watch('one.one.one.one')
        watcher.register_handlers()

        a.one = A()
        a.one.two = A()
        a.one.two = A()
        a.one.two[0].one = A()
        a.one.two[1].one = A()
        a.one.two[0].one.two = A()
        a.one.two[1].one.two = a.one.two[0].one.two[0]

        self.assertEquals(7, len(self.events))
        self.assertEquals(6, len(self.dispatcher._handlers))

        del a.one.two[0].one
        #a.unlink()
        watcher.unregister_handlers()
        watcher.unregister_handlers()
        self.assertEquals(0, len(self.dispatcher._handlers))
コード例 #2
0
    def test_braking_big_diamond(self):
        """
        Test diamond shaped dependencies a -> b -> c -> d, a -> b' -> c' -> d
        """
        a = A()
        watcher = EventWatcher(a, self._handler)
        watcher.watch('one.two.one.two')
        #watcher.watch('one.one.one.one')
        watcher.register_handlers()

        a.one = A()
        a.one.two = A()
        a.one.two = A()
        a.one.two[0].one = A()
        a.one.two[1].one = A()
        a.one.two[0].one.two = A()
        a.one.two[1].one.two = a.one.two[0].one.two[0]

        self.assertEquals(7, len(self.events))
        self.assertEquals(6, len(self.dispatcher._handlers))

        del a.one.two[0].one
        #a.unlink()
        watcher.unregister_handlers()
        watcher.unregister_handlers()
        self.assertEquals(0, len(self.dispatcher._handlers))
コード例 #3
0
ファイル: propertypages.py プロジェクト: tonystark97/gaphor
class NamedElementPropertyPage(object):
    """
    An adapter which works for any named item view.

    It also sets up a table view which can be extended.
    """

    interface.implements(IPropertyPage)
    component.adapts(uml2.NamedElement)

    order = 10

    NAME_LABEL = _('Name')

    def __init__(self, subject):
        assert subject is None or isinstance(
            subject, uml2.NamedElement), '%s' % type(subject)
        self.subject = subject
        self.watcher = EventWatcher(subject)
        self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)

    def construct(self):
        page = gtk.VBox()

        subject = self.subject
        if not subject:
            return page

        hbox = create_hbox_label(self, page, self.NAME_LABEL)
        entry = gtk.Entry()
        entry.set_text(subject and subject.name or '')
        hbox.pack_start(entry)
        page.set_data('default', entry)

        # monitor subject.name attribute
        changed_id = entry.connect('changed', self._on_name_change)

        def handler(event):
            if event.element is subject and event.new_value is not None:
                entry.handler_block(changed_id)
                entry.set_text(event.new_value)
                entry.handler_unblock(changed_id)

        self.watcher.watch('name', handler) \
                    .register_handlers()
        entry.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_name_change(self, entry):
        self.subject.name = entry.get_text()
コード例 #4
0
ファイル: propertypages.py プロジェクト: tonystark97/gaphor
class CommentItemPropertyPage(object):
    """
    Property page for Comments
    """
    interface.implements(IPropertyPage)
    component.adapts(uml2.Comment)

    order = 0

    def __init__(self, subject):
        self.subject = subject
        self.watcher = EventWatcher(subject)

    def construct(self):
        subject = self.subject
        page = gtk.VBox()

        if not subject:
            return page

        label = gtk.Label(_('Comment'))
        label.set_justify(gtk.JUSTIFY_LEFT)
        page.pack_start(label, expand=False)

        buffer = gtk.TextBuffer()
        if subject.body:
            buffer.set_text(subject.body)
        text_view = gtk.TextView()
        text_view.set_buffer(buffer)
        text_view.show()
        text_view.set_size_request(-1, 100)
        page.pack_start(text_view)
        page.set_data('default', text_view)

        changed_id = buffer.connect('changed', self._on_body_change)

        def handler(event):
            if not text_view.props.has_focus:
                buffer.handler_block(changed_id)
                buffer.set_text(event.new_value)
                buffer.handler_unblock(changed_id)

        self.watcher.watch('body', handler) \
                    .register_handlers()
        text_view.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_body_change(self, buffer):
        self.subject.body = buffer.get_text(buffer.get_start_iter(),
                                            buffer.get_end_iter())
コード例 #5
0
ファイル: propertypages.py プロジェクト: dieterv/gaphor
class CommentItemPropertyPage(object):
    """
    Property page for Comments
    """
    interface.implements(IPropertyPage)
    component.adapts(UML.Comment)

    order = 0

    def __init__(self, subject):
        self.subject = subject
        self.watcher = EventWatcher(subject)

    def construct(self):
        subject = self.subject
        page = gtk.VBox()

        if not subject:
            return page

        label = gtk.Label(_('Comment'))
        label.set_justify(gtk.JUSTIFY_LEFT)
        page.pack_start(label, expand=False)

        buffer = gtk.TextBuffer()
        if subject.body:
            buffer.set_text(subject.body)
        text_view = gtk.TextView()
        text_view.set_buffer(buffer)
        text_view.show()
        text_view.set_size_request(-1, 100)
        page.pack_start(text_view)
        page.set_data('default', text_view)

        changed_id = buffer.connect('changed', self._on_body_change)

        def handler(event):
            if not text_view.props.has_focus:
                buffer.handler_block(changed_id)
                buffer.set_text(event.new_value)
                buffer.handler_unblock(changed_id)

        self.watcher.watch('body', handler) \
                    .register_handlers()
        text_view.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_body_change(self, buffer):
        self.subject.body = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())
コード例 #6
0
ファイル: propertypages.py プロジェクト: dieterv/gaphor
class NamedElementPropertyPage(object):
    """
    An adapter which works for any named item view.

    It also sets up a table view which can be extended.
    """

    interface.implements(IPropertyPage)
    component.adapts(UML.NamedElement)

    order = 10

    NAME_LABEL = _('Name')

    def __init__(self, subject):
        assert subject is None or isinstance(subject, UML.NamedElement), '%s' % type(subject)
        self.subject = subject
        self.watcher = EventWatcher(subject)
        self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
    
    def construct(self):
        page = gtk.VBox()

        subject = self.subject
        if not subject:
            return page

        hbox = create_hbox_label(self, page, self.NAME_LABEL)
        entry = gtk.Entry()        
        entry.set_text(subject and subject.name or '')
        hbox.pack_start(entry)
        page.set_data('default', entry)

        # monitor subject.name attribute
        changed_id = entry.connect('changed', self._on_name_change)

        def handler(event):
            if event.element is subject and event.new_value is not None:
                entry.handler_block(changed_id)
                entry.set_text(event.new_value)
                entry.handler_unblock(changed_id)

        self.watcher.watch('name', handler) \
                    .register_handlers()
        entry.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_name_change(self, entry):
        self.subject.name = entry.get_text()
コード例 #7
0
ファイル: propertypages.py プロジェクト: weizx208/gaphor
class NamedElementPropertyPage(object):
    """An adapter which works for any named item view.

    It also sets up a table view which can be extended.
    """

    order = 10

    NAME_LABEL = _("Name")

    def __init__(self, subject):
        assert subject is None or isinstance(subject, UML.NamedElement), "%s" % type(
            subject
        )
        self.subject = subject
        self.watcher = EventWatcher(subject)
        self.size_group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.HORIZONTAL)

    def construct(self):
        page = Gtk.VBox()

        subject = self.subject
        if not subject:
            return page

        hbox = create_hbox_label(self, page, self.NAME_LABEL)
        entry = Gtk.Entry()
        entry.set_text(subject and subject.name or "")
        hbox.pack_start(entry, True, True, 0)
        page.default = entry

        # monitor subject.name attribute
        changed_id = entry.connect("changed", self._on_name_change)

        def handler(event):
            if event.element is subject and event.new_value is not None:
                entry.handler_block(changed_id)
                entry.set_text(event.new_value)
                entry.handler_unblock(changed_id)

        self.watcher.watch("name", handler).register_handlers()
        entry.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_name_change(self, entry):
        self.subject.name = entry.get_text()
コード例 #8
0
class CommentItemPropertyPage(PropertyPageBase):
    """Property page for Comments."""

    order = 0

    def __init__(self, subject):
        self.subject = subject
        self.watcher = EventWatcher(subject)

    def construct(self):
        subject = self.subject
        page = Gtk.VBox()

        if not subject:
            return page

        label = Gtk.Label(label=_("Comment"))
        label.set_justify(Gtk.Justification.LEFT)
        page.pack_start(label, False, True, 0)

        buffer = Gtk.TextBuffer()
        if subject.body:
            buffer.set_text(subject.body)
        text_view = Gtk.TextView()
        text_view.set_buffer(buffer)
        text_view.show()
        text_view.set_size_request(-1, 100)
        page.pack_start(text_view, True, True, 0)
        page.default = text_view

        changed_id = buffer.connect("changed", self._on_body_change)

        def handler(event):
            if not text_view.props.has_focus:
                buffer.handler_block(changed_id)
                buffer.set_text(event.new_value)
                buffer.handler_unblock(changed_id)

        self.watcher.watch("body", handler).register_handlers()
        text_view.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_body_change(self, buffer):
        self.subject.body = buffer.get_text(
            buffer.get_start_iter(), buffer.get_end_iter(), False
        )
コード例 #9
0
    def test_diamond(self):
        """
        Test diamond shaped dependencies a -> b -> c, a -> b' -> c
        """
        a = A()
        watcher = EventWatcher(a, self._handler)
        watcher.watch('one.two.one.two')
        #watcher.watch('one.one.one.one')
        watcher.register_handlers()

        a.one = A()
        a.one.two = A()
        a.one.two = A()
        a.one.two[0].one = A()
        a.one.two[1].one = a.one.two[0].one
        a.one.two[0].one.two = A()

        self.assertEquals(6, len(self.events))

        a.unlink()
        watcher.unregister_handlers()
        watcher.unregister_handlers()
コード例 #10
0
    def test_cyclic(self):
        """
        Test cyclic dependency a -> b -> c -> a.
        """
        a = A()
        watcher = EventWatcher(a, self._handler)
        watcher.watch('one.two.one.two')
        #watcher.watch('one.one.one.one')
        watcher.register_handlers()

        a.one = A()
        a.one.two = A()
        a.one.two = A()
        a.one.two[0].one = a

        self.assertEquals(4, len(self.events))

        #a.one.two[0].one.two = A()
        #a.one.two[0].one.two = A()

        a.unlink()
        self.assertEquals(1, len(self.dispatcher._handlers))
コード例 #11
0
    def test_cyclic(self):
        """
        Test cyclic dependency a -> b -> c -> a.
        """
        a = A()
        watcher = EventWatcher(a, self._handler)
        watcher.watch('one.two.one.two')
        #watcher.watch('one.one.one.one')
        watcher.register_handlers()

        a.one = A()
        a.one.two = A()
        a.one.two = A()
        a.one.two[0].one = a

        self.assertEquals(4, len(self.events))

        #a.one.two[0].one.two = A()
        #a.one.two[0].one.two = A()

        a.unlink()
        self.assertEquals(1, len(self.dispatcher._handlers))
コード例 #12
0
    def test_diamond(self):
        """
        Test diamond shaped dependencies a -> b -> c, a -> b' -> c
        """
        a = A()
        watcher = EventWatcher(a, self._handler)
        watcher.watch('one.two.one.two')
        #watcher.watch('one.one.one.one')
        watcher.register_handlers()

        a.one = A()
        a.one.two = A()
        a.one.two = A()
        a.one.two[0].one = A()
        a.one.two[1].one = a.one.two[0].one
        a.one.two[0].one.two = A()

        self.assertEquals(6, len(self.events))

        a.unlink()
        watcher.unregister_handlers()
        watcher.unregister_handlers()
コード例 #13
0
ファイル: propertypages.py プロジェクト: dieterv/gaphor
class AttributesPage(object):
    """
    An editor for attributes associated with classes and interfaces.
    """

    interface.implements(IPropertyPage)
    component.adapts(items.ClassItem)

    order = 20

    def __init__(self, item):
        super(AttributesPage, self).__init__()
        self.item = item
        self.watcher = EventWatcher(item.subject)
        
    def construct(self):
        page = gtk.VBox()

        if not self.item.subject:
            return page

        # Show attributes toggle
        hbox = gtk.HBox()
        label = gtk.Label('')
        label.set_justify(gtk.JUSTIFY_LEFT)
        hbox.pack_start(label, expand=False)
        button = gtk.CheckButton(_('Show attributes'))
        button.set_active(self.item.show_attributes)
        button.connect('toggled', self._on_show_attributes_change)
        hbox.pack_start(button)
        page.pack_start(hbox, expand=False)

        def create_model():
            return ClassAttributes(self.item, (str, bool, object))

        self.model = create_model()
        
        tip = """\
Add and edit class attributes according to UML syntax. Attribute syntax examples
- attr
- + attr: int
- # /attr: int
"""
        tree_view = create_tree_view(self.model, (_('Attributes'), _('S')), tip)
        page.pack_start(tree_view)

        @async(single=True)
        def handler(event):
            # Single it's asynchronous, make sure all properties are still there
            if not tree_view.props.has_focus and self.item and self.item.subject:
                self.model = create_model()
                tree_view.set_model(self.model)

        self.watcher.watch('ownedAttribute.name', handler) \
            .watch('ownedAttribute.isDerived', handler) \
            .watch('ownedAttribute.visibility', handler) \
            .watch('ownedAttribute.isStatic', handler) \
            .watch('ownedAttribute.lowerValue<LiteralSpecification>.value', handler) \
            .watch('ownedAttribute.upperValue<LiteralSpecification>.value', handler) \
            .watch('ownedAttribute.defaultValue<LiteralSpecification>.value', handler) \
            .watch('ownedAttribute.typeValue<LiteralSpecification>.value', handler) \
            .register_handlers()
        tree_view.connect('destroy', self.watcher.unregister_handlers)
        return page
        
    @transactional
    def _on_show_attributes_change(self, button):
        self.item.show_attributes = button.get_active()
        self.item.request_update()
コード例 #14
0
class AssociationEndPropertyPage(PropertyPageBase):
    """Property page for association end properties."""

    order = 0

    NAVIGABILITY = [None, False, True]

    def __init__(self, subject):
        self.subject = subject
        self.watcher = EventWatcher(subject)

    def construct(self):
        vbox = Gtk.VBox()

        entry = Gtk.Entry()
        # entry.set_text(UML.format(self.subject, visibility=True, is_derived=Truemultiplicity=True) or '')

        # monitor subject attribute (all, cause it contains many children)
        changed_id = entry.connect("changed", self._on_end_name_change)

        def handler(event):
            if not entry.props.has_focus:
                entry.handler_block(changed_id)
                entry.set_text(
                    UML.format(
                        self.subject,
                        visibility=True,
                        is_derived=True,
                        multiplicity=True,
                    ) or "")
                # entry.set_text(UML.format(self.subject, multiplicity=True) or '')
                entry.handler_unblock(changed_id)

        handler(None)

        self.watcher.watch("name", handler).watch(
            "aggregation", handler).watch("visibility", handler).watch(
                "lowerValue", handler).watch("upperValue",
                                             handler).register_handlers()
        entry.connect("destroy", self.watcher.unregister_handlers)

        vbox.pack_start(entry, True, True, 0)

        entry.set_tooltip_text("""\
Enter attribute name and multiplicity, for example
- name
+ name [1]
- name [1..2]
~ 1..2
- [1..2]\
""")

        combo = Gtk.ComboBoxText()
        for t in ("Unknown navigation", "Not navigable", "Navigable"):
            combo.append_text(t)

        nav = self.subject.navigability
        combo.set_active(self.NAVIGABILITY.index(nav))

        combo.connect("changed", self._on_navigability_change)
        vbox.pack_start(combo, False, True, 0)

        combo = Gtk.ComboBoxText()
        for t in ("No aggregation", "Shared", "Composite"):
            combo.append_text(t)

        combo.set_active(["none", "shared",
                          "composite"].index(self.subject.aggregation))

        combo.connect("changed", self._on_aggregation_change)
        vbox.pack_start(combo, False, True, 0)

        return vbox

    @transactional
    def _on_end_name_change(self, entry):
        UML.parse(self.subject, entry.get_text())

    @transactional
    def _on_navigability_change(self, combo):
        nav = self.NAVIGABILITY[combo.get_active()]
        UML.model.set_navigability(self.subject.association, self.subject, nav)

    @transactional
    def _on_aggregation_change(self, combo):
        self.subject.aggregation = ("none", "shared",
                                    "composite")[combo.get_active()]
コード例 #15
0
class DependencyPropertyPage(PropertyPageBase):
    """Dependency item editor."""

    order = 0

    element_factory = inject("element_factory")

    DEPENDENCY_TYPES = (
        (_("Dependency"), UML.Dependency),
        (_("Usage"), UML.Usage),
        (_("Realization"), UML.Realization),
        (_("Implementation"), UML.Implementation),
    )

    def __init__(self, item):
        super(DependencyPropertyPage, self).__init__()
        self.item = item
        self.size_group = Gtk.SizeGroup(Gtk.SizeGroupMode.HORIZONTAL)
        self.watcher = EventWatcher(self.item)

    def construct(self):
        page = Gtk.VBox()

        hbox = create_hbox_label(self, page, _("Dependency type"))

        self.combo = create_uml_combo(self.DEPENDENCY_TYPES,
                                      self._on_dependency_type_change)
        hbox.pack_start(self.combo, False, True, 0)

        hbox = create_hbox_label(self, page, "")

        button = Gtk.CheckButton(_("Automatic"))
        button.set_active(self.item.auto_dependency)
        button.connect("toggled", self._on_auto_dependency_change)
        hbox.pack_start(button, True, True, 0)

        self.watcher.watch("subject",
                           self._on_subject_change).register_handlers()
        button.connect("destroy", self.watcher.unregister_handlers)

        self.update()

        return page

    def _on_subject_change(self, event):
        self.update()

    def update(self):
        """
        Update dependency type combo box.

        Disallow dependency type when dependency is established.
        """
        combo = self.combo
        item = self.item
        index = combo.get_model().get_index(item.dependency_type)
        combo.props.sensitive = not item.auto_dependency
        combo.set_active(index)

    @transactional
    def _on_dependency_type_change(self, combo):
        combo = self.combo
        cls = combo.get_model().get_value(combo.get_active())
        self.item.dependency_type = cls
        if self.item.subject:
            self.element_factory.swap_element(self.item.subject, cls)
            self.item.request_update()

    @transactional
    def _on_auto_dependency_change(self, button):
        self.item.auto_dependency = button.get_active()
        self.update()
コード例 #16
0
class OperationsPage(PropertyPageBase):
    """An editor for operations associated with classes and interfaces."""

    order = 30
    name = "Operations"

    def __init__(self, item):
        super(OperationsPage, self).__init__()
        self.item = item
        self.watcher = EventWatcher(item.subject)

    def construct(self):
        page = Gtk.VBox()

        if not self.item.subject:
            return page

        # Show operations toggle
        hbox = Gtk.HBox()
        label = Gtk.Label(label="")
        label.set_justify(Gtk.Justification.LEFT)
        hbox.pack_start(label, False, True, 0)
        button = Gtk.CheckButton(label=_("Show operations"))
        button.set_active(self.item.show_operations)
        button.connect("toggled", self._on_show_operations_change)
        hbox.pack_start(button, True, True, 0)
        page.pack_start(hbox, False, True, 0)

        def create_model():
            return ClassOperations(self.item, (str, bool, bool, object))

        self.model = create_model()
        tip = """\
Add and edit class operations according to UML syntax. Operation syntax examples
- call()
- + call(a: int, b: str)
- # call(a: int: b: str): bool
"""
        tree_view = create_tree_view(self.model,
                                     (_("Operation"), _("A"), _("S")), tip)
        page.pack_start(tree_view, True, True, 0)

        @AsyncIO(single=True)
        def handler(event):
            if not tree_view.props.has_focus and self.item and self.item.subject:
                self.model = create_model()
                tree_view.set_model(self.model)

        self.watcher.watch("ownedOperation.name", handler).watch(
            "ownedOperation.isAbstract",
            handler).watch("ownedOperation.visibility", handler).watch(
                "ownedOperation.returnResult.lowerValue", handler
            ).watch("ownedOperation.returnResult.upperValue", handler).watch(
                "ownedOperation.returnResult.typeValue", handler).watch(
                    "ownedOperation.formalParameter.lowerValue",
                    handler).watch(
                        "ownedOperation.formalParameter.upperValue",
                        handler).watch(
                            "ownedOperation.formalParameter.typeValue",
                            handler).watch(
                                "ownedOperation.formalParameter.defaultValue",
                                handler).register_handlers()
        tree_view.connect("destroy", self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_show_operations_change(self, button):
        self.item.show_operations = button.get_active()
        self.item.request_update()
コード例 #17
0
ファイル: propertypages.py プロジェクト: tonystark97/gaphor
class AttributesPage(object):
    """
    An editor for attributes associated with classes and interfaces.
    """

    interface.implements(IPropertyPage)
    component.adapts(items.ClassItem)

    order = 20

    def __init__(self, item):
        super(AttributesPage, self).__init__()
        self.item = item
        self.watcher = EventWatcher(item.subject)

    def construct(self):
        page = gtk.VBox()

        if not self.item.subject:
            return page

        # Show attributes toggle
        hbox = gtk.HBox()
        label = gtk.Label('')
        label.set_justify(gtk.JUSTIFY_LEFT)
        hbox.pack_start(label, expand=False)
        button = gtk.CheckButton(_('Show attributes'))
        button.set_active(self.item.show_attributes)
        button.connect('toggled', self._on_show_attributes_change)
        hbox.pack_start(button)
        page.pack_start(hbox, expand=False)

        def create_model():
            return ClassAttributes(self.item, (str, bool, object))

        self.model = create_model()

        tip = """\
Add and edit class attributes according to UML syntax. Attribute syntax examples
- attr
- + attr: int
- # /attr: int
"""
        tree_view = create_tree_view(self.model, (_('Attributes'), _('S')),
                                     tip)
        page.pack_start(tree_view)

        @async (single=True)
        def handler(event):
            # Single it's asynchronous, make sure all properties are still there
            if not tree_view.props.has_focus and self.item and self.item.subject:
                self.model = create_model()
                tree_view.set_model(self.model)

        self.watcher.watch('ownedAttribute.name', handler) \
            .watch('ownedAttribute.isDerived', handler) \
            .watch('ownedAttribute.visibility', handler) \
            .watch('ownedAttribute.isStatic', handler) \
            .watch('ownedAttribute.lowerValue', handler) \
            .watch('ownedAttribute.upperValue', handler) \
            .watch('ownedAttribute.defaultValue', handler) \
            .watch('ownedAttribute.typeValue', handler) \
            .register_handlers()
        tree_view.connect('destroy', self.watcher.unregister_handlers)
        return page

    @transactional
    def _on_show_attributes_change(self, button):
        self.item.show_attributes = button.get_active()
        self.item.request_update()
コード例 #18
0
ファイル: propertypages.py プロジェクト: dieterv/gaphor
class OperationsPage(object):
    """
    An editor for operations associated with classes and interfaces.
    """

    interface.implements(IPropertyPage)
    component.adapts(items.ClassItem)

    order = 30

    def __init__(self, item):
        super(OperationsPage, self).__init__()
        self.item = item
        self.watcher = EventWatcher(item.subject)
        
    def construct(self):
        page = gtk.VBox()

        if not self.item.subject:
            return page

        # Show operations toggle
        hbox = gtk.HBox()
        label = gtk.Label("")
        label.set_justify(gtk.JUSTIFY_LEFT)
        hbox.pack_start(label, expand=False)
        button = gtk.CheckButton(_("Show operations"))
        button.set_active(self.item.show_operations)
        button.connect('toggled', self._on_show_operations_change)
        hbox.pack_start(button)
        page.pack_start(hbox, expand=False)

        def create_model():
            return ClassOperations(self.item, (str, bool, bool, object))

        self.model = create_model()
        tip = """\
Add and edit class operations according to UML syntax. Operation syntax examples
- call()
- + call(a: int, b: str)
- # call(a: int: b: str): bool
"""
        tree_view = create_tree_view(self.model, (_('Operation'), _('A'), _('S')), tip)
        page.pack_start(tree_view)

        @async(single=True)
        def handler(event):
            if not tree_view.props.has_focus and self.item and self.item.subject:
                self.model = create_model()
                tree_view.set_model(self.model)

        self.watcher.watch('ownedOperation.name', handler) \
            .watch('ownedOperation.isAbstract', handler) \
            .watch('ownedOperation.visibility', handler) \
            .watch('ownedOperation.returnResult.lowerValue<LiteralSpecification>.value', handler) \
            .watch('ownedOperation.returnResult.upperValue<LiteralSpecification>.value', handler) \
            .watch('ownedOperation.returnResult.typeValue<LiteralSpecification>.value', handler) \
            .watch('ownedOperation.formalParameter.lowerValue<LiteralSpecification>.value', handler) \
            .watch('ownedOperation.formalParameter.upperValue<LiteralSpecification>.value', handler) \
            .watch('ownedOperation.formalParameter.typeValue<LiteralSpecification>.value', handler) \
            .watch('ownedOperation.formalParameter.defaultValue<LiteralSpecification>.value', handler) \
            .register_handlers()
        tree_view.connect('destroy', self.watcher.unregister_handlers)

        return page
        
    @transactional
    def _on_show_operations_change(self, button):
        self.item.show_operations = button.get_active()
        self.item.request_update()
コード例 #19
0
ファイル: propertypages.py プロジェクト: dieterv/gaphor
class DependencyPropertyPage(object):
    """
    Dependency item editor.
    """

    interface.implements(IPropertyPage)
    component.adapts(items.DependencyItem)

    order = 0

    element_factory = inject('element_factory')

    DEPENDENCY_TYPES = (
        (_('Dependency'), UML.Dependency),
        (_('Usage'), UML.Usage),
        (_('Realization'), UML.Realization),
        (_('Implementation'), UML.Implementation))

    def __init__(self, item):
        super(DependencyPropertyPage, self).__init__()
        self.item = item
        self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
        self.watcher = EventWatcher(self.item)

        
    def construct(self):
        page = gtk.VBox()

        hbox = create_hbox_label(self, page, _('Dependency type'))

        self.combo = create_uml_combo(self.DEPENDENCY_TYPES,
            self._on_dependency_type_change)
        hbox.pack_start(self.combo, expand=False)

        hbox = create_hbox_label(self, page, '')

        button = gtk.CheckButton(_('Automatic'))
        button.set_active(self.item.auto_dependency)
        button.connect('toggled', self._on_auto_dependency_change)
        hbox.pack_start(button)

        self.watcher.watch('subject', self._on_subject_change).register_handlers()
        button.connect('destroy', self.watcher.unregister_handlers)

        self.update()

        return page


    def _on_subject_change(self, event):
        self.update()


    def update(self):
        """
        Update dependency type combo box.

        Disallow dependency type when dependency is established.
        """
        combo = self.combo
        item = self.item
        index = combo.get_model().get_index(item.dependency_type)
        combo.props.sensitive = not item.auto_dependency
        combo.set_active(index)


    @transactional
    def _on_dependency_type_change(self, combo):
        combo = self.combo
        cls = combo.get_model().get_value(combo.get_active())
        self.item.dependency_type = cls
        if self.item.subject:
            self.element_factory.swap_element(self.item.subject, cls)
            self.item.request_update()


    @transactional
    def _on_auto_dependency_change(self, button):
        self.item.auto_dependency = button.get_active()
        self.update()
コード例 #20
0
ファイル: diagramitem.py プロジェクト: amolenaar/gaphor
class DiagramItem(
    UML.Presentation, StereotypeSupport, EditableTextSupport, metaclass=DiagramItemMeta
):
    """
    Basic functionality for all model elements (lines and elements!).

    This class contains common functionality 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 contains some glue-code for
    diacanvas.DiaCanvasItem and gaphor.UML.Element.

    Example:
        class ElementItem(diacanvas.CanvasElement, DiagramItem):
            connect = DiagramItem.connect
            disconnect = DiagramItem.disconnect
            ...

    @cvar style: styles information (derived from DiagramItemMeta)
    """

    dispatcher = inject("element_dispatcher")
    element_factory = inject("element_factory")

    def __init__(self, id=None):
        UML.Presentation.__init__(self, factory=self.element_factory)
        EditableTextSupport.__init__(self)
        StereotypeSupport.__init__(self)

        self._id = id

        # properties, which should be saved in file
        self._persistent_props = set()

        def update(event):
            self.request_update()

        self.watcher = EventWatcher(self, default_handler=update)

        self.watch("subject").watch(
            "subject.appliedStereotype.classifier.name",
            self.on_element_applied_stereotype,
        )

    id = property(lambda self: self._id, doc="Id")

    def set_prop_persistent(self, name):
        """
        Specify property of diagram item, which should be saved in file.
        """
        self._persistent_props.add(name)

    # TODO: Use adapters for load/save functionality
    def save(self, save_func):
        if self.subject:
            save_func("subject", self.subject)

        save_func("show_stereotypes_attrs", self.show_stereotypes_attrs)

        # save persistent properties
        for p in self._persistent_props:
            save_func(p, getattr(self, p.replace("-", "_")))

    def load(self, name, value):
        if name == "subject":
            type(self).subject.load(self, value)
        elif name == "show_stereotypes_attrs":
            self._show_stereotypes_attrs = eval(value)
        else:
            try:
                setattr(self, name.replace("-", "_"), eval(value))
            except:
                logger.warning(
                    "%s has no property named %s (value %s)" % (self, name, value)
                )

    def postload(self):
        if self.subject:
            self.update_stereotype()
            self.update_stereotypes_attrs()

    def save_property(self, save_func, name):
        """
        Save a property, this is a shorthand method.
        """
        save_func(name, getattr(self, name.replace("-", "_")))

    def save_properties(self, save_func, *names):
        """
        Save a property, this is a shorthand method.
        """
        for name in names:
            self.save_property(save_func, name)

    def unlink(self):
        """
        Remove the item from the canvas and set subject to None.
        """
        if self.canvas:
            self.canvas.remove(self)
        super(DiagramItem, self).unlink()

    def request_update(self):
        """
        Placeholder for gaphor.Item's request_update() method.
        """
        pass

    def pre_update(self, context):
        EditableTextSupport.pre_update(self, context)

    def post_update(self, context):
        EditableTextSupport.post_update(self, context)

    def draw(self, context):
        EditableTextSupport.draw(self, context)

    def item_at(self, x, y):
        return self

    def on_element_applied_stereotype(self, event):
        if self.subject:
            self.update_stereotype()
            self.request_update()

    def watch(self, path, handler=None):
        """
        Watch a certain path of elements starting with the DiagramItem.
        The handler is optional and will default to a simple
        self.request_update().

        Watches should be set in the constructor, so they can be registered
        and unregistered in one shot.

        This interface is fluent(returns self).
        """
        self.watcher.watch(path, handler)
        return self

    def register_handlers(self):
        self.watcher.register_handlers()

    def unregister_handlers(self):
        self.watcher.unregister_handlers()
コード例 #21
0
ファイル: propertypages.py プロジェクト: tonystark97/gaphor
class DependencyPropertyPage(object):
    """
    Dependency item editor.
    """

    interface.implements(IPropertyPage)
    component.adapts(items.DependencyItem)

    order = 0

    element_factory = inject('element_factory')

    DEPENDENCY_TYPES = ((_('Dependency'), uml2.Dependency),
                        (_('Usage'), uml2.Usage), (_('Realization'),
                                                   uml2.Realization),
                        (_('Implementation'), uml2.Implementation))

    def __init__(self, item):
        super(DependencyPropertyPage, self).__init__()
        self.item = item
        self.size_group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL)
        self.watcher = EventWatcher(self.item)

    def construct(self):
        page = gtk.VBox()

        hbox = create_hbox_label(self, page, _('Dependency type'))

        self.combo = create_uml_combo(self.DEPENDENCY_TYPES,
                                      self._on_dependency_type_change)
        hbox.pack_start(self.combo, expand=False)

        hbox = create_hbox_label(self, page, '')

        button = gtk.CheckButton(_('Automatic'))
        button.set_active(self.item.auto_dependency)
        button.connect('toggled', self._on_auto_dependency_change)
        hbox.pack_start(button)

        self.watcher.watch('subject',
                           self._on_subject_change).register_handlers()
        button.connect('destroy', self.watcher.unregister_handlers)

        self.update()

        return page

    def _on_subject_change(self, event):
        self.update()

    def update(self):
        """
        Update dependency type combo box.

        Disallow dependency type when dependency is established.
        """
        combo = self.combo
        item = self.item
        index = combo.get_model().get_index(item.dependency_type)
        combo.props.sensitive = not item.auto_dependency
        combo.set_active(index)

    @transactional
    def _on_dependency_type_change(self, combo):
        combo = self.combo
        cls = combo.get_model().get_value(combo.get_active())
        self.item.dependency_type = cls
        if self.item.subject:
            self.element_factory.swap_element(self.item.subject, cls)
            self.item.request_update()

    @transactional
    def _on_auto_dependency_change(self, button):
        self.item.auto_dependency = button.get_active()
        self.update()
コード例 #22
0
ファイル: propertypages.py プロジェクト: tonystark97/gaphor
class OperationsPage(object):
    """
    An editor for operations associated with classes and interfaces.
    """

    interface.implements(IPropertyPage)
    component.adapts(items.ClassItem)

    order = 30

    def __init__(self, item):
        super(OperationsPage, self).__init__()
        self.item = item
        self.watcher = EventWatcher(item.subject)

    def construct(self):
        page = gtk.VBox()

        if not self.item.subject:
            return page

        # Show operations toggle
        hbox = gtk.HBox()
        label = gtk.Label("")
        label.set_justify(gtk.JUSTIFY_LEFT)
        hbox.pack_start(label, expand=False)
        button = gtk.CheckButton(_("Show operations"))
        button.set_active(self.item.show_operations)
        button.connect('toggled', self._on_show_operations_change)
        hbox.pack_start(button)
        page.pack_start(hbox, expand=False)

        def create_model():
            return ClassOperations(self.item, (str, bool, bool, object))

        self.model = create_model()
        tip = """\
Add and edit class operations according to UML syntax. Operation syntax examples
- call()
- + call(a: int, b: str)
- # call(a: int: b: str): bool
"""
        tree_view = create_tree_view(self.model,
                                     (_('Operation'), _('A'), _('S')), tip)
        page.pack_start(tree_view)

        @async (single=True)
        def handler(event):
            if not tree_view.props.has_focus and self.item and self.item.subject:
                self.model = create_model()
                tree_view.set_model(self.model)

        self.watcher.watch('ownedOperation.name', handler) \
            .watch('ownedOperation.isAbstract', handler) \
            .watch('ownedOperation.visibility', handler) \
            .watch('ownedOperation.returnResult.lowerValue', handler) \
            .watch('ownedOperation.returnResult.upperValue', handler) \
            .watch('ownedOperation.returnResult.typeValue', handler) \
            .watch('ownedOperation.formalParameter.lowerValue', handler) \
            .watch('ownedOperation.formalParameter.upperValue', handler) \
            .watch('ownedOperation.formalParameter.typeValue', handler) \
            .watch('ownedOperation.formalParameter.defaultValue', handler) \
            .register_handlers()
        tree_view.connect('destroy', self.watcher.unregister_handlers)

        return page

    @transactional
    def _on_show_operations_change(self, button):
        self.item.show_operations = button.get_active()
        self.item.request_update()
コード例 #23
0
class DiagramItem(
        with_metaclass(
            DiagramItemMeta,
            type('NewBase',
                 (UML.Presentation, StereotypeSupport, EditableTextSupport),
                 {}))):
    """
    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 contains some glue-code for
    diacanvas.DiaCanvasItem and gaphor.UML.Element.

    Example:
        class ElementItem(diacanvas.CanvasElement, DiagramItem):
            connect = DiagramItem.connect
            disconnect = DiagramItem.disconnect
            ...

    @cvar style: styles information (derived from DiagramItemMeta)
    """

    dispatcher = inject('element_dispatcher')

    def __init__(self, id=None):
        UML.Presentation.__init__(self)
        EditableTextSupport.__init__(self)
        StereotypeSupport.__init__(self)

        self._id = id

        # properties, which should be saved in file
        self._persistent_props = set()

        def update(event):
            self.request_update()

        self.watcher = EventWatcher(self, default_handler=update)

        self.watch('subject') \
            .watch('subject.appliedStereotype.classifier.name', self.on_element_applied_stereotype)

    id = property(lambda self: self._id, doc='Id')

    def set_prop_persistent(self, name):
        """
        Specify property of diagram item, which should be saved in file.
        """
        self._persistent_props.add(name)

    # TODO: Use adapters for load/save functionality
    def save(self, save_func):
        if self.subject:
            save_func('subject', self.subject)

        save_func('show_stereotypes_attrs', self.show_stereotypes_attrs)

        # save persistent properties
        for p in self._persistent_props:
            save_func(p, getattr(self, p.replace('-', '_')))

    def load(self, name, value):
        if name == 'subject':
            type(self).subject.load(self, value)
        elif name == 'show_stereotypes_attrs':
            self._show_stereotypes_attrs = eval(value)
        else:
            try:
                setattr(self, name.replace('-', '_'), eval(value))
            except:
                logger.warning('%s has no property named %s (value %s)'%\
                (self, name, value))

    def postload(self):
        if self.subject:
            self.update_stereotype()
            self.update_stereotypes_attrs()

    def save_property(self, save_func, name):
        """
        Save a property, this is a shorthand method.
        """
        save_func(name, getattr(self, name.replace('-', '_')))

    def save_properties(self, save_func, *names):
        """
        Save a property, this is a shorthand method.
        """
        for name in names:
            self.save_property(save_func, name)

    def unlink(self):
        """
        Remove the item from the canvas and set subject to None.
        """
        if self.canvas:
            self.canvas.remove(self)
        super(DiagramItem, self).unlink()

    def request_update(self):
        """
        Placeholder for gaphor.Item's request_update() method.
        """
        pass

    def pre_update(self, context):
        EditableTextSupport.pre_update(self, context)

    def post_update(self, context):
        EditableTextSupport.post_update(self, context)

    def draw(self, context):
        EditableTextSupport.draw(self, context)

    def item_at(self, x, y):
        return self

    def on_element_applied_stereotype(self, event):
        if self.subject:
            self.update_stereotype()
            self.request_update()

    def watch(self, path, handler=None):
        """
        Watch a certain path of elements starting with the DiagramItem.
        The handler is optional and will default to a simple
        self.request_update().
        
        Watches should be set in the constructor, so they can be registered
        and unregistered in one shot.

        This interface is fluent(returns self).
        """
        self.watcher.watch(path, handler)
        return self

    def register_handlers(self):
        self.watcher.register_handlers()

    def unregister_handlers(self):
        self.watcher.unregister_handlers()
コード例 #24
0
class AttributesPage(PropertyPageBase):
    """An editor for attributes associated with classes and interfaces."""

    order = 20
    name = "Attributes"

    def __init__(self, item):
        super(AttributesPage, self).__init__()
        self.item = item
        self.watcher = EventWatcher(item.subject)

    def construct(self):
        page = Gtk.VBox()

        if not self.item.subject:
            return page

        # Show attributes toggle
        hbox = Gtk.HBox()
        label = Gtk.Label(label="")
        label.set_justify(Gtk.Justification.LEFT)
        hbox.pack_start(label, False, True, 0)
        button = Gtk.CheckButton(label=_("Show attributes"))
        button.set_active(self.item.show_attributes)
        button.connect("toggled", self._on_show_attributes_change)
        hbox.pack_start(button, True, True, 0)
        page.pack_start(hbox, False, True, 0)

        def create_model():
            return ClassAttributes(self.item, (str, bool, object))

        self.model = create_model()

        tip = """\
Add and edit class attributes according to UML syntax. Attribute syntax examples
- attr
- + attr: int
- # /attr: int
"""
        tree_view = create_tree_view(self.model, (_("Attributes"), _("S")),
                                     tip)
        page.pack_start(tree_view, True, True, 0)

        @AsyncIO(single=True)
        def handler(event):
            # Single it's asynchronous, make sure all properties are still there
            if not tree_view.props.has_focus and self.item and self.item.subject:
                self.model = create_model()
                tree_view.set_model(self.model)

        self.watcher.watch("ownedAttribute.name", handler).watch(
            "ownedAttribute.isDerived",
            handler).watch("ownedAttribute.visibility", handler).watch(
                "ownedAttribute.isStatic",
                handler).watch("ownedAttribute.lowerValue", handler).watch(
                    "ownedAttribute.upperValue",
                    handler).watch("ownedAttribute.defaultValue",
                                   handler).watch("ownedAttribute.typeValue",
                                                  handler).register_handlers()
        tree_view.connect("destroy", self.watcher.unregister_handlers)
        return page

    @transactional
    def _on_show_attributes_change(self, button):
        self.item.show_attributes = button.get_active()
        self.item.request_update()
コード例 #25
0
ファイル: propertypages.py プロジェクト: dieterv/gaphor
class AssociationEndPropertyPage(object):
    """
    Property page for association end properties.
    """

    interface.implements(IPropertyPage)
    component.adapts(UML.Property)

    order = 0

    NAVIGABILITY = [None, False, True]

    def __init__(self, subject):
        self.subject = subject
        self.watcher = EventWatcher(subject)

    def construct(self):
        vbox = gtk.VBox()

        entry = gtk.Entry()
        #entry.set_text(UML.format(self.subject, visibility=True, is_derived=Truemultiplicity=True) or '')

        # monitor subject attribute (all, cause it contains many children)
        changed_id = entry.connect('changed', self._on_end_name_change)
        def handler(event):
            if not entry.props.has_focus:
                entry.handler_block(changed_id)
                entry.set_text(UML.format(self.subject,
                                          visibility=True, is_derived=True,
                                          multiplicity=True) or '')
                #entry.set_text(UML.format(self.subject, multiplicity=True) or '')
                entry.handler_unblock(changed_id)
        handler(None)

        self.watcher.watch('name', handler) \
                    .watch('aggregation', handler)\
                    .watch('visibility', handler)\
                    .watch('lowerValue<LiteralSpecification>.value', handler)\
                    .watch('upperValue<LiteralSpecification>.value', handler)\
                    .register_handlers()
        entry.connect("destroy", self.watcher.unregister_handlers)

        vbox.pack_start(entry)

        entry.set_tooltip_text("""\
Enter attribute name and multiplicity, for example
- name
+ name [1]
- name [1..2]
~ 1..2
- [1..2]\
""")

        combo = gtk.combo_box_new_text()
        for t in ('Unknown navigation', 'Not navigable', 'Navigable'):
            combo.append_text(t)
        
        nav = self.subject.navigability
        combo.set_active(self.NAVIGABILITY.index(nav))

        combo.connect('changed', self._on_navigability_change)
        vbox.pack_start(combo, expand=False)

        combo = gtk.combo_box_new_text()
        for t in ('No aggregation', 'Shared', 'Composite'):
            combo.append_text(t)
        
        combo.set_active(['none', 'shared', 'composite'].index(self.subject.aggregation))

        combo.connect('changed', self._on_aggregation_change)
        vbox.pack_start(combo, expand=False)
     
        return vbox

    @transactional
    def _on_end_name_change(self, entry):
        UML.parse(self.subject, entry.get_text())

    @transactional
    def _on_navigability_change(self, combo):
        nav = self.NAVIGABILITY[combo.get_active()]
        UML.model.set_navigability(self.subject.association, self.subject, nav)

    @transactional
    def _on_aggregation_change(self, combo):
        self.subject.aggregation = ('none', 'shared', 'composite')[combo.get_active()]
コード例 #26
0
ファイル: propertypages.py プロジェクト: tonystark97/gaphor
class AssociationEndPropertyPage(object):
    """
    Property page for association end properties.
    """

    interface.implements(IPropertyPage)
    component.adapts(uml2.Property)

    order = 0

    NAVIGABILITY = [None, False, True]

    def __init__(self, subject):
        self.subject = subject
        self.watcher = EventWatcher(subject)

    def construct(self):
        vbox = gtk.VBox()

        entry = gtk.Entry()
        #entry.set_text(format(self.subject, visibility=True, is_derived=Truemultiplicity=True) or '')

        # monitor subject attribute (all, cause it contains many children)
        changed_id = entry.connect('changed', self._on_end_name_change)

        def handler(event):
            if not entry.props.has_focus:
                entry.handler_block(changed_id)
                entry.set_text(
                    format(self.subject,
                           visibility=True,
                           is_derived=True,
                           multiplicity=True) or '')
                #entry.set_text(format(self.subject, multiplicity=True) or '')
                entry.handler_unblock(changed_id)

        handler(None)

        self.watcher.watch('name', handler) \
                    .watch('aggregation', handler)\
                    .watch('visibility', handler)\
                    .watch('lowerValue', handler)\
                    .watch('upperValue', handler)\
                    .register_handlers()
        entry.connect("destroy", self.watcher.unregister_handlers)

        vbox.pack_start(entry)

        entry.set_tooltip_text("""\
Enter attribute name and multiplicity, for example
- name
+ name [1]
- name [1..2]
~ 1..2
- [1..2]\
""")

        combo = gtk.combo_box_new_text()
        for t in ('Unknown navigation', 'Not navigable', 'Navigable'):
            combo.append_text(t)

        nav = self.subject.navigability
        combo.set_active(self.NAVIGABILITY.index(nav))

        combo.connect('changed', self._on_navigability_change)
        vbox.pack_start(combo, expand=False)

        combo = gtk.combo_box_new_text()
        for t in ('No aggregation', 'Shared', 'Composite'):
            combo.append_text(t)

        combo.set_active(['none', 'shared',
                          'composite'].index(self.subject.aggregation))

        combo.connect('changed', self._on_aggregation_change)
        vbox.pack_start(combo, expand=False)

        return vbox

    @transactional
    def _on_end_name_change(self, entry):
        parse(self.subject, entry.get_text())

    @transactional
    def _on_navigability_change(self, combo):
        nav = self.NAVIGABILITY[combo.get_active()]
        modelfactory.set_navigability(self.subject.association, self.subject,
                                      nav)

    @transactional
    def _on_aggregation_change(self, combo):
        self.subject.aggregation = ('none', 'shared',
                                    'composite')[combo.get_active()]