% erdiagram.sty
%
% A very basic set of macros that in a tikz environment can be 
% used to produce ER and EER diagrams
%
% Author: Peter McBrien, pjm@ic.ac.uk
% Release: 0.01 20th November 2022
%
\ProvidesPackage{erdiagram}
\usepackage{tikz}
\usepackage{xstring}
\usepackage{soul}

\usetikzlibrary{fit}
\usetikzlibrary{shapes}
\usetikzlibrary{arrows}
\usetikzlibrary{positioning}
\usetikzlibrary{backgrounds}
\usetikzlibrary{calc}

\pgfmathsetmacro{\hexRadiusScale}{1/cos(30)}
\pgfmathsetmacro{\subclassxshift}{3.5em}
\pgfmathsetmacro{\subclassyshift}{1.8em}
\pgfmathsetmacro{\erattributeoffset}{1em}
\pgfmathsetmacro{\erhalfattributespace}{0.6em}
\pgfmathsetmacro{\erattributespace}{1.2em}

% Few utility macros
\def\keyname#1{\setuldepth{a}\ul{#1}} % needs soul package
\def\putbox(#1,#2)(#3,#4)#5{\put(#1,#2){\makebox(#3,#4){\shortstack{#5}}}}

% Define the arm and angle options
\def\myarm{5em}
\def\myangle{0}
\tikzset{
  arm/.default=0em,
  arm/.code={\def\myarm{#1}}, % store value in \myarm
  angle/.default=0,
  angle/.code={\def\myangle{#1}} % store value in \myangle
}

% Define the dogleg to path
\tikzset{
    dogleg/.style = {to path={
        % We need to calculate a couple of coordinates to help us draw
        % the path. 
        let
            % Same as (\tikztotarget)++(\myangle:\myarm)
            \p1=($(\tikztotarget)+(\myangle:\myarm)$)
        in
            -- ++(\myangle:\myarm) coordinate (tmp)
            % Find the projection of the (tmp) coordinate
            % on the line from the target to p1
            -- ($(\tikztotarget)!(tmp)!(\p1)$)
            -- (\tikztotarget)\tikztonodes
    }}
}

\tikzset{
  er diagram/.style={
    background rectangle/.style={fill=er},
    show background rectangle,
    %xshift=-1em,
    %yshift=-3em,
    very thick,
    draw=black,
    node distance=2em,
    minimum width=1.5em,
    minimum height=1.5em,
    font=\sffamily,
    %on grid,
    >=stealth',
    entity/.style={
      rectangle,
      draw,
      text width=6em,
      align=center,
      minimum height=3em,
      fill=white
    },
    subclassentity/.style={
      entity,
      node distance=1em
    },
    weakentity/.style={
      entity,
      double distance=0.2em
    },
    junction/.style={
      inner ysep=0em,
      inner xsep=0em,
      minimum width=0.4pt,
      minimum height=0.4pt,
      fill=black,
      draw=black,
      rectangle
    },
    attribute/.style={
      inner ysep=0em,
      inner xsep=0em,
      minimum width=1em,
      node distance=3em
    },
    hexagon/.style={
      regular polygon,
      regular polygon sides=6
    },
    generalisation/.style={
      chamfered rectangle,
      chamfered rectangle xsep=2.5em, 
      minimum height=1.5em,
      minimum width=5em,
      node distance=2em,
      draw,
      fill=generalisation
    },
    relationship/.style={
      diamond,
      aspect=2, 
      draw,
      text width=3em,
      align=center,
      fill=relationship
    },
    isa/.style={
      ->,
      draw
    },
    subclasshorizontal/.style={
      rectangle,
      text width=6em,
      minimum height=0em,
      draw,
      opacity=0.5,
      fill=none
    },
    subclassvertical/.style={
      rectangle,
      text width=0em,
      minimum width=0em,
      minimum height=3em,
      draw,
      opacity=0.5,
      fill=none
    },
    empty/.style={
      rectangle,
      text width=6em,
      minimum height=3em,
      draw,
      opacity=0.5,
      fill=none
    }
  }
}

%\newlength{erhalfattributespace}
%\def\erhalfattributespace{0.6em}
\colorlet{er}{yellow!80!white}
\colorlet{bader}{orange!80!white}

\colorlet{entity}{yellow!80!white}
\colorlet{attribute}{white}
\colorlet{relationship}{white}
\colorlet{weakentity}{yellow!80!white}
\colorlet{generalisation}{white}
%\StrSubstitute{#1}{\\}{ }[\lab]
%\def\ertikzlabel#1{\saveexpandmode\noexpandarg
%\StrSubstitute{#1}{\_}{ }[\lab]
%\restoreexpandmode\lab}
%\def\ertikzlabel#1{#1}
%\def\ertikzlabel#1{\saveexpandmode\noexpandarg\StrSubstitute{#1}{\\}{ }[\lab]{\lab}}

% All the string manipulation needs the xstring package
\def\erentity[#1]#2{\saveexpandmode\noexpandarg\StrSubstitute{#2}{\\}{ }[\lab]
\node[entity] (\lab) [#1] {#2}}

\def\erweakentity[#1]#2{\saveexpandmode\noexpandarg\StrSubstitute{#2}{\\}{ }[\lab]
\node[weakentity] (\lab) [#1] {#2}}

\def\errelationship[#1]#2{\saveexpandmode\noexpandarg\StrSubstitute{#2}{\\}{ }[\lab]
\node[relationship] (\lab) [#1] {\begin{picture}(0,0)
\putbox(0,0)(0,0){\shortstack[c]{#2}}\end{picture}}}

\def\erisa#1#2{\path[isa] (#1) edge (#2)}

\def\erinvolvement#1#2#3#4{\path[] (#1) edge node[pos=0.5,#4] {#3} (#2)}

\def\erscaffoldnode#1#2#3{\node[node distance=0em,minimum width=1em,minimum height=1em] (#2) [#3=of #1] {}}
%
\def\erattributemodified[#1]#2#3#4#5{\StrSubstitute{#3}{\_}{ }[\erlab]\node[node distance=1.5em,minimum width=0em,minimum height=0em,inner sep=0.25em,fill=white,draw=black,circle] (\erlab) [#1,label={[label distance=0em]#4:#5}] {} edge [-] (#2)}

\def\erattribute[#1]#2#3#4{\erattributemodified[#1]{#2}{#3}{#4}{#3}}

\def\eroptionalattribute[#1]#2#3#4{\erattributemodified[#1]{#2}{#3}{#4}{#3?}}

\def\eroptionalmultiattribute[#1]#2#3#4{\erattributemodified[#1]{#2}{#3}{#4}{#3*}}

\def\ermultiattribute[#1]#2#3#4{\erattributemodified[#1]{#2}{#3}{#4}{#3+}}

\def\erkeyattribute[#1]#2#3#4{\erattributemodified[#1]{#2}{#3}{#4}{\keyname{#3}}}

\def\ergeneralisation[#1]#2#3{\node[generalisation] (#2 #3) [#1] {#3} edge [->] (#2)}
