Measuring List Items in Tasks and Making Changes Accordingly
If you a can accept a (slightly) modified input of the task list like :
\MCQ{Some choice\\
Another choice\\
A choice with a larger width that will break on two lines\\
The last one
}
below is a working solution.
It uses parsing and iteration from package listofitems
and a few functions of etoolbox
package. Th key idea is to first iterate to find the maximl width, an secondly to iterate to build the body of the tasks
environment. This is made rather elaborated because of the very special handling of tasks
content (I used for that the answer from clemens for the question tasks-environment-vs-pgffors-foreach). If you would use a more standard environment, everything can be codded in four or five lines.
\documentclass{article}
\usepackage[papersize={600pt,800pt},top=50pt,left=50pt,right=50pt,bottom=50pt]{geometry}
\usepackage{tikz}
\usepackage{calc}
\usepackage{enumitem}
\usepackage{tasks}
\usepackage{listofitems}
\usepackage{etoolbox}
\makeatletter
\renewcommand\normalsize{\@setfontsize\normalsize{13.5pt}{17pt}}
\normalsize
\makeatother
\definecolor{ChoiceGray}{RGB}{204,204,204}
\newcommand*\Choice[1]{%
\begin{tikzpicture}[baseline=-5pt]
\node [gray,minimum width=22pt,minimum height=22pt,draw=ChoiceGray,rounded corners] {\large #1};
\end{tikzpicture}}
\newcounter{ChoiceLabel}
\newcommand*\ChoiceLabel{%
\refstepcounter{ChoiceLabel}%
\hskip1em\llap{\Choice{\Alph{ChoiceLabel}}}%
}
%------------------------
\newcommand\switchtwo[2]{#2#1}
\newcommand\expandsecond[2]{\expandafter\switchtwo\expandafter{#1}{#2}}
\newlength{\tsklenmax}
\newcommand{\setTaskLenMax}[1]{\setlength{\tsklenmax}{#1}}
\newcommand{\maxdim}[2]{\ifdimgreater{#1}{#2}{#1}{#2}}
\newcommand*{\MCQ}[1]{
% initize
\ifdef{\taskslist}{\renewcommand*\taskslist{}}{\newcommand*\taskslist{}}
\ifdef{\thetasks}{\let\thetasks\undefined}{}
\newlength{\tsklen}\newlength{\tsklentempmax}
\setlength{\tsklentempmax}{\tsklenmax}
% read tasks
\setsepchar{\\} \ignoreemptyitems
\greadlist*\thetasks{#1}
% find maximal width
\foreachitem\atask\in\thetasks{
\settowidth{\tsklen}{\atask}
\setlength{\tsklentempmax}{\maxdim{\tsklen}{\tsklentempmax}}
}
% choose task version
\ifdimgreater{\tsklentempmax}{\tsklenmax}{\def\usestar{\noexpand\task*}}{\def\usestar{\noexpand\task}}
% populate task list
\foreachitem\atask\in\thetasks{
\begingroup
\edef\x{\endgroup
\expandafter\noexpand\csname g@addto@macro\endcsname
\noexpand\taskslist{\usestar \atask}%
}\x
}
% display tasks
\setcounter{ChoiceLabel}{0}%
\expandsecond\taskslist
{\begin{tasks}[after-item-skip=3mm,label=\ChoiceLabel](2)}
\end{tasks}
}
\begin{document}
\setTaskLenMax{250pt}
\begin{enumerate}
\item question 1
\MCQ{Some choice\\
Another choice\\
A choice with a larger width that will break on two lines\\
The last one
}
\item Question 2
\MCQ{Some choice\\
Another choice\\
With reduced larger width \\
The last one
}
\end{enumerate}
\end{document}
Resulting in:
The new MCQ
command and its auxillary functions/length are defined at the end of the preamble.
Obviously, as you already load tikz
to create the fancy labels, you could replace list handling and iteration by those of pgf
.
Here I use listofitems
to initially parse the argument of \MCQ
with \task
as a separator. It loops through the parsed \tasklist
measuring the longest one. If that longest one exceeds the threshold, here 200pt, it builds a token list that substitutes \task*
wherever there had been \task
in the original argument.
The original syntax of the OP is preserved.
\documentclass{article}
\usepackage[papersize={600pt,800pt},top=50pt,left=50pt,right=50pt,bottom=50pt]{geometry}
\usepackage{tikz}
\usepackage{calc}
\usepackage{enumitem}
\usepackage{tasks}
\makeatletter
\renewcommand\normalsize{\@setfontsize\normalsize{13.5pt}{17pt}}
\normalsize
\makeatother
\definecolor{ChoiceGray}{RGB}{204,204,204}
\newcommand*\Choice[1]{%
\begin{tikzpicture}[baseline=-5pt]
\node [gray,minimum width=22pt,minimum height=22pt,draw=ChoiceGray,rounded corners] {\large #1};
\end{tikzpicture}}
\newcounter{ChoiceLabel}
\newcommand*\ChoiceLabel{%
\refstepcounter{ChoiceLabel}%
\hskip1em\llap{\Choice{\Alph{ChoiceLabel}}}}%
\newtoks\tasktoks
\usepackage{listofitems}
\newcommand*{\MCQ}[1]{%
\setsepchar{\task}%
\ignoreemptyitems%
\readlist*\tasklist{#1}%
\def\longtask{0pt}%
\foreachitem\taskitem\in\tasklist{% MEASURE THE LONGEST TASK
\setbox0=\hbox{\taskitem}%
\ifdim\wd0>\longtask\relax\edef\longtask{\the\wd0}\fi%
}%
\setcounter{ChoiceLabel}{0}%
\ifdim\longtask>200pt\relax% FOR LONG TASKS, EMPLOY \task*
\foreachitem\taskitem\in\tasklist{%
\tasktoks\expandafter{\the\tasktoks\task*}%
\tasktoks\expandafter\expandafter\expandafter{%
\expandafter\the\expandafter\tasktoks\taskitem}%
}%
\else%
\tasktoks{#1}%
\fi%
\def\tmp{ \begin{tasks}[after-item-skip=3mm,label=\ChoiceLabel](2)}%
\expandafter\tmp\the\tasktoks%
\end{tasks}%
}
\begin{document}
\begin{enumerate}[label=\arabic*.,leftmargin=1cm]
\item{Question text here.
\MCQ{
\task Some choice
\task Another choice
\task Third choice
\task The last one
}
}
\end{enumerate}
\begin{enumerate}[label=\arabic*.,leftmargin=1cm]
\item{Question text here.
\MCQ{
\task Some choice
\task Another choice
\task A choice with larger width that will break on two lines
\task The last one
}
}
\end{enumerate}
\end{document}