I am trying to learn how to use \mathchoice
.
Before the solution was posted for Non-invasive replacement for \fbox?, I attempted to use mathchoice
to adjust the size of the parameter before measuring its height, depth and width. To simply things, I first defined:
\newcommand{\SetHeightDepthWidth}[1]{%
\settoheight{\fillbox@height}{#1}%
\settodepth{\fillbox@depth}{#1}%
\settowidth{\fillbox@width}{#1}%
}%
Then adjusted the beginning of the \fillbox
macro as:
\newcommand{\fillbox}[1]{%
\ifmmode%
\mathchoice%
{\SetHeightDepthWidth{$\displaystyle#1$}}%
{\SetHeightDepthWidth{$\textstyle#1$}}%
{\SetHeightDepthWidth{$\scriptstyle#1$}}%
{\SetHeightDepthWidth{$\scriptscriptstyle#1$}}%
\else%
\SetHeightDepthWidth{#1}%
\fi%
Before these changes, the output was:
But with the above changes I get:
So, what happened? To me it appears to be some problem related to the grouping due to the extra brace groups required to pass in the four parameters to \mathchoice
, but don't know how to fix it. Does \mathchoice
behave differently than many of the other types of conditional macros such as \iftoggle{condition}{code if true}{code if false}
from the etoolbox
package?
Code:
The new code is marked and the old code is left commented to simplify comparison.
\documentclass{article}
\usepackage{tikz}
\makeatletter
\newlength\fillbox@height%
\newlength\fillbox@depth%
\newlength\fillbox@width%
\newcommand{\SetHeightDepthWidth}[1]{% new
\settoheight{\fillbox@height}{#1}% new
\settodepth{\fillbox@depth}{#1}% new
\settowidth{\fillbox@width}{#1}% new
}%
\newcommand{\fillbox}[1]{%
\ifmmode% new
\mathchoice% new
{\SetHeightDepthWidth{$\displaystyle#1$}}% new
{\SetHeightDepthWidth{$\textstyle#1$}}% new
{\SetHeightDepthWidth{$\scriptstyle#1$}}% new
{\SetHeightDepthWidth{$\scriptscriptstyle#1$}}% new
\else% new
\SetHeightDepthWidth{#1}% new
\fi% new
%\ifmmode%
% \settoheight{\fillbox@height}{$#1$}%
% \settodepth{\fillbox@depth}{$#1$}%
% \settowidth{\fillbox@width}{$#1$}%
%\else%
% \settoheight{\fillbox@height}{#1}%
% \settodepth{\fillbox@depth}{#1}%
% \settowidth{\fillbox@width}{#1}%
%\fi%
\raisebox{-\fillbox@depth}{%
\begin{tikzpicture}[scale=1]
\pgfsetfillcolor{yellow!90!red}
\pgfsetfillopacity{0.5}
\pgfsetrectcap
\fill (0,-\fillbox@depth) rectangle (\fillbox@width,\fillbox@height);
\pgfsetfillcolor{yellow!50!black}
\pgfsetfillopacity{1}
\fill (0,-\fillbox@depth)
rectangle (\fillbox@width,-\fillbox@depth+.1pt);
\fill (0,\fillbox@height)
rectangle (\fillbox@width,\fillbox@height-.1pt);
\fill (0,-\fillbox@depth)
rectangle (.1pt,\fillbox@height);
\fill (\fillbox@width,-\fillbox@depth)
rectangle (\fillbox@width-.1pt,\fillbox@height);
\end{tikzpicture}%
\kern-\fillbox@width%
}%
#1%
}
\makeatother
\begin{document}
\vskip1em
$\fillbox{p}_{\fillbox{x}}
\mathrel{\stackrel{\fillbox{_{~+}}}{\fillbox{\leftarrow}}}
\fillbox{(}\fillbox{\frac{\fillbox{1}}{\fillbox{2}}}\fillbox{\cdot}
\fillbox{a}_{\fillbox{x}}\fillbox{\cdot}%
\fillbox{\Delta}\fillbox{t}^{\fillbox{2}}\fillbox{)} \fillbox{+}
\fillbox{(}\fillbox{v}_{\fillbox{x}}\fillbox{\cdot}%
\fillbox{\Delta}\fillbox{t}\fillbox{)}$\fillbox{;}\par
$\fillbox{v}_{\fillbox{x}}
\mathrel{\stackrel{\fillbox{_{~+}}}{\fillbox{\leftarrow}}}
\fillbox{a}_{\fillbox{x}}\fillbox{\cdot}%
\fillbox{\Delta}\fillbox{t}$\fillbox{;}\par
%
% This section is not relevant to the problem here.
%\vskip1em
%$p_x \mathrel{\stackrel{_{~+}}{\leftarrow}}
% (\frac{1}{2}\cdot a_x\cdot\Delta t^2) + (v_x\cdot\Delta t)$;\par
%$v_x \mathrel{\stackrel{_{~+}}{\leftarrow}} a_x\cdot\Delta t$;\par
%
\end{document}
Best Answer
\mathchoice
acts at the end of the math list when TeX is making a horizontal list by putting the math boxes in the right places. So the "choice" happens way after you are attempting to use the lengths. (They are being set in a group and left as zero, but you can't simply make a global assignment as the timing is all wrong.)Look at any uses of
\mathchoice
(or its wrapper\mathpalette
) in plain or latex.ltx. The usual idiom is that you need to put the entire command including all its arguments so, using fbox for simplicity:would work, although usually you simplify things by defining a helper macro that takes the math style as an argument, for example in latex.ltx
\smash
in math mode uses this form with\mathsm@sh
being a version of\smash
that takes (eg)\scriptstyle
as an additional argument. So something likeOr you can let the AMS take care of you