Sparx Systems Forum
Enterprise Architect => Automation Interface, Add-Ins and Tools => Topic started by: SteveC on September 13, 2018, 02:17:26 am
-
We are looking for a way to get a list of elements on the current diagram. This can be using code or SQL query.
It looks like using the DiagramObjects property on the Diagram class might be the way to go, but it is not clear how one might get the elements from this collection. Similarly, t_diagramobjects seems to be the table to query, but it's not clear how to parse element references from it.
Thanks in advance for any guidance!
-
Yes - uses the diagram.diagramobjects then for each of the diagramobjects use the ElementID to access the element object and its properties
-
It is a simple as:
foreach (EA.DiagramObject diagramObject in diagram.DiagramObjects) {
EA.Element element = Repository.GetElementByID(diagramObject.ElementID);
// work with the element here
}
Thanks!
-
Is there a way to find the diagram by package and then list all the elements of the diagram? I am trying to do that in c#
-
Is there a way to find the diagram by package and then list all the elements of the diagram? I am trying to do that in c#
There is no "the" diagram relating to a package, but the Package class has a .Diagrams collection which you can loop through to find the diagram you want, and then iterate over that Diagram's .DiagramObjects to retrieve the elements shown on the diagram.
HTH,
/Uffe
-
There's the composite diagram for an element which you can call THE diagram. Objects with t_object.NType == 8 have a composite diagram which can be found via that dreaded t_xref.
q.
-
Packages are even funnier. You don't need to set a composite diagram in order to navigate to the diagram on double-click.
EA simply opens the first diagram under the package it finds when double-clicking on a package in a diagram.
Geert
-
Yeah. We got so used to EAUI... For composite elements you can choose an arbitrary diagram. But for packages it's always that first diagram.
q.
-
Not only that, but two elements can share the same target diagram, while two packages cannot.
/U
-
Not only that, but two elements can share the same target diagram, while two packages cannot.
/U
Yeah, We had all sort of issues with our automatic diagrammer until we realised that two different elements were pointing tot he same diagram!
Just because you can, doesn't mean you should... ;D
Paolo
-
Is there a way to find the diagram by package and then list all the elements of the diagram? I am trying to do that in c#
There is no "the" diagram relating to a package, but the Package class has a .Diagrams collection which you can loop through to find the diagram you want, and then iterate over that Diagram's .DiagramObjects to retrieve the elements shown on the diagram.
HTH,
/Uffe
I have tried the below code so far:
EA.Collection packages = Rep.Models;
for (short ip = 0; ip < packages.Count; ip++)
{
EA.Package child = (EA.Package)packages.GetAt(ip);
foreach (EA.Diagram theDiagram in child.Diagrams)
{
foreach (EA.DiagramObject theDiagramObject in theDiagram.DiagramObjects)
{
Console.WriteLine(theDiagramObject.ElementID);
}[img]
https://ibb.co/2KxDtXH
[/img]
I have included the image link here. So far, I am getting the package but not getting anything on [b]child.Diagrams[/b]. Am I missing something?
}
}
-
Hi again,
Yes. You're not traversing the package structure properly.
child is actually the "Models" root node, not the "StateMachineDiagram1" view.
/Uffe
-
If you call the same function recursively for all sub-packages if you can traverse the whole model.
But be aware that this will be very time consuming in a "real" model.
You might want to think about how to restrict it to what you really need.
You can either do that by letting the user select a package, or diagram and starting from there, or use an SQL Query to get only the elements or packages you need.
Geert
PS. Usually a State Machine diagram is not owned by a package directly, but by a State Machine element. In that case you'll have to iterate the EA.Element.Diagrams collection because it will not be in the EA.Package.Diagrams collection.
-
Thanks for your suggestion. It indeed lies inside Element.Diagrams, not inside Package.Diagrams. I have tried the below code:
EA.Collection models = Rep.Models;
for (short i1 = 0; i1 < models.Count; i1++)
{
EA.Package childModel = (EA.Package)models.GetAt(i1);
EA.Collection packages = childModel.Packages;
for (short i2 = 0; i2 < packages.Count; i2++)
{
EA.Package childPackage = (EA.Package)packages.GetAt(i2);
EA.Collection elements = childPackage.Elements;
foreach (EA.Element element in elements)
{
packageNames.Add($"{element.Type} : {element.Name}");
foreach (EA.Connector item in element.Connectors)
{
packageNames.Add($"Trigger: {item.TransitionEvent} \n Effect: {item.TransitionAction}");
//packageNames.Add(item.ClientEnd.);
}
}
}
What I am now trying to achieve is a JSON or XML representation of the state machine like the below structure:
states:
- name: Off
- name: Boot
- name: uPError
transitions:
- from: Off
to: Boot
trigger: register
effects: [switch on uP]
- from: Boot
to: Wait for HK
trigger: after(1s)
effects: [start HK]
and later convert it to YAML file. I am trying to traverse inside the diagram to find the connection, but still hasn't got to find the from and to state machine reference. Although I can see a property Start Point X and End Point X in connector, it doesn't contain any information about the from or to which state machine it's coming or going.
-
To and from elements are referenced using the ClientID (From) and SupplierID (To) of the connector.
Use Repository.GetElementByID() get get to the other end.
For a correct model you should indeed not need the diagram at all to be able to parse the whole statemachine like you are doing now.
Just be aware that quite often "orphaned" elements remain in the project browser.
Geert
-
Are you talking about selecting specific element or package, for example using the below documentation?
https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html (https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html)
-
Are you talking about selecting specific element or package, for example using the below documentation?
https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html (https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html)
Yes, indeed.
That is a way to allow the user to select where to start.
If you are making an add-in you can add a context menu option to start your functionality.
Another option would be use to use the construct picker to let the user select an element.
Geert
-
Are you talking about selecting specific element or package, for example using the below documentation?
https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html (https://sparxsystems.com/enterprise_architect_user_guide/13.0/automation/objecttypeenum.html)
Yes, indeed.
That is a way to allow the user to select where to start.
If you are making an add-in you can add a context menu option to start your functionality.
Another option would be use to use the construct picker to let the user select an element.
Geert
It is working with the following code, so far the package and element is working fine, except the diagram, I am trying to find a way to navigate to elements of diagram but so far haven't been succeeded:
EA.Package pack;
EA.Diagram diag;
EA.Element ele;
switch (Rep.GetContextItemType())
{
case EA.ObjectType.otPackage:
{
pack = Rep.GetContextObject();
EA.Collection elements = pack.Elements;
foreach (EA.Element element in elements)
{
if (element.Type != "Trigger")
{
packageNames.Add($"{element.Type} : {element.Name}");
}
foreach (EA.Connector item in element.Connectors)
{
int clientId = item.ClientID;
int supplierId = item.SupplierID;
EA.Element clientElement = Rep.GetElementByID(clientId);
EA.Element supplierElement = Rep.GetElementByID(supplierId);
packageNames.Add($" From : {clientElement.Name}\n To: {supplierElement.Name}\n Trigger: {item.TransitionEvent}\n Effect: {item.TransitionAction}");
}
}
break;
}
case EA.ObjectType.otDiagram:
{
diag = Rep.GetContextObject();
foreach (EA.Element element in diag.DiagramObjects)
{
if (element.Type != "Trigger")
{
packageNames.Add($"{element.Type} : {element.Name}");
}
foreach (EA.Connector item in element.Connectors)
{
int clientId = item.ClientID;
int supplierId = item.SupplierID;
EA.Element clientElement = Rep.GetElementByID(clientId);
EA.Element supplierElement = Rep.GetElementByID(supplierId);
packageNames.Add($" From : {clientElement.Name}\n To: {supplierElement.Name}\n Trigger: {item.TransitionEvent}\n Effect: {item.TransitionAction}");
}
}
break;
}
case EA.ObjectType.otElement:
{
ele = Rep.GetContextObject();
packageNames.Add($"{ele.Type} : {ele.Name}");
foreach (EA.Connector item in ele.Connectors)
{
int clientId = item.ClientID;
int supplierId = item.SupplierID;
EA.Element clientElement = Rep.GetElementByID(clientId);
EA.Element supplierElement = Rep.GetElementByID(supplierId);
packageNames.Add($" From : {clientElement.Name}\n To: {supplierElement.Name}\n Trigger: {item.TransitionEvent}\n Effect: {item.TransitionAction}");
}
break;
}
}
-
foreach (EA.Element element in diag.DiagramObjects)
This is where you are going wrong. There are no EA.Elements in the DiagramObjects collection, only EA.DiagramObjects (yes, sometimes it's that obvious, certainly not always though ;D)
Try
foreach (EA.DiagramObject diagramObject in diag.DiagramObjects)
Geert