Skip to main content

cxx2flow_lib/display/
tikz.rs

1use petgraph::visit::{EdgeRef, IntoEdgeReferences, IntoNodeReferences};
2
3use crate::error::{Error, Result};
4use crate::graph::{Graph, GraphNodeType};
5
6use super::GraphDisplay;
7#[derive(Debug, Default)]
8pub struct Tikz {}
9
10impl Tikz {
11    pub fn new() -> Self {
12        Tikz {}
13    }
14}
15
16impl GraphDisplay for Tikz {
17    fn generate_from_graph(&self, graph: &Graph) -> Result<String> {
18        let mut res = r#"
19\documentclass[tikz,border=10pt]{standalone}
20\usepackage{ctex}
21\usetikzlibrary{graphdrawing}
22\usetikzlibrary{shapes}
23\usepackage{spverbatim}
24\usepackage{varwidth}
25\usetikzlibrary{graphs}
26\usegdlibrary{layered}
27\usepackage[T1]{fontenc}% NOT OT1!
28\usepackage{lmodern}% Latin Modern fonts,
29  % a modern variant of Computer Modern fonts
30\let\ttdefault\rmdefault
31\tikzstyle{block} = [%
32   draw,thick,fill=blue!0,
33   inner sep=0.3cm,
34   text centered, minimum height=1em,
35   execute at begin node={\begin{varwidth}{8em}},
36   execute at end node={\end{varwidth}}]
37\begin{document}
38\tikz [layered layout, sibling distance=3cm] {
39  "#
40        .to_string();
41        for (id, i) in graph.node_references() {
42            match i {
43                GraphNodeType::Begin => res.push_str(
44                    format!(
45                        "\\node[draw] (D{}) [rounded rectangle, block] {{ Begin }};\n",
46                        id.index()
47                    )
48                    .as_str(),
49                ),
50                GraphNodeType::End => res.push_str(
51                    format!(
52                        "\\node[draw] (D{}) [rounded rectangle, block] {{ End }};\n",
53                        id.index()
54                    )
55                    .as_str(),
56                ),
57                GraphNodeType::Node(str) => res.push_str(
58                    format!(
59                        "\\node[draw] (D{}) [rectangle, block] {{ \\spverb${}$ }};\n",
60                        id.index(),
61                        str.replace('%', "\\%")
62                    )
63                    .replace('\n', " ")
64                    .as_str(),
65                ),
66                GraphNodeType::Choice(str) => res.push_str(
67                    format!(
68                        "\\node[draw] (D{}) [diamond, aspect=2, block] {{ \\spverb${}$ }};\n",
69                        id.index(),
70                        str.replace('%', "\\%")
71                    )
72                    .replace('\n', " ")
73                    .as_str(),
74                ),
75                GraphNodeType::Dummy => {
76                    return Err(Error::UnexpectedDummyGraphNode {
77                        graph: graph.clone(),
78                    });
79                } // all dummy node will be eliminated
80            }
81        }
82        for i in graph.edge_references() {
83            match i.weight() {
84                crate::graph::EdgeType::Normal => res.push_str(
85                    format!(
86                        "\\draw (D{}) edge[->] (D{});\n",
87                        i.source().index(),
88                        i.target().index()
89                    )
90                    .as_str(),
91                ),
92                crate::graph::EdgeType::Branch(t) => res.push_str(
93                    format!(
94                        "\\draw (D{}) edge[->, below] node {{ {} }} (D{});\n",
95                        i.source().index(),
96                        i.target().index(),
97                        if *t { "Y" } else { "N" }
98                    )
99                    .as_str(),
100                ),
101            }
102        }
103        res.push_str(
104            r#"
105}
106\end{document}
107  "#,
108        );
109        Ok(res)
110    }
111}