%% This is file 'prerex.sty'
%%
%% Copyright (C) 2006-08 R. D. Tennent, rdt@cs.queensu.ca
%% 
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
%% of this license or (at your option) any later version.
%% The latest version of this license is in
%%   http://www.latex-project.org/lppl.txt
%% and version 1.3 or later is part of all distributions of LaTeX
%% version 2003/12/01 or later.
%% 
%% This work has the LPPL maintenance status "author-maintained".
%
% Instructions supported inside  \begin{chart} ... \end{chart}:
%
%   \[req]{half|full}course x,y: {course code}{course title}{timetable code}  
%
%   \mini x,y: {course code}
%
%   solid arrow:  \prereq x0,y0,x1,y1:    \prereqc x0,y0,x1,y1;curvature:
%   dotted arrow: \coreq x0,y0,x1,y1:     \coreqc x0,y0,x1,y1;curvature:
%   dashed arrow: \recomm x0,y0,x1,y1:    \recommc x0,y0,x1,y1;curvature:
%
%   \text x,y: {line of text}
%
%   \grid      coordinate grid background
%
% Stand-alone instructions (for explanatory notes):
%
%   \solidarrow     in-line solid arrow
%   \dottedarrow    in-line dotted arrow
%   \dashedarrow    in-line dashed arrow
%
%   \lightbox  in-line light course box
%   \boldbox   in-line bold course box
%
% The following defaults are defined in prerex.sty 
% (but may be re-defined by the user):
%
%   \newcommand{\DefaultCurvature}{20}    
%
%     where the argument should be in the range 0-100; 0 means no curvature.
%
%   \newcommand{\CourseURL}[3]{file:#3.html}
%
%     where the arguments supplied at the call are the x and y coordinates
%     and the course code.
%
%   \newcommand{\background}{LightYellow}
%
%     where LightYellow is defined by 
%
%       \definecolor{LightYellow}{rgb}{1.0,1.0,0.878431} 
%
%   \setlength{\unit}{5.8pt} (the absolute size of a coordinate unit)
%   \setcounter{diagheight}{75}  but reduced to 65 in landscape mode
%   \newcommand{\solidwidth}{0.5pt}
%   \newcommand{\dottedwidth}{0.8pt}
%   \newcommand{\dashedwidth}{0.5pt}
%   \newcommand{\boldwidth}{1.0pt}
%
% The nominal diagram width is 10 + (\textwidth divided by \unit).
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{prerex}[2008/05/16 v4.1 LaTeX style for prerequisite charts, pgf version]

% Changelog:
%
%  Version 4.1
%
%  Version 4.0
%
%   Implement the \text command to place a line of text (centered at the coordinates) in a chart
%
%  Version 3.8.1:
%
%   adjust arraystretch factors to work with long-ascender fonts such as Futura
%   adjust inner sep parameters to work with oblique/italic fonts
%   remove workaround for pgf-1.10 bug described at
%      http://sourceforge.net/forum/forum.php?thread_id=1621660&forum_id=477363
%   require version 1.18 (or later) of pgf
%
%  Version 3.8:
%
%    require version 1.10 (or later) of pgf
%
%  Version 3.7:
%
%    anchor nodes must be non-null for latex/dvips
%
%  Version 3.6:
%
%    first pgf-based version
%
%  Version 3.5:
%  Version 3.4:
%
%    introduce arrow borders to improve the appearance of crossing arrows
%    change default widths to artifacts created when arrow borders 
%      occlude box boundaries
%
%  Version 3.3:
%
%    arrows (as well as course boxes and minis) are hyperlinked with coordinate URIs
%
%  Version 3.2:
%
%  Version 3.1:
%
%  Version 3.0:
%
%   "anchor" hyperlinks are added to coordinate grid to allow computation of
%      chart coordinates at mouse clicks 
%
%  Version 2.0:
%
%    CourseURL now takes 3 arguments
%    box/mini coordinates displayed in (some) PDF viewers when grid on
%
%  Version 1.0.2:
%
%    using \relsize{-3} rather than \scriptsize
%    using \textsf in \lightbox and \boldbox
%
%  Version 1.0.1:
%
%    using \RequirePackage rather than \usepackage (suggested by Herbert Voss)
%
\newlength{\unit}
\newlength{\@unitmult}

\setlength{\unit}{5.8pt}

\RequirePackage{relsize}
\RequirePackage{calc}
\RequirePackage{pgf}[2006/10/11] 
\RequirePackage{tikz}
\usetikzlibrary{arrows}
\RequirePackage{ifthen}
\RequirePackage{multido}
\PassOptionsToPackage{urlcolor=black,colorlinks}{hyperref}
\RequirePackage{hyperref}
\RequirePackage{textcomp}


\definecolor{light}{gray}{0.5}
\definecolor{somewhatlight}{gray}{0.7}
\definecolor{verylight}{gray}{0.85}
\definecolor{white}{rgb}{1.0,1.0,1.0} % not transparent, hides grid
\definecolor{LightYellow}{rgb}{1.0,1.0,0.878431} 

\newcommand{\DefaultCurvature}{20} % 0 for no curvature
\newcommand{\CourseURL}[3]{file:#3.html}
\newcommand{\background}{LightYellow}

\newcommand{\solidwidth}{0.5pt}
\newcommand{\boldwidth}{1.0pt}
\newcommand{\dottedwidth}{0.8pt}
\newcommand{\dashedwidth}{0.5pt}

\newcounter{@myangle}
\newcounter{@inangle}
\newcounter{@dx}
\newcounter{@dy}

\newif\ifgridon
\gridonfalse
\newcounter{@gridwidth}
\newcounter{@gridright}
\newcounter{@gridheight}
\newcounter{@gridtop}

\newcounter{@diagwidth}
\newcounter{diagheight}


\setcounter{diagheight}{75}
\ifdim\paperwidth>\paperheight
  \setcounter{diagheight}{65}
\fi

\def\@halfcourse#1,#2:#3#4#5{%
\node[draw,thin,fill=\background,rounded corners=2pt](x#1y#2) at (#1,#2)%
{\textsf{%
\let\savearraystretch=\arraystretch%
\renewcommand{\arraystretch}{0.8}%
\href{\CourseURL{#1}{#2}{#3}}{\begin{tabular}{@{\hspace{1pt}}c@{\hspace{1pt}}}%
\mbox{\relsize{-3}#3}\,\hfill\,\mbox{\relsize{-3}#5}\\ #4%
\end{tabular}}}%
\let\arraystretch=\savearraystretch%
};%
}

\def\@reqhalfcourse#1,#2:#3#4#5{%
\node[draw,line width=\boldwidth,fill=\background,rounded corners=2pt](x#1y#2) at (#1,#2)%
{\textsf{\textbf{%
\let\savearraystretch=\arraystretch%
\renewcommand{\arraystretch}{0.8}%
\href{\CourseURL{#1}{#2}{#3}}{\begin{tabular}{@{\hspace{1pt}}c@{\hspace{1pt}}}%
\mbox{\relsize{-3}#3}\,\hfill\,\mbox{\relsize{-3}#5}\\ #4%
\end{tabular}}}%
\let\arraystretch=\savearraystretch%
}};%
}

\def\@fullcourse#1,#2:#3#4#5{%
\node[draw,thin,fill=\background,rounded corners=2pt](x#1y#2) at (#1,#2)%
{\textsf{%
\let\savearraystretch=\arraystretch%
\renewcommand{\arraystretch}{1.7}%
\href{\CourseURL{#1}{#2}{#3}}{\begin{tabular}{@{\hspace{1pt}}c@{\hspace{1pt}}}%
\mbox{\relsize{-3}#3}\,\hfill\,\mbox{\relsize{-3}#5}\\ #4%
\end{tabular}}}%
\let\arraystretch=\savearraystretch%
};%
}


\def\@reqfullcourse#1,#2:#3#4#5{%
\node[draw,line width=\boldwidth,fill=\background,rounded corners=2pt](x#1y#2) at (#1,#2)%
{\textsf{\textbf{%
\let\savearraystretch=\arraystretch%
\renewcommand{\arraystretch}{1.7}%
\href{\CourseURL{#1}{#2}{#3}}{\begin{tabular}{@{\hspace{1pt}}c@{\hspace{1pt}}}%
\mbox{\relsize{-3}#3}\,\hfill\,\mbox{\relsize{-3}#5}\\ #4%
\end{tabular}}}}%
\let\arraystretch=\savearraystretch%
};%
}


\def\@mini#1,#2:#3{%
\node[fill=white,inner sep=2pt,draw=white](x#1y#2) at (#1,#2)%
{\textsf{%
\href{\CourseURL{#1}{#2}{#3}}{%
\mbox{\relsize{-3}#3}}}};%
}

\def\@text#1,#2:#3{%
% include coordinates if grid on, but don't hyperlink if grid off
\ifgridon
  \node[fill=white,inner sep=2pt,draw=white](x#1y#2) at (#1,#2)%
{\href{coord: #1,#2}{\mbox{#3}}};%
\else
  \node[fill=white,inner sep=2pt,draw=white](x#1y#2) at (#1,#2){\mbox{#3}};%
\fi
}

\def\@prereq#1,#2,#3,#4:{%
  \setcounter{@dy}{#2-#4}
  \ifnum\the@dy<10 
    \@straight#1,#2,#3,#4:
  \else\ifnum#1=#3 
    \@straight#1,#2,#3,#4:
  \else\ifnum#2=#4 
    \@straight#1,#2,#3,#4:
  \else
    \@prereqc#1,#2,#3,#4;\DefaultCurvature:
  \fi\fi\fi
}

\def\@prereqc#1,#2,#3,#4;#5:{%
  \ifnum#5=0 
    \@straight#1,#2,#3,#4:
  \else
    \@curved#1,#2,#3,#4;#5:
  \fi
} 

\def\@recomm#1,#2,#3,#4:{%
  \setcounter{@dy}{#2-#4}
  \ifnum\the@dy<10 
    \@straightDashed#1,#2,#3,#4:
  \else\ifnum#1=#3 
    \@straightDashed#1,#2,#3,#4:
  \else\ifnum#2=#4 
    \@straightDashed#1,#2,#3,#4:
  \else
    \@recommc#1,#2,#3,#4;\DefaultCurvature:
  \fi\fi\fi
}

\def\@recommc#1,#2,#3,#4;#5:{%
  \ifnum#5=0 
    \@straightDashed#1,#2,#3,#4:
  \else
    \@curvedDashed#1,#2,#3,#4;#5:
  \fi
} 

\def\@coreq#1,#2,#3,#4:{%
  \setcounter{@dy}{#2-#4}
  \ifnum\the@dy<10 
    \@straightDotted#1,#2,#3,#4:
  \else\ifnum#1=#3 
    \@straightDotted#1,#2,#3,#4:
  \else\ifnum#2=#4 
    \@straightDotted#1,#2,#3,#4:
  \else
    \@coreqc#1,#2,#3,#4;\DefaultCurvature:
  \fi\fi\fi
}

\def\@coreqc#1,#2,#3,#4;#5:{%
  \ifnum#5=0 
    \@straightDotted#1,#2,#3,#4:
  \else
    \@curvedDotted#1,#2,#3,#4;#5:
  \fi
} 


\def\@grid{
  \gridontrue
  \renewcommand{\CourseURL}[3]{coord: ##1,##2} % "coord:" makes it look like a URI
  \setcounter{@gridwidth}{(\the@diagwidth-5) / 10}
  \setcounter{@gridright}{10 * \value{@gridwidth}}
  \setcounter{@gridheight}{\thediagheight / 10}
  \setcounter{@gridtop}{10 * \value{@gridheight} }
  \setlength{\@unitmult}{\unit * 5}

   \multido{\i = 0 + 1}{\value{@gridright}}
     {\draw[line width=0.3pt,draw=verylight] (\i,0) -- (\i,\value{@gridtop});}
   
   \draw[line width=0.3pt,draw=verylight] (\value{@gridright},0) -- (\value{@gridright},\value{@gridtop});
 
   \multido{\i = 0 + 1}{\value{@gridtop}}
     {\draw[line width=0.3pt,draw=verylight] (0,\i) -- (\value{@gridright},\i);}
 
   \draw[line width=0.3pt,draw=verylight] (0,\value{@gridtop}) -- (\value{@gridright},\value{@gridtop});
     
    \multido{\i = 0 + 10}{\value{@gridwidth}}
      {\node at (\i,-4){\mbox{\textsf{\small \i}}};}

    \node at (\the@gridright,-4){\mbox{\textsf{\small\the@gridright}}} ;
  
    \multido{\i = 0 + 10}{\value{@gridheight}}
      {\node at (-5,\i){\mbox{\textsf{\small \i}}};}

    \node at (-5,\the@gridtop){\mbox{\textsf{\small\the@gridtop}}};
 
    \setcounter{@gridtop}{\value{@gridtop} + 4}
    \multido{\i = 0 + 10}{\value{@gridwidth}}
      {\node at (\i,\value{@gridtop}){\mbox{\textsf{\small \i}}};}

    \node at (\the@gridright,\the@gridtop){\mbox{\textsf{\small\the@gridright}}} ;
 
    \setcounter{@gridright}{\value{@gridright} + 5}
    \multido{\i = 0 + 10}{\value{@gridheight}}
      {\node at (\value{@gridright},\i){\mbox{\textsf{\small \i}}};}

    % anchors are to allow computation of coordinates from mouse clicks:

    \node at (\the@gridright,\the@gridtop) {\href{anchor: \the@gridright,\the@gridtop}{\kern1sp}};  % latex/dvips requires non-null href box
    \node at (-5,-4) {\href{anchor: -5,-4}{\kern1sp}};

    \setcounter{@gridtop}{\value{@gridtop} - 4}
    \node at (\the@gridright,\the@gridtop){\mbox{\textsf{\small\the@gridtop}}};
 
    \setcounter{@gridwidth}{2 * \value{@gridwidth}}
    \setcounter{@gridheight}{2 * \value{@gridheight}}
    \multido{\i = 0 + 1}{\value{@gridwidth}}
      {\draw[x=\@unitmult,y=\@unitmult,line width=0.4pt,draw=somewhatlight] (\i,0) -- (\i,\value{@gridheight});}
 
     \draw[x=\@unitmult,y=\@unitmult,line width=0.4pt,draw=somewhatlight] (\value{@gridwidth},0) -- (\value{@gridwidth},\value{@gridheight});
  
    \multido{\i = 0 + 1}{\value{@gridheight}}
      {\draw[x=\@unitmult,y=\@unitmult,line width=0.4pt,draw=somewhatlight] (0,\i) -- (\value{@gridwidth},\i);}
 
    \draw[x=\@unitmult,y=\@unitmult,line width=0.4pt,draw=somewhatlight] (0,\value{@gridheight}) -- (\value{@gridwidth},\value{@gridheight});

}

\newenvironment{chart}
{ \setcounter{@diagwidth}{10 + 1 * \ratio{\textwidth}{\unit}}
  \let\halfcourse=\@halfcourse
  \let\reqhalfcourse=\@reqhalfcourse
  \let\fullcourse=\@fullcourse
  \let\reqfullcourse=\@reqfullcourse
  \let\mini=\@mini
  \let\text=\@text
  \let\prereq=\@prereq
  \let\prereqc=\@prereqc
  \let\coreq=\@coreq
  \let\coreqc=\@coreqc   
  \let\recomm=\@recomm
  \let\recommc=\@recommc
  \let\grid=\@grid
  \begin{tikzpicture}[x=\unit,y=\unit]
  \tikzstyle{every rectangle node}=[inner xsep=1.8pt,inner ysep=0.5pt]
  \setcounter{@gridwidth}{(\the@diagwidth-5) / 10}
  \setcounter{@gridright}{10 * \value{@gridwidth}}
  \setcounter{@gridheight}{\thediagheight / 10}
  \setcounter{@gridtop}{10 * \value{@gridheight} }
  \useasboundingbox (0,-2) rectangle (\value{@gridright},\value{@gridtop});
}
{ 
  \end{tikzpicture}
}

\def\@straight#1,#2,#3,#4:{%
\ifgridon
  \draw[draw=white,line width=1.5pt](x#1y#2) -- (x#3y#4) node[midway] {\href{coord: #1,#2,#3,#4}{\quad}};
\else
  \draw[draw=white,line width=1.5pt](x#1y#2) -- (x#3y#4) ;
\fi
  \draw[-latex',draw=white,very thin](x#1y#2) -- (x#3y#4) ;
  \draw[line width=\solidwidth](x#1y#2) -- (x#3y#4) ;
}


\def\@curved#1,#2,#3,#4;#5:{

  \ifnum#3<#1 
    \setcounter{@dx}{#1-#3}
    \setcounter{@myangle}{(-#5) * \the@dx * \the@dy * 2}
  \else 
    \setcounter{@dx}{#3-#1}
    \setcounter{@myangle}{#5 * \the@dx * \the@dy * 2}
  \fi
  \setcounter{@myangle}{\the@myangle / ((\the@dx + \the@dy) * (\the@dx + \the@dy))}
  \setcounter{@inangle}{180 - \the@myangle}
  \ifgridon
    \draw[draw=white,line width=1.5pt](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) node[midway] {\href{coord: #1,#2,#3,#4}{\quad}} ;
  \else
    \draw[draw=white,line width=1.5pt](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
  \fi
  \draw[-latex',draw=white,very thin](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
  \draw[line width=\solidwidth](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
}

\def\@straightDashed#1,#2,#3,#4:{%
\ifgridon
  \draw[draw=white,line width=1.5pt] (x#1y#2) -- (x#3y#4) node[midway] {\href{coord: #1,#2,#3,#4}{\quad}};
\else
  \draw[draw=white,line width=1.5pt] (x#1y#2) -- (x#3y#4);
\fi
\draw[-latex',draw=white,very thin] (x#1y#2) -- (x#3y#4);
\draw[dashed,line width=\dashedwidth] (x#1y#2) -- (x#3y#4);
}

\def\@curvedDashed#1,#2,#3,#4;#5:{
  \ifnum#3<#1 
    \setcounter{@dx}{#1-#3}
    \setcounter{@myangle}{(-#5) * \the@dx * \the@dy * 2}
  \else 
    \setcounter{@dx}{#3-#1}
    \setcounter{@myangle}{#5 * \the@dx * \the@dy * 2}
  \fi
  \setcounter{@myangle}{\the@myangle / ((\the@dx + \the@dy) * (\the@dx + \the@dy))}
  \setcounter{@inangle}{180 - \the@myangle}
  \ifgridon
    \draw[draw=white,line width=1.5pt](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) node[midway] {\href{coord: #1,#2,#3,#4}{\quad}} ;
  \else
    \draw[draw=white,line width=1.5pt](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
  \fi
  \draw[-latex',draw=white,very thin](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
  \draw[dashed,line width=\dashedwidth](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
}

\def\@straightDotted#1,#2,#3,#4:{%
\ifgridon
  \draw[draw=white,line width=1.5pt] (x#1y#2) -- (x#3y#4) node[midway] {\href{coord: #1,#2,#3,#4}{\quad}};
\else
  \draw[draw=white,line width=1.5pt] (x#1y#2) -- (x#3y#4);
\fi
\draw[-latex',draw=white,very thin] (x#1y#2) -- (x#3y#4);
\draw[loosely dotted,line width=\dottedwidth] (x#1y#2) -- (x#3y#4);
}

\def\@curvedDotted#1,#2,#3,#4;#5:{
  \ifnum#3<#1 
    \setcounter{@dx}{#1-#3}
    \setcounter{@myangle}{(-#5) * \the@dx * \the@dy * 2}
  \else 
    \setcounter{@dx}{#3-#1}
    \setcounter{@myangle}{#5 * \the@dx * \the@dy * 2}
  \fi
  \setcounter{@myangle}{\the@myangle / ((\the@dx + \the@dy) * (\the@dx + \the@dy))}
  \setcounter{@inangle}{180 - \the@myangle}
  \ifgridon
    \draw[draw=white,line width=1.5pt](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) node[midway] {\href{coord: #1,#2,#3,#4}{\quad}} ;
  \else
    \draw[draw=white,line width=1.5pt](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
  \fi
  \draw[-latex',draw=white,very thin](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
  \draw[loosely dotted,line width=\dottedwidth](x#1y#2) to[out=\the@myangle,in=\the@inangle,relative] (x#3y#4) ;
}

\def\solidarrow{%
\tikz[x=\unit,y=\unit,baseline=-0.5ex]
\draw[-latex',line width =\solidwidth] (0,0) -- (4,0);
}

\def\dottedarrow{%
\tikz[x=\unit,y=\unit,baseline=-0.5ex]
\draw[loosely dotted,line width=\dottedwidth,-latex'] (0,0) -- (4,0);
}

\def\dashedarrow{%
\tikz[x=\unit,y=\unit,baseline=-0.5ex]
\draw[dashed,line width=\dashedwidth,-latex'] (0,0) -- (4,0);
}

\def\lightbox{%
\tikz[thin,baseline=-0.5ex]\node[draw,fill=\background,rounded corners=2pt,inner sep=1.8pt] 
{\textsf{light}};}

\def\boldbox{%
\tikz[baseline=-0.65ex]\node[draw,line width=\boldwidth,fill=\background,rounded corners=2pt,inner sep=2.0pt] 
{\textsf{\textbf{bold}}};}

