2

Following-up this answer, how can I edit the command \FillAnswerRules to enclose the leaders by a border/frame by using tocolorbox or mdframed so that I can get the same output of \CountAnswerRules?

enter image description here

\documentclass{exam}

\usepackage{xparse,xcolor,tcolorbox,mdframed,pgffor,blindtext}

\renewcommand{\questionshook}{%
    \setlength{\leftmargin}{0pt}%
    \setlength{\labelwidth}{-\labelsep}%
    \setlength{\topsep}{0\baselineskip}
}

\ExplSyntaxOn
\keys_define:nn { diaa / answers }
{
    num-lines .int_set:N = \l_diaa_answers_numlines_int ,
    d .dim_set:N = \l__diaa_answers_distance_dim,
    t .dim_set:N = \l__diaa_answers_thickness_dim,
    c .tl_set:N  = \l__diaa_answers_color_tl,
    num-lines .initial:n = 3,
    d .initial:n = 10mm,
    t .initial:n = 0.2pt,
    c .initial:n = gray,
}

\NewDocumentCommand{\FillAnswerRules}{O{}}
{
    \group_begin:
    \par
    \keys_set:nn { diaa / answers } { #1 }
    \leaders \hbox:n
    {
        \makebox[\textwidth][s]{
            \color{\l__diaa_answers_color_tl}
            \vrule width 0pt height \l__diaa_answers_distance_dim % the distance
            \leaders\hrule height \l__diaa_answers_thickness_dim\hfill
        }
    }\vfill
    \clearpage
    \group_end:
}

\NewDocumentCommand{\CountAnswerRules}{O{}}
{
    \keys_set:nn { diaa / answers } { #1 }

    \begin{mdframed}[
        innerrightmargin = 10pt, innertopmargin = 20pt,
        innerleftmargin = 10pt, innerbottommargin = 20pt,
        leftmargin = 0pt,
        rightmargin = 0pt,
        linecolor=black, linewidth = 2pt]

        \setlength{\parskip}{0pt}
        \setlength{\baselineskip}{\l__diaa_answers_distance_dim}
        \foreach \i in {1,...,\l_diaa_answers_numlines_int} {\color{\l__diaa_answers_color_tl}%
            \noindent\rule{\linewidth}{\l__diaa_answers_thickness_dim}\par
        }

    \end{mdframed}
}

\ExplSyntaxOff

\begin{document}
    \begin{questions}
        \question short question \CountAnswerRules[d = 20pt]
        \question \blindtext[1]\FillAnswerRules[t = 1pt]
    \end{questions}
\end{document}
Diaa
  • 9,599

1 Answers1

3

You can use the tcolorbox height fill and text fill options for this. In the code below, I wrap the \FillAnswerRules leaders inside a tcolorbox environment defined by:

\NewTColorBox { fillAnswerRules } { O{} }
  {
    height~fill, text~fill, colback=white, boxrule=2pt, sharp~corners,
    boxsep=0pt, left=10pt, right=10pt, top=8pt, bottom=0pt, #1
  }

The tildes (~) stand for spaces here, because I do this between \ExplSyntaxOn and \ExplSyntaxOff; otherwise, you would use normal spaces instead of the tildes. Note that I specified the option sharp corners to perfectly match the appearance of the mdframed box, but the tcolorbox default with rounded corners looks better in my opinion.

I also modified the code inside the outer leaders so that the upper rule inside the box doesn't start too far from the top of the box and the lower rule doesn't come too close to the bottom of the box. This corresponds to the following lines:

\vrule width 0pt height 0.5\l__diaa_answers_distance_dim
       depth 0.5\l__diaa_answers_distance_dim
\leaders \hrule height \l__diaa_answers_thickness_dim \hfill

Here is the full code:

\documentclass{exam}
\usepackage{xparse,xcolor,tcolorbox,mdframed,pgffor,blindtext}
% The tcolorbox library 'breakable' is needed for /tcb/height fill; 'xparse' is
% not necessary here, but convenient and powerful (the use of \NewTColorBox
% may prove useful for future evolutions of the code).
\tcbuselibrary{breakable, xparse}

\renewcommand{\questionshook}{%
    \setlength{\leftmargin}{0pt}%
    \setlength{\labelwidth}{-\labelsep}%
    \setlength{\topsep}{0\baselineskip}
}

\ExplSyntaxOn

\keys_define:nn { diaa / answers }
{
    num-lines .int_set:N = \l_diaa_answers_numlines_int ,
    d .dim_set:N = \l__diaa_answers_distance_dim,
    t .dim_set:N = \l__diaa_answers_thickness_dim,
    c .tl_set:N  = \l__diaa_answers_color_tl,
    num-lines .initial:n = 3,
    d .initial:n = 10mm,
    t .initial:n = 0.2pt,
    c .initial:n = gray,
}

\NewTColorBox { fillAnswerRules } { O{} }
  {
    height~fill, text~fill, colback=white, boxrule=2pt, sharp~corners,
    boxsep=0pt, left=10pt, right=10pt, top=8pt, bottom=0pt, #1
  }

\NewDocumentCommand{\FillAnswerRules}{O{}}
{
  \begin{fillAnswerRules}
    \keys_set:nn { diaa / answers } { #1 }
    \leaders \hbox:n
      {
        \makebox[\textwidth][s]
          {
            \color{\l__diaa_answers_color_tl}
            % Vertically center the following \leaders inside a “line” that
            % is \l__diaa_answers_distance_dim high.
            \vrule width 0pt height 0.5\l__diaa_answers_distance_dim
                   depth 0.5\l__diaa_answers_distance_dim
            \leaders \hrule height \l__diaa_answers_thickness_dim \hfill
          }
      }\vfill
    \null
  \end{fillAnswerRules}
}

\NewDocumentCommand{\CountAnswerRules}{O{}}
{
    \keys_set:nn { diaa / answers } { #1 }

    \begin{mdframed}[
        innerrightmargin = 10pt, innertopmargin = 20pt,
        innerleftmargin = 10pt, innerbottommargin = 20pt,
        leftmargin = 0pt,
        rightmargin = 0pt,
        linecolor=black, linewidth = 2pt]

        \setlength{\parskip}{0pt}
        \setlength{\baselineskip}{\l__diaa_answers_distance_dim}
        \foreach \i in {1,...,\l_diaa_answers_numlines_int}
          {
            \color{\l__diaa_answers_color_tl}
            \noindent\rule{\linewidth}{\l__diaa_answers_thickness_dim}\par
          }

    \end{mdframed}
}

\ExplSyntaxOff

\begin{document}
  \begin{questions}
    \question Short question \CountAnswerRules[d=20pt, t=1pt]
    \question \blindtext[1]\FillAnswerRules[d=20pt, t=1pt]
  \end{questions}
\end{document}

enter image description here

If you replace:

\vrule width 0pt height 0.5\l__diaa_answers_distance_dim
       depth 0.5\l__diaa_answers_distance_dim

with the original

\vrule width 0pt height \l__diaa_answers_distance_dim

the second box looks like this:

enter image description here

If you further remove the top=8pt, bottom=0pt from the ... options of the \NewTColorBox { fillAnswerRules } { O{} } {...}, the second box becomes:

enter image description here

The full example looks better in my opinion.

frougon
  • 24,283
  • 1
  • 32
  • 55
  • Thanks for the informative answer. I would like to understand more how technically setting both the height and the depth to half the spacing each helps get the preferred output layout. Would you recommend me an answer that graphically explains the role of each one? – Diaa Feb 21 '20 at 09:07
  • 1
    Please see the updated answer. Basically, in the original code, each rule is at baseline level, there is a full height of \l__diaa_answers_distance_dim - \l__diaa_answers_thickness_dim above it and no space below it. With my change, vertical blank space is more equally spread around each rule. – frougon Feb 21 '20 at 09:21
  • Many thanks for the explanation. I found out that setting bottom = 0.25 <spacing> , top = 0pt with depth = 0pt yields better eye-comforting layout for me. – Diaa Feb 21 '20 at 11:35