\NeedsTeXFormat{LaTeX2e} \ProvidesClass{cccbform}[2024-11-08 In the Beginning, There Was Chaos] \LoadClass{scrartcl} \RequirePackage{geometry, calc, xparse, xcolor, hyperref, tikz, fontspec, changepage, letltxmacro, textpos} % address \newcommand{\address}{% Chaos Computer Club Berlin / CCC~(B)~e.~V.\\ Marienstr.~11\\ 10117~Berlin } % page \geometry{a4paper, margin=1.5cm, inner=2.5cm} \pagestyle{empty} % fonts \setmainfont{Barlow} % colors \definecolor{fieldcolor}{gray}{0.94} \definecolor{bordercolor}{gray}{0.5} % lengths \def\deflength#1#2{\newlength{#1}\setlength{#1}{#2}} \setlength{\parindent}{0pt} \setlength{\fboxsep}{0pt} \deflength{\formfieldheight}{14pt} \deflength{\formskip}{0.5em} \deflength{\indentstep}{1cm} \deflength{\borderwidth}{0.5pt} % counters \newcounter{fieldnum} \def\@autofieldname{field\thefieldnum} % abbreviations \def\@formdefaults{% backgroundcolor=fieldcolor,bordercolor=fieldcolor,% borderwidth=0pt,charsize=\formfieldheight% } % address placement helper \newcommand{\@dinaddress}{% \begin{tikzpicture}[remember picture, overlay] \node[anchor=north west] at (current page.north west) [xshift=2.35cm, yshift=-5cm] {% \begin{minipage}{10cm} \emph{an den} \par \vspace{\formskip} \noindent\address \end{minipage} }; \end{tikzpicture} } % % % form@, fake@, and full@ variants of the form elements: % % (raw@: renamed / prefixed hyperref command) % form@: PDF form element (some viewers don't print it) % fake@: A colored box, non-interactive (but will be printed!) % full@: a stack of fake@ and form@ on top of each other % % The general parameter convention here is: height, width multiplier % - height is optional and defaults to \formfieldheight, giving the right size % for a single-line text field % - width is "mandatory" but always used followed by \linewidth, so passing an % empty argument works and is effectively equivalent to passing 1 % rename commands to make nice names available \LetLtxMacro\raw@TextField\TextField \LetLtxMacro\raw@CheckBox\CheckBox \let\CheckBox\relax % wrapped form fields with defaults filled in \NewDocumentCommand{\form@TextField}{O{\formfieldheight} m}{% \stepcounter{fieldnum} \expandafter\raw@TextField\expandafter[\@formdefaults, name=\@autofieldname, width=\dimexpr #2\linewidth - 4pt \relax, height=\dimexpr #1 - 3pt \relax ]{}% } \NewDocumentCommand{\form@MultilineTextField}{O{\formfieldheight} m}{% \stepcounter{fieldnum} \expandafter\raw@TextField\expandafter[\@formdefaults, name=\@autofieldname, multiline=true, width=\dimexpr #2\linewidth - 4pt \relax, height=\dimexpr #1 - 3pt \relax ]{}% } \NewDocumentCommand{\form@CheckBox}{}{% \stepcounter{fieldnum} \expandafter\raw@CheckBox\expandafter[\@formdefaults, name=\@autofieldname, width=\dimexpr \formfieldheight - 3pt \relax, height=\dimexpr \formfieldheight - 3pt \relax ]{}% } % fake form fields to put *under* the PDF form fields \NewDocumentCommand{\fake@TextField}{O{\formfieldheight} m}{% \begin{tikzpicture}[baseline=0.6ex] \fill[fieldcolor] (0,0) rectangle (#2\linewidth - 2\borderwidth,#1); \draw[dash pattern=on 0.5\borderwidth off 5\borderwidth,bordercolor, line width=\borderwidth, line cap=round] (0,0) -- (#2\linewidth - 2\borderwidth,0); \end{tikzpicture} } \LetLtxMacro\fake@MultilineTextField\fake@TextField \NewDocumentCommand{\fake@CheckBox}{}{% \begin{tikzpicture}[baseline=0.6ex] \fill[fieldcolor] (0,0) rectangle (\formfieldheight,\formfieldheight); \draw[bordercolor,line width=\borderwidth] (0,0) rectangle (\formfieldheight,\formfieldheight); \end{tikzpicture} } % "full" stacked version of fake + actual form field \NewDocumentCommand{\full@TextField}{O{\formfieldheight} m}{% \leavevmode\smash{\rlap{\fake@TextField[#1]{#2}}}% \raisebox{-1.5pt}{\kern-0.5pt\form@TextField[#1]{#2}}% } \NewDocumentCommand{\full@MultilineTextField}{O{\formfieldheight} m}{% \leavevmode\smash{\rlap{\fake@MultilineTextField[#1]{#2}}}% \raisebox{-1.5pt}{\kern-0.5pt\form@MultilineTextField[#1]{#2}}% } \NewDocumentCommand{\full@CheckBox}{}{% \leavevmode\smash{\rlap{\fake@CheckBox}}% \raisebox{-1.75pt}{\kern-0.5pt\form@CheckBox}% } % % % exposed form elements % Text{text…} - just text, with proper spacing \NewDocumentCommand{\Text}{m}{% \par#1\par\vspace{\formskip} } % TextField{label} - a single-line input \RenewDocumentCommand{\TextField}{m}{% \par% {\small #1\strut}\\% \full@TextField{}% \par\vspace{\formskip}% } % ShortTextField[width]{label} - a single-line input that doesn't have full width % (50% by default) \NewDocumentCommand{\ShortTextField}{O{0.5} m}{% \par% {\small #2\strut}\\% \full@TextField{#1}% \par\vspace{\formskip}% } % MultilineTextField[height]{label} - a multi-line input \NewDocumentCommand{\MultilineTextField}{O{} m}{% \par% {\small #2\strut}\\% \full@MultilineTextField[#1]{}% \par\vspace{\formskip}% } % Signature[label] - a field not fillable on the computer, big enough for a signature \NewDocumentCommand{\Signature}{O{Datum, Unterschrift}}{% \par% {\small #1\strut}\\% \fake@MultilineTextField[1.0cm]{0.5}% \par\vspace{\formskip}% } % Notes[label] - a slightly taller fake field that fills the whole width \NewDocumentCommand{\Notes}{O{Vermerke}}{% \par% {\small #1\strut}\\% \fake@MultilineTextField[1.5cm]{}% \par\vspace{\formskip}% } % Checkbox{label} - a checkbox; label can be long and will linebreak reasonably pretty \NewDocumentCommand{\Checkbox}{m}{% \par% \full@CheckBox\quad% \begin{minipage}[t]{\dimexpr \linewidth - \formfieldheight - 1em \relax}% #1% \end{minipage}% \par\vspace{\formskip}% } % CheckboxOther[width]{label} - a checkbox for a write-in option \NewDocumentCommand{\CheckboxOther}{O{0.5} m}{% \par% \full@CheckBox\quad#2\quad\full@TextField{#1}% \par\vspace{\formskip}% } % high-level structure % Section{title} - a form section \NewDocumentCommand{\Section}{m}{% \vspace{1.5cm}% {\Large\bfseries #1}% \par\vspace{2\formskip}% } % Subsection{title} - slightly smaller than section \NewDocumentCommand{\Subsection}{m}{% \vspace{1.0cm}% {\large\bfseries #1}% \par\vspace{\formskip}% } % Rule - a horizontal rule, with correct spacing \NewDocumentCommand{\Rule}{}{% \vspace{\formskip}% \rule{\linewidth}{\borderwidth}% \vspace{2\formskip}% } % RuleSection - rule followed by a small note *immediately* below, before the spacing % (e.g. to separate public / internal sections of a form) \NewDocumentCommand{\RuleSection}{m}{% \vspace{\formskip}% \leavevmode\rule{\linewidth}{\borderwidth}\\% {\details{#1}}% \par\vspace{2\formskip} } % \begin{Indented}[factor] ... \end{Indented} - indent a section \NewDocumentEnvironment{Indented}{O{}}{% \begin{adjustwidth}{#1\indentstep}{0pt}% }{% \end{adjustwidth}% } % TwoColumns{left}{right} - put two sections side-by-side \NewDocumentCommand{\TwoColumns}{m m}{% \begin{minipage}[t]{0.48\linewidth}% #1% \end{minipage}% \hfill \begin{minipage}[t]{0.48\linewidth}% #2% \end{minipage}% \par } % details{text} - (use instead of font sizes, small text) \NewDocumentCommand{\details}{m}{% {\scriptsize #1}% } % % % common title patterns % LogoTitle{title} - logo on the right, title on the left \NewDocumentCommand{\LogoTitle}{m}{ \begin{tikzpicture}[remember picture, overlay] \node[anchor=north east] at (current page.north east) [xshift=-1.5cm, yshift=-1.5cm] {% \includegraphics[width=3cm]{logo.pdf}% }; \end{tikzpicture}% \\[1cm]{\huge\bfseries #1}\\[1.5cm] } % AddressTitle{title} - title at the top, address, then the form below \NewDocumentCommand{\AddressTitle}{m}{ \@dinaddress \\[1cm]\smash{{\huge\bfseries #1}}\\[4cm] } % need to emit \Form ; hyperref generates incomplete CheckBox appearance data, % which causes problems with some viewers - so it's currently better not to % generate any at all \AtBeginDocument{ \Form[NeedAppearances=false] }