# Overlapping TikZ nodes to look as a tape strip

Friends, I need to highlight specific letters. My set contains only A, N, C, Q and P, so I decided to make them look as a tape strip (ressembles a good old Turing Machine tape). The following code poorly tries to achieve that. Since I had an immutable set of letters and a defined order, I used the xstring package.

\documentclass{article}

\usepackage{tikz}
\usepackage{xstring}

\newcommand*\myblackbox[1]{%
\begin{tikzpicture}
\node[draw,inner sep=1pt, minimum height=0.2cm, minimum width=0.2cm] {\tiny\tt\raisebox{0pt}[\height][0pt]{#1}};
\end{tikzpicture}}

\newcommand*\mygraybox[1]{%
\begin{tikzpicture}
\node[draw,inner sep=1pt, draw=gray!60, minimum height=0.2cm, minimum width=0.2cm] {\color{gray!60}\tiny\tt\raisebox{0pt}[\height][0pt]{#1}};
\end{tikzpicture}}

\DeclareRobustCommand*\drawboxes[1]{%
\IfSubStr{#1}{A}{\myblackbox{A}}{\mygraybox{A}}%
\IfSubStr{#1}{N}{\myblackbox{N}}{\mygraybox{N}}%
\IfSubStr{#1}{C}{\myblackbox{C}}{\mygraybox{C}}%
\IfSubStr{#1}{Q}{\myblackbox{Q}}{\mygraybox{Q}}%
\IfSubStr{#1}{P}{\myblackbox{P}~}{\mygraybox{P}~}}

\begin{document}

\drawboxes{ACQ} Hello world.

\end{document}


This is the output:

The squares are arranged side by side. So far so good, but I'd like to make them slightly overlap each others, like this:

The black boxes have higher priority, so they need to be on top of the gray ones. My solution is very simple, so I understand that a possible solution might have another method.

Any ideas?

-

I would put all the nodes into one tikzpicture, give all the nodes an outer xsep=0pt (which means that the edge of the node is defined as the middle of the border line), place them using a chain with a node distance of 0pt, and use the backgrounds library to put the gray nodes behind the black ones using \begin{pgfonlayer}{background}...\end{pgfonlayer}.

(Some additional optimisations of the code: You can use font=\tiny\tt to define the font options in the node style; instead of using the raisebox you can just define all nodes to have a text depth=0pt; and setting the color in the node options means you don't have to use \color in the node text).

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{chains,backgrounds}

\usepackage{xstring}

\tikzset{
tape node/.style={
on chain,
draw,
inner sep=1pt,
outer xsep=0pt,
minimum height=0.2cm,
minimum width=0.2cm,
text depth=0pt,
font=\tiny\tt
}
}

\newcommand*\myblackbox[1]{%
\node[
tape node
] {#1};
}

\newcommand*\mygraybox[1]{%
\begin{pgfonlayer}{background}
\node[
tape node,
gray!60
] {#1};
\end{pgfonlayer}
}

\DeclareRobustCommand*\drawboxes[1]{%
\begin{tikzpicture}[
start chain=going right,
node distance=0pt
]
\IfSubStr{#1}{A}{\myblackbox{A}}{\mygraybox{A}}%
\IfSubStr{#1}{N}{\myblackbox{N}}{\mygraybox{N}}%
\IfSubStr{#1}{C}{\myblackbox{C}}{\mygraybox{C}}%
\IfSubStr{#1}{Q}{\myblackbox{Q}}{\mygraybox{Q}}%
\IfSubStr{#1}{P}{\myblackbox{P}~}{\mygraybox{P}~}
\end{tikzpicture}
}

\begin{document}

\drawboxes{ACQ} Hello world.
\end{document}

-
Very impressive solution, Jake! I had no idea of how to put the gray nodes behind the black ones. Your answer is complete, very didatic and easy to understand, thanks a million! – Paulo Cereda Jul 14 '11 at 23:36
You could avoid the backgrounding if you made the gray nodes black but with some transparency. – Andrew Stacey Mar 8 '12 at 9:21

This a version of Jake's answer without chain. I start with tikz 1.1 without chain and I don't use it. I used maximum width and only one macro. I kept fine things text depth layers, font and I add a foreach.

\documentclass{article}
\usepackage{tikz} \usetikzlibrary{backgrounds}
\usepackage{xstring}

\tikzset{
tape node/.style={
anchor       = west, % to replace the chain
#1,
draw,
inner sep    = 1pt,
outer xsep   = 0pt,
minimum size = 0.2cm,
text depth   = 0pt,
font=\tiny\tt
}
}

\newcommand*\mybox[3]{%
\begin{pgfonlayer}{#3}
\node[tape node = #2](last) at (last.east) {#1};% my chain
\end{pgfonlayer}
}

\DeclareRobustCommand*\drawboxes[1]{%
\begin{tikzpicture}
\node[inner sep=0pt](last){}; % to start "my" chain
\foreach \letter in {A,N,C,Q,P} {% more easy to adapt
\IfSubStr{#1}{\letter}{%
\mybox{\letter}{black}{main}}{%
\mybox{\letter}{gray!60}{background}
}
}
\end{tikzpicture}
}

\begin{document}
\drawboxes{ACQ} Hello world.
\end{document}

-
 Thanks Altermundus! It looks very impressive! :) – Paulo Cereda Mar 8 '12 at 9:50 @PauloCereda Thanks but the great part of the work comes from Jake. – Alain Matthes Mar 8 '12 at 9:55

Based on your original code, using subtractions of \pgflinewidth and opacity as Andrew Stacey suggested in the comments on Jake's answer.

\documentclass{standalone}

\usepackage{tikz}
\usepackage{xstring}

\newcommand*\myblackbox[1]{%
\begin{tikzpicture}
\node[
draw,
inner sep=1pt,
minimum height=0.2cm,
minimum width=0.2cm
] {\tiny\tt\raisebox{0pt}[\height][0pt]{#1}};
\end{tikzpicture}%
}

\newcommand*\mygraybox[1]{%
\begin{tikzpicture}
\node[
draw,
inner sep=1pt,
minimum height=0.2cm,
minimum width=0.2cm,
opacity=0.4
] {\tiny\tt\raisebox{0pt}[\height][0pt]{#1}};
\end{tikzpicture}%
}

\DeclareRobustCommand*\drawboxes[1]{%
\IfSubStr{#1}{A}{\myblackbox{A}}{\mygraybox{A}}\hspace{-\pgflinewidth}%
\IfSubStr{#1}{N}{\myblackbox{N}}{\mygraybox{N}}\hspace{-\pgflinewidth}%
\IfSubStr{#1}{C}{\myblackbox{C}}{\mygraybox{C}}\hspace{-\pgflinewidth}%
\IfSubStr{#1}{Q}{\myblackbox{Q}}{\mygraybox{Q}}\hspace{-\pgflinewidth}%
\IfSubStr{#1}{P}{\myblackbox{P}~}{\mygraybox{P}~}}

\begin{document}

\drawboxes{ACQ} Hello world.

\end{document}


-
Nice idea, Mark! Thanks! :) – Paulo Cereda Mar 8 '12 at 10:36
I like Jake's version the best, but I thought a minimally changed version would make a nice addition. – Mark S. Everitt Mar 8 '12 at 10:51