Skip to content

Commit 1569be3

Browse files
Adds support for iconPosition on element styles (options are Top, Bottom, Left).
1 parent e328063 commit 1569be3

File tree

9 files changed

+107
-1
lines changed

9 files changed

+107
-1
lines changed

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## v4.2.0 (unreleased)
4+
5+
- structurizr-dsl: Adds support for `iconPosition` on element styles (options are `Top`, `Bottom`, `Left`).
6+
37
## v4.1.0 (28th May 2025)
48

59
- structurizr-client: Fixes https://github.com/structurizr/java/issues/413 (Cannot push to main branch, when branch feature is activated).

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ signing.secretKeyRingFile=/some/path
55
ossrhUsername=username
66
ossrhPassword=password
77

8-
version=4.1.0
8+
version=4.2.0

structurizr-core/src/main/java/com/structurizr/view/ElementStyle.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ public final class ElementStyle extends AbstractStyle {
4141
@JsonInclude(value = JsonInclude.Include.NON_NULL)
4242
private String icon;
4343

44+
@JsonInclude(value = JsonInclude.Include.NON_NULL)
45+
private IconPosition iconPosition;
46+
4447
@JsonInclude(value = JsonInclude.Include.NON_NULL)
4548
private Border border;
4649

@@ -290,6 +293,24 @@ public ElementStyle icon(String icon) {
290293
return this;
291294
}
292295

296+
/**
297+
* Gets the icon position to use when rendering the element.
298+
*
299+
* @return an IconPosition, or null if not specified
300+
*/
301+
public IconPosition getIconPosition() {
302+
return iconPosition;
303+
}
304+
305+
public void setIconPosition(IconPosition iconPosition) {
306+
this.iconPosition = iconPosition;
307+
}
308+
309+
public ElementStyle iconPosition(IconPosition iconPosition) {
310+
setIconPosition(iconPosition);
311+
return this;
312+
}
313+
293314
/**
294315
* Gets the border used when rendering the element.
295316
*
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.structurizr.view;
2+
3+
public enum IconPosition {
4+
5+
Top,
6+
Bottom,
7+
Left
8+
9+
}

structurizr-dsl/src/main/java/com/structurizr/dsl/ElementStyleDslContext.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ protected String[] getPermittedTokens() {
2727
return new String[] {
2828
StructurizrDslTokens.ELEMENT_STYLE_SHAPE_TOKEN,
2929
StructurizrDslTokens.ELEMENT_STYLE_ICON_TOKEN,
30+
StructurizrDslTokens.ELEMENT_STYLE_ICON_POSITION_TOKEN,
3031
StructurizrDslTokens.ELEMENT_STYLE_WIDTH_TOKEN,
3132
StructurizrDslTokens.ELEMENT_STYLE_HEIGHT_TOKEN,
3233
StructurizrDslTokens.ELEMENT_STYLE_BACKGROUND_TOKEN,

structurizr-dsl/src/main/java/com/structurizr/dsl/ElementStyleParser.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.structurizr.util.StringUtils;
66
import com.structurizr.view.Border;
77
import com.structurizr.view.ElementStyle;
8+
import com.structurizr.view.IconPosition;
89
import com.structurizr.view.Shape;
910

1011
import java.io.File;
@@ -318,4 +319,33 @@ void parseIcon(ElementStyleDslContext context, Tokens tokens, boolean restricted
318319
}
319320
}
320321

322+
void parseIconPosition(ElementStyleDslContext context, Tokens tokens) {
323+
Map<String, IconPosition> iconPositions = new HashMap<>();
324+
String iconPositionsAsString = "";
325+
for (IconPosition iconPosition : IconPosition.values()) {
326+
iconPositions.put(iconPosition.toString().toLowerCase(), iconPosition);
327+
iconPositionsAsString += iconPosition;
328+
iconPositionsAsString += "|";
329+
}
330+
iconPositionsAsString = iconPositionsAsString.substring(0, iconPositionsAsString.length()-1);
331+
332+
ElementStyle style = context.getStyle();
333+
334+
if (tokens.hasMoreThan(FIRST_PROPERTY_INDEX)) {
335+
throw new RuntimeException("Too many tokens, expected: iconPosition <" + iconPositionsAsString + ">");
336+
}
337+
338+
if (tokens.includes(FIRST_PROPERTY_INDEX)) {
339+
String iconPosition = tokens.get(1).toLowerCase();
340+
341+
if (iconPositions.containsKey(iconPosition)) {
342+
style.setIconPosition(iconPositions.get(iconPosition));
343+
} else {
344+
throw new RuntimeException("The icon position \"" + iconPosition + "\" is not valid");
345+
}
346+
} else {
347+
throw new RuntimeException("Expected: iconPosition <" + iconPositionsAsString + ">");
348+
}
349+
}
350+
321351
}

structurizr-dsl/src/main/java/com/structurizr/dsl/StructurizrDslParser.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,9 @@ void parse(List<String> lines, File dslFile, boolean fragment, boolean includeIn
834834
} else if (ELEMENT_STYLE_ICON_TOKEN.equalsIgnoreCase(firstToken) && inContext(ElementStyleDslContext.class)) {
835835
new ElementStyleParser().parseIcon(getContext(ElementStyleDslContext.class), tokens, restricted);
836836

837+
} else if (ELEMENT_STYLE_ICON_POSITION_TOKEN.equalsIgnoreCase(firstToken) && inContext(ElementStyleDslContext.class)) {
838+
new ElementStyleParser().parseIconPosition(getContext(ElementStyleDslContext.class), tokens);
839+
837840
} else if (RELATIONSHIP_STYLE_TOKEN.equalsIgnoreCase(firstToken) && inContext(StylesDslContext.class)) {
838841
RelationshipStyle relationshipStyle = new RelationshipStyleParser().parseRelationshipStyle(getContext(), tokens.withoutContextStartToken());
839842
startContext(new RelationshipStyleDslContext(relationshipStyle));

structurizr-dsl/src/main/java/com/structurizr/dsl/StructurizrDslTokens.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class StructurizrDslTokens {
7171
static final String ELEMENT_STYLE_COLOUR_TOKEN = "colour";
7272
static final String ELEMENT_STYLE_COLOR_TOKEN = "color";
7373
static final String ELEMENT_STYLE_ICON_TOKEN = "icon";
74+
static final String ELEMENT_STYLE_ICON_POSITION_TOKEN = "iconPosition";
7475
static final String ELEMENT_STYLE_OPACITY_TOKEN = "opacity";
7576
static final String ELEMENT_STYLE_BORDER_TOKEN = "border";
7677
static final String ELEMENT_STYLE_FONT_SIZE_TOKEN = "fontSize";

structurizr-dsl/src/test/java/com/structurizr/dsl/ElementStyleParserTests.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.structurizr.view.Border;
44
import com.structurizr.view.ElementStyle;
5+
import com.structurizr.view.IconPosition;
56
import com.structurizr.view.Shape;
67
import org.junit.jupiter.api.Test;
78

@@ -543,4 +544,40 @@ void test_parseIcon_SetsTheIconFromAFile() {
543544
assertTrue(elementStyle.getIcon().startsWith("data:image/png;base64,"));
544545
}
545546

547+
@Test
548+
void test_parseIconPosition_ThrowsAnException_WhenThereAreTooManyTokens() {
549+
try {
550+
parser.parseIconPosition(elementStyleDslContext(), tokens("iconPosition", "top", "extra"));
551+
fail();
552+
} catch (Exception e) {
553+
assertEquals("Too many tokens, expected: iconPosition <Top|Bottom|Left>", e.getMessage());
554+
}
555+
}
556+
557+
@Test
558+
void test_parseIconPosition_ThrowsAnException_WhenTheShapeIsMissing() {
559+
try {
560+
parser.parseIconPosition(elementStyleDslContext(), tokens("iconPosition"));
561+
fail();
562+
} catch (Exception e) {
563+
assertEquals("Expected: iconPosition <Top|Bottom|Left>", e.getMessage());
564+
}
565+
}
566+
567+
@Test
568+
void test_parseIconPosition_ThrowsAnException_WhenTheShapeIsNotValid() {
569+
try {
570+
parser.parseIconPosition(elementStyleDslContext(), tokens("iconPosition", "right"));
571+
fail();
572+
} catch (Exception e) {
573+
assertEquals("The icon position \"right\" is not valid", e.getMessage());
574+
}
575+
}
576+
577+
@Test
578+
void test_parseIconPosition_SetsTheIconPosition() {
579+
parser.parseIconPosition(elementStyleDslContext(), tokens("iconPosition", "top"));
580+
assertEquals(IconPosition.Top, elementStyle.getIconPosition());
581+
}
582+
546583
}

0 commit comments

Comments
 (0)