Author Topic: Primiary DiagramObject in Selection via Script  (Read 4885 times)

Daiim

  • EA User
  • **
  • Posts: 51
  • Karma: +0/-0
    • View Profile
Primiary DiagramObject in Selection via Script
« on: April 10, 2025, 01:54:37 am »
Hello together,

I try to figure out via (J)Script, which of the element in the currentDiagram.SelectedObjects is the primary one (the object with the dashed frame around it that is also used for alignment). What I already tried:

- guessed, it is the first one in the collection (it is not)
- using the coordinates of the DiagramObject (top, left, right, bottom) and try to match the mouse point
- try to figure out what the undocumented function HitTest(string, number) @EA.Diagram does

Has anyone a tip for me?

Thank you very much!
Daiim
« Last Edit: April 10, 2025, 05:28:55 pm by Daiim »

Geert Bellekens

  • EA Guru
  • *****
  • Posts: 13404
  • Karma: +567/-33
  • Make EA work for YOU!
    • View Profile
    • Enterprise Architect Consultant and Value Added Reseller
Re: Primiary DiagramObject in Selection via Script
« Reply #1 on: April 10, 2025, 07:30:28 am »
Have you checked the Z-order?

Geert

Daiim

  • EA User
  • **
  • Posts: 51
  • Karma: +0/-0
    • View Profile
Re: Primiary DiagramObject in Selection via Script
« Reply #2 on: April 10, 2025, 05:45:51 pm »
Thank you Geert for your hint.

The z-order is not the solution (for DiagramObject it's the property 'Sequence') but this raised an idea that gave the solution:

  • it's the EA.Repository.GetContextObject() that gives you the EA.Element that is selected primary if you've selected a set of DiagramObjects on a Diagram. You can check the type of the context with EA.Repository.GetContextItemType()

Documentation is here: https://sparxsystems.com/enterprise_architect_user_guide/17.0/add-ins___scripting/repository3.html

Only side-question left: how to use EA.Repository.GetContextItem(object item) and what is it used for? I got no idea from the description in the documentation.

Thanks for all and best regards!
Daiim
« Last Edit: April 10, 2025, 05:48:35 pm by Daiim »

philchudley

  • EA User
  • **
  • Posts: 744
  • Karma: +21/-0
  • EA Consultant / Trainer - Sparx Europe
    • View Profile
Re: Primiary DiagramObject in Selection via Script
« Reply #3 on: April 10, 2025, 07:06:49 pm »
The problem with GetContexObject is that the object could be selected anywhere, including the browser, so I suggest you use this method to get the GUID (or ID) of the selected object, then use Diagram.SelectedObjects, iterate and select the matching object from GetContextObject (if no match then the object has been selected else where).

That should get you to the element (object) you are after

Phil
Models are great!
Correct models are even greater!

Daiim

  • EA User
  • **
  • Posts: 51
  • Karma: +0/-0
    • View Profile
Re: Primiary DiagramObject in Selection via Script
« Reply #4 on: April 11, 2025, 02:20:30 am »
The problem with GetContexObject is that the object could be selected anywhere, including the browser, so I suggest you use this method to get the GUID (or ID) of the selected object, then use Diagram.SelectedObjects, iterate and select the matching object from GetContextObject (if no match then the object has been selected else where).

That should get you to the element (object) you are after

Correct. But as the script runs in the context "Diagram" (as every script in the "Diagram Script Group"), this is not an issue in this case. So EA.Diagram.SelectedObjects gives me every selected DiagramObject and EA.Repository.GetContextObject() provides the primary object (precise EA.Element).

For everyone in the community, here is the code to BulkLink elements on a Diagram according to settings in a config object defined hard-coded in the script.
To run this create a JScript in a "Diagram Group" within the script window (name can be choosen as you like and must not be equal to the function name inside the script).

Code: [Select]
function OnDiagramScript()
{
var currentDiagram as EA.Diagram;
currentDiagram = Repository.GetCurrentDiagram();

if ( currentDiagram == null ) {
Session.Output("No diagram is selected. Done.");
return;
}

var selectedObjects as EA.Collection;
selectedObjects = currentDiagram.SelectedObjects;

if (selectedObjects.Count <= 0) {
Session.Output("No object is selected. Done.");
return;
}

if (selectedObjects.Count == 1) {
Session.Output("At least 2 objects MUST be selected. Done.");
return;
}

var primaryElement as EA.Element;
primaryElement = Repository.GetContextObject();

if (primaryElement == null) {
Session.Output("Could not find primary selection. Done.");
return;
}

for (var index = 0; index < selectedObjects.Count; index++)
{
var currentObject as EA.DiagramObject;
currentObject = selectedObjects.GetAt(index);

var currentElement as EA.Element;
currentElement = Repository.GetElementByID(currentObject.ElementID);

if (primaryElement.ElementID == currentElement.ElementID)
continue;

var link as EA.Connector;

if (linkDef.LinkDirection === undefined)
linkDef.LinkDirection = "ToPrimary";

if (linkDef.LinkDirection == "ToPrimary") {
link = LinkElementFromTo(currentElement, primaryElement, linkDef);
}
else {
link = LinkElementFromTo(primaryElement, currentElementElement, linkDef);
}

if (link == null) {
Session.Output("Failed to create link from '" + currentElement.Name + "' to '"+ primaryElement.Name +"'.");
}
}

Repository.ReloadDiagram(currentDiagram.DiagramID);
}

var linkDef = {
LinkName : "enhances",
LinkType : "Association",
LinkStereotype : "Application Function",
LinkDirection : "ToPrimary"
};

Repository.EnsureOutputVisible("Script");

OnDiagramScript(linkDef);

And the function that links two elements:
Code: [Select]
function LinkElementFromTo(sourceElement, targetElement, linkDef)
{
if (sourceElement == null) {
var msg = { Source : "LinkElementFromTo", Error : "Parameter @SourceElement is null." };
throw msg;
}

if (targetElement == null) {
var msg = { Source : "LinkElementFromTo", Error : "Parameter @TargetElement is null." };
throw msg;
}

if (linkDef == null) {
var msg = { Source : "LinkElementFromTo", Error : "Parameter @LinkDef is null." };
throw msg;
}


var source as EA.Element;
var target as EA.Element;

source = sourceElement;
target = targetElement;

//Session.Output("Source: " + source.Name + ", ID: " + source.ElementID);
//Session.Output("Target: " + target.Name + ", ID: " + target.ElementID);

var link as EA.Connector;

if (linkDef.LinkName === undefined)
linkDef.LinkName = "";

if (linkDef.LinkType === undefined)
linkDef.LinkType = "Association";

link = source.Connectors.AddNew(linkDef.LinkName, linkDef.LinkType);

if (link == null) {
var msg = { Source : "LinkElementFromTo::_Elements.AddNew", Error : "Failed to create link." };
throw msg;
}

if (linkDef.LinkStereotype !== undefined)
link.StereotypeEx = linkDef.LinkStereotype;

link.ClientID = source.ElementID;
link.SupplierID = target.ElementID;

link.Update();

source.Elements.Refresh();
target.Elements.Refresh();

return link;
}
« Last Edit: April 11, 2025, 02:23:35 am by Daiim »

Eve

  • EA Administrator
  • EA Guru
  • *****
  • Posts: 8085
  • Karma: +118/-20
    • View Profile
Re: Primiary DiagramObject in Selection via Script
« Reply #5 on: April 11, 2025, 03:39:05 pm »
Can I suggest Repository.CurrentSelection, which gives you more information about what is selected.

EASelection Class

It will tell you that the selection is on the diagram (selection.Location == "Diagram"), the element being displayed in all the properties windows, (selection.Context) and the full list of the elements in that selection. (selection.List)

Those are all properties that are available without additional database queries. You can use them in locations like building menus or update commands without negatively impacting performance. The final significant property for that object is the ElementSet, which will load all of the selected objects. It will be a faster way of accessing all of the selected objects than calling Repository.GetElementByID or Repository.GetElementByGuid for each item individually.

Daiim

  • EA User
  • **
  • Posts: 51
  • Karma: +0/-0
    • View Profile
Re: Primiary DiagramObject in Selection via Script
« Reply #6 on: April 11, 2025, 05:41:25 pm »
Can I suggest Repository.CurrentSelection, which gives you more information about what is selected.

EASelection Class

It will tell you that the selection is on the diagram (selection.Location == "Diagram"), the element being displayed in all the properties windows, (selection.Context) and the full list of the elements in that selection. (selection.List)

Those are all properties that are available without additional database queries. You can use them in locations like building menus or update commands without negatively impacting performance. The final significant property for that object is the ElementSet, which will load all of the selected objects. It will be a faster way of accessing all of the selected objects than calling Repository.GetElementByID or Repository.GetElementByGuid for each item individually.

Great, thank you for this hint. Sorrowly I have no intellisense/context in the script editor for an variable declared with "var selection as EASelection;". It is quite plodding to switch between documentation and coding.