I would like to achieve the following:
Namely a top left node, a bottom left node with the same width as the top left node (with possibly different height), and a right node with the total height of two left nodes. The right node must contain multiple things, possibly pictures.
The following code solves this:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usetikzlibrary{fit}
\usetikzlibrary{calc}
\begin{document}
\newdimen\XCoordA
\newdimen\YCoordA
\newdimen\XCoordB
\newdimen\YCoordB
\newcommand*{\ExtractCoordinateA}[1]{\path (#1); \pgfgetlastxy{\XCoordA}{\YCoordA};}%
\newcommand*{\ExtractCoordinateB}[1]{\path (#1); \pgfgetlastxy{\XCoordB}{\YCoordB};}%
\pgfdeclarelayer{toplayer}%
\pgfdeclarelayer{background}%
\pgfsetlayers{background,toplayer}%
\begin{tikzpicture}[
block/.style= {inner sep=10pt, font=\footnotesize, align=center, draw, thick},
left_block/.style= {block, minimum width=100pt},
zerofit_block/.style= {block, inner sep=0pt},
inner_text/.style= {inner sep=0pt, font=\small, align=center},
inner_text_small/.style= {inner_text, font=\tiny},
]
\begin{pgfonlayer}{background}
\node [left_block, fill=green!50!white]
(block_top_left) {This is\\block\_top\_left};
\node [left_block, fill=red!50!white, below=0.2 of block_top_left.south west, anchor=north west]
(block_bottom_left) {block\_bottom\_left};
\end{pgfonlayer}
\begin{pgfonlayer}{toplayer}
\node [inner_text, below right=-0.7 and 1 of block_top_left]
(block_right_label) {This is\\block\_right};
\node [inner_text_small, below=0.1 of block_right_label]
(block_right_text) {This is\\block\_right's\\text};
\end{pgfonlayer}
\begin{pgfonlayer}{background}
\ExtractCoordinateA{$(block_top_left.north) - (0,0.4pt)$}; %0.4pt is half of the thick line width
\ExtractCoordinateB{$(block_right_label)$};
\coordinate (block_right_north) at (\XCoordB,\YCoordA);
\ExtractCoordinateA{$(block_bottom_left.south) + (0,0.4pt)$};
\coordinate (block_right_south) at (\XCoordB,\YCoordA);
\coordinate (block_right_east_west_inner_sep) at (0.5,0);
\coordinate (block_right_west) at ($(block_right_label.west) - (block_right_east_west_inner_sep)$);
\coordinate (block_right_east) at ($(block_right_label.east) + (block_right_east_west_inner_sep)$);
\node [zerofit_block, fill=yellow!50!white, fit=(block_right_north) (block_right_south) (block_right_west) (block_right_east)]
(block_right) {};
\end{pgfonlayer}
\end{tikzpicture}%
\end{document}
There are numerous ugly things about this solution that I don't like:
- Width of the two left nodes are controlled manually, with
minimum width
, but I would like to have the wider node have just aninner sep
and the narrower node stretch in width to follow it. - Controlling the fitted right node's north, south, east and west with four manually calculated coordinates seems like overkill and just feels wrong.
- North and south artificial coordinate of the fitted right node require that the drawn line thickness is subtracted. This is not even manually calculated but hardcoded to half the draw thickness; as soon as the draw thickness of the nodes change, this must be adjusted by hand.
- The worst problem: Right block's inner blocks (block_right_label and block_right_text) are manually positioned. It would be better to somehow control the fitted node edges and draw the inner nodes after the fitted node has been positioned. This way, I could precisely control the spacing between the right fitted node and the left nodes, maybe even set it equal to the spacing between the left nodes. Not to mention that manually positioning the inner nodes will not achieve a perfectly equal top and bottom inner sep like this.
Am I approaching this problem completely wrong? Fit seems like the wrong solution here. In any case, can you offer me solutions for any number of the above problems?