    001// Copyright 2023 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007//     http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.corelib.components;
    016
    017import org.apache.tapestry5.BindingConstants;
    018import org.apache.tapestry5.ComponentResources;
    019import org.apache.tapestry5.MarkupWriter;
    020import org.apache.tapestry5.annotations.Environmental;
    021import org.apache.tapestry5.annotations.Parameter;
    022import org.apache.tapestry5.annotations.Property;
    023import org.apache.tapestry5.commons.Messages;
    024import org.apache.tapestry5.ioc.annotations.Inject;
    025import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
    026import org.apache.tapestry5.services.javascript.JavaScriptSupport;
    027
    028/**
    029 * Component that renders a <a href="http://graphviz.org">Graphviz</a> graph using
    030 * <a href="https://www.npmjs.com/package/@hpcc-js/wasm">@hpcc-js/wasm</a>. It's mostly
    031 * intended to be used internally at Tapestry, hence the limited set of options.
    032 *
    033 * @tapestrydoc
    034 * @since 5.8.3
    035 */
    036public class Graphviz
    037{
    038
    039    /**
    040     * A Graphviz graph described in its DOT language.
    041     */
    042    @Parameter(required = true, allowNull = false)
    043    @Property
    044    private String value;
    045
    046    /**
    047     * Defines whether a link to download the graph as an SVG file should be provided.
    048     */
    049    @Parameter(defaultPrefix = BindingConstants.LITERAL, value = "false")
    050    private boolean showDownloadLink;
    051
    052    /**
    053     * Defines whether a the Graphviz source should be shown.
    054     */
    055    @Parameter(defaultPrefix = BindingConstants.LITERAL, value = "false")
    056    private boolean showSource;
    057
    058    @Environmental
    059    private JavaScriptSupport javaScriptSupport;
    060
    061    @Inject
    062    private AjaxResponseRenderer ajaxResponseRenderer;
    063
    064    @Inject
    065    private ComponentResources resources;
    066
    067    @Inject
    068    private Messages messages;
    069
    070    // Read value only once if showSource = true
    071    private String cachedValue;
    072
    073    void setupRender(MarkupWriter writer)
    074    {
    075
    076        cachedValue = value;
    077        String elementName = resources.getElementName();
    078        if (elementName == null)
    079        {
    080            elementName = "div";
    081        }
    082
    083        final String id = javaScriptSupport.allocateClientId(resources);
    084        writer.element(elementName, "id", id);
    085        writer.end();
    086
    087        javaScriptSupport.require("t5/core/graphviz").with(cachedValue, id, showDownloadLink);
    088
    089        if (showDownloadLink)
    090        {
    091            writer.element("a", "href", "#", "id", id + "-download", "download", id + ".svg");
    092            writer.write(messages.get("download-graphviz-image"));
    093            writer.end();
    094        }
    095
    096        if (showSource)
    097        {
    098            writer.element("pre", "id", id + "-source");
    099            writer.write(cachedValue);
    100            writer.end();
    101        }
    102
    103    }
    104
    105}