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}