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 lack of options. 032 * 033 * @tapestrydoc 034 */ 035public class Graphviz 036{ 037 038 /** 039 * A Graphviz graph described in its DOT language. 040 */ 041 @Parameter(required = true, allowNull = false) 042 @Property 043 private String value; 044 045 /** 046 * Defines whether a link to download the graph as an SVG file should be provided. 047 */ 048 @Parameter(defaultPrefix = BindingConstants.LITERAL, value = "false") 049 private boolean showDownloadLink; 050 051 /** 052 * Defines whether a the Graphviz source should be shown. 053 */ 054 @Parameter(defaultPrefix = BindingConstants.LITERAL, value = "false") 055 private boolean showSource; 056 057 @Environmental 058 private JavaScriptSupport javaScriptSupport; 059 060 @Inject 061 private AjaxResponseRenderer ajaxResponseRenderer; 062 063 @Inject 064 private ComponentResources resources; 065 066 @Inject 067 private Messages messages; 068 069 // Read value only once if showSource = true 070 private String cachedValue; 071 072 void setupRender(MarkupWriter writer) 073 { 074 075 cachedValue = value; 076 String elementName = resources.getElementName(); 077 if (elementName == null) 078 { 079 elementName = "div"; 080 } 081 082 final String id = javaScriptSupport.allocateClientId(resources); 083 writer.element(elementName, "id", id); 084 writer.end(); 085 086 javaScriptSupport.require("t5/core/graphviz").with(cachedValue, id, showDownloadLink); 087 088 if (showDownloadLink) 089 { 090 writer.element("a", "href", "#", "id", id + "-download", "download", id + ".svg"); 091 writer.write(messages.get("download-graphviz-image")); 092 writer.end(); 093 } 094 095 if (showSource) 096 { 097 writer.element("pre", "id", id + "-source"); 098 writer.write(cachedValue); 099 writer.end(); 100 } 101 102 } 103 104}