archimatetool / archi

Archi: ArchiMate Modelling Tool
https://www.archimatetool.com
MIT License
970 stars 270 forks source link

Text label display according to a given expression #576

Closed Phillipus closed 4 years ago

Phillipus commented 4 years ago

The aim is to implement something similar to Herve's Specialization plug-in where an alternate expression can be specified for displaying text on a diagram node or connection. So we must credit @herve91 with the original idea and implementation for this. :-)

  1. There will be a text box in the Properties tab where the expression is entered
  2. The expression is stored internally as a string in a "feature"
  3. If the expression is present it is evaluated and converted to a string that is displayed on the node or connection label instead of the name

Examples of expressions:

${name}
${documentation}
${name}\n${documentation}
Hello World

Starting code is in branch "text-render".

Phillipus commented 4 years ago

Obviously we want this implemented on these objects:

  1. ArchiMate Connections
  2. ArchiMate Elements

But which of the following visual objects do we also want this on?

  1. Other Connections
  2. Groups
  3. Notes
  4. Sketch objects
  5. Canvas objects

I have my doubts about Notes and Sketch/Canvas objects since they are free text.

Phillipus commented 4 years ago

I've added a Property section text control to enter the expression. But where should this go? As it is part of the display options it should really go in the "Appearance" tab (like the "Display Name" tick-box for a Connection) but it seems unintuitive there.

For testing I've just stuck it at the top of the "Main" tab:

Image 1

Phillipus commented 4 years ago

Current expression options are (as well as \n for newline):

${name}
${documentation}

But when typing these in they seem to me long-winded, and wonder if we could use as short codes:

${n}
${d}
jbsarrodie commented 4 years ago

I'll test soon. But in the meantime, some comments...

But which of the following visual objects do we also want this on? I have my doubts about Notes and Sketch/Canvas objects since they are free text.

I'd say most if not all of them. It makes sens on notes because this would allow some nice features like displaying the documentation of the element connected to the note. And now that most visual objects have properties, there might be some use-cases related to mixing object's text and properties.

But where should this go? As it is part of the display options it should really go in the "Appearance" tab (like the "Display Name" tick-box for a Connection) but it seems unintuitive there.

I think it has to go in the Main tab, but below Name field. I wonder whether we need a checkbox to enable this feature ([ ] Use custom label), or if it simply has to come with a default value ${name} (in this case, maybe we need a button at the end to reset its value), or maybe even simply make sure that an empty label is replaced by the object's name.

But when typing these in they seem to me long-winded, and wonder if we could use as short codes

I think we have to support Hervé's options as they are, but add some shorter options too. Maybe at some point we could mark historical options as deprecated. But personally I won't go for too short option neither, because it might become hard to read ($[name} seems ok to me, ${doc} would be just fine).

Phillipus commented 4 years ago

I think it has to go in the Main tab, but below Name field.

That's a pain because Name and Documentation fields are one section (AbstractNameDocumentationSection). It can be done but all the existing Property Sections will have to be refactored to split Name and Documentation.

I wonder whether we need a checkbox to enable this feature ([ ] Use custom label), or if it simply has to come with a default value ${name} (in this case, maybe we need a button at the end to reset its value), or maybe even simply make sure that an empty label is replaced by the object's name.

If the field is empty the default text is shown (name or note/sticky content)

I think we have to support Hervé's options as they are

It won't make any difference since Herve stores the expression in a Property and we store it in a Feature.

Phillipus commented 4 years ago

For now lets support all objects in an ArchiMate View and think about Sketch and Canvas later.

this would allow some nice features like displaying the documentation of the element connected to the note.

I wonder if we could do this by referencing another object by its ID? Something like:

${documentation:1234-5678-9876}

or:

${ref:1234-5678-9876${documentation}}

Which returns the documentation that is in the object with the ID "1234-5678-9876"

Problems with this approach:

herve91 commented 4 years ago

I think we have to support Hervé's options as they are

Because I'm using properties, my implementation is linked to the elements and relationships themselves so the same label applies in all the views. Your implementation, which allows have different labels in each view, is much better ;-)

jbsarrodie commented 4 years ago

That's a pain because Name and Documentation fields are one section

So let's move label in Appearance tab and keep Main and Properties for everything which is purely related to model elements and not visual objects.

If the field is empty the default text is shown (name or note/sticky content)

Good

It won't make any difference since Herve stores the expression in a Property and we store it in a Feature.

I was thinking about people who could create a script to switch from props to features, or simply copy and past them. But I agree this is not a big issue if we are slightly incompatible.

For now lets support all objects in an ArchiMate View and think about Sketch and Canvas later.

Agree. I wasn't saying to do everything now.

Problems with this approach:

  • The user would need to get the ID of the other object

Yes, that's the issue and why I'm planning to navigate connections (but not relationships)

Phillipus commented 4 years ago

So let's move label in Appearance tab and keep Main and Properties for everything which is purely related to model elements and not visual objects.

I've created a sub-tab "Display" off of the Main tab as an experiment, We can, if we like, have a multi-line text box instead of a single line text box so user doesn't have to use \n for new lines.

Phillipus commented 4 years ago

I've just made a change to TextRenderer and added:

public static final boolean MULTI_LINE = true;

So we can try out single-line or multi-line text controls.

Phillipus commented 4 years ago

"text-render" git branch has been cherry-picked, rebased and re-pushed to tidy it up.

Phillipus commented 4 years ago

Added some expressions for Properties and a Note linked to another object (shows the linked object's documentation)

Phillipus commented 4 years ago

I've refactored things so that each text expression renderer can register itself to handle text expressions and return the resulting display string. Each renderer implements ITextRenderer and registers itself with the main TextRenderer class. So we have one for name, documentation, properties, relations etc. This is so plug-ins can contribute to rendering the text.

heretyk999 commented 4 years ago

I am really looking forward to having this feature. When it comes to expressions it would be great to have also something like ${element-type} which resolved to ArchiMate Element type, e.g. Business process, etc. The rationale is: to be able very easily recreate the style used in "Mastering ArchiMate" with its explicit indication of type (instead of relying only on a combination of icon and color). It would be even better if one is able to define it for selected elements in one go as something like "default display label" :)

Phillipus commented 4 years ago

@WaruiOkami Yes, that's possible, and I've just committed a "TypeRenderer".

Example - given a Business Process with the name "Create Contract" and this expression:

${name} (${type})

This would render as on the View as:

Create Contract (Business Process)

Phillipus commented 4 years ago

I've created a sub-tab "Display" off of the Main tab as an experiment, We can, if we like, have a multi-line text box instead of a single line text box so user doesn't have to use \n for new lines.

After playing with this for some time now I much prefer the multi-line text box over the single line one

Phillipus commented 4 years ago

Here's an example of my experiments.

Given the following name and documentation of an element:

ex1

With these Properties:

ex2

And this Text Expression:

ex3

We get this:

ex4

heretyk999 commented 4 years ago

That is looking great :) If I may suggest something: if you are looking for a place for text expression - have you considered making it part of the "appearance" tab? For me it seems logical (i.e. this was the place I looked for this feature before) to put it together with font, text alignment and such things - after all, all of this defines how the element looks.

Phillipus commented 4 years ago

Yes, I am considering that. But if so, it should be a sub-tab of the Appearance tab (with tab name something like "Display" or "Text Expression") as there are too many UI controls on the Appearance tab and this really needs some space for a multi-line text control.

jbsarrodie commented 4 years ago

I first thought it should be on the Appearance tab, but I now think it should be separated because we could extend this mecanism to the Model Tree, not on a per concept basis, but with a setting on Folders to change the way concepts inside this folder are listed.

A typical example would be to define a display expression '${name} (${viewpoint})' for the Views folder.

Phillipus commented 4 years ago

...we could extend this mecanism to the Model Tree, not on a per concept basis, but with a setting on Folders to change the way concepts inside this folder are listed.

A typical example would be to define a display expression '${name} (${viewpoint})' for the Views folder.

First implementation of this is committed.

jbsarrodie commented 4 years ago

Hi,

I've played a bit with this neaw feature and it is awesome! I really like the way it has been implemented (I've been able to extend some part of it quickly).

Things I'm working on atm:

Some remarks:

Phillipus commented 4 years ago

Sounds great!

Make sure you got the latest "text-render" branch because I've been deleting it and re-adding it on top of the latest master branch a lot to keep things up to date (I think I even did that yesterday). I won't do that now that you are working on it.

I'm adding a ${wordwrap:maxlength:text} macro to allow some kind of wordwrapping. I think this might be helpful for relationships when description is a bit too long.

How would this work in the Connection Figure? The figure's label can only handle "\n" characters.

It seems that some sequences of characters are removed from the text.

I thought this would be because of TextRenderer#renderNewLines()? Must be some other reason? Perhaps use a special char sequence instead of \n? Something like ${CR} or similar?

Label set on folders are really great but we have to set them on each folder. Would it be possible to define some inheritance so that setting a label on a top level folder would apply anywhere below, unless another label is defined (in this case ${name} would allow to reset to default behaviour).

Should be possible.

(dream_mode on)...

(dream_mode off) - probably not possible, or at least not easy, given the way the Tree works.

As plugin can expose new macros

Yes, but we have to be careful about the order of calling each one ("I will certainly change a bit the order of execution so that the result of some macro can be used as input for the next ones.")

I look forward to seeing your new stuff. What I've done so far was just a starting point. Feel free to change things. The only thing I feel strongly about is having the multi-text control for the expression as it gives a lot of room.

jbsarrodie commented 4 years ago

Make sure you got the latest "text-render" branch...

Ok, I'll check before commiting my changes

How would this work in the Connection Figure?

That's really simple: the idea is to simply insert newlines after each word reaching the "maxlength" of each line.

So if a concept has for name The quick brown fox jumps over the lazy dog, then ${wordwrap:15:${name}} would render as

The quick brown
fox jumps over
the lazy dog

Perhaps use a special char sequence instead of \n? Something like ${CR} or similar?

That's a good idea, but if I implement it I'll go for ${nl} (for newline) ;-)

I look forward to seeing your new stuff. What I've done so far was just a starting point. Feel free to change things. The only thing I feel strongly about is having the multi-text control for the expression as it gives a lot of room.

I really like the multi-line control ;-)

I'll try to commit something before end of week. Would be good to to publish an "Early Access 3" next week :-)

Phillipus commented 4 years ago

but if I implement it I'll go for ${nl} (for newline) ;-)

I thought of that but not sure if nl is sometimes used relating to language internationalisation.

AlbertoDMendoza commented 4 years ago

I'm not sure if this was noted on the thread, but one of the advantages of Herve's plugin is that the label replacement can be controlled by element, but also by view. So the same element can have one name on one view, and another name on another view. This helps when switching from an over view where element names might not be very important to a more detailed view where those same elements require further detail.

Also, my main mechanism of delivery is embedding diagrams into web pages. So I'd like to request that the HTML report can also support this naming mechanism. Which Herve's plugin doesn't.

jbsarrodie commented 4 years ago

one of the advantages of Herve's plugin is that the label replacement can be controlled by element, but also by view.

Well, in fact that's the opposite: Herve's plugin stores the label macro in an element property, so the same label is used everywhere. The only thing you can do is set a view to not use labels, but you can't have 3 different views showing the same element with 3 different labels.

This native implementation in Archi takes care of this: label is similar to color, font...: it is on a per view basis.

I'd like to request that the HTML report can also support this naming mechanism

That will work by design because HTML report use images created using the view rendering mecanism

Which Herve's plugin doesn't.

That's strange, but that's perhaps because Herve uses some very specific tricks for his plugin to work.

AlbertoDMendoza commented 4 years ago

it is on a per view basis.

Yay!

That will work by design

Double Yay!

Phillipus commented 4 years ago

Double Yay!

Have another Yay!

Phillipus commented 4 years ago

Also, I want to again recognise and respect @herve91 for the work he has done on this in his Specialization plug-in.

He was at a disadvantage when he first developed his plug-in because there are no easy "hooks" to set the text (or icons) in Archi's code so he had to resort to analysing the code and come up with workarounds. That was not an easy task, and I know from personal experience that Eclipse/Archi code is very complicated. A major undertaking!

We have the advantage now of building on Herve's work to try and produce a "native" solution. This is not meant in any way to ride over Herve's work. We are building on it! Thanks!

Phillipus commented 4 years ago

As we are releasing the initial version of this with Archi 4.7 EA3 let's document what we have so far:

So far, Text Expressions apply to Folders in the Model Tree and graphical objects in ArchiMate Views. They can be edited in the "Label" tab in the Properties window. Text Expressions for a Folder apply to the Folder's child objects.

Expression Display
${name} Name
${documentation} Documentation
${content} Text content of a Note
${type} Type of object
${viewpoint} Viewpoint name (can only be set on an ArchiMate View Folder in the Model Tree and applies to its child View nodes)
${strength} Applies only to ArchiMate Influence connections and displays its Strength, if set
${linkeddoc} Applies only to Notes. Display the documentation of the first connected object (if it has documentation)
${properties} Display all Property key/values in a list like "key: value"
${propertiesvalues} Display all Properties' values in a list
${properties:separator:key} Display the values of all instances of the given Property having "key" as key, concatenated using "separator" as separator
${property:key} Display the value of the Property whose key is "key"
${model:property:key} Display the value of the Property in the root model whose key is "key"
${view:property:key} Display the value of the Property in the parent View whose key is "key"

@jbsarrodie JB, can you provide a summary of your "filtered properties with separator" so I can add it to this list?

Done ;-)

jbsarrodie commented 4 years ago

Note: while updating the list, I wonder is this should be named ${properties:separator:key} or ${property:separator:key} ? (after all, this simply extend ${property:key} for the case where the same key is used multiple times)

Phillipus commented 4 years ago

I think ${property:separator:key} to be the same. I can change it.

Phillipus commented 4 years ago

I think ${property:separator:key} to be the same. I can change it.

@jbsarrodie It doesn't work if we use property because renderPropertyValue() will have already replaced it by the time it gets to renderPropertiesValuesCustomList(). So we need to either have order of precedence or use the original "properties" or something else. ~And properties is already used to list all values. So all expression tags need to be different.~

jbsarrodie commented 4 years ago

or use the original "properties" or something else. And properties is already used to list all values. So all expression tags need to be different.

There's no conflict with ${properties} because regexps are mutually exclusives, while I agree there is some conflict with ${property:key} because we cannot exclude that key might contain : (actually, all properties used by Jasper contain it).

So It might be best to simply keep it as it is (ie. ${properties:separator:key})

Phillipus commented 4 years ago

There's no conflict with ${properties}

You're right, my bad.

So It might be best to simply keep it as it is (ie. ${properties:separator:key})

Yep

Phillipus commented 4 years ago
  1. I can fix "\n" not rendering as a newline, too, so it can be used as a separator.
  2. Are we OK with the feature name "formatExpression" - this is how it is stored in XML
  3. We agree to use multi-line? I can get rid of single-line code, then
  4. OK with "Display" on the tab? OK with it under Main tab?
Phillipus commented 4 years ago

Embedded expression is something I think @herve91 supports.

  1. Add a property in the model, lang = en
  2. Add properties to an object like en = English Name, fr = Nom Francais
  3. Add an expression to the object ${property:${model:property:lang}}

Which evaluates to "The value of property whose key is the value of the model's property whose key is lang"

jbsarrodie commented 4 years ago
  1. I can fix "\n" not rendering as a newline, too, so it can be used as a separator.

Would be good

  1. Are we OK with the feature name "formatExpression" - this is how it is stored in XML

Why not use "labelExpression" as this is about label ?

  1. We agree to use multi-line? I can get rid of single-line code, then

Of course yes

  1. OK with "Display" on the tab? OK with it under Main tab?

I would suggest to rename it to "Label" and move it after analysis because Main, Properties and Analysis are related to the underlying concept so we want to keep them together, then start adding "Label" which will also be available for folder, and then view only specific tabs like Appearance and Figure.

BTW, there's something strange that I noticed on Windows and Linux: the string "Display" has some space before, is not aligned with other tabs' label and has a flat background. Same is true for Figure tab: image

Phillipus commented 4 years ago

BTW, there's something strange that I noticed on Windows and Linux: the string "Display" has some space before, is not aligned with other tabs' label and has a flat background. Same is true for Figure tab:

These are sub-tabs. "Figure" is a sub-tab of Appearance. This way they can be grouped.

Phillipus commented 4 years ago

Why not use "labelExpression" as this is about label ?

We are using it also for folders in the tree. I guess that is a label. I think I was trying to aim for something neutral in case we have a case where it is not used for a label, although I don't know what that case would be.

jbsarrodie commented 4 years ago

These are sub-tabs. "Figure" is a sub-tab of Appearance. This way they can be grouped.

Do we really need this, I find it counter intuitive and annoying because we can not hide/show such group. Would it break something if they were normal tabs ?

We are using it also for folders in the tree. I guess that is a label. I think I was trying to aim for something neutral in case we have a case where it is not used for a label, although I don't know what that case would be.

I think this will always be a label, and if someday we have something else, I guess we'll be able to add another feature.

Phillipus commented 4 years ago

Would it break something if they were normal tabs ?

Nope.

We can have this:

2

Or even this:

1

jbsarrodie commented 4 years ago

At first I would had voted for the second option, but now that we can also set a label for folders' content I think it is better to keep the "Label" tab separated.

Phillipus commented 4 years ago

At first I would had voted for the second option, but now that we can also set a label for folders' content I think it is better to keep the "Label" tab separated.

Good point. I also think it looks a bit crowded.

I've committed the changes if you want to test.

jbsarrodie commented 4 years ago

I've committed the changes if you want to test.

Just tested and everything is fine. My only comment (but this will be for EA4) is that when we use ${linkeddoc}, the note content is not refreshed when the linked element documentation changed. But that's a minor point for the moment.

Phillipus commented 4 years ago

the note content is not refreshed when the linked element documentation changed.

This will not be easy to solve.

To remain lightweight, each EditPart only listens to eCore notifications from its contained IDiagramModelComponent and its Properties and Features (see LightweightEContentAdapter).

In order to respond to another objects' eCore notifications it would also have to know which object is connected via a connection, track when those connections and linked objects were added and removed, and register another adapter to listen to its changes. and de-register the adapter if the other object is deleted. This kind of breaks the whole EditPart listener paradigm and would be difficult to implement.

Phillipus commented 4 years ago

But let's release EA3 today and think about that issue. The workaround is to either close and re-open the View or delete and undelete the Note or the connected object.

@jbsarrodie OK for EA3 now?

jbsarrodie commented 4 years ago

OK for EA3 now?

Of course yes !

Phillipus commented 4 years ago

Reminder to me to look at this:

Label set on folders are really great but we have to set them on each folder. Would it be possible to define some inheritance so that setting a label on a top level folder would apply anywhere below, unless another label is defined (in this case ${name} would allow to reset to default behavior).