Skip to content

Features and Advanced Usage

Bruno Silva edited this page Jun 9, 2025 · 2 revisions

🚧

FluentFxCss

You can make use of another library called FluentFxCss to create/add styles in a more fluent manner, instead of producing CSS code directly.

For example, the code in examples.digraph can instead be as follows:

if (g.numVertices() > 0) {

    ShapeStyleDefinition style = FluentFxCss.shapeStyle()
            .fill(Color.GOLD)
            .stroke(Color.BROWN)
            .build();

    graphView.getStylableVertex("A").setStyleInline(style.toCssInline());
}

Also, in cases where we wish to produce the CSS configuration programmatically or when we don't want to distribute the smartgraph.css file, we can create a temporary CSS file and pass it on to the smartgraph panel. Example of instantiation and auxiliary method:

URI stylesheetURI = createStylesheet();

SmartGraphProperties properties = new SmartGraphProperties();
SmartPlacementStrategy initialPlacement = new SmartCircularSortedPlacementStrategy();
ForceDirectedLayoutStrategy<String> automaticPlacementStrategy = new ForceDirectedSpringGravityLayoutStrategy<>();

SmartGraphPanel<String, String> graphView = new SmartGraphPanel<>(g,
        properties,
        initialPlacement,
        stylesheetURI,
        automaticPlacementStrategy);

// ...

private static URI createStylesheet() {

    /* .graph */
    PaneStyleDefinition graph = FluentFxCss.paneStyle()
            .backgroundColor(Color.BLACK)
            .build();

    /* .vertex and .vertex:hover */
    ShapeStyleDefinition vertex = FluentFxCss.shapeStyle()
            .fill(Color.web("#3498db"))
            .stroke(Color.web("#2980b9"))
            .strokeWidth(2)
            .dropShadow(BlurType.GAUSSIAN, Color.web("#00ffff"), 15, 0.8, 0, 0)
            .opacity(0.5)
            .build();

    ShapeStyleDefinition vertexHover = FluentFxCss.shapeStyle()
            .strokeWidth(4)
            .build();

    /* .vertex-label */
    TextStyleDefinition vertexLabelText = FluentFxCss.textStyle()
            .fontWeight(FontWeight.BOLD)
            .fontSize(8, UnitValue.PT)
            .fontFamily("sans-serif")
            .build();

    RegionStyleDefinition vertexLabelBackground = FluentFxCss.regionStyle()
            .padding(UnitValue.PX, 5)
            .dropShadow(BlurType.GAUSSIAN, Color.web("#00ffff"), 10, 0.6, 0, 0)
            .build();

    StyleDefinition vertexLabel = vertexLabelText.mergeWith(vertexLabelBackground);

    /* .edge and .edge:hover */
    ShapeStyleDefinition edge = FluentFxCss.shapeStyle()
            .stroke(Color.WHITE)
            .strokeWidth(2)
            .dropShadow(BlurType.GAUSSIAN, Color.web("#00ffff"), 10, 0.6, 0, 0)
            .fill(Color.TRANSPARENT)
            .strokeLineCap(StrokeLineCap.ROUND)
            .opacity(0.8)
            .build();

    ShapeStyleDefinition edgeHover = FluentFxCss.shapeStyle()
            .strokeWidth(3)
            .build();

    TextStyleDefinition edgeLabelText = FluentFxCss.textStyle()
            .fontWeight(FontWeight.NORMAL)
            .fontSize(5, UnitValue.PT)
            .fontFamily("sans-serif")
            .build();

    RegionStyleDefinition edgeLabelBackground = FluentFxCss.regionStyle()
            .dropShadow(BlurType.GAUSSIAN, Color.web("#00ffff"), 10, 0.6, 0, 0)
            .build();

    StyleDefinition edgeLabel = edgeLabelText.mergeWith(edgeLabelBackground);

    TextStyleDefinition edgeLabelTextHover = FluentFxCss.textStyle()
            .fontWeight(FontWeight.BOLD)
            .fontSize(5, UnitValue.PT)
            .fontFamily("sans-serif")
            .build();

    RegionStyleDefinition edgeLabelBackgroundHover = FluentFxCss.regionStyle()
            .backgroundRadius(5)
            .borderRadius(5)
            .build();

    StyleDefinition edgeLabelHover = edgeLabelTextHover.mergeWith(edgeLabelBackgroundHover);


    /* Compose CSS */
    String graphClass = graph.toCssClass("graph");
    String vertexClass = vertex.toCssClass("vertex");
    String vertexHoverClass = vertexHover.toCssPseudoClass("vertex", PseudoClassValue.HOVER);

    String vertexLabelClass = vertexLabel.toCssClass("vertex-label");

    String edgeClass = edge.toCssClass("edge");
    String edgeHoverClass = edgeHover.toCssPseudoClass("edge", PseudoClassValue.HOVER);

    String edgeLabelClass = edgeLabel.toCssClass("edge-label");
    String edgeLabelHoverClass = edgeLabelHover.toCssPseudoClass("edge-label", PseudoClassValue.HOVER);

    String css = String.join("\n",
            graphClass,
            vertexClass,
            vertexHoverClass,
            vertexLabelClass,
            edgeClass,
            edgeHoverClass,
            edgeLabelClass,
            edgeLabelHoverClass
    );

    try {
        // Create a temporary file (OS will handle cleanup eventually, but you can delete on exit)
        Path tempCssFile = Files.createTempFile("dynamic-style", ".css");
        Files.write(tempCssFile, css.getBytes(StandardCharsets.UTF_8));

        // Convert to URI
        return tempCssFile.toUri(); // This works with getStylesheets().add(cssUri.toString());
    } catch(Exception e) {
        System.err.println("Cannot create temporary file.");
    }

    return null;
}

Clone this wiki locally