# Want nodes to have linked heights based on which input is larger

So I'm trying to make a worksheet template for students to create pdfs for student markup. The inputs create what is going to go in the question box as well as the hints box.

I want to create the height for these two boxes dynamically - that is I want them to be the same and to scale based on the inputs. The Answer box should take up the remaining space on the page. I'm having a few issues:

1. I currently am having the Question box height based on the input, and scaling the Hint box to match. I'd like to have them be the bigger of the two.

2. I currently cannot get the resulting image to center on the page.

I'm really not sure that I am doing this the most efficient way, but I'm open to suggestions. I'd like to automate the process to make it easy to produce content for my students.

\documentclass{article}
\pagestyle{empty}
\usepackage[top=.5in, left=.5in, right=.5in, bottom=.5in]{geometry}
\usepackage{tikz}
\usepackage{calc}
\usetikzlibrary{arrows, positioning, calc, fit}
\newcommand\WS[2]{
\begin{tikzpicture}

% The Question
\node[
draw=red,
fill=red!10,
rounded corners=6pt,
text width=.55\textwidth,
minimum height=.1\textheight,
inner sep=20pt,
align=center]
(Question)
{
#1
};
% The Label
\node[
draw=red,
fill=red!30,
rounded corners=6pt,
anchor=north west,
inner sep=5pt]
at (Question.north west)
{
Question
};

% The Hints
\path let
\p1=($(Question.south)-(Question.north)$),
\n1 = {veclen(\p1)-0.4pt}      % 0.4pt is the width of the border line
in
node[
draw=blue,
fill=blue!10,
rounded corners=6pt,
text width=.35\textwidth,
minimum height=\n1,
right=0pt of Question.north east,
anchor=north west,
align=center,
inner sep=5pt]
(Hint)
{
#2
};
% The Label
\node[
draw=blue,
fill=blue!30,
rounded corners=6pt,
anchor=north west,
inner sep=5pt]
at (Hint.north west)
{
Hint
};

\path let
\p2 = ($(Question.west)-(Hint.east)$),
\n2 = {veclen(\p2)-0.4pt},  % 0.4pt is the width of the border
% line
\p3 = ($(Question.north)-(Question.south)$),
\n3 = {\textheight-veclen(\p3)-10.4pt}
in
node[
draw=green,
fill=green!10,
rounded corners=6pt,
text height=\n3,
below=0pt of Question.south west,
anchor=north west,
minimum width=\n2]
{
};
% The Label
\node[
draw=green,
fill=green!30,
rounded corners=6pt,
anchor=north west,
inner sep=5pt]
{
};

\end{tikzpicture}
}

\begin{document}

\WS{
Suppose you have a right triangle as presented below.  Let $a=2$ cm, and
$b=3$ cm.  How long would $c$ be?
\par
\begin{tikzpicture}
\draw[rounded corners=0pt] (0,0) -- (2,0) -- (2,3) -- (0,0);
\end{tikzpicture}
\par
Remember to leave your answers as a square root, and to show all work and
leave units.
}
{
\begin{itemize}
\item Think about the pythagorean formula.
\item It involves squares.
\end{itemize}
}

\end{document}
-
2. \noindent before \WS or the inner \begin{tikzpicture}. –  Qrrbrbirlbel Dec 10 '12 at 20:29

UPDATE: Improved the placement of the table and the marks. Vastly improved the readability of the code and reduced the size by the use of styles and loops.

A different idea. Instead of putting all inside tikz nodes, put the question and the hints in a table. This should take care of making two "cells" of the same height. Then use the celebrated macro \tikzmark at strategic points, so that we can later draw lines around each cell and compose the desired layout.

The following MWE implements this idea:

\documentclass{article}
\pagestyle{empty}
\usepackage[top=.5in, left=.5in, right=.5in, bottom=.5in]{geometry}
\usepackage{tikz}
\usepackage{array}
\usetikzlibrary{calc}

% Declaration of tikzmark
\def\tikzmark#1{\tikz[remember picture, overlay]\coordinate (#1);}

% Some styles
\tikzset{
Frame/.style={rounded corners = 6pt, fill opacity = .1, draw = #1, fill = #1},
Label/.style={rounded corners = 6pt, anchor = north west, inner sep = 5pt, fill = #1!30, draw = #1},
}

\newcommand\WS[2]{%
% First, typeset the text inside two cells of a table
% and put several \tikzmarks at strategic points
% ------------------------------------------------------------------ table ----------
\tikzmark{table top}% This mark is at top of the centered environment which contains the table
\begin{center}
\tikzmark{table left}% This mark is at left border in the table
% The following contrived specification ensures a padding of \tablepadding around the cells
\\[2mm]% Top separation
#1 &\tikzmark{table column}& #2 & \\ % Table column marks the left edge of the Hint column
\end{tabular}\tikzmark{table right}% Mark at the right border of the table
\end{center}
\noindent\tikzmark{table bottom} % Mark the horizontal position of the bottom of the table
% -------------------------------------------------------------- end table ----------
% Then draw the frames and labels
\begin{tikzpicture}[remember picture, overlay]
% Compute the relevant corners
\coordinate (Question-north west) at (table top-|table left);
\coordinate (Question-south east) at (table bottom-|table column);
\coordinate (Hints-north west)    at (table top-|table column);
\coordinate (Hints-south east)    at (table bottom-|table right);
\coordinate (Answer-north west)   at (table bottom-|table left);
\coordinate (bottom margin) at ([yshift=.5in] current page.south);
\coordinate (Answer-south east)   at (bottom margin-|table right);
% Draw the three frames and labels in a single loop :-)
\filldraw[Frame=\color] (\what-north west) rectangle (\what-south east);
\node[Label=\color]  at (\what-north west) { \what };
}
\end{tikzpicture}
}

\begin{document}
\noindent
\WS{
Suppose you have a right triangle as presented below.  Let $a=2$ cm, and
$b=3$ cm.  How long would $c$ be?
\par
\begin{center}
\begin{tikzpicture}
\draw (0,0) -- (2,0) node[midway,below] {$a$}
-- (2,3) node[midway,right] {$b$}
-- (0,0) node[midway,left]  {$c$};
\end{tikzpicture}
\end{center}
\par
Remember to leave your answers as a square root, and to show all work and
leave units.
}
{
\begin{itemize}
\item Think about the pythagorean formula.
\item It involves squares.
\end{itemize}
}

With the desired result (after compiling twice, as required by remember picture option):

-
I like this solution. However, when I centered the triangle via \begin{center} ... \end{center} and added a label to the bottom of the triangle, \draw[rounded corners=0pt] (0,0) -- (2,0) node[midway, below] {$a$} -- (2,3) -- (0,0);, it caused the text to be pushed up into the box containing the word Question. It was fine again after adding labels for the other two edges of the triangle. Not sure why that made it okay? –  Matthew Short Dec 11 '12 at 7:20
Each time you make a change, you have to recompile twice. This is required because of the remember picture option. –  JLDiaz Dec 11 '12 at 8:03
Thank you! That fixes everything. This is really quite nice, and achieves all of my goals for the upcoming spring semester. –  Matthew Short Dec 11 '12 at 14:50

I’ve got one and a half methods:

### Solution 1

We measure the height of “Question” and of the “Hint” box and use the maximum height for text height. Because the inner sep is included in the measured height we subtract that again.

I had problems with \par inside a node inside TikZ inside of a box. There’s probably a plainTeX reason for it.
Instead of your \pars I put the inner tikzpicture inside of a center environment, which looks in my opinion even better because it introduces vertical space.

### Solution 1 ½

To circumvent the \par problem, I put only the text itself into a \parbox and measure the height of that, similar to Solution 1, but there seems to be some other fiddling heights to be involved …

## Code

\documentclass{article}
\pagestyle{empty}
\usepackage[top=.5in, left=.5in, right=.5in, bottom=.5in]{geometry}
\usepackage{tikz}
\usepackage{calc}
\usetikzlibrary{arrows, positioning, calc}
\tikzset{
all nodes/.style={
rounded corners=6pt,
},
small node/.style={
all nodes,
inner sep=5pt,
anchor=north west,
},
big node/.style={
all nodes,
align=center,
},
question/.style={
big node,
draw=red,
fill=red!10,
text width=.55\textwidth,
inner sep=20pt,
},
question label/.style={
small node,
draw=red,
fill=red!30,
},
hint/.style={
big node,
draw=blue,
fill=blue!10,
text width=.35\textwidth,
inner sep=5pt,
},
hint label/.style={
small node,
draw=blue,
fill=blue!30,
},
big node,
draw=green,
fill=green!10,
},
small node,
draw=green,
fill=green!30,
},
reset/.style={
rounded corners=0pt,
minimum height=0pt,
inner sep=.3333em,
text width=,% reset
}
}
\newlength{\nodeheighta}
\newlength{\nodeheightb}
\newcommand\WS[2]{%
\sbox0{\tikz[inner sep=0pt,outer sep=0pt]{\node[question] (Question) {#1};}}%
\sbox1{\tikz[inner sep=0pt,outer sep=0pt]{\node[hint] (Hint) {#2};}}%
\setlength{\nodeheighta}{\ht0}%
\setlength{\nodeheightb}{\ht1}%
\ifdim\nodeheighta<\nodeheightb\nodeheighta=\nodeheightb\fi%
\noindent%
\begin{tikzpicture}
\node[question, minimum height=\nodeheighta,] (Question) {#1};
\node[question label] at (Question.north west) {Question};
\node[hint, minimum height=\nodeheighta, right=0pt of Question.north east, anchor=north west] (Hint) {#2};
\node[hint label] at (Hint.north west) {Hint};

\path let
\p2 = ($(Question.west)-(Hint.east)$),
\n2 = {veclen(\p2)-\pgflinewidth},  % 0.4pt is the width of the border line
\p3 = ($(Question.north)-(Question.south)$),
\n3 = {\textheight-veclen(\p3)-10.4pt}
in node[
text height=\n3,
below=0pt of Question.south west,
anchor=north west,
minimum width=\n2
% The Label
\end{tikzpicture}%
}

\begin{document}
\WS{
Suppose you have a right triangle as presented below.  Let $a=2$ cm, and
$b=3$ cm.  How long would $c$ be?
\begin{center}
\begin{tikzpicture}[reset,auto=right]
\draw (0,0) -- node {$a$} (2,0) -- node {$b$} (2,3)  -- node {$c$} (0,0);
\end{tikzpicture}
\end{center}
Remember to leave your answers as a square root, and to show all work and
leave units.
}
{
\begin{itemize}
\item Think about the pythagorean formula.%\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~\\~% dirty method to test when Hint > Question
\item It involves squares.
I like this solution. You also took time to make a large number of styles to clean up the code. However, changing the triangle to have a bottom label via \draw[rounded corners=0pt] (0,0) -- (2,0) node[midway,below] {$a$} -- (2,3) -- (0,0); causes all sorts of craziness. Any idea why it breaks this code? –  Matthew Short Dec 11 '12 at 7:28