meta-nod.mkiv / last modification: 2020-01-30 14:16
%D \module
%D   [       file=meta-nod,
%D        version=2016.11.23,
%D          title=\METAPOST\ Graphics,
%D       subtitle=Nodes,
%D         author={Alan Braslau and Hans Hagen},
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\registerctxluafile{meta-nod}{}

\unprotect

\defineMPinstance
  [nodes]
  [\s!format=metafun,
   \s!extensions=\v!yes,
   \s!initializations=\v!yes,
   \c!method=\s!double]

\defineframed
  [node]
  [\c!frame=\v!off]

\defineframed
  [smallnode]
  [node]
  [\c!foregroundstyle=\small]

% \startMPdefinitions{nodes}
%     loadmodule "node" ;
% \stopMPdefinitions

\protect

%D This module provides a simple \TEX\ layer on top of the nodes library that
%D is preloaded in \METAFUN. More information can be found in the manual and
%D article.
%D
%D We strongly advice to use the \METAPOST\ interface and only provide this
%D \TEX\ variant as proof of concept. There are no plans to extend this module
%D because we see no advantage in using a \TEX\ interface over a \METAPOST\
%D one.
%D
%D \startbuffer
%D \startnodes
%D    \placenode[0,0]{A}
%D    \placenode[1,0]{B}
%D    \connectnodes [0,1] [option=doublearrow]
%D \stopnodes
%D
%D \startnodes[dx=2cm,rotation=45]
%D    \placenode[0,0]{A}
%D    \placenode[1,0]{B}
%D    \placenode[1,1]{C}
%D    \placenode[0,1]{D}
%D    \connectnodes [0,2] [option=doublearrow,label=a,offset=.05]
%D    \connectnodes [1,3] [option=doublearrows]
%D \stopnodes
%D
%D \startnodes[dx=2cm,dy=2cm]
%D    \nodeMPcode{ahlength  := 12pt ; ahangle := 30 ; ahvariant := 1 ;}
%D    \mpcode{ahlength  := 12pt ; ahangle := 30 ; ahvariant := 1 ;}
%D    \placenode[0,1]{\node{A}}
%D    \placenode[1,1]{\node{B}}
%D    \placenode[0,0]{\node{C}}
%D    \placenode[1,0]{\node{D}}
%D    \connectnodes [0,3] [option=arrow,label={ }]
%D    \connectnodes [1,2] [option=arrow]
%D \stopnodes
%D \stopbuffer
%D
%D \typebuffer
%D
%D \startlinecorrection \getbuffer \stoplinecorrection

\unprotect

\installcorenamespace{metanodes}
\installcorenamespace{metanodesoption}
\installcorenamespace{metanodesalternative}
\installcorenamespace{metanodesposition}

% todo: maybe instances

\installparameterhandler \??metanodes {metanodes}
\installsetuphandler     \??metanodes {metanodes}

\setupmetanodes
  [\c!option        =,
   \c!alternative   =,
   \c!offset        =0,
   \c!position      =,
   \c!label         =,
   \c!dx            =2\emwidth,
   \c!dy            =2\emwidth,
   \c!rotation      =90,
   \c!rulethickness =.5pt,
   \c!command       =]

\newtoks\t_every_meta_nodes
\newtoks\t_meta_nodes

\let\stopnodes\relax

%D Hm, we started out simple but it now quickly becomes the usual mess of
%D \TEX, \METAPOST\ and \LUA. Hard to understand.

\newcount\c_meta_nodes_n

\unexpanded\def\startnodes
  {\dosingleempty\meta_nodes_start}

\def\meta_nodes_start[#1]#2\stopnodes
  {\hpack\bgroup
   \iffirstargument
     \setupcurrentmetanodes[#1]%
   \fi
   \edef\p_meta_option{\metanodesparameter\c!option}%
   \edef\p_meta_alternative{\metanodesparameter\c!alternative}%
   \the\t_every_meta_nodes
   \c_meta_nodes_n\zerocount
   \t_meta_nodes\emptytoks
   #2\removeunwantedspaces
   % for alan, will be commented:
   \writestatus{metanodes}{\detokenize\expandafter{\the\t_meta_nodes}}%
   \clf_grph_nodes_initialize
   \startMPcode
     mfun_node_init(%
        \the\dimexpr\metanodesparameter\c!dx\relax,%
        \the\dimexpr\metanodesparameter\c!dy\relax,%
        \metanodesparameter\c!rotation%
     ) ;
     \the\t_meta_nodes ;
     mfun_node_flush ;
   \stopMPcode
   \clf_grph_nodes_reset
   \egroup}

\unexpanded\def\grph_nodes_node
  {\dodoubleempty\grph_nodes_node_two}

\def\grph_nodes_node_two[#1][#2]%
  {\grph_nodes_node_two_indeed[#1][#2]}

\def\grph_nodes_node_two_indeed[#1,#2][#3]#4%
  {\begingroup
   \ifsecondargument
     \setupcurrentmetanodes[#3]%
   \fi
   \edef\p_label{#4}%
   \edef\p_reference{\metanodesparameter\c!reference}%
   \ifx\p_reference\empty\else
      \clf_grph_nodes_register{\p_reference}\c_meta_nodes_n\relax
   \fi
   \normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{%
     mfun_node_make(\number#1,\number#2%
       \ifx\p_label\empty
         ,""%
       \else
         ,"\metanodesparameter\c!command{\p_label}"%
       \fi
     );%
   }}%
   \advance\c_meta_nodes_n\plusone}

\appendtoks
   \let\placenode\grph_nodes_node
\to \t_every_meta_nodes

\unexpanded\def\grph_nodes_fromto
  {\dodoubleempty\grph_nodes_fromto_two}

\def\grph_nodes_fromto_two[#1][#2]%
  {\grph_nodes_fromto_two_indeed[#1][#2]}% get rid of {n,m}

\letvalue{\??metanodesposition            }\empty
\setvalue{\??metanodesposition         top}{.top}
\setvalue{\??metanodesposition      bottom}{.bot}
\setvalue{\??metanodesposition        left}{.lft}
\setvalue{\??metanodesposition       right}{.rt}
\setvalue{\??metanodesposition   upperleft}{.ulft}
\setvalue{\??metanodesposition     topleft}{.ulft}
\setvalue{\??metanodesposition     lefttop}{.ulft}
\setvalue{\??metanodesposition  upperright}{.urt}
\setvalue{\??metanodesposition    topright}{.urt}
\setvalue{\??metanodesposition    righttop}{.urt}
\setvalue{\??metanodesposition   lowerleft}{.llft}
\setvalue{\??metanodesposition  bottomleft}{.llft}
\setvalue{\??metanodesposition  leftbottom}{.llft}
\setvalue{\??metanodesposition  lowerright}{.lrt}
\setvalue{\??metanodesposition bottomright}{.lrt}
\setvalue{\??metanodesposition rightbottom}{.lrt}

\def\grph_nodes_fromto_two_indeed[#1,#2][#3]% we can't group because etoksapp doesn't like that
  {\begingroup
   \ifsecondargument
     \setupcurrentmetanodes[#3]%
   \fi
   \edef\p_label        {\metanodesparameter\c!label}%
   \edef\p_rulethickness{\metanodesparameter\c!rulethickness}%
   \edef\p_command      {\metanodesparameter\c!command}% better get an error early
   \normalexpanded{\endgroup\noexpand\etoksapp\t_meta_nodes{%
     \ifcsname\??metanodesalternative\metanodesparameter\c!alternative\endcsname
       \lastnamedcs
     \else
       \csname\??metanodesalternative\endcsname
     \fi
     \space
     mfun_nodes_fromto\begincsname\??metanodesposition\metanodesparameter\c!position\endcsname(%
       \metanodesparameter\c!offset,%
     % \number#1,\number#2%
       \clf_grph_nodes_resolve{#1},\clf_grph_nodes_resolve{#2}%
       \ifx\p_label\empty
         ,""%
       \else
         ,"\ifx\p_command\empty\p_label\else\p_command{\p_label}\fi"%
       \fi
     )%
     \space
     \ifcsname\??metanodesoption\metanodesparameter\c!option\endcsname
       \lastnamedcs
     \else
       \csname\??metanodesoption\endcsname
     \fi
     \space
     \ifx\p_rulethickness\empty \else
       withpen pencircle scaled \the\dimexpr\p_rulethickness\relax
     \fi
     ;%
   }}}

\setvalue{\??metanodesalternative             }{draw}
\setvalue{\??metanodesalternative        arrow}{drawarrow}
\setvalue{\??metanodesalternative  doublearrow}{drawdblarrow}
\setvalue{\??metanodesalternative doublearrows}{drawdoublearrows}

\setvalue{\??metanodesoption                  }{}
\setvalue{\??metanodesoption            dashed}{dashed evenly}
\setvalue{\??metanodesoption            dotted}{dashed withdots scaled .5}

\appendtoks
   \let\connectnodes\grph_nodes_fromto
\to \t_every_meta_nodes

\unexpanded\def\grph_nodes_code#1%
  {\etoksapp\t_meta_nodes{#1}}

\appendtoks
   \let\nodeMPcode\grph_nodes_code
   \let\mpcode\grph_nodes_code
\to \t_every_meta_nodes

\protect \endinput