%D \module
%D   [       file=typo-ada,
%D        version=2022.04.04,
%D          title=\CONTEXT\ Typesetting Macros,
%D       subtitle=Adaptive,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Typesetting Macros / Adaptive}

% Musical timestamp: the postponed by COVID concert of Gazpacho in Zwolle NL: a joy
% to see dedicated and talented musicians perform their work in perfection and as a
% well balanced and equiped team.

\unprotect

\ifdefined\d_adaptive_width \else
    \newdimension\d_adaptive_width
    \newdimension\d_adaptive_height
    \newdimension\d_adaptive_depth
    \newdimension\d_adaptive_line
    \newdimension\d_adaptive_hsize
    \newbox      \b_adaptive_box
\fi

\aliasdimension\usedadaptivewidth \d_adaptive_width
\aliasdimension\usedadaptiveheight\d_adaptive_height
\aliasdimension\usedadaptivedepth \d_adaptive_depth
\aliasdimension\usedadaptiveline  \d_adaptive_line
\aliasdimension\usedadaptivehsize \d_adaptive_hsize

\registerctxluafile{typo-ada}{autosuffix}

\aliased\let\usedadaptivebox\b_adaptive_box

\lettonothing\m_adaptive_color
\lettonothing\m_adaptive_alternative

\permanent\def\usedadaptivecolor      {\m_adaptive_color}
\permanent\def\usedadaptivealternative{\m_adaptive_alternative}

\permanent\protected\untraced\def\usedadaptivetotal{\dimexpr\usedadaptiveheight+\usedadaptivedepth\relax}

\definesystemattribute[adaptive][public]

\installcorenamespace{adaptive}

\installcommandhandler \??adaptive {adaptive} \??adaptive

% \appendtoks
%     %
% \to \everydefineadaptive

\setupadaptive
  [\c!foregroundstyle=,
   \c!foregroundcolor=,
   \c!color=gray,
   \c!alternative=,
   \c!rulethickness=\linewidth,
   \c!method=1,
   \c!stretch=,
   \c!shrink=,
  %\c!width=8\lineheight,  % default same as external figure
  %\c!height=6\lineheight, % default same as external figure
  %\c!strut=\v!no,
   \c!margin=2\emwidth]

\permanent\protected\def\adaptivehbox{\typo_adaptive_box\zerocount}
\permanent\protected\def\adaptivevbox{\typo_adaptive_box\plusone  }

\aliased\let\adaptivebox\adaptivehbox

\tolerant\def\typo_adaptive_box#1#*[#S#2]#*[#S#3]%
   {\ifcase#1\dontleavehmode\fi
    \begingroup
    \ifhastok={#2}%
      \lettonothing\currentadaptive
      \setupcurrentadaptive[#2]%
    \else
      \cdef\currentadaptive{#2}%
      \setupcurrentadaptive[#3]%
    \fi
    \edef\p_setups{\adaptiveparameter\c!setups}%
    \dowithnextboxcontent
      {\useadaptivestyleandcolor\c!foregroundstyle\c!foregroundcolor
       \ifcstok{\adaptiveparameter\c!strut}\v!yes
         \ifcase#1%
           \strut
         \else
            % maybe \begstrut .. \endstrut
         \fi
       \fi}
      {\ifempty\p_setups
         % there is no need for postprocessing
       \else
         \clf_setadaptive {
           method         \adaptiveparameter\c!method
           setups        {\p_setups}%
           location      {\adaptiveparameter\c!location}%
           color         {\adaptiveparameter\c!color}%
           alternative   {\adaptiveparameter\c!alternative}%
           rulethickness {\adaptiveparameter\c!rulethickness}%
         }%
       \fi
       \scratchdimen{\adaptiveparameter\c!margin}%
       % maybe when method == 2 then no \hss
       \uleaders
         \s!callback {\adaptiveattribute}%
         \ifcase#1%
           \hbox
             \s!spread \scratchdimen
             \bgroup
               \hss\box\nextbox\hss
             \egroup
           \hskip
         \else
           \vbox
             \s!spread \scratchdimen
             \bgroup
               \vss\box\nextbox\vss
             \egroup
           \vskip
         \fi
           \zeropoint
           \s!plus  \ifchkdimexpr\adaptiveparameter\c!stretch\or\lastchkdimension\else\scratchdimen\fi
           \s!minus \ifchkdimexpr\adaptiveparameter\c!shrink \or\lastchkdimension\else\scratchdimen\fi
         \endgroup}%
    \ifcase#1\hbox\else\vbox\fi}

%D \startbuffer
%D y\adaptive\hbox to5cm{x\rightarrowfill x}y\par
%D y\adaptive\hbox to5cm{x\leftarrowfill  x}y\par
%D \stopbuffer
%D
%D \typebuffer \startlinecorrection\getbuffer\stoplinecorrection

\permanent\protected\def\adaptive
  {\dowithnextbox{\adaptivecheckbox\nextbox\box\nextbox}}

%D Here is a test case, expect more:
%D
%D \starttyping
%D \startMPdefinitions
%D     def TickTock =
%D         interim linecap := squared;
%D         save p ; path p ; p := fullsquare xysized(AdaptiveWidth,.9(AdaptiveHeight+AdaptiveDepth)) ;
%D         fill p withcolor AdaptiveColor ;
%D         draw bottomboundary (p enlarged (-AdaptiveThickness) )
%D             withdashes (3*AdaptiveThickness)
%D             withpen pencircle scaled AdaptiveThickness
%D             withcolor white ;
%D     enddef ;
%D \stopMPdefinitions
%D
%D \startsetups adaptive:test
%D     \setbox\usedadaptivebox\hbox to \usedadaptivewidth yoffset -.9\usedadaptivedepth \bgroup
%D         \hss
%D         \startMPcode
%D             TickTock ;
%D         \stopMPcode
%D         \hss
%D    \egroup
%D \stopsetups
%D
%D \definecolor[adaptive:tick][.25(blue,green)]
%D \definecolor[adaptive:tock][.75(blue,green)]
%D
%D \defineadaptive
%D   [tick]
%D   [setups=adaptive:test,
%D    color=adaptive:tick,
%D    foregroundcolor=white,
%D    foregroundstyle=\infofont,
%D    strut=yes]
%D
%D \defineadaptive
%D   [tock]
%D   [tick]
%D   [color=adaptive:tock]
%D
%D \dorecurse{5}{
%D     \dostepwiserecurse{1}{150}{1}{%
%D         this~#1.##1 is~#1.##1 test~#1.##1
%D         \ifodd##1\relax
%D             \adaptivebox[tick]{\hss tick #1.##1\hss}
%D         \else
%D             \adaptivebox[tock]{\hss tock #1.##1\hss}
%D         \fi
%D     }
%D     \blank
%D }
%D
%D \setupexternalfigures
%D   [location={default,global}]
%D
%D \startsetups adaptive:test
%D     \setbox\usedadaptivebox\hbox to \usedadaptivewidth yoffset -\usedadaptivedepth \bgroup
%D         \externalfigure
%D           [cow.pdf]
%D           [width=\usedadaptivewidth,
%D            height=\usedadaptiveheight+\usedadaptivedepth]%
%D    \egroup
%D \stopsetups
%D
%D \startsetups adaptive:test
%D     \setbox\usedadaptivebox\hbox to \usedadaptivewidth yoffset .25ex \bgroup
%D         \startMPcode
%D             drawarrow ((0,0) -- (\the\usedadaptivewidth,0)) randomized (ExHeight/2);
%D         \stopMPcode
%D    \egroup
%D \stopsetups
%D
%D \dorecurse{5}{
%D     \dostepwiserecurse{1}{150}{1}{%
%D         this~#1.##1 is~#1.##1 test~#1.##1
%D         {\adaptivebox[strut=yes,setups=adaptive:test]{}}
%D     }
%D     \blank
%D }
%D
%D \page
%D
%D % How about stretch on an float (make it fit)
%D
%D \startsetups adaptive:test
%D     \setbox\usedadaptivebox\vbox to \usedadaptivetotal \bgroup
%D         \externalfigure
%D           [cow.pdf]
%D           [width=\usedadaptivewidth,
%D            height=\usedadaptivetotal]%
%D    \egroup
%D \stopsetups
%D
%D \ruledvbox to \textheight {
%D     \par \begstrut \samplefile{tufte} \endstrut \par
%D     \adaptivevbox[strut=yes,setups=adaptive:test]{\hsize\textwidth\hss}
%D     \par \begstrut \samplefile{tufte} \endstrut
%D }
%D
%D \stoptyping

%D This kind of usage for \type {\uluaders} is a bit weird but the fact that we
%D can put a callback on it combined with it being something with optional glue
%D has some potential anyway. Consider it a playground for myself. I considered
%D extending inserts with seomething like this. Very little code is involved.
%D
%D \starttyping
%D \dorecurse {2} {
%D     \setexcept[left] {\strut\red   EXCEPT L#1.1}%
%D     \samplefile{tufte}
%D     \dorecurse{12}{\setexcept[right]{\strut\blue  EXCEPT R#1.##1}}%
%D     \setexcept[left] {\strut\green EXCEPT L#1.2}%
%D     \samplefile{tufte}
%D     \blank
%D     \samplefile{tufte}
%D }
%D \stoptyping
%D
%D The ideas to keep the except within the text areas and force a page break
%D otherwise: the except depth is part of the page total & goal check.

\def\typo_adaptive_except
  {\finalizeobjectbox\nextbox
   \setbox\nextbox\hpack{\box\nextbox}%
   \smashbox\nextbox
   \clf_setadaptive {method \plustwo location {\currentexceptlocation}}%
   \uleaders
     nobreak % no a break in the par builder
     line    % kick in early (post line break, not in vpackage)
     \s!callback {\adaptiveattribute}%
     \hpack{\box\nextbox}%
     \hskip\zeropoint
   \endgroup}

\mutable\lettonothing\currentexceptlocation

\permanent\tolerant\protected\def\setexcept[#1]%
   {\dontleavehmode
    \begingroup
    % todo: outer and inner
    \cdef\currentexceptlocation{#1}%
    \dowithnextboxcs\typo_adaptive_except\hbox}

\protect