Skip to content

Make legend fill whitespace #134

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JorisvanRoy opened this issue Mar 16, 2021 · 16 comments · Fixed by #143
Closed

Make legend fill whitespace #134

JorisvanRoy opened this issue Mar 16, 2021 · 16 comments · Fixed by #143
Milestone

Comments

@JorisvanRoy
Copy link

Hi,

Whenever I create a diagram with this plugin I like to implement the Legend with my diagrams. Whenever I add the legend to the diagrams it is put at the bottom right of the picture like this.
C1

If it would be possible then it would be awesome to have the legend fill the remaining whitespace instead of creating more whitespace. Something like this:
C1 New

@Potherca
Copy link
Member

Hi, thank you for taking the time to report this! Although I like the idea, I am not sure if this is something that can be implemented in this lib, as the placement and rendering is done by PlantUML itself.

Something might be possible (with hidden lines for instance) but it will take a lot of trial and error to figuring things out.
I am not sure if any of the maintainers is willing to spend the time needed to come up with a solution for this.

Do you happen to have any ideas towards implementation yourself?

@JorisvanRoy
Copy link
Author

Sadly i dont have much experience in PlantUML, so i dont have any insight into how this could be implemented.

@Potherca
Copy link
Member

Potherca commented Apr 11, 2021

I've played around with this a bit and I don't think there is any way for us to improve upon the current behavior.

The only thing that I can think of to slightly improve the diagram is to use SHOW_DYNAMIC_LEGEND() so at least the legend is smaller (as it will only show the types that are actually used in the diagram, instead of all of 'm).

The problem is that PlantUML adds the legend in a separate space by itself, at the bottom of the diagram:

Left center Right
left center right

There is a post on the PlantUML forum requesting something similar but it doesn't seem to have much attention. You could try upvoting and commenting there to see if this could be implemented on the PlantUML side of things.

@JorisvanRoy For now, unless you strongly disagree, I'm in favor of closing this issue, as we can't fix this in C4-PlantUML itself.

@Potherca Potherca added the Can't Fix Issue lies outside of this project. label Apr 11, 2021
@kirchsth
Copy link
Member

@Potherca, @JorisvanRoy: I found a workaround via note, but I cannot remove the shadow or line of the note (the text in the middle is copied from the dynamic legend definiton)

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

Person(admin, "Administrator")
System_Boundary(c1, "Sample System") {
    Container(web_app, "Web Application", "C#, ASP.NET Core 2.1 MVC", "Allows users to compare multiple Twitter timelines")
}
System(twitter, "Twitter")

Rel(admin, web_app, "Uses", "HTTPS")
Rel(web_app, twitter, "Gets tweets from", "HTTPS")


skinparam note {
    backgroundcolor white
    bordercolor white
}

note left of c1 
|<color:$LEGEND_TITLE_COLOR>**Legend**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
endnote

note right of twitter
|<color:$LEGEND_TITLE_COLOR>**Legend**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
endnote
@enduml

Legend in note

BR Helmut

@Potherca
Copy link
Member

Potherca commented Apr 11, 2021

That can be resolved by using skinparam shadowing false

@kirchsth
Copy link
Member

kirchsth commented Apr 11, 2021

@Potherca, @JorisvanRoy: It's not 100% perfect but very generic

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Container.puml

skinparam shadowing false


skinparam note {
    backgroundcolor white
    bordercolor white
}

!$COLOR_A_5 = "#7f3b08"
!$COLOR_A_4 = "#b35806"
!$COLOR_A_3 = "#e08214"
!$COLOR_A_2 = "#fdb863"
!$COLOR_A_1 = "#fee0b6"
!$COLOR_NEUTRAL = "#f7f7f7"
!$COLOR_B_1 = "#d8daeb"
!$COLOR_B_2 = "#b2abd2"
!$COLOR_B_3 = "#8073ac"
!$COLOR_B_4 = "#542788"
!$COLOR_B_5 = "#2d004b"
!$COLOR_REL_LINE = "#8073ac"
!$COLOR_REL_TEXT = "#8073ac"

UpdateElementStyle("person", $bgColor=$COLOR_A_5, $fontColor=$COLOR_NEUTRAL, $borderColor=$COLOR_A_1, $shadowing="true")





Container_Ext(A, "A", "t")
Person(B, "B")
System(C, "C", "t")
System_Boundary(SB0, "Sample System 0") {
Container(D, "D", "t")
}
System_Boundary(SB1, "Sample System 1") {
  Container(E, "E", "t")
}

Rel_R(A,B,"uses")
Rel_R(A,C,"uses")
Rel_D(B,C,"uses")
Rel_R(C,D,"uses")
Rel_D(B,D,"uses")
Rel_D(C,E,"uses")

note as legend1
<#white,#white>|<color:$LEGEND_TITLE_COLOR>**Legend1**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
endnote

note as legend2
<#white,#white>|<color:$LEGEND_TITLE_COLOR>**Legend2**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
endnote

note as legend3
<#white,#white>|<color:$LEGEND_TITLE_COLOR>**Legend3**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
endnote

!unquoted procedure Lay_L($from, $to)
$from -[hidden]L- $to
!endprocedure

Lay_L(C,legend1)
Lay_L(SB1,legend2)
Lay_D(D,legend3)
@enduml


BR Helmut

PS.: the problem is the white small line on the left side of "C" (I think it could be a problem of the Lay_L definition, but I found no workaround)

kirchsth added a commit to kirchsth/C4-PlantUML that referenced this issue Apr 12, 2021
@kirchsth
Copy link
Member

Hi @JorisvanRoy, @Potherca
I added MR #143, can you check it (via my extended branch )?
BR Helmut

@Potherca
Copy link
Member

I like these changes a lot but as they are non-trivial (i.e. moving from the PlantUML legend entity to a note) I would want the opinions of @aheil / @adrianvlupu / @RicardoNiepel / @IOrlandoni / @Crashedmind / @stawirej before merging it

@kirchsth
Copy link
Member

kirchsth commented Apr 13, 2021

Hi,
I see the changes only as an extension not as an replacement of the existing Legend calls!!!!!!
The positioning itself is sometimes problematic therefore it cannot be an overall solution.

My MR supports only 1 legend (I used instead of notes one concrete rectangle with alias "legendArea")

BR Helmut

PS.: In the meantime https://forum.plantuml.net/9032/legend-unnecessarily-extends-diagram-size?show=13621 contains a better layout (more in the right corner) based on "-[hidden]-->" therefore I plan to add an additional call which creates only the legend (SHOW_FLOATING_LEGEND() == $getLegendArea($hideStereotype)) and the (hidden) relation can be added separately too.
But I'm sure it will not work in all scenarious

@Potherca Potherca removed the Can't Fix Issue lies outside of this project. label Apr 13, 2021
@kirchsth
Copy link
Member

Hi @Potherca,

I think found a better solution, with the new calls "SHOW_FLOATING_LEGEND()" and "SET_FLOATING_DISTANCE()"

@startuml
!include https://raw.githubusercontent.com/kirchsth/C4-PlantUML/extended/C4_Container.puml

' New SHOW_FLOATING_LEGEND(), SET_FLOATING_DISTANCE()

!procedure $getHideStereotype($hideStereotype) 
!if ($hideStereotype=="true")
hide stereotype
!endif
!endprocedure

!procedure $getLegendTable() 
<#00000000,#00000000>|<color:$LEGEND_TITLE_COLOR>**Legend**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
!endprocedure

!procedure $getLegendArea($areaAlias, $hideStereotype) 
$getHideStereotype($hideStereotype)
rectangle $areaAlias<<legendArea>> [
$getLegendTable()
]
!endprocedure

!function $getHiddenLine($distance)
  !return '-[hidden]' + %substr('------------', 0, %intval($distance) + 1)
!endfunction

' enables that legend can be located in diagram, has to be last call in diagram
!unquoted procedure SHOW_FLOATING_LEGEND($alias="FLOATINGLEGEND", $hideStereotype="true")
$getLegendArea($alias, $hideStereotype)
!endprocedure

' PlantUML bug: lines which does "not match" with the orientation/direction of the diagram
' uses the same length therefore the method offers no direction at all.
' If a direction is required the Lay_...() methods can be used
!unquoted procedure SET_FLOATING_DISTANCE($from, $to, $distance="0")
$from $getHiddenLine($distance) $to
!endprocedure


Person(A1, "Person A1")
Container(B1, "Container B1", "techn")
System(C1, "System C1")
Container(A2, "Container A2", "techn")
System(A3, "Ext. System A3")
System(A3, "Ext. System A3")

Rel_R(A3, B1, "uses")
Rel_R(B1, C1, "calls")
Rel_D(A1, A2, "uses")
Rel_D(A1, A3, "uses")
Rel_D(A2, A3, "calls")
Rel_D(A2, C1, "calls")

SHOW_FLOATING_LEGEND()
SET_FLOATING_DISTANCE(FLOATINGLEGEND, C1, $distance=1)

SHOW_FLOATING_LEGEND(Legend2)
SET_FLOATING_DISTANCE(B1, Legend2, $distance=3)
@enduml

It is still not perfect:
a) it is relative to existing elements (not to the diagram corners)
b) PlantUML has a "bug(?)" that the long distances are only considered in the orientation/direction of the diagram layout itself (see below) therefore we cannot support all directions, and therefore I removed it completely.
c) and if somebody wants the working directions then he can use the Lay_...() calls.

@startuml
top to bottom direction
' not working
[S] -L-- [Left3]
[S] -R--- [Right4]
' working
[S] -U-- [Up3]
[S] -D--- [Down4]
@enduml

BR Helmut

@Potherca
Copy link
Member

Would it be possible to use a note without adding a direction/link to an existing element?

Or use a separate element (for instance rectangle) instead of a note?

@kirchsth
Copy link
Member

kirchsth commented Apr 15, 2021

the floating area is already a separate rectangle with the name $areaAlias (and no note anymore)

!procedure $getLegendArea($areaAlias, $hideStereotype)
$getHideStereotype($hideStereotype)

' rectangle [
rectangle $areaAlias<> [

' generated table
$getLegendTable()

' end of rctangle ]
]
!endprocedure

If you use no link then it has no clear position like

@startuml
!include https://raw.githubusercontent.com/kirchsth/C4-PlantUML/extended/C4_Container.puml

' New SHOW_FLOATING_LEGEND(), SET_FLOATING_DISTANCE()

!procedure $getHideStereotype($hideStereotype) 
!if ($hideStereotype=="true")
hide stereotype
!endif
!endprocedure

!procedure $getLegendTable() 
<#00000000,#00000000>|<color:$LEGEND_TITLE_COLOR>**Legend**</color> |
$showActiveLegendEntries($tagDefaultLegend)
$showActiveLegendEntries($tagCustomLegend)
!endprocedure

!procedure $getLegendArea($areaAlias, $hideStereotype) 
$getHideStereotype($hideStereotype)
rectangle $areaAlias<<legendArea>> [
$getLegendTable()
]
!endprocedure

!function $getHiddenLine($distance)
  !return '-[hidden]' + %substr('------------', 0, %intval($distance) + 1)
!endfunction

' enables that legend can be located in diagram, has to be last call in diagram
!unquoted procedure SHOW_FLOATING_LEGEND($alias="FLOATINGLEGEND", $hideStereotype="true")
$getLegendArea($alias, $hideStereotype)
!endprocedure

' PlantUML bug: lines which does "not match" with the orientation/direction of the diagram
' uses the same length therefore the method offers no direction at all.
' If a direction is required the Lay_...() methods can be used
!unquoted procedure SET_FLOATING_DISTANCE($from, $to, $distance="0")
$from $getHiddenLine($distance) $to
!endprocedure


Person(A1, "Person A1")
Container(B1, "Container B1", "techn")
System(C1, "System C1")
Container(A2, "Container A2", "techn")
System(A3, "Ext. System A3")
System(A3, "Ext. System A3")

Rel_R(A3, B1, "uses")
Rel_R(B1, C1, "calls")
Rel_D(A1, A2, "uses")
Rel_D(A1, A3, "uses")
Rel_D(A2, A3, "calls")
Rel_D(A2, C1, "calls")

' makes the rectangle visisble
skinparam shadowing<<legendArea>> true
' #00000000 is transparent
skinparam rectangle<<legendArea>> {
    backgroundcolor green
    bordercolor red
}


SHOW_FLOATING_LEGEND()
' link removed
' SET_FLOATING_DISTANCE(FLOATINGLEGEND, C1, $distance=1)

SHOW_FLOATING_LEGEND(Legend2)
' link removed
' SET_FLOATING_DISTANCE(B1, Legend2, $distance=3)
@enduml

BR Helmut

PS.: you can have notes without a link too

@startuml
[component C1]

[component C2]

note as N1
this is a note 1
endnote

' N1 -- C1

note as N2
this is a note 2
endnote
N2 -- [component C2]
@enduml

@kirchsth
Copy link
Member

@Potherca, @JorisvanRoy: I think the existing MR #143 is not the best solution, should I add the SHOW_FLOATING_LEGEND() and SET_FLOATING_DISTANCE() calls (maybe with better names)?
BR Helmut

@Potherca
Copy link
Member

Yeah, I think so. Awesome work on this, by the way!

kirchsth added a commit to kirchsth/C4-PlantUML that referenced this issue Apr 20, 2021
…() and Lay_Distance() (instead of SHOW_LEGEND_UP(), ..._DOWN(), ..._LEFT(), ..._RIGHT())
kirchsth added a commit to kirchsth/C4-PlantUML that referenced this issue Apr 20, 2021
kirchsth added a commit to kirchsth/C4-PlantUML that referenced this issue Apr 21, 2021
…() and Lay_Distance() (3 - legend is reserved; LEGEND() is new default alias)
@kirchsth
Copy link
Member

kirchsth commented Apr 21, 2021

@JorisvanRoy: I think I found a solution which works in all scenarios. Can you check it and give me a feedback? You can test it in my extended branch.

@Potherca: MR #143 is updated with the final implementation and can be merged.

==============

(In combination with SHOW_FLOATING_LEGEND()) a greater distance between an element and the
e.g. floating legend could be required that all e.g. corners of the drawing area can be reached.

  • Lay_Distance(from, to, ?distance): Sets the distance between from and to with down alignment (Lay_Distance(from,to,0) equals Lay_D(from, to)). The default alias of the floating legend is LEGEND().

==============

SHOW_FLOATING_LEGEND(?alias, ?hideStereotype) and LEGEND()

LAYOUT_WITH_LEGEND() and SHOW_LEGEND(?hideStereotype)` adds the legend at the bottom right of the picture like below and additional whitespace is created.

Therefore a floating legend can be added via SHOW_FLOATING_LEGEND(), positioned with Lay_Distance() and existing whitespace is reused like below.

  • `SHOW_FLOATING_LEGEND(?alias, ?hideStereotype): shows the legend in the drawing area
  • LEGEND(): is the default alias of the created floating legend and can be used in Lay_Distance() call
@startuml Compact Legend Layout Sample
!include https://raw.githubusercontent.com/kirchsth/C4-PlantUML/extended/C4_Container.puml

Person(a, "Person A")
Container(b, "Container B", "techn")
System(c, "System C")
Container(d, "Container D", "techn")
Container_Ext(e, "Ext. Container E", "techn")

Rel_R(a, b, "calls")
Rel_D(b, c, "uses")
Rel_D(c, d, "uses")
Rel_R(d, e, "updates")

SHOW_FLOATING_LEGEND()
Lay_Distance(LEGEND(), e, 1)
@enduml

Compact Legend Layout Sample

@kirchsth
Copy link
Member

@Potherca I think you can add it to release 2.3. too

@Potherca Potherca added this to the v2.3.0 milestone Apr 23, 2021
@stale stale bot added the stale Issue has not been active for 60 days label Jun 22, 2021
@Potherca Potherca added the not-stale Stop issue from being marked stale by bot label Jun 23, 2021
@stale stale bot removed the stale Issue has not been active for 60 days label Jun 23, 2021
@plantuml-stdlib plantuml-stdlib deleted a comment from stale bot Jun 23, 2021
Potherca added a commit that referenced this issue Jul 4, 2021
 #134: Legend fill whitespace with SHOW_FLOATING_LEGEND() and Lay_Distance()
@Potherca Potherca moved this to Todo in All Projects Jul 3, 2022
@Potherca Potherca moved this from Todo to Done in All Projects Jul 3, 2022
@Potherca Potherca removed the not-stale Stop issue from being marked stale by bot label Aug 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

3 participants