Skip to content

Instantly share code, notes, and snippets.

@rohit507
Created May 13, 2015 17:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rohit507/0337e824de60b2fa2bf0 to your computer and use it in GitHub Desktop.
Save rohit507/0337e824de60b2fa2bf0 to your computer and use it in GitHub Desktop.
\documentclass[]{article}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{ifxetex,ifluatex}
\usepackage{fixltx2e} % provides \textsubscript
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\else % if luatex or xelatex
\ifxetex
\usepackage{mathspec}
\usepackage{xltxtra,xunicode}
\else
\usepackage{fontspec}
\fi
\defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
\newcommand{\euro}{€}
\fi
% use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
% use microtype if available
\IfFileExists{microtype.sty}{%
\usepackage{microtype}
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
}{}
\usepackage[style=numeric,backend=bibtex,natbib]{biblatex}
\addbibresource{references.bib}
\ifxetex
\usepackage[setpagesize=false, % page size defined by xetex
unicode=false, % unicode breaks when used with xetex
xetex]{hyperref}
\else
\usepackage[unicode=true]{hyperref}
\fi
\hypersetup{breaklinks=true,
bookmarks=true,
pdfauthor={},
pdftitle={A Module Type System for Embedded System Synthesis},
colorlinks=true,
citecolor=blue,
urlcolor=blue,
linkcolor=magenta,
pdfborder={0 0 0}}
\urlstyle{same} % don't use monospace font for urls
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt plus 2pt minus 1pt}
\setlength{\emergencystretch}{3em} % prevent overfull lines
\setcounter{secnumdepth}{0}
\title{A Module Type System for Embedded System Synthesis}
\author{Rohit Ramesh}
\date{}
\usepackage{tikz}
%\usetikzlibrary{
% ,graphs
% ,graphdrawing}
%\usegdlibrary{trees,layered}
\usepackage{todonotes}
\usepackage{module-type-diagram}
\let\oldtodo\todo
\DeclareDocumentCommand \todo {D[]{} +m} {
\oldtodo[size=\tiny,#1]{\emph{Todo:} #2}
}
\begin{document}
\resizebox{\columnwidth}{!}{
\begin{modulediagram}
\module(modfoo){bar}{
\port <east> (etest) {eport};
\port[supprequ] <east> (etest2) {eportd};
\port <north> (ntest) {nport};
\port <north> (ntest2) {nport2};
\port[supp] <west> (wtest) {wport};
\port[requ] <west> (wtest2) {westport};
\port <south> (stest) {sport};
\port <south> (stest2) {spor3t};
};
\node[draw,right=of modfoo] (testnode) {testnode};
\fittedmodule[thick][outer sep = 1cm]
<modfoo,testnode> (testfit) {test label $\aleph$} {
\port <east> (eteest) {eport};
\port[supprequ] <east> (eteset2) {eportd};
\port <north> (nteset) {nport};
\port <north> (nteset2) {nport2};
\port[supp] <west> (wteset) {wport};
\port[requ] <west> (wteset2) {westport};
\port <south> (steset) {sport};
};
\end{modulediagram}
}
\end{document}
% A Latex Package for creating Module Type System Block
% Diagrams
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{module-type-system}
\RequirePackage{tikz}
\RequirePackage{ifthen}
\RequirePackage{xparse}
% TODO : I have no clue which of these libraries I actually need :V if anyone
% wants to cull the useless ones I'd appreciate it.
\usetikzlibrary{
graphs,
shapes,
calc,
intersections,
through,
fit,
backgrounds,
positioning,
arrows,%
shapes.misc,% wg. rounded rectangle
shapes.arrows,%
chains,%
matrix,%
scopes,%
decorations.pathmorphing,% /pgf/decoration/random steps | erste Graphik
shadows,%
fixedpointarithmetic
}
% ### Default Styles ###
\tikzset{
% The depth of the notches for the various port shapes
,notch depth/.initial = 2pt
% The ammount of buffer space to have on either side of a module's
% center box to leave aside for port placement.
,module center overrun/.initial = 15pt
}
% Styles applied to every mtd diagram
\tikzstyle{mtd-diagram}=[
remember picture
]
% The default style for the wrapper object that allows MTD modules to
% be positioned as single objects.
\tikzstyle{mtd-module-wrap}=[
,inner sep = 0pt
,outer sep = 0pt
]
% The style for the center box of an MTD module
\tikzstyle{mtd-module-center}=[
,black
,draw
,rounded corners
,inner sep = 3pt
,align = center
]
% Default Style for the boxes that contain a set of ports
\tikzstyle{mtd-portbox}=[
,inner sep = 0pt
,outer sep = 0pt
,node distance = 4pt
]
% Default style for a single port
\tikzstyle{mtd-port}=[
,draw
,inner sep = 3pt
,align = center
]
\tikzstyle{mtd-fit-module-wrap}=[
,mtd-module-wrap
]
\tikzstyle{mtd-fit-innerfit}=[
,inner sep = 0pt
,outer sep = 0pt
]
\tikzstyle{mtd-fit-label}=[
,node distance = 4pt
,parent-innerfit/.style={above=of ##1.north}
,anchor=south
]
\tikzstyle{mtd-fit-module-center}=[
,mtd-module-center
]
\tikzstyle{mtd-fit-portbox}=[
]
\tikzstyle{supplier}=[
port-type=supply
]
\tikzstyle{requester}=[
port-type=request
]
\tikzstyle{supplier requester}=[
port-type=supplyrequest
]
\tikzstyle{normal port}=[
port-type=normal
]
% Shortcut style options, these are just light aliases to other styles that
% are easier to type out
\tikzstyle{norm}=[normal port]
\tikzstyle{supp}=[supplier]
\tikzstyle{requ}=[requester]
\tikzstyle{supprequ}=[supplier requester]
\tikzstyle{rc}=[rounded coreners]
% Directional Style Options, if you need to change these for styling
% purposes you are doing it wrong. They mostly exist to provide shims for
% tikz workarounds, and to cleanly encapsulate certains heirarchies.
\tikzstyle{mtd-portbox-north}=[
,mtd-portbox
]
\tikzstyle{mtd-portbox-south}=[
,mtd-portbox
]
\tikzstyle{mtd-portbox-east}=[
,mtd-portbox
]
\tikzstyle{mtd-portbox-west}=[
,mtd-portbox
]
\tikzstyle{mtd-fit-portbox-north}=[
,mtd-portbox-north
,mtd-fit-portbox
]
\tikzstyle{mtd-fit-portbox-south}=[
,mtd-portbox-south
,mtd-fit-portbox
]
\tikzstyle{mtd-fit-portbox-east}=[
,mtd-portbox-east
,mtd-fit-portbox
]
\tikzstyle{mtd-fit-portbox-west}=[
,mtd-portbox-west
,mtd-fit-portbox
]
\tikzstyle{mtd-port-north}=[
,mtd-port
]
\tikzstyle{mtd-port-south}=[
,mtd-port
]
\tikzstyle{mtd-port-east}=[
,mtd-port
]
\tikzstyle{mtd-port-west}=[
,mtd-port
]
% ### Do Not Edit Below This Line ###
% If flags for modifying Ports
% Directional Flags
\newif\if@isnorth
\newif\if@issouth
\newif\if@iseast
\newif\if@iswest
\tikzset{
% Default settings the user should not be able to override
% (at least if they don't edit the bits they're not supposed to edit)
,mtd diagram/.append style={
,remember picture
}
,mtd-portbox-north/.append style={
,anchor=south
}
,mtd-portbox-south/.append style={
,anchor=north
}
,mtd-portbox-east/.append style={
,anchor=west
}
,mtd-portbox-west/.append style={
,anchor=east
}
,mtd-port-east/.append style={
,previous-port/.style={below=of ##1.sw,anchor=nw}
}
,mtd-port-west/.append style={
,previous-port/.style={below=of ##1.se,anchor=ne}
}
,mtd-port-north/.append style={
,previous-port/.style={right=of ##1.se,anchor=sw}
}
,mtd-port-south/.append style={
,previous-port/.style={right=of ##1.ne,anchor=nw}
}
% Boolean flags for direction
,port-info/is north/.initial = false
,port-info/is north/.is if=@isnorth
,port-info/is north/.default = false
,port-info/is south/.initial = false
,port-info/is south/.is if=@issouth
,port-info/is south/.default = false
,port-info/is east/.initial = false
,port-info/is east/.is if=@iseast
,port-info/is east/.default = false
,port-info/is west/.initial = false
,port-info/is west/.is if=@iswest
,port-info/is west/.default = false
% Switch for Direction and Flag settings
,port-dir/.is choice
,port-dir/north/.style={
,port-info/is north = true
,port-info/is south = false
,port-info/is east = false
,port-info/is west = false
,mtd-port-north
}
,port-dir/south/.style={
,port-info/is north = false
,port-info/is south=true
,port-info/is east = false
,port-info/is west = false
,mtd-port-south
}
,port-dir/west/.style={
,port-info/is north = false
,port-info/is south = false
,port-info/is east = false
,port-info/is west = true
,mtd-port-west
}
,port-dir/east/.style={
,port-info/is north = false
,port-info/is south = false
,port-info/is east = true
,port-info/is west = false
,mtd-port-east
}
,port-dir/reset/.style={
,port-info/is north = false
,port-info/is south = false
,port-info/is east = false
,port-info/is west = false
}
,port-type/.is choice
,port-type/.initial = normal
,port-type/normal/.style={
,normshape
}
,port-type/supply/.style={
,suppshape
}
,port-type/request/.style={
,requshape
}
,port-type/supplyrequest/.style={
,supprequshape
}
}
% Advance a point in direction theta for distance r
% #1 = x
% #2 = y
% #3 = theta
% #4 = r
\DeclareDocumentCommand \@advancepoint {m m m m}{
\pgfmathsetmacro{\mts@xo}{sin(#3) * #4}
\pgfmathsetmacro{\mts@yo}{cos(#3) * #4}
\pgfmathsetmacro{#1}{#1 + \mts@xo}
\pgfmathsetmacro{#2}{#2 + \mts@yo}
}
% Copy a point into a pair of new macros.
% #1 = destx
% #2 = desty
% #3 = srcx
% #4 = srcy
\DeclareDocumentCommand \@copypoint {m m m m}{
\pgfmathsetmacro{#1}{#3}
\pgfmathsetmacro{#2}{#4}
}
% A command to draw a normal ine between two points
% as poart of a PGF Backgroun Path process, assumes
% that a the startx and y are where the path is at
% the beginning of the command.
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@normline {m m m m}{
\pgfpathlineto{\pgfpoint{#3}{#4}}
}
% returns the connection point for each side of a normal block
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@normconn {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% xc,yc := the point in the middle of the line
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5}
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5}
% Actualize point
\pgfpoint{\mts@xc}{\mts@yc}
}
% Draw the bowed out line for supplires in the correct
% direction, assumes that the line is going counter clockwise.
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@suppline {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% Calculate key constants / gather variables
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth}
% Calculate key constants / gather variables
% theta_a := the angle along the path of the line -
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)}
% theta_b := the angle perpendicular to the path of the line
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90}
% Get points for current line
\@copypoint{\mts@xc}{\mts@yc}{\mts@xa}{\mts@ya}
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetaa}{\mts@notchdepth}
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{\mts@notchdepth}
\@copypoint{\mts@xd}{\mts@yd}{\mts@xb}{\mts@yb}
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetaa}{-\mts@notchdepth}
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetab}{\mts@notchdepth}
% Actualize Line
\pgfpathlineto{\pgfpoint{\mts@xc}{\mts@yc}}
\pgfpathlineto{\pgfpoint{\mts@xd}{\mts@yd}}
\pgfpathlineto{\pgfpoint{\mts@xb}{\mts@yb}}
}
% returns the connection point for each side of a supplier
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@suppconn {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% Calculate key constants / gather variables
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth}
% Calculate key constants / gather variables
% theta_a := the angle along the path of the line -
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)}
% theta_b := the angle perpendicular to the path of the line
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90}
% xc,yc := the point in the middle of the line
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5}
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5}
% move center point correctly
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{\mts@notchdepth}
% Actualize point
\pgfpoint{\mts@xc}{\mts@yc}
}
% Draw the bowed in line for requesters in the correct
% direction, assumes that the line is going counter clockwise.
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@requline {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% Calculate key constants / gather variables
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth}
% theta_a := the angle along the path of the line
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)}
% theta_b := the angle perpendicular to the path of the line
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90}
% Get points for current line
\@copypoint{\mts@xc}{\mts@yc}{\mts@xa}{\mts@ya}
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{\mts@notchdepth}
\@copypoint{\mts@xd}{\mts@yd}{\mts@xa}{\mts@ya}
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetaa}{\mts@notchdepth}
\@copypoint{\mts@xe}{\mts@ye}{\mts@xb}{\mts@yb}
\@advancepoint{\mts@xe}{\mts@ye}{\mts@thetaa}{-\mts@notchdepth}
\@copypoint{\mts@xf}{\mts@yf}{\mts@xb}{\mts@yb}
\@advancepoint{\mts@xf}{\mts@yf}{\mts@thetab}{\mts@notchdepth}
% Actualize Line
\pgfpathlineto{\pgfpoint{\mts@xc}{\mts@yc}}
\pgfpathlineto{\pgfpoint{\mts@xd}{\mts@yd}}
\pgfpathlineto{\pgfpoint{\mts@xe}{\mts@ye}}
\pgfpathlineto{\pgfpoint{\mts@xf}{\mts@yf}}
\pgfpathlineto{\pgfpoint{\mts@xb}{\mts@yb}}
}
% returns the connection point for each side of a requester
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@requconn {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% Calculate key constants / gather variables
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth}
% Calculate key constants / gather variables
% theta_a := the angle along the path of the line -
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)}
% theta_b := the angle perpendicular to the path of the line
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90}
% xc,yc := the point in the middle of the line
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5}
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5}
% Actualize point
\pgfpoint{\mts@xc}{\mts@yc}
}
% Draw the wavy line for supp/receivers in the correct
% direction, assumes that the line is going counter clockwise.
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@supprequline {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% Calculate key constants / gather variables
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth}
% theta_a := the angle along the path of the line
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)}
% theta_b := the angle perpendicular to the path of the line
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90}
% hnd := half the notch depth
\pgfmathsetmacro{\mts@hnd}{\mts@notchdepth * 0.5}
% xc,yc := the point in the middle of the line
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5}
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5}
% Get points for current line
\@copypoint{\mts@xd}{\mts@yd}{\mts@xa}{\mts@ya}
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetab}{\mts@notchdepth}
\@copypoint{\mts@xe}{\mts@ye}{\mts@xa}{\mts@ya}
\@advancepoint{\mts@xe}{\mts@ye}{\mts@thetaa}{\mts@notchdepth}
\@copypoint{\mts@xf}{\mts@yf}{\mts@xc}{\mts@yc}
\@advancepoint{\mts@xf}{\mts@yf}{\mts@thetaa}{-\mts@hnd}
\@copypoint{\mts@xg}{\mts@yg}{\mts@xc}{\mts@yc}
\@advancepoint{\mts@xg}{\mts@yg}{\mts@thetaa}{\mts@hnd}
\@advancepoint{\mts@xg}{\mts@yg}{\mts@thetab}{\mts@notchdepth}
\@copypoint{\mts@xh}{\mts@yh}{\mts@xb}{\mts@yb}
\@advancepoint{\mts@xh}{\mts@yh}{\mts@thetaa}{-\mts@notchdepth}
\@advancepoint{\mts@xh}{\mts@yh}{\mts@thetab}{\mts@notchdepth}
% Actualize Line
\pgfpathlineto{\pgfpoint{\mts@xd}{\mts@yd}}
\pgfpathlineto{\pgfpoint{\mts@xe}{\mts@ye}}
\pgfpathlineto{\pgfpoint{\mts@xf}{\mts@yf}}
\pgfpathlineto{\pgfpoint{\mts@xg}{\mts@yg}}
\pgfpathlineto{\pgfpoint{\mts@xh}{\mts@yh}}
\pgfpathlineto{\pgfpoint{\mts@xb}{\mts@yb}}
}
% returns the connection point for each side of a supplier/requester
% #1 = x1
% #2 = y1
% #3 = x2
% #4 = y2
\DeclareDocumentCommand \@supprequconn {m m m m}{
% Initial setup
\pgfmathsetmacro{\mts@xa}{#1}
\pgfmathsetmacro{\mts@ya}{#2}
\pgfmathsetmacro{\mts@xb}{#3}
\pgfmathsetmacro{\mts@yb}{#4}
% Calculate key constants / gather variables
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth}
% Calculate key constants / gather variables
% theta_a := the angle along the path of the line -
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)}
% theta_b := the angle perpendicular to the path of the line
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90}
% xc,yc := the point in the middle of the line
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5}
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5}
% move center point correctly
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{(0.5 * \mts@notchdepth)}
% Actualize point
\pgfpoint{\mts@xc}{\mts@yc}
}
% #1 = shape name
% #2 = special line command
% #3 = special conn point command
\DeclareDocumentCommand \@initportshape {m m m} {
\pgfdeclareshape{#1}{
\inheritsavedanchors[from=rectangle] % this is nearly a rectangle
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
\backgroundpath{
% store lower right in xa/ya and upper right in xb/yb
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
% construct main path
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\if@iswest
#2{\pgf@xa}{\pgf@ya}{\pgf@xa}{\pgf@yb}
\else
\@normline{\pgf@xa}{\pgf@ya}{\pgf@xa}{\pgf@yb}
\fi
\if@isnorth
#2{\pgf@xa}{\pgf@yb}{\pgf@xb}{\pgf@yb}
\else
\@normline{\pgf@xa}{\pgf@yb}{\pgf@xb}{\pgf@yb}
\fi
\if@iseast
#2{\pgf@xb}{\pgf@yb}{\pgf@xb}{\pgf@ya}
\else
\@normline{\pgf@xb}{\pgf@yb}{\pgf@xb}{\pgf@ya}
\fi
\if@issouth
#2{\pgf@xb}{\pgf@ya}{\pgf@xa}{\pgf@ya}
\else
\@normline{\pgf@xb}{\pgf@ya}{\pgf@xa}{\pgf@ya}
\fi
\pgfpathclose
}
% Anchors defined by sensible people in a language that is
% only the devil's 3rd cousin
\anchor{northconn}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
#3{\pgf@xa}{\pgf@yb}{\pgf@xb}{\pgf@yb}
}
\anchor{southconn}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
#3{\pgf@xb}{\pgf@ya}{\pgf@xa}{\pgf@ya}
}
\anchor{westconn}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
#3{\pgf@xa}{\pgf@ya}{\pgf@xa}{\pgf@yb}
}
\anchor{eastconn}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
#3{\pgf@xb}{\pgf@yb}{\pgf@xb}{\pgf@ya}
}
\anchor{nw}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfpoint{\pgf@xa}{\pgf@yb}
}
\anchor{ne}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfpoint{\pgf@xb}{\pgf@yb}
}
\anchor{sw}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfpoint{\pgf@xa}{\pgf@ya}
}
\anchor{se}{
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
\pgfpoint{\pgf@xb}{\pgf@ya}
}
}
}
% Initialize the various port types
\@initportshape{normshape}{\@normline}{\@normconn}
\@initportshape{suppshape}{\@suppline}{\@suppconn}
\@initportshape{requshape}{\@requline}{\@requconn}
\@initportshape{supprequshape}{\@supprequline}{\@supprequconn}
\ExplSyntaxOn
% some helper / wrapper commands around \pgfplacenodelater
% #1 = identifier for nodes to be placed later
% #2 = elements to be placed
\DeclareDocumentCommand \@placenodelater {r() +m}{
\cs_new_protected:cpn {mtd@#1-save}
{
% Save Necessary Registers
\cs_gset_eq:cN {mtd@#1-name} \pgfpositionnodelatername
\cs_gset_eq:cN {mtd@#1-minx} \pgfpositionnodelaterminx
\cs_gset_eq:cN {mtd@#1-miny} \pgfpositionnodelaterminy
\cs_gset_eq:cN {mtd@#1-maxx} \pgfpositionnodelatermaxx
\cs_gset_eq:cN {mtd@#1-maxy} \pgfpositionnodelatermaxy
\box_if_exist:cF{mtd@#1-box} {\box_new:c {mtd@#1-box}}
\box_gset_eq:cN {mtd@#1-box} \pgfpositionnodelaterbox
% Calculate Length and Width as well
\pgfmathsetmacro{\mtd@tempwid}
{\pgfpositionnodelatermaxx - \pgfpositionnodelaterminx}
\pgfmathsetmacro{\mtd@temphei}
{\pgfpositionnodelatermaxy - \pgfpositionnodelaterminy}
\cs_gset_eq:cN {mtd@#1-height} \mtd@temphei
\cs_gset_eq:cN {mtd@#1-width} \mtd@tempwid
}
{
\exp_args:Nc \pgfpositionnodelater {mtd@#1-save} #2
}
}
% #1 = identifier for nodes already saved by \@placenodelater
% #2 = location for the node to be placed at
\DeclareDocumentCommand \@placenodenow {r() +m}{
\cs_gset_eq:Nc \pgfpositionnodelatername {mtd@#1-name}
\cs_gset_eq:Nc \pgfpositionnodelaterminx {mtd@#1-minx}
\cs_gset_eq:Nc \pgfpositionnodelaterminy {mtd@#1-miny}
\cs_gset_eq:Nc \pgfpositionnodelatermaxx {mtd@#1-maxx}
\cs_gset_eq:Nc \pgfpositionnodelatermaxy {mtd@#1-maxy}
\box_gset_eq:Nc \pgfpositionnodelaterbox {mtd@#1-box}
\pgfpositionnodenow{#2}
}
% Provide Outer Modular diagram environment
% #1 = options to pass to tikz
\DeclareDocumentEnvironment{modulediagram}{D[]{}}
{
\begin{tikzpicture}[mtd-diagram,#1]
}
{
\end{tikzpicture}
}
% The specifier for a module that contains a number of ports
% #1 = outerbox styles
% #2 = innerbox styles
% #3 = outerbox name
% #4 = innerbox content
% #5 = port specifiers
\DeclareDocumentCommand \module {D[]{} D[]{} r() +m +m}{
\node[mtd-module-wrap,#1] (#3) {
\tikz[]{
% Initialize Local Variables
\def\currentmodulename{#3}
\tikzstyle{local-port-style}=[]
% Initialise Data Structures and the like to store ports
\seq_clear_new:c {#3-north-ports}
\seq_clear_new:c {#3-south-ports}
\seq_clear_new:c {#3-east-ports}
\seq_clear_new:c {#3-west-ports}
\seq_clear_new:c {#3-port-cleanup}
% Run port specifiers to store ports into relevant structures
#5
% Construct each side's portboxes and save into temporary scopes
\@placenodelater(#3-north-portbox){
\node[mtd-portbox-north](#3-portbox-north){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[remember~picture]{ \seq_use:cn {#3-north-ports}{;} }
};
}
\@placenodelater(#3-south-portbox){
\node[mtd-portbox-south](#3-portbox-south){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[]{ \seq_use:cn {#3-south-ports}{;} }
};
}
\@placenodelater(#3-east-portbox){
\node[mtd-portbox-east](#3-portbox-east){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[]{ \seq_use:cn {#3-east-ports}{;} }
};
}
\@placenodelater(#3-west-portbox){
\node[mtd-portbox-west](#3-portbox-west){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[]{ \seq_use:cn {#3-west-ports}{;} }
};
}
% Construct the central box using information on each portboxes's
% length and width
\pgfkeysgetvalue{/tikz/module~center~overrun}{\mtd@mco}
\pgfmathsetmacro{\mtd@centralwidth}
{max(\use:c{mtd@#3-north-portbox-width}
,\use:c{mtd@#3-south-portbox-width}) + \mtd@mco}
\pgfmathsetmacro{\mtd@centralheight}
{max(\use:c{mtd@#3-east-portbox-height}
,\use:c{mtd@#3-west-portbox-height}) + \mtd@mco}
\node[
,mtd-module-center
,minimum~width=\mtd@centralwidth
,minimum~height=\mtd@centralheight
,#2
](#3-center){#4};
% Place port boxes relative to the central box
\@placenodenow(#3-north-portbox){\pgfpointanchor{#3-center}{north}}
\@placenodenow(#3-south-portbox){\pgfpointanchor{#3-center}{south}}
\@placenodenow(#3-east-portbox){\pgfpointanchor{#3-center}{east}}
\@placenodenow(#3-west-portbox){\pgfpointanchor{#3-center}{west}}
% Active any cleanup code that's to be run after placement
\seq_use:cn {#3-port-cleanup}{}
}
};
}
% The command to create a fit module, which will be placed around a
% set of elements.
% #1 = Styles to be exported to every element inside the fitted module.
% Should not have position specifiers or anything that will 'draw' or
% 'fill' as those will be applied to everything from the top down.
% #2 = Styles to be exported to the innerfit box, meant for things like
% transperancies and borders. All other styles can be added in with the
% port specifiers using the local name information.
% #3 = Tikz elements to fit around
% #4 = Fit module name
% #5 = Label content
% #6 = port specifiers
\DeclareDocumentCommand \fittedmodule { D[]{} D[]{} r<> r() +m +m}{
% Set local variables
\def\currentmodulename{#4}
\tikzstyle{local-port-style}=[#1]
\tikzstyle{#4-label-style}=[]
% Gather elements to fit around into list
\seq_clear_new:c {#4-fit-elements}
\seq_set_from_clist:cn {#4-fit-elements} {#3}
% Initialise Data Structures and the like to store ports
\seq_clear_new:c {#4-north-ports}
\seq_clear_new:c {#4-south-ports}
\seq_clear_new:c {#4-east-ports}
\seq_clear_new:c {#4-west-ports}
\seq_clear_new:c {#4-port-cleanup}
% Run port specifiers to store ports into relevant structures
#6
% Place the inner fit node
\node[
,mtd-fit-innerfit
,fit=(\seq_use:cn {#4-fit-elements} {)(})
,#1
,#2
] (#4-innerfit){};
% Place the label above the inner fitted node
\node[
,mtd-fit-label
,parent-innerfit=#4-innerfit
,#1
,#4-label-style
](#4-label){#5};
% Construct each side's portboxes and save into temporary scopes
\@placenodelater(#4-north-portbox){
\node[mtd-fit-portbox-north](#4-portbox-north){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[#1]{ \seq_use:cn {#4-north-ports}{;} }
};
}
\@placenodelater(#4-south-portbox){
\node[mtd-fit-portbox-south](#4-portbox-south){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[#1]{ \seq_use:cn {#4-south-ports}{;} }
};
}
\@placenodelater(#4-east-portbox){
\node[mtd-fit-portbox-east](#4-portbox-east){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[#1]{ \seq_use:cn {#4-east-ports}{;} }
};
}
\@placenodelater(#4-west-portbox){
\node[mtd-fit-portbox-west](#4-portbox-west){
% Local variables
\let\prevnode\undefined
% Get all the ports from the list
\tikz[#1]{ \seq_use:cn {#4-west-ports}{;} }
};
}
% Construct the central box using information on each portboxes's
% length and width
\pgfkeysgetvalue{/tikz/module~center~overrun}{\mtd@mco}
\pgfmathsetmacro{\mtd@centralwidth}
{max(\use:c{mtd@#4-north-portbox-width}
,\use:c{mtd@#4-south-portbox-width}) + \mtd@mco}
\pgfmathsetmacro{\mtd@centralheight}
{max(\use:c{mtd@#4-east-portbox-height}
,\use:c{mtd@#4-west-portbox-height}) + \mtd@mco}
% Place the center
\node[
,mtd-fit-module-center
,fit=(#4-innerfit)(#4-label)
,minimum~width=\mtd@centralwidth
,minimum~height=\mtd@centralheight
,#1
](#4-center){};
% Place port boxes relative to the central box
\@placenodenow(#4-north-portbox){\pgfpointanchor{#4-center}{north}}
\@placenodenow(#4-south-portbox){\pgfpointanchor{#4-center}{south}}
\@placenodenow(#4-east-portbox){\pgfpointanchor{#4-center}{east}}
\@placenodenow(#4-west-portbox){\pgfpointanchor{#4-center}{west}}
% Active any cleanup code that's to be run after placement
\seq_use:cn {#4-port-cleanup}{}
% Place the module wrapper that we'll use for positioning mainly.
\node[
,mtd-fit-module-wrap
,fit=(#4-center)(#4-portbox-north)(#4-portbox-south)
(#4-portbox-east)(#4-portbox-west)
,#1
](#4){};
}
% The command to add a port to a module, should only work within
% a module's port specifier block.
% #1 = port styles
% #2 = position specifier
% #3 = port name
% #4 = port content
\DeclareDocumentCommand \port {D[]{} r<> r() +m}{
% Code that is run on the creation of a node
\seq_put_right:cn {\currentmodulename-#2-ports} {
% Add previous node info to current style data
\ifthenelse{\isundefined\prevnode}
{\tikzstyle{pp}=[]}
{\tikzstyle{pp}=[previous-port=\prevnode]}
% Generate Nod
\node[
,port-type=normal
,port-dir=#2
,local-port-style
,pp
,#1
] (#3) {#4};
% Bootstrap for next section,
\def\prevnode{#3}
% Generate Forward and Reverse "Pseudo-Anchors"
\ifthenelse{\equal{#2}{north}}{
\coordinate(#3-conn) at (#3.northconn);
\coordinate(#3-rear) at (#3.south);
}{}
\ifthenelse{\equal{#2}{south}}{
\coordinate(#3-conn) at (#3.southconn);
\coordinate(#3-rear) at (#3.north);
}{}
\ifthenelse{\equal{#2}{east}}{
\coordinate(#3-conn) at (#3.eastconn);
\coordinate(#3-rear) at (#3.west);
}{}
\ifthenelse{\equal{#2}{west}}{
\coordinate(#3-conn) at (#3.westconn);
\coordinate(#3-rear) at (#3.east);
}{}
}
% Code that is run after all the elements are placed.
\seq_put_left:co {\currentmodulename-port-cleanup}{
}
}
\ExplSyntaxOff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment