2

I am trying to construct an entity relationship diagram using TikZ. I have used this excellent answer given by Mark Wibrow. However, I would prefer that the entity name is given within the matrix, with a line dividing it from its properties, rather than as a label above the matrix.

I had the idea that I ought to be trying to programmatically insert a header row at the beginning of the matrix instead of setting the label text, but I have no idea how to do this. I've spent a while reading various parts of the PGF/TikZ manual and experimenting with the code, but I can't find anything helpful, and at the moment I find PGF/TikZ quite bewildering.

I worked out that I can use row 1/.style in the entity/.code \tikzset command to address the first row. I tried to use row 1/.style={node contents={#1}} to set the text in it, but I guess this gets overwritten later on when the \properties command is used.

So here is the code from the other answer:

\documentclass[a4paper]{article} 
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    entity/.code={
        \tikzset{
            label={#1},
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white
        }%
        \def\entityname{#1}%

    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}
\begin{tikzpicture}
\matrix [entity=articles] {
    \properties{
        classkey, 
        class_type,
        class_desc
    }
};
\end{tikzpicture}

\end{document}

Which produces:

Instead I'd like to have something like this:

Bernard
  • 271,350
MJeffryes
  • 123

1 Answers1

3

In this very example, you could do an almost trivial surgery. Since the dimensions of these thingies are fixed, all you have to do is to draw the boundary of the label node and use the same dimensions as the ones of the property nodes. In more detail, all I did was to replace

 label={#1},

by

label={[text width=1in,draw,inner xsep=0.25cm,yshift=-\pgflinewidth]#1},

If you want this text centered, do

label={[text width=1in,draw,inner xsep=0.25cm,yshift=-\pgflinewidth,align=center]#1},

Whether or not I necessarily recommend to go this way is a different question.

\documentclass[a4paper]{article} 
\usepackage{tikz}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{matrix}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows}
\usetikzlibrary{calc}

\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    entity/.code={
        \tikzset{
            label={[text width=1in,draw,inner xsep=0.25cm,yshift=-\pgflinewidth]#1},
            name=#1,
            inner sep=0pt,
            every entity/.try,
            fill=white
        }%
        \def\entityname{#1}%

    },
    entity anchor/.style={matrix anchor=#1.center},
    every entity/.style={
            draw,
    },
    every property/.style={
        inner xsep=0.25cm, inner ysep=0.125cm, anchor=west, text width=1in
    },
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}
\def\property#1{\node[name=\entityname-#1, every property/.try]{#1};}
\def\properties{\begingroup\catcode`\_=11\relax\processproperties}
\def\processproperties#1{\endgroup%
    \def\propertycode{}%
    \foreach \p in {#1}{%
        \expandafter\expandafter\expandafter\gdef\expandafter\expandafter\expandafter\propertycode%
            \expandafter\expandafter\expandafter{\expandafter\propertycode\expandafter\property\expandafter{\p}\\}%
    }%
    \propertycode%
}

\begin{document}
\begin{tikzpicture}
\matrix [entity={articles}] {
    \properties{
        classkey, 
        class_type,
        class_desc
    }
};
\end{tikzpicture}

\end{document}

enter image description here

UPDATE: Just for fun an alternative with multipart nodes in which you can access its elements.

\documentclass[a4paper]{article} 
\usepackage{tikz}
\usepackage{etoolbox}
\usetikzlibrary{shapes.multipart}
\usetikzlibrary{positioning}
\usetikzlibrary{shadows.blur}
\usetikzlibrary{calc}


\def\numtext#1{% from https://tex.stackexchange.com/a/67926/121799
  \ifcase#1\or one\or two\or three\or four\or five\or six\or seven\or eight\or nine\or ten\or
eleven\or twelve\or thirteen\or fourteen\or fifteen\or sixteen\or seventeen\or eighteen\or nineteen\or twenty\or Lots\fi}


\makeatletter % from https://tex.stackexchange.com/a/88336/121799
\newcommand{\GetCurrentNodeName}{\tikz@fig@name}
\makeatother
\tikzset{Line/.style={
        path picture={
            \draw (\GetCurrentNodeName.text split west) -- (\GetCurrentNodeName.text split east);
        }}}


% based on \Bytes from https://tex.stackexchange.com/a/67926/121799
\newcommand{\Properties}[2][]{
\def\nodecontents{}%
\foreach[count=\l] \k in {#2} {
    \xappto{\nodecontents}{\noexpand\nodepart{\numtext{\l}}\k}
    \xdef\mycount{\l}
}
\node [rectangle split,rectangle split parts=\mycount,draw, rectangle split draw splits=false,
Line,alias=X,#1] {\nodecontents};
}


\makeatletter
\pgfarrowsdeclare{crow's foot}{crow's foot}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}%
  \pgfarrowsrightextend{+.5\pgflinewidth}%
}
{
  \pgfutil@tempdima=0.5pt%
  \advance\pgfutil@tempdima by.25\pgflinewidth%
  \pgfsetdash{}{+0pt}%
  \pgfsetmiterjoin%
  \pgfpathmoveto{\pgfqpoint{0pt}{-6\pgfutil@tempdima}}%
  \pgfpathlineto{\pgfqpoint{-6\pgfutil@tempdima}{0pt}}%
  \pgfpathlineto{\pgfqpoint{0pt}{6\pgfutil@tempdima}}%
  \pgfusepathqstroke%
}


\tikzset{
    zig zag to/.style={
        to path={(\tikztostart) -| ($(\tikztostart)!#1!(\tikztotarget)$) |- (\tikztotarget)}
    },
    zig zag to/.default=0.5,
    one to many/.style={
        -crow's foot, zig zag to
    },
    many to one/.style={
        crow's foot-, zig zag to
    },
    many to many/.style={
        crow's foot-crow's foot, zig zag to
    }
}

\begin{document}

\begin{tikzpicture}
\Properties[name=leftnode,blur shadow,fill=white]{articles,classkey,class\_type,class\_desc}
\Properties[above right=3cm of leftnode,name=aboverightnode]{enlightened beings,ducks,
marmots,koala bears}
\Properties[right=4cm of leftnode,name=rightnode]{keys,house keys,
car keys,burrow keys}
\draw [many to one] (aboverightnode)     to (leftnode.two east);
\draw [many to one] (rightnode)     to (leftnode.three east);
\end{tikzpicture}

\end{document}

enter image description here