How to vertically and horizontally centre text and images in (different) table cells?

I have a table which contains images in one column. I would like the first column to have text centred vertically and horizontally. I would like the second column to have text left justified and centred vertically. I would like the third column to contain a small image centred vertically and horizontally. The final two columns should both be left justified and aligned at the top of the cell.

The closest I have come to this is with the code below:

\documentclass[10pt]{article}

\usepackage{tikz}
\usepackage{array}
\usepackage{booktabs}

\newcommand*{\tabbox}[4][t]{%
\vspace{#3}\parbox[#1][3.7\baselineskip]{#2}{\strut#4\strut}}

\begin{document}

\begin{tabular}{c p{2cm} c p{3cm} p{3cm}}
\toprule
\midrule
Short Text &
Slightly Longer Text &
\tabbox[t]{3cm}{0pt}{
\begin{tikzpicture}
% Draw beam and end lines
\draw (-1.5,-0.75) rectangle (1.5,0.75) ;
\end{tikzpicture}
}
&
Some text that extends onto more than one line as there's plenty of it. &
Some text that extends onto more than one line as there's plenty of it. Some text that extends onto more than one line as there's plenty of it. \\
Short Text  &
Slightly Longer Text &
\tabbox[t]{3cm}{0pt}{
\begin{tikzpicture}
% Draw beam and end lines
\draw (-1.5,-0.75) rectangle (1.5,0.75) ;
\end{tikzpicture}
}  &
Short Text & \\
Short Text & Slightly Longer Text & Short Text & Short Text & \\
Short Text & Slightly Longer Text & Short Text & Short Text & \\
\bottomrule
\end{tabular}

\end{document}


This is partly based on the advice here. The 'm' column specifier doesn't seem to have any effect on the first column. Also the picture is not automatically accommodated by the table cell vertically.

How can I achieve the effect I want?

Edit

Here is another attempt which almost works based on the advice in this question

\documentclass[10pt]{article}

\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{array}
\usepackage{booktabs}

\begin{document}

\begin{tabular}{c p{2cm} p{3cm} p{3cm} p{3cm}}
\toprule
\midrule
Short Text &
Slightly Longer Text &
\begin{tikzpicture}[baseline={($(current bounding box.center)+(0,-0.5ex)$)}]
% Draw beam and end lines
\draw (-1.5,-0.75) rectangle (1.5,0.75) ;
\useasboundingbox (current bounding box.north west) ++(0,1ex) (current bounding box.south east) ++(0,-1ex);
\end{tikzpicture}
&
Some text that extends onto more than one line as there's plenty of it. &
Some text that extends onto more than one line as there's plenty of it. Some text that extends onto more than one line as there's plenty of it. \\
Short Text  &
Slightly Longer Text &
\begin{tikzpicture}[baseline={($(current bounding box.center)+(0,-0.5ex)$)}]
% Draw beam and end lines
\draw (-1.5,-0.75) rectangle (1.5,0.75) ;
\useasboundingbox (current bounding box.north west) ++(0,1ex) (current bounding box.south east) ++(0,-1ex);
\end{tikzpicture}
&
Short Text & \\
Short Text & Slightly Longer Text & Short Text & Short Text & \\
Short Text & Slightly Longer Text & Short Text & Short Text & \\
\bottomrule
\end{tabular}

\end{document}

-
What are you trying to achieve with the \tabbox command? It seems to me that this messes up the vertical alignment of the picture column. Also, do you want to include tikzpictures, or images you load using includegraphics, or both? –  Jake Nov 1 '11 at 0:02
I was using the \tabbox command as suggested in the link to another StackExchange in the question (here). If I comment it out, the effect is still not as I want though. In this case I do want to use tikzpictures and have found some info on this in this question. I have added my latest attempt based on this above, but it's still not right. I would also like a more general solution that would work for other images in the future. –  crobar Nov 1 '11 at 8:59

The problem is in understanding precisely how tabular works.

Each cell has a reference point of reference and all the reference points are eventually put on the same horizontal line. For l, c, and r cells the reference point is on the baseline; for a p cell the reference point is on the first line's baseline; for m cells the reference point is midway from the top and the bottom of the text; for b cells it's on the last line's baseline.

Thus a tabular specification such as

{l m{3cm} p{3cm}}


will not place the middle cells of a row mid aligned with respect to the last cell, but rather its content will stick above the last column by (slightly less than) half its vertical size.

The kind of alignment you're trying to get can't be obtained without measuring the cells' contents, as Stefan Kottwitz's answer about \tabbox shows: that 3.7\baselineskip was good for that example, not in general.

Here's a way out, in your specific case (note the use of \adjustbox for the picture):

\documentclass{article}

\usepackage{tikz}
\usepackage{array}

\newcommand{\finalcells}[2]{%
\begingroup\sbox0{\begin{minipage}{3cm}\raggedright#1\end{minipage}}%
\sbox2{\begin{minipage}{3cm}\raggedright#2\end{minipage}}%
\xdef\finalheight{\the\dimexpr\ht0+\dp0+\smallskipamount\relax}%
\xdef\finalheightB{\the\dimexpr\ht2+\dp2+\smallskipamount\relax}%
\ifdim\finalheightB>\finalheight
\global\let\finalheight\finalheightB
\fi\endgroup
\begin{minipage}[t][\finalheight][t]{3cm}\raggedright#1\end{minipage}&
\begin{minipage}[t][\finalheight][t]{3cm}\raggedright#2\end{minipage}}

\begin{document}

\begin{tabular}{c m{2cm} m{3cm}  m{3cm} m{3cm}}
\toprule
\midrule
Short Text &
Slightly Longer Text &
\begin{tikzpicture}
% Draw beam and end lines
\draw (-1.5,-0.75) rectangle (1.5,0.75) ;
\end{tikzpicture}%
}
&
\finalcells{Some text that extends onto more than one line as there's plenty of it.}
{Some text that extends onto more than one line as there's plenty of it.
Some text that extends onto more than one line as there's plenty of it.} \\
\bottomrule
\end{tabular}

\end{document}


-
Thanks, it'll take me a while to understand completely, but it works! The only issue is that in a subsequent line of cells, the final cells butt up against the cells above without a space (in the cells with the most text that is). –  crobar Nov 1 '11 at 16:54
I've added a \smallskipamount at the end of the boxes. –  egreg Nov 1 '11 at 17:00
Thanks, as a final question, where can I find further information on the \sbox0, \sbox2, and \the\dimexpr\ht0 type things you have used? I've tried google, but it's hard to know what to search for exactly. –  crobar Nov 2 '11 at 10:27
@crobar The LaTeX Companion has many of these tricks –  egreg Nov 2 '11 at 12:39