% wallcalendar.cls % % Wall Calendar % % A wall calendar document class with custom layouts and support for internationalization. % % (c) Gambhiro Bhikkhu, 2026 % Contact: https://gambhiro.github.io % % LPPL LaTeX Public Project License \NeedsTeXFormat{LaTeX2e} \ProvidesClass{wallcalendar}[2026/03/14 v1.6.0 A wall calendar document class with custom layouts and support for internationalization.] % * Preliminary Declarations \RequirePackage{pgfopts} \RequirePackage{calc} \newlength\calPaperWidth \newlength\calPaperHeight \newlength\calTextWidth \newlength\calTextHeight \newlength\@wall@leftMargin \newlength\@wall@rightMargin \newlength\@wall@topMargin \newlength\@wall@bottomMargin \newlength\@wall@trimSpace \def\@wall@eventsCsv{} \def\@wall@moonsCsv{} \def\@wall@dateAnnotationsStr{} \def\@wall@markDefaultsCsv{} \def\@wall@translationsInputFile{} \newcommand*\theMonthName{} % * Options % % Paper sizes and ratios. % % : Choral Octavo = 6.75in x 10.5in = 171.45mm x 266.7mm , r = 1.5555 % : The calendar row is 40mm (without bleed) = 1.5748in % % : When photo is above the calendar row, it has only three side bleed. % : So aspect ratio: % : (10.5in - 40mm + 3mm) / (6.75in + 6mm) = % : (266.7 - 40 + 3) / (171.45 + 6) = % : = 1.2944 \newif\ifvarnishmask \newif\ifshowframe \newif\iftranslationsAutoload \newif\ifloadBabel \newif\ifgridSurround \newif\ifsundayFirst \pgfkeys{ /wall/.is family, /wall, defaults/.style = { year = \the\year, altyear = \empty, loadBabel = false, language = english, translationsAutoload = true, dateAnnotations = true, imageFolder = {./src-images}, choralOctavoPaper, hMargin = 17mm, topMargin = 20.5mm, bottomMargin = 10mm, trimSpace = 35mm, }, year/.store in = \CalendarYear, year/.initial = \the\year, altyear/.store in = \CalendarAltYear, altyear/.initial = \empty, language/.store in = \@wall@calendarLanguage, loadBabel/.is if = loadBabel, translationsInputFile/.store in = \@wall@translationsInputFile, translationsInputFile/.initial = {}, translationsAutoload/.is if = translationsAutoload, eventsCsv/.store in = \@wall@eventsCsv, eventsCsv/.initial = {}, moonsCsv/.store in = \@wall@moonsCsv, moonsCsv/.initial = {}, markDefaultsCsv/.store in = \@wall@markDefaultsCsv, markDefaultsCsv/.initial = {}, varnishmask/.is if = varnishmask, showframe/.is if = showframe, gridSurround/.is if = gridSurround, sundayFirst/.is if = sundayFirst, dateAnnotations/.store in = \@wall@dateAnnotationsStr, dateAnnotations/.initial = true, imageFolder/.store in = \@wall@imageFolder, paperWidth/.code = {\setlength{\calPaperWidth}{#1}}, paperHeight/.code = {\setlength{\calPaperHeight}{#1}}, hMargin/.code = {\setlength{\@wall@leftMargin}{#1}% \setlength{\@wall@rightMargin}{#1}}, leftMargin/.code = {\setlength{\@wall@leftMargin}{#1}}, rightMargin/.code = {\setlength{\@wall@rightMargin}{#1}}, topMargin/.code = {\setlength{\@wall@topMargin}{#1}}, bottomMargin/.code = {\setlength{\@wall@bottomMargin}{#1}}, trimSpace/.code = {\setlength{\@wall@trimSpace}{#1}}, % Paper sizes choralOctavoPaper/.style = {paperWidth = 6.75in, paperHeight = 10.5in}, a2Paper/.style = {paperWidth = 420mm, paperHeight = 594mm}, a2PaperLandscape/.style = {paperWidth = 594mm, paperHeight = 420mm}, a3Paper/.style = {paperWidth = 297mm, paperHeight = 420mm}, a3PaperLandscape/.style = {paperWidth = 420mm, paperHeight = 297mm}, a4Paper/.style = {paperWidth = 210mm, paperHeight = 297mm}, a4PaperLandscape/.style = {paperWidth = 297mm, paperHeight = 210mm}, a5Paper/.style = {paperWidth = 148mm, paperHeight = 210mm},% r = 1.4142 = sqrt(2) prevPaper/.style = {paperWidth = 170mm, paperHeight = 250mm},% r = 1.4705 } % Debug with: \wlog{YEA: \the\@wall@bottomMargin} \DeclareOption*{% \PassOptionsToClass{\CurrentOption}{memoir} } \pgfkeys{/wall, defaults} \ProcessPgfOptions{/wall} \ProcessOptions\relax % Set the week list style based on sundayFirst option. % This macro is used in TikZ style definitions to avoid TeX conditional nesting issues. \ifsundayFirst \def\@wall@weekListStyle{week list sunday} \else \def\@wall@weekListStyle{week list} \fi % * More Declarations % ** Load memoir \LoadClass[11pt,oneside]{memoir} % ** Temp variables \newlength\@tmp@a \newlength\@tmp@b \newlength\@tmp@c \newlength\@tmp@z \newlength\@tmp@width \newlength\@tmp@height % ** Require packages \ifloadBabel \RequirePackage[\@wall@calendarLanguage]{babel} \fi \RequirePackage{nag} % Don't use [cmyk] option on xcolor. Declare text colors either in gray or cmyk (for color). \RequirePackage{xcolor} \RequirePackage{graphicx} \DeclareGraphicsExtensions{.pdf,.png,.jpg} \graphicspath{{\@wall@imageFolder}} \RequirePackage{xparse} \RequirePackage{soul} \RequirePackage{eso-pic} \RequirePackage{ccicons} \RequirePackage{multicol} \RequirePackage{wasysym} \RequirePackage{pdftexcmds} \RequirePackage{etoolbox} \RequirePackage{luacode} \RequirePackage{xcoffins} %\RequirePackage{xstring} %\RequirePackage{stringstrings} \ifloadBabel \RequirePackage[final,babel=true]{microtype} \else \RequirePackage[final]{microtype} \fi \RequirePackage{tikz} \usetikzlibrary{calendar} \usetikzlibrary{positioning} \usetikzlibrary{fit} \usetikzlibrary{shapes.geometric} % http://tex.stackexchange.com/a/20426/831 \pgfdeclarelayer{one} \pgfdeclarelayer{two} \pgfsetlayers{main,one,two} \pgfkeys{% /tikz/on layer/.code={ \pgfonlayer{#1}\begingroup \aftergroup\endpgfonlayer \aftergroup\endgroup } } % ** Colors \definecolor{textbody}{gray}{0} % pantone 1245C, RGB 191,145,12 HEX: #BF910C % pantone 1255C, CMYK 0,27.5,100,34 \definecolor{gold}{cmyk}{0,0.275,1,0.34} \definecolor{darkgold}{cmyk}{0.27,0.53,1,0.09} %\definecolor{orangegold}{cmyk}{0,0.31,0.89,0} \colorlet{orangegold}{darkgold} \colorlet{month}{darkgold} \colorlet{gridcolor}{black!30} \colorlet{weekday}{black} \colorlet{weekend}{black!50} \colorlet{mooncolor}{textbody} \definecolor{sunday}{RGB}{255,0,0} \definecolor{datenum}{gray}{0.3} \definecolor{plannerdatenum}{gray}{0} \definecolor{quote}{gray}{0.3} \definecolor{notes}{gray}{0.3} \definecolor{gridcolor}{gray}{0.5} \colorlet{pagebgcolor}{gridcolor!60} % =showframe= option colors: \colorlet{photo-frame}{blue} \colorlet{quote-frame}{red} \colorlet{heading-frame}{brown} \colorlet{calendar-frame}{orange} \colorlet{events-frame}{green} \ifshowframe \colorlet{calendarbg}{black!50} \else \colorlet{calendarbg}{white} \fi % ** Page Size and Trim Marks \ifshowtrims \setstocksize{\calPaperHeight + \@wall@trimSpace}{\calPaperWidth + \@wall@trimSpace} \setlength{\paperheight}{\calPaperHeight} \setlength{\paperwidth}{\calPaperWidth} \quarkmarks \settrims{0.5\stockheight - 0.5\paperheight}{0.5\stockwidth - 0.5\paperwidth} \settrimmedsize{\calPaperHeight}{\calPaperWidth}{*} \else\relax \setstocksize{\calPaperHeight}{\calPaperWidth} \settrims{0pt}{0pt} \settrimmedsize{\stockheight}{\stockwidth}{*} \fi %\settypeblocksize{\stockheight}{\stockwidth}{*} % TODO: calculate margins by ratios to paper size \setlrmarginsandblock{\@wall@leftMargin}{\@wall@rightMargin}{*} \setulmarginsandblock{\@wall@topMargin}{\@wall@bottomMargin}{*} \setheadfoot{0pt}{0pt} \setheaderspaces{0pt}{*}{*} \checkandfixthelayout% This will typeout values in pt. \settypeoutlayoutunit{mm}% It is useful to see layout values in mm too. \typeoutlayout \setlength{\calTextWidth}{\calPaperWidth - \@wall@leftMargin - \@wall@rightMargin} \setlength{\calTextHeight}{\calPaperHeight - \@wall@topMargin - \@wall@bottomMargin} % ** Base font sizes and indents \def\@wall@fontSize{11} \def\@wall@lineHeight{13.6} \renewcommand{\normalsize}{% \@setfontsize\normalsize\@wall@fontSize\@wall@lineHeight \abovedisplayskip 11\p@ \@plus3\p@ \@minus6\p@ \abovedisplayshortskip \z@ \@plus3\p@ \belowdisplayshortskip 6.5\p@ \@plus3.5\p@ \@minus3\p@ \belowdisplayskip \abovedisplayskip \color{textbody} \let\@listi\@listI} \normalsize \setlength{\vgap}{1.5em} \setlength{\vindent}{\vgap} \setlength{\vleftmargin}{2em} \setlength{\parskip}{0pt} \setlength{\parindent}{0pt} \setlength{\fboxsep}{0pt} % ** Helpers % % The =varnishmask= and =showframe= class options are handled by the same =\placeholder= % helper command to avoid having to use two commands and repeating the content % argument. \definecolor{varnishmask}{gray}{0} % http://tex.stackexchange.com/a/59571/831 \newcommand*{\strcmpblank}[3]{% \ifnum\pdf@strcmp{#1}{}=\z@ #2\else #3\fi } \newcommand\@placeholder@pre[1]{% \settowidth{\@tmp@width}{#1}% \settototalheight{\@tmp@height}{#1}% \def\@spacer{\rule{\@tmp@width}{0pt}\rule{0pt}{\@tmp@height}}% } % #1 -- [fill=red, opacity=0.2], additional options used for showframe % #2 -- "hasvarnish", to indicate varnishmask color replacement when =varnishmask= option is used % #3 -- the content to hold the place for \newcommand\placeholder[3][]{% \ifvarnishmask% \ifstrequal{#2}{hasvarnish}{% \@placeholder@pre{#3}% \tikz\node[fill=varnishmask, inner sep=0pt]{\@spacer};% }{}% \else% \ifshowframe% \@placeholder@pre{#3}% \tikz\node[inner sep=0pt, opacity=0.6, #1]{\@spacer};% \else% #3% \fi% \fi% } \newif\ifsixrowsmonth \sixrowsmonthfalse \newif\iffourrowsmonth \fourrowsmonthfalse \pgfkeys{/pgf/calendar/six rows month/.code={% % Monday-first: new week starts on Monday (weekday 0). % Sunday-first: new week starts on Sunday (weekday 6). \ifsundayFirst \ifnum\pgfcalendarifdateday=30\relax % Sunday (start of new week in Sunday-first) \ifnum\pgfcalendarifdateweekday=6\relax \pgfcalendarmatchestrue \fi \else \ifnum\pgfcalendarifdateday=31\relax % Sunday \ifnum\pgfcalendarifdateweekday=6\relax \pgfcalendarmatchestrue \fi % Monday (day 30 was Sunday = new row, day 31 is Monday) \ifnum\pgfcalendarifdateweekday=0\relax \pgfcalendarmatchestrue \fi \fi \fi \else \ifnum\pgfcalendarifdateday=30\relax % Monday \ifnum\pgfcalendarifdateweekday=0\relax \pgfcalendarmatchestrue \fi \else \ifnum\pgfcalendarifdateday=31\relax % Monday \ifnum\pgfcalendarifdateweekday=0\relax \pgfcalendarmatchestrue \fi % Tuesday \ifnum\pgfcalendarifdateweekday=1\relax \pgfcalendarmatchestrue \fi \fi \fi \fi% }} % Four rows month: February with exactly 28 days where the 1st falls on the % week-start day (Monday for monday-first, Sunday for sunday-first). % We detect this by checking if day 28 falls on the last column of the week. \pgfkeys{/pgf/calendar/four rows month/.code={% \ifnum\pgfcalendarifdateday=28\relax \ifsundayFirst % Sunday-first: last column is Saturday (weekday 5) \ifnum\pgfcalendarifdateweekday=5\relax \pgfcalendarmatchestrue \fi \else % Monday-first: last column is Sunday (weekday 6) \ifnum\pgfcalendarifdateweekday=6\relax \pgfcalendarmatchestrue \fi \fi \fi% }} % * Keys setup % ** /put photo \def\@wall@photo@putPhoto#1{#1} \def\@wall@photo@setYOffset{} \pgfkeys{ /put photo/.is family, /put photo, simple/.code = {% \def\@wall@photo@putPhoto##1{% \includegraphics{##1}% }% \def\@wall@photo@setYOffset{}% }, full page/.code = {% \def\@wall@photo@putPhoto##1{% \includegraphics[% keepaspectratio,% width={\calPaperWidth + 2\@t@bleed},% ]{##1}% }% \def\@wall@photo@setYOffset{}% }, full width above calendar/.code = {% \def\@wall@photo@putPhoto##1{% \includegraphics[% keepaspectratio,% width={\calPaperWidth + 2\@t@bleed},% ]{##1}% }% \def\@wall@photo@setYOffset{% \setlength{\@t@yOffset}{\@t@calendar@height + \@t@bleed + 1pt}% }% }, full width/.code = {% \def\@wall@photo@putPhoto##1{% \includegraphics[% keepaspectratio,% width={\calPaperWidth + 2\@t@bleed},% ]{##1}% }% \def\@wall@photo@setYOffset{% \setlength{\@t@yOffset}{\@t@calendar@height + \@t@bleed}% }% }, left/.code = {% \def\@wall@photo@putPhoto##1{% \begin{minipage}[t][\height][b]{\calPaperWidth + 6mm}% \raggedright \placeholder[fill=photo-frame]{hasvarnish}{% \includegraphics[width=0.66\calPaperWidth + 3mm]{##1}% }% \vfill\mbox{}% \end{minipage}% }% \def\@wall@photo@setYOffset{}% }, right/.code = {% \def\@wall@photo@putPhoto##1{% \begin{minipage}[t][\height][b]{\calPaperWidth + 6mm}% \raggedleft \placeholder[fill=photo-frame]{hasvarnish}{% \includegraphics[width=0.66\calPaperWidth + 3mm]{##1}% }% \vfill\mbox{}% \end{minipage}% }% \def\@wall@photo@setYOffset{}% }, } % ** /put quote \def\@wall@quote@putQuote#1{#1} \pgfkeys{ /put quote/.is family, /put quote, simple/.code = {% \def\@wall@quote@putQuote##1{% ##1% }% }, left/.code = {% \def\@wall@quote@putQuote##1{% \begin{minipage}[b][0.5\calPaperHeight][t]{\calPaperWidth + 6mm}% \raggedright% \mbox{}\vfill% \hspace*{8mm}% \begin{minipage}{0.33\calPaperWidth - 10mm}% \raggedleft% \quoteFmt% ##1% \end{minipage}% \end{minipage}% }% }, right/.code = {% \def\@wall@quote@putQuote##1{% \begin{minipage}[b][0.5\calPaperHeight][t]{\calPaperWidth + 6mm}% \raggedleft% \mbox{}\vfill% \begin{minipage}{0.33\calPaperWidth - 10mm}% \raggedright% \quoteFmt% ##1% \end{minipage}% \hspace*{8mm}% \end{minipage}% }% }, } % ** /Photo \newif\ifPhotoEnabled \PhotoEnabledtrue \pgfkeys{ /Photo/.is family, /Photo, init/.style = { defaults/.style = {disabled = false, file = {}, thumbFile = {}, caption = {}, bleed = 0pt, xOffset=0pt, yOffset=0pt}, disabled/.initial = false, file/.initial = {}, thumbFile/.initial = {}, caption/.initial = {}, bleed/.initial = 0pt, xOffset/.initial = 0pt, yOffset/.initial = 0pt, }, } % ** /Quote \pgfkeys{ /Quote/.is family, /Quote, init/.style = { defaults/.style = {position=center, text={}, xOffset=0pt, yOffset=0pt}, position/.initial = {}, text/.initial = {}, xOffset/.initial = 0pt, yOffset/.initial = 0pt, }, } % ** /Calendar \pgfkeys{ /Calendar/.is family, /Calendar, init/.style = { defaults/.style = {bg/.style={opacity=0.5}}, bg/.style = {}, minimum height/.initial = {}, }, } % ** /Events \pgfkeys{ /Events/.is family, /Events, init/.style = { defaults/.style = {day code = {}, marks = {}, text = {}}, day code/.initial = {}, marks/.initial = {}, text/.initial = {}, }, } % ** /Txt \pgfkeys{ /Txt/.is family, /Txt, init/.style = { defaults/.style = {text = {}}, text/.initial = {}, }, } % ** /parseMonthEvents \def\eIdx{} \def\eMaxIdx{} \def\eMark{} \def\eIsoDate{} \def\eYear{} \def\eMonth{} \def\eMonthShort{} \def\eDay{} \def\eDayText{} \def\eFootnote{} \def\eSidenote{} \pgfkeys{ /parseMonthEvents/.is family, /parseMonthEvents, month/.initial = {}, filter pred/.initial = nil, format func/.initial = nil, format cmd/.initial = {}, events csv/.initial = {}, mark defaults csv/.initial = {}, min events/.initial = {}, defaults/.style = { month = \theMonthName, filter pred = nil, format func = nil, format cmd = {\textsuperscript{\eIdx}~\eMonthShort~\eDay:~\eFootnote\par}, events csv = \@wall@eventsCsv, mark defaults csv = \@wall@markDefaultsCsv, min events = nil, }, } % ** /parseYearEvents \pgfkeys{ /parseYearEvents/.is family, /parseYearEvents, year/.initial = {}, filter pred/.initial = nil, format func/.initial = nil, format cmd/.initial = {}, events csv/.initial = {}, mark defaults csv/.initial = {}, min events/.initial = {}, defaults/.style = { year = \CalendarYear, filter pred = nil, format func = nil, format cmd = {\textsuperscript{\eIdx}~\eMonthShort~\eDay:~\eFootnote\ifnumless{\eIdx}{\eMaxIdx}{,\space}{.}}, events csv = \@wall@eventsCsv, mark defaults csv = \@wall@markDefaultsCsv, min events = nil, }, } % * Event Marks % ** Star \newcommand\StarMark{*} \newcommand\NoteStarMark{*} % ** Kite % % A kite mark that is the same height as the =\StarMark=. Note that the star (*) % character is usually higher than the x-height, so it is not in the vertical % center of its glyph box (i.e. not at the center of the character x): % % #+latex: \frame{x} \frame{*} \newlength\@wall@starHeight % Measure the star's height here, so that we are measuring with the current typeface. \newcommand\KiteMark{% \setlength{\@wall@starHeight}{\totalheightof{*}}% \begin{tikzpicture} \node (box) [ rectangle, minimum height=\@wall@starHeight, minimum width=3.4pt, inner sep=0pt, line width=0pt, ] {}; \node[ kite, draw, textbody, fill=textbody, scale=0.15, kite vertex angles=60, above=0pt of box.north, anchor=north, ] {};% \end{tikzpicture}% } % Same as \KiteMark but with scale=0.2 \newcommand\NoteKiteMark{\raisebox{1pt}{% \setlength{\@wall@starHeight}{\totalheightof{*}}% \begin{tikzpicture} \node (box) [ rectangle, minimum height=\@wall@starHeight, minimum width=3.4pt, inner sep=0pt, line width=0pt, ] {}; \node[ kite, draw, textbody, fill=textbody, scale=0.2, kite vertex angles=60, above=0pt of box.north, anchor=north, ] {};% \end{tikzpicture}% }} % ** Moons \tikzstyle{moon circle}=[ circle, inner sep=0pt, line width=0pt, minimum height=8pt, ] \newlength\@wall@moonRaise \setlength{\@wall@moonRaise}{-0.7pt} \newcommand\NewMoon{} \newcommand\FirstQuarter{} \newcommand\FullMoon{} \newcommand\LastQuarter{} \newcommand\@wall@NewMoon{% \raisebox{\@wall@moonRaise}{% \tikz\node[moon circle, fill=mooncolor] {};% }} \newcommand\@wall@FullMoon{% \raisebox{\@wall@moonRaise}{% \tikz\node[moon circle, draw, mooncolor, line width=0.3pt] {};% }} \newcommand\@wall@FirstQuarter{% \raisebox{\@wall@moonRaise}{% \begin{tikzpicture} \node [moon circle, name=waxing] {}; \path[fill=mooncolor] (waxing.north) -- (waxing.south) to[out=-180,in=-90] (waxing.west) to[out=90,in=-180] (waxing.north); \end{tikzpicture}% }} \newcommand\@wall@LastQuarter{% \raisebox{\@wall@moonRaise}{% \begin{tikzpicture} \node [moon circle, name=waning] {}; \path[fill=mooncolor] (waning.north) -- (waning.south) to[out=0,in=-90] (waning.east) to[out=90,in=0] (waning.north); \end{tikzpicture}% }} \newcommand\@wall@useDefaultMoons{% \renewcommand\NewMoon{\@wall@NewMoon}% \renewcommand\FirstQuarter{\@wall@FirstQuarter}% \renewcommand\FullMoon{\@wall@FullMoon}% \renewcommand\LastQuarter{\@wall@LastQuarter}% } \newcommand\plannerMoonSize{\@setfontsize\plannerMoonSize{14}{14}} \newcommand*\plannerMoonFormat[1]{{\plannerMoonSize #1}} \newcommand\@wall@planner@NewMoon{\plannerMoonFormat{\CIRCLE}} \newcommand\@wall@planner@FirstQuarter{\plannerMoonFormat{\LEFTcircle}} \newcommand\@wall@planner@FullMoon{\plannerMoonFormat{\Circle}} \newcommand\@wall@planner@LastQuarter{\plannerMoonFormat{\RIGHTcircle}} \newcommand\@wall@usePlannerMoons{% \renewcommand\NewMoon{\@wall@planner@NewMoon}% \renewcommand\FirstQuarter{\@wall@planner@FirstQuarter}% \renewcommand\FullMoon{\@wall@planner@FullMoon}% \renewcommand\LastQuarter{\@wall@planner@LastQuarter}% } \@wall@useDefaultMoons % ** Date Annotations % #1 = (opt) color % #2 = date as '2018-09-14' \newcommand*\dateCircle[2][textbody]{% \node[ circle, minimum height=12pt, draw, color={#1}, above right=2pt and 0pt of {cal-#2.mid}, anchor=mid, ] {};% } % #1 = (opt) color % #2 = date as '2018-09-14' \newcommand*\dateSquare[2][textbody]{% \node[ rectangle, minimum width=12pt, minimum height=12pt, draw, color={#1}, above right=2pt and 0pt of {cal-#2.mid}, anchor=mid, ] {};% } % #1 = (opt) color % #2 = date as '2018-09-14' \newcommand*\dateStart[2][textbody]{% \node (#2-rec) [ rectangle, minimum width=12pt, minimum height=12pt, above right=2pt and 0pt of {cal-#2.mid}, anchor=mid, ] {};% \node (#2-a) [above left=-6pt and 0pt of {#2-rec.north east}] {};% \node (#2-b) [above left=-6pt and -1pt of {#2-rec.north}] {};% \node (#2-c) [above left=-6pt and -3pt of {#2-rec.west}] {};% \node (#2-d) [above left=-6pt and -1pt of {#2-rec.south}] {};% \node (#2-e) [above left=-6pt and 0pt of {#2-rec.south east}] {};% \draw [color={#1}] (#2-a.mid) -- (#2-b.mid) -- (#2-c.mid) -- (#2-d.mid) -- (#2-e.mid); } % #1 = (opt) color % #2 = date as '2018-09-14' \newcommand*\dateEnd[2][textbody]{% \node (#2-rec) [ rectangle, minimum width=12pt, minimum height=12pt, above right=2pt and 0pt of {cal-#2.mid}, anchor=mid, ] {};% \node (#2-a) [above right=-6pt and 0pt of {#2-rec.north west}] {};% \node (#2-b) [above right=-6pt and -1pt of {#2-rec.north}] {};% \node (#2-c) [above right=-6pt and -3pt of {#2-rec.east}] {};% \node (#2-d) [above right=-6pt and -1pt of {#2-rec.south}] {};% \node (#2-e) [above right=-6pt and 0pt of {#2-rec.south west}] {};% \draw [color={#1}] (#2-a.mid) -- (#2-b.mid) -- (#2-c.mid) -- (#2-d.mid) -- (#2-e.mid); } % #1 = (opt) color % #2 = date as '2018-09-14' \newcommand*\dateUnder[2][textbody]{% \node (#2-rec) [ rectangle, minimum width=12pt, minimum height=12pt, above right=3pt and 0pt of {cal-#2.mid}, anchor=mid, ] {};% \draw [color={#1}] (#2-rec.south west) -- (#2-rec.south east); } % * User Commands % ** \textbackslash SetPhoto % \SetPhoto[bleed=3mm]{June} \newcommand\SetPhoto[2][]{% \pgfkeys{% /Photo/#2/.is family, /Photo/#2, /Photo/init, defaults, file={#2}, #1% }% } % ** \textbackslash SetCalendar % \SetCalendar[bg={opacity=0.8}]{June} \newcommand\SetCalendar[2][]{% \pgfkeys{% /Calendar/#2/.is family, /Calendar/#2, /Calendar/init, defaults, #1% }% } % ** \textbackslash SetQuote % \SetQuote[position=top right, text align=right]{June}{% % first line\\ % second line\\ % third line\\ % fourth line % } \newcommand\SetQuote[3][]{% \pgfkeys{% /Quote/#2/.is family, /Quote/#2, /Quote/init, defaults, text={#3}, #1% }% } % ** \textbackslash SetEvents % FIXME: Needs at least a =\SetEvents{#2}= to set defaults. % \SetEvents[yshift={10pt}]{August}{% % marks % }{% % text % } % % #1 : options % #2 : month name % #3 : marks % #4 : text \newcommand\SetEvents[4][]{% \pgfkeys{% /Events/#2/.is family, /Events/#2, /Events/init, defaults, marks={#3}, text={#4}, #1% }% } % ** \textbackslash MonthPage % The =/MonthPage= key is set in-place for each page, not collecting options per month. \pgfkeys{ /MonthPage/.is family, /MonthPage, layout/.style = {layout handlers/#1/.get = \@wall@month@doLayout}, put photo/.style = {/put photo/#1}, put quote/.style = {/put quote/#1}, defaults/.style = {layout = small landscape, put photo = simple, put quote = simple}, layout handlers/.cd, full page/.initial = \@wall@fullPageLayout, small landscape/.initial = \@wall@smallLandscapeLayout, photo and notes/.initial = \@wall@photoAndNotesLayout, large calendar/.initial = \@wall@largeCalendarLayout, } % FIXME: handle case when no =\SetPhoto{#2}= was called, and so options are not % initialized. This happens for example when bleed value is missing, and =.get= % returns =\@val=: % % : ! Missing number, treated as zero. % : % : \@val % : l.30 \MonthPage[layout=full page]{August} % % For now, just make sure there is a =\SetPhoto{August}= before =\MonthPage{August}=. % % \MonthPage[layout=full page]{June} \newcommand\MonthPage[2][]{% \pgfkeys{/MonthPage, defaults, #1}% \@wall@month@doLayout{#2}% } % ** \textbackslash SetTxt % \SetTxt{August Quote}{% % The text of the quote. % } % % #1 : key % #2 : text \newcommand\SetTxt[2]{% \pgfkeys{% /Txt/#1/.is family, /Txt/#1, /Txt/init, defaults, text={#2}, }% } % ** \textbackslash txt % \txt{August Quote} % % #1: text key \newcommand\txt[1]{% \pgfkeys{/Txt/#1/text/.get=\@val}% \@val% } % ** \textbackslash parseMonthEvents \def\@t@monthName{} \def\@t@eventsCsv{} \def\@t@markDefaultsCsv{} \def\@t@filterPred{} \def\@t@formatFunc{} \def\@t@formatCmd{} \def\@t@minEvents{} % Font format for event mark numbers (footnote-index style) placed above day numbers in calendars \newcommand\monthMarkFmt{\fontsize{7}{7}\selectfont\color{textbody}} \newcommand\symbolSpace{\thinspace} \newcommand\symbolSeparator{,\symbolSpace} % Semicolon to close the tikz calendar. Necessary before starting to use \node % or \draw commands. \newcommand\semicolonEndTikzCalendar{% ;% } % #1 = option keys \newcommand*\parseMonthEvents[1][]{% \pgfkeys{/parseMonthEvents, defaults, #1, month/.get=\@t@monthName, filter pred/.get=\@t@filterPred, format func/.get=\@t@formatFunc, format cmd/.get=\@t@formatCmd, events csv/.get=\@t@eventsCsv, mark defaults csv/.get=\@t@markDefaultsCsv, min events/.get=\@t@minEvents, }% \luadirect{ require("wallcalendar-helpers.lua") monthEvents( \luastring{\@t@monthName}, \@t@filterPred, \@t@formatFunc, \luastringO{\@t@formatCmd}, \luastring{\@t@eventsCsv}, \luastring{\@t@markDefaultsCsv}, \@t@minEvents )}} % ** \textbackslash parseYearEvents \def\@t@yearNum{} % #1 = option keys \newcommand*\parseYearEvents[1][]{% \pgfkeys{/parseYearEvents, defaults, #1, year/.get=\@t@year, filter pred/.get=\@t@filterPred, format func/.get=\@t@formatFunc, format cmd/.get=\@t@formatCmd, events csv/.get=\@t@eventsCsv, mark defaults csv/.get=\@t@markDefaultsCsv, min events/.get=\@t@minEvents, }% \luadirect{ require("wallcalendar-helpers.lua") yearEvents( tonumber(\@t@year), \@t@filterPred, \@t@formatFunc, \luastringO{\@t@formatCmd}, \luastring{\@t@eventsCsv}, \luastring{\@t@markDefaultsCsv}, \@t@minEvents )}} % ** \textbackslash parseMonthMarksDayText % % NOTE: Tikz will not work with parsing options as with =\parseMonthEvents=. % % It will parse the CSV file set with the =eventsCsv= class option. \newlength\dayTextXshift \newlength\dayTextYshift \setlength{\dayTextXshift}{0pt} \setlength{\dayTextYshift}{0pt} \newlength\markNumberAbove \newlength\markNumberRight \setlength{\markNumberAbove}{-10pt} \setlength{\markNumberRight}{-3pt} \newlength\markDayTextAbove \newlength\markDayTextRight \setlength{\markDayTextAbove}{-10pt} \setlength{\markDayTextRight}{-3pt} % Suffix appended to the calendar day node name when positioning event marks. % Empty by default (marks reference the day node itself). Layouts with % separate day-number nodes (e.g.\ rigel / photo-and-notes) set this to % {-daynumber} so marks are positioned relative to the day number, avoiding % overflow on the last grid column. \def\@wall@markNodeSuffix{} \newcommand\parseMonthMarksDayText{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksDayText(\luastring{\theMonthName}, nil, \luastring{\@wall@eventsCsv}) tex.sprint(';') }} \newcommand\parseMonthMarksDayTextMonth[1]{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksDayText(\luastring{#1}, nil, \luastring{\@wall@eventsCsv}) tex.sprint(';') }} % ** \textbackslash parseMonthMarksDayTextUsing \newcommand*\parseMonthMarksDayTextUsing[1]{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksDayText(\luastring{\theMonthName}, nil, \luastring{#1}) }} \newcommand\parseMonthMarksDayTextMonthUsing[2]{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksDayText(\luastring{#1}, nil, \luastring{#2}) }} % ** \textbackslash parseMonthMarksDayTextInlineUsing \newcommand*\parseMonthMarksDayTextInlineUsing[1]{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksDayTextInline(\luastring{\theMonthName}, nil, \luastring{#1}) }} % ** \textbackslash parseMonthMarksNote \newcommand*\parseMonthMarksNote{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksNote(\luastring{\theMonthName}, nil, \luastring{\@wall@eventsCsv}, \luastring{\@wall@markDefaultsCsv}, \luastring{\@wall@markNodeSuffix}) }} % ** \textbackslash parseMonthMarksNoteUsing \newcommand*\parseMonthMarksNoteUsing[1]{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksNote(\luastring{\theMonthName}, nil, \luastring{#1}, \luastring{\@wall@markDefaultsCsv}, \luastring{\@wall@markNodeSuffix}) }} % ** \textbackslash parseMonthInlineNotes \newcommand*\parseMonthInlineNotes{% \luadirect{ require("wallcalendar-helpers.lua") monthInlineNotes(\luastring{\theMonthName}, nil, \luastring{\@wall@eventsCsv}, \luastring{\@wall@markDefaultsCsv}) }} % * Page Layouts % ** Initial setup % % Applying a blank, bare pagestyle, the layout macro should position the parts of % the page. \makepagestyle{month} \makeoddhead{month}{}{}{} \makeevenhead{month}{}{}{} \makeoddfoot{month}{}{}{} \makeevenfoot{month}{}{}{} \pagestyle{month} % These elements are common to all layouts. One Coffin for each part of the % page: % % - Photo % - Quote % - Calendar % - Events \NewCoffin\@wall@pageWrap \NewCoffin\@wall@photo \NewCoffin\@wall@quote \NewCoffin\@wall@calendar \NewCoffin\@wall@events \NewCoffin\@wall@notepad \NewCoffin\@wall@photoPageWrap \NewCoffin\@wall@notesPageWrap % ** Formatting hooks and temp vars \newlength\@t@bleed \newlength\@t@rightOffset \newlength\@t@minipageWidth \newlength\@t@calendar@minimumHeight \newlength\@t@calendar@height \newlength\@t@calendar@hmargin \newlength\@t@calendar@verticalSpacing \newlength\@t@calendar@dayYshift \newlength\@t@calendar@dayXshift \newlength\@t@calendar@gridHeight \newlength\@t@calendar@gridHeightFourRows \newlength\@t@calendar@gridHeightFiveRows \newlength\@t@calendar@gridHeightSixRows \newlength\@t@xOffset \newlength\@t@yOffset \def\@t@file{} \newcommand*\monthFmt{}% \newcommand*\yearFmt{}% \newcommand*\dayLetterColor{}% \newcommand*\dayLetterFmt{}% \newcommand*\dayTextFmt{}% \newcommand*\quoteFmt{}% \newcommand*\headingFmt{}% \newcommand*\calendarFmt{}% \newcommand*\eventsFmt{}% \newcommand*\dayLetterTextFmt[1]{#1} % ** Layout Reset, \textbackslash @wall@layout@reset % % A reset macro for the beginning of a layout, to make sure parameters are not % carried from one layout to the next. \newcommand\@wall@layout@reset{% \renewcommand*\monthFmt{}% \renewcommand*\yearFmt{}% \renewcommand*\dayLetterColor{}% \renewcommand*\dayLetterFmt{}% \renewcommand*\dayTextFmt{}% \renewcommand*\quoteFmt{}% \renewcommand*\headingFmt{}% \renewcommand*\calendarFmt{}% \renewcommand*\eventsFmt{}% \def\@t@file{}% \setlength{\@t@calendar@height}{0pt}% \setlength{\@t@calendar@hmargin}{0pt}% \setlength{\@t@calendar@dayYshift}{0pt}% \setlength{\@t@calendar@dayXshift}{0pt}% \setlength{\@t@bleed}{0pt}% \setlength{\@t@rightOffset}{0pt}% \setlength{\@t@minipageWidth}{0pt}% \setlength{\@t@xOffset}{0pt}% \setlength{\@t@yOffset}{0pt}% \setlength{\@t@calendar@gridHeight}{0pt}% \setlength{\@t@calendar@gridHeightFourRows}{0pt}% \setlength{\@t@calendar@gridHeightFiveRows}{0pt}% \setlength{\@t@calendar@gridHeightSixRows}{0pt}% \def\@wall@markNodeSuffix{}% \renewcommand\monthMarkFmt{\fontsize{7}{7}\selectfont\color{textbody}}% } % ** Full Page, \textbackslash @wall@fullPageLayout % *** Setup formatting hooks % % Renew this in your document when customizing the variables for this layout. % % This must not introduce paragraph breaks or whitespace characters, so follow % everything with =%=. \newcommand\fullPageFmt{% \renewcommand*\monthFmt{\LARGE}% \renewcommand*\yearFmt{\LARGE}% \renewcommand*\dayLetterColor{}% \renewcommand*\dayLetterFmt{\tiny}% \renewcommand*\dayTextFmt{\small}% \renewcommand*\quoteFmt{}% \renewcommand*\headingFmt{\centering}% \renewcommand*\calendarFmt{\centering}% \renewcommand*\eventsFmt{\setlength{\parindent}{0pt}\raggedleft\footnotesize}% } % *** Init \newcommand\@wall@fullPageLayout[2][]{% \makeatletter \renewcommand*\theMonthName{#2} \@wall@layout@reset \fullPageFmt \colorlet{weekday}{black} \colorlet{weekend}{black!70} % *** Lengths and sizes % Bleed: \pgfkeys{/Photo/#2/bleed/.get=\@val} \setlength{\@t@bleed}{\@val} \def\@t@monthnum{\monthToNum{#2}} % Calendar height: % % 40mm = 1.5748 inch % 43mm = 1.6929 inch \setlength{\@t@calendar@height}{40mm + \@t@bleed} % See if there was a height given in the options \pgfkeys{/Calendar/#2/minimum height/.get=\@val} \ifx\@val\empty \relax \else \setlength{\@t@calendar@height}{\@val + \@t@bleed} \fi % Calendar horizontal margin: \setlength{\@t@calendar@hmargin}{20pt} % Calculate offsets: % NOTE: the -4pt and -2pt offset is somehow necessary for the sides to align % with the edges \setlength{\@t@rightOffset}{\@t@bleed +\@t@calendar@hmargin -4pt} \setlength{\@t@minipageWidth}{\calPaperWidth -2\@t@calendar@hmargin -2pt} % *** Set the coffin contents % Page wrap: \SetHorizontalCoffin\@wall@pageWrap{% \color{white}% \rule{\textwidth}{0pt}% \rule{0pt}{\textheight}% } % Photo: \pgfkeys{/Photo/#2/file/.get=\@t@file} \SetHorizontalCoffin\@wall@photo{% \placeholder[fill=photo-frame]{hasvarnish}{% \@wall@photo@putPhoto{\@t@file}% }% } % Quote: \SetHorizontalCoffin\@wall@quote{% \placeholder[fill=quote-frame]{}{% \begin{minipage}{\linewidth}% \quoteFmt \pgfkeys{/Quote/#2/text/.get=\@val}% \@val% \end{minipage}% }% } % Calendar: \SetHorizontalCoffin\@wall@calendar{% \ifvarnishmask\relax \else \begin{tikzpicture} \node (bg) [ fill = calendarbg, opacity = 0.5, minimum width = {\calPaperWidth + 2\@t@bleed}, anchor=north west, /Calendar/#2/bg, % override the style, in case bleed was set above minimum height = {\@t@calendar@height}, ] at (0,0) {}; \node (heading) [ below right=10pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=heading-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \headingFmt {\monthFmt\@tr@monthNumName{\@t@monthnum}} \hfill \strcmpblank{\CalendarAltYear}{% {\yearFmt\CalendarYear}% }{% {\yearFmt\CalendarYear/\CalendarAltYear}% }% \end{minipage}% }% }; \node (calendar) [ below right=35pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=calendar-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \calendarFmt \hspace*{-2pt}\tikz{\tikzMonthCalendar@fullpage{\@t@monthnum};}% \end{minipage}% }% }; \node (events) [ below=0pt of calendar.south west, anchor=north west, ] {% \placeholder[fill=events-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \eventsFmt \pgfkeys{/Events/#2/text/.get=\@val}% \@val% \end{minipage}% }% }; \end{tikzpicture}% \fi }% \SetHorizontalCoffin % *** Join the coffins \@wall@photo@setYOffset \pgfkeys{/Photo/#2/xOffset/.get=\@val} \addtolength{\@t@xOffset}{\@val} \pgfkeys{/Photo/#2/yOffset/.get=\@val} \addtolength{\@t@yOffset}{\@val} % NOTE: a small whitespace is visible on the left edge of the page when bleed is 0pt, a space must be getting in somewhere. \JoinCoffins*\@wall@pageWrap[l,t]\@wall@photo[l,t](-\spinemargin -\@t@bleed + \@t@xOffset, \uppermargin + \@t@bleed + \@t@yOffset) \pgfkeys{/Quote/#2/xOffset/.get=\@val} \setlength{\@t@xOffset}{\@val} \pgfkeys{/Quote/#2/yOffset/.get=\@val} \setlength{\@t@yOffset}{\@val} \JoinCoffins*\@wall@pageWrap[l,t]\@wall@quote[l,t](\@t@xOffset, \@t@yOffset) \JoinCoffins*\@wall@pageWrap[l,b]\@wall@calendar[l,b](-\spinemargin -\@t@bleed, \textheight +\uppermargin -\paperheight -\@t@bleed) \makeatother % *** Typeset \clearpage \TypesetCoffin\@wall@pageWrap% }% \@wall@fullPageLayout % *** Tikz calendar % #1 = number of the month with leading zero \newcommand*{\tikzMonthCalendar@fullpage}[1]{% \pgfkeys{/Events/\monthName{#1}/marks/.get=\@eventmarks}% \calendar (cal#1) [alnitak, dates=\CalendarYear-#1-01 to \CalendarYear-#1-last] \@eventmarks;% } % ** Small Landscape, \textbackslash @wall@smallLandscapeLayout % *** Setup formatting hooks % % Renew this in your document when customizing the variables for this layout. % % This must not introduce paragraph breaks or whitespace characters, so follow % everything with =%=. \newcommand\smallLandscapeFmt{% \renewcommand*\monthFmt{\LARGE}% \renewcommand*\yearFmt{\LARGE}% \renewcommand*\dayLetterColor{}% \renewcommand*\dayLetterFmt{\tiny}% \renewcommand*\dayTextFmt{\small}% \renewcommand*\quoteFmt{\centering}% \renewcommand*\headingFmt{\centering}% \renewcommand*\calendarFmt{\centering}% \renewcommand*\eventsFmt{\setlength{\parindent}{0pt}\raggedright\footnotesize}% \setlength{\@t@calendar@minimumHeight}{85mm}% \setlength{\@t@calendar@hmargin}{20pt}% % 5mm: day headings % 20mm: events % 6.5mm: white space \setlength{\@t@calendar@verticalSpacing}{20mm + 5mm + 6.5mm}% } % *** Init \newcommand\@wall@smallLandscapeLayout[2][]{% \makeatletter \renewcommand*\theMonthName{#2} \@wall@layout@reset \smallLandscapeFmt \colorlet{weekday}{black} \colorlet{weekend}{black!70} % *** Lengths and sizes % Bleed: \pgfkeys{/Photo/#2/bleed/.get=\@val} \setlength{\@t@bleed}{\@val} \def\@t@monthnum{\monthToNum{#2}} % Calendar height: % % Default height to fit: % % - day headings % - days in a grid, 6 rows % - events % - bottom bleed \setlength{\@t@calendar@height}{\@t@calendar@minimumHeight + \@t@bleed} % See if there was a height given in the options \pgfkeys{/Calendar/#2/minimum height/.get=\@val} \ifx\@val\empty \relax \else \setlength{\@t@calendar@height}{\@val + \@t@bleed} \fi % Calculate offsets: \setlength{\@tmp@a}{\@t@calendar@verticalSpacing} \setlength{\@tmp@b}{\@t@calendar@height -\@tmp@a} \setlength{\@t@calendar@dayYshift}{0.1666\@tmp@b}% 1/6 = 0.1666 \setlength{\@t@calendar@gridHeightSixRows}{\@tmp@b} \setlength{\@t@calendar@gridHeightFiveRows}{\@tmp@b -0.1666\@tmp@b} \setlength{\@t@calendar@gridHeightFourRows}{\@tmp@b -0.3332\@tmp@b} % NOTE: the -4pt and -2pt offset is somehow necessary for the sides to align % with the edges \setlength{\@t@rightOffset}{\@t@bleed +\@t@calendar@hmargin -4pt} \setlength{\@t@minipageWidth}{\calPaperWidth -2\@t@calendar@hmargin -2pt} \setlength{\@t@calendar@dayXshift}{0.1428\@t@minipageWidth}% 1/7 = 0.1428 % *** Set the coffin contents % Page wrap: \SetHorizontalCoffin\@wall@pageWrap{% \color{white}% \rule{\textwidth}{0pt}% \rule{0pt}{\textheight}% } % Photo: \pgfkeys{/Photo/#2/file/.get=\@t@file} \SetHorizontalCoffin\@wall@photo{% \placeholder[fill=photo-frame]{hasvarnish}{% \@wall@photo@putPhoto{\@t@file}% }% } % Quote: \SetHorizontalCoffin\@wall@quote{% \placeholder[fill=quote-frame]{}{% \begin{minipage}{\linewidth}% \quoteFmt \pgfkeys{/Quote/#2/text/.get=\@val}% \@val% \end{minipage}% }% } % Calendar: \SetHorizontalCoffin\@wall@calendar{% \ifvarnishmask\relax \else \begin{tikzpicture} \node (bg) [ fill = calendarbg, opacity = 1, minimum width = {\calPaperWidth + 2\@t@bleed}, anchor=north west, /Calendar/#2/bg, % override the style, in case bleed was set above minimum height = {\@t@calendar@height}, ] at (0,0) {}; \node (heading) [ below right=10pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=heading-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \headingFmt {\monthFmt\@tr@monthNumName{\@t@monthnum}} \hfill \strcmpblank{\CalendarAltYear}{% {\yearFmt\CalendarYear}% }{% {\yearFmt\CalendarYear/\CalendarAltYear}% }% \end{minipage}% }% }; \node (calendar) [ below right=35pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=calendar-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \calendarFmt \hspace*{-5pt}% FIXME \tikz{\tikzMonthCalendar@smallLandscape{\@t@monthnum};}% \end{minipage}% }% }; \node (events) [ above right=10mm and {\@t@rightOffset} of bg.south west, anchor=south west, ] {% \placeholder[fill=events-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \eventsFmt \pgfkeys{/Events/#2/text/.get=\@val}% \@val% \end{minipage}% }% }; \end{tikzpicture}% \fi }% \SetHorizontalCoffin % *** Join the coffins % % Only using =yOffset=. The quote should be centered on the x axis. % % Join coffins so that the photo is in a fixed position, i.e. relative to the % pageWrap, not relative to other coffins. It prevents accidental shifts when the % other coffins are empty (when =varnishmask= is on) or have too much content. % The quote has to be centered between the photo and the calendar with manual tweaking. % The height of the quote is not known, the height of the calendar plus its heading is not known. % TODO move the photo with /Photo/#2/xOffset and yOffset as at the full page layout \pgfkeys{/Quote/#2/yOffset/.get=\@val} \setlength{\@t@yOffset}{\@val} \JoinCoffins*\@wall@photo[hc,b]\@wall@quote[hc,t](0pt, \@t@yOffset) \pgfkeys{/Photo/#2/yOffset/.get=\@val} \setlength{\@t@yOffset}{\@val} % NOTE: Taking the bottom edge of the photo as fixed. % yOffset must be set to pull the photo down into position \JoinCoffins*\@wall@pageWrap[hc,t]\@wall@photo[hc,b](0pt, \uppermargin + \@t@yOffset) % Calendar is aligned to the bottom of the page. \JoinCoffins*\@wall@pageWrap[hc,b]\@wall@calendar[hc,b](0pt, \textheight +\uppermargin -\paperheight -\@t@bleed) \makeatother % *** Typeset \clearpage \TypesetCoffin\@wall@pageWrap% }% \@wall@smallLandscapeLayout % *** Tikz calendar % #1 = number of the month with leading zero \newcommand*{\tikzMonthCalendar@smallLandscape}[1]{% \pgfkeys{/Events/\monthName{#1}/marks/.get=\@eventmarks}% \calendar (cal#1) [betelgeuse, dates=\CalendarYear-#1-01 to \CalendarYear-#1-last] \@eventmarks;% } % ** Photo And Notes, \textbackslash @wall@photoAndNotesLayout % *** Setup formatting hooks \newcommand\notepadContent{% \begin{minipage}{\@t@minipageWidth}% \setlength\parindent{0pt}% \setlength\parskip{10pt}% \color{black!40}% \ifsixrowsmonth \dotfill\par \dotfill\par \else \iffourrowsmonth \dotfill\par \dotfill\par \dotfill\par \dotfill\par \dotfill\par \dotfill\par \else \dotfill\par \dotfill\par \dotfill\par \dotfill\par \fi \fi \end{minipage}% } \newcommand\photoAndNotesFmt{% \renewcommand*\monthFmt{\LARGE}% \renewcommand*\yearFmt{\LARGE}% \renewcommand*\dayLetterColor{}% \renewcommand*\dayLetterFmt{\small}% \renewcommand*\dayLetterTextFmt[1]{\tiny\textls*{\MakeUppercase{##1}}}% \renewcommand*\dayTextFmt{\small}% \renewcommand*\quoteFmt{\centering}% \renewcommand*\headingFmt{\centering}% \renewcommand*\calendarFmt{\centering}% \renewcommand*\eventsFmt{\setlength{\parindent}{0pt}\raggedright\fontsize{6}{8}\selectfont}% \def\@wall@markNodeSuffix{-daynumber}% \setlength{\markNumberAbove}{-6pt}% \setlength{\@t@calendar@minimumHeight}{\calPaperHeight - 30mm}% \setlength{\@t@calendar@hmargin}{20pt}% % white space to allow: % - month and year label % - notepad area % - extra white space \setlength{\@t@calendar@verticalSpacing}{30mm}% } % *** Init \newcommand\@wall@photoAndNotesLayout[2][]{% \makeatletter \renewcommand*\theMonthName{#2} \@wall@layout@reset \photoAndNotesFmt \pgfkeys{/Photo/#2/disabled/.get=\@val} \ifdefstring{\@val}{true}{\PhotoEnabledfalse}{\PhotoEnabledtrue} % *** Lengths and sizes % % Bleed: \pgfkeys{/Photo/#2/bleed/.get=\@val} \setlength{\@t@bleed}{\@val} \def\@t@monthnum{\monthToNum{#2}} % Determine if this month needs six rows: \settowidth{\@tmp@z}{% \begin{tikzpicture} \calendar [ dates=\CalendarYear-\@t@monthnum-01 to \CalendarYear-\@t@monthnum-last, execute at begin day scope={ \ifdate{six rows month}{\global\sixrowsmonthtrue}{\global\sixrowsmonthfalse} \ifdate{four rows month}{\global\fourrowsmonthtrue}{} \ifdate{day of month=29}{\global\fourrowsmonthfalse}{} }, ]; \end{tikzpicture} } % Calendar height: % % Default height to fit: % % - day headings % - days in a grid, 6 rows % - events % - bottom bleed \setlength{\@t@calendar@height}{\@t@calendar@minimumHeight + \@t@bleed} % See if there was a height given in the options \pgfkeys{/Calendar/#2/minimum height/.get=\@val} \ifx\@val\empty \relax \else \setlength{\@t@calendar@height}{\@val + \@t@bleed} \fi % Calculate offsets: \setlength{\@tmp@a}{\@t@calendar@verticalSpacing} \setlength{\@tmp@b}{\@t@calendar@height -\@tmp@a} \setlength{\@t@calendar@dayYshift}{0.1666\@tmp@b}% 1/6 = 0.1666 \setlength{\@t@calendar@gridHeightSixRows}{\@tmp@b} \setlength{\@t@calendar@gridHeightFiveRows}{\@tmp@b -0.1666\@tmp@b} \setlength{\@t@calendar@gridHeightFourRows}{\@tmp@b -0.3332\@tmp@b} % NOTE: the -4pt and -2pt offset is somehow necessary for the sides to align % with the edges \setlength{\@t@rightOffset}{\@t@bleed +\@t@calendar@hmargin -4pt} \setlength{\@t@minipageWidth}{\calPaperWidth -2\@t@calendar@hmargin -2pt} \setlength{\@t@calendar@dayXshift}{0.1428\@t@minipageWidth}% 1/7 = 0.1428 % *** Set the coffin contents % Photo page wrap: \SetHorizontalCoffin\@wall@photoPageWrap{% \color{white}% \rule{\textwidth}{0pt}% \rule{0pt}{\textheight}% } % Notes page wrap: \SetHorizontalCoffin\@wall@notesPageWrap{% \color{white}% \rule{\textwidth}{0pt}% \rule{0pt}{\textheight}% } % Photo: \ifPhotoEnabled \pgfkeys{/Photo/#2/file/.get=\@t@file} \SetHorizontalCoffin\@wall@photo{% \placeholder[fill=photo-frame]{hasvarnish}{% \@wall@photo@putPhoto{\@t@file}% }% } \fi % Quote: \ifPhotoEnabled \SetHorizontalCoffin\@wall@quote{% \placeholder[fill=quote-frame]{}{% \begin{minipage}{\linewidth}% \quoteFmt \pgfkeys{/Quote/#2/text/.get=\@val}% \@val% \end{minipage}% }% } \fi % Notepad: \SetHorizontalCoffin\@wall@notepad{% \placeholder[fill=quote-frame]{}{% \notepadContent% }% } % Calendar: \SetHorizontalCoffin\@wall@calendar{% \ifvarnishmask\relax \else \begin{tikzpicture} \node (bg) [ fill = calendarbg, opacity = 1, minimum width = {\calPaperWidth + 2\@t@bleed}, anchor=north west, /Calendar/#2/bg, % override the style, in case bleed was set above minimum height = {\@t@calendar@height}, ] at (0,0) {}; \node (heading) [ below right=10pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=heading-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \headingFmt {\monthFmt\@tr@monthNumName{\@t@monthnum}} \hfill \strcmpblank{\CalendarAltYear}{% {\yearFmt\CalendarYear}% }{% {\yearFmt\CalendarYear/\CalendarAltYear}% }% \end{minipage}% }% }; \node (calendar) [ below right=35pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=calendar-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \calendarFmt \hspace*{-5pt}% FIXME \tikz{\tikzMonthCalendar@photoAndNotes{\@t@monthnum};}% \end{minipage}% }% }; \node (events) [ below right=5pt and 0pt of calendar.south west, anchor=north west, ] {% \placeholder[fill=events-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \eventsFmt \pgfkeys{/Events/#2/text/.get=\@val}% \@val% \end{minipage}% }% }; \end{tikzpicture}% \fi }% \SetHorizontalCoffin % *** Join the coffins \ifPhotoEnabled \@wall@photo@setYOffset \pgfkeys{/Photo/#2/xOffset/.get=\@val} \addtolength{\@t@xOffset}{\@val} \pgfkeys{/Photo/#2/yOffset/.get=\@val} \addtolength{\@t@yOffset}{\@val} \JoinCoffins*\@wall@photoPageWrap[l,t]\@wall@photo[l,t](-\spinemargin -\@t@bleed + \@t@xOffset, \uppermargin + \@t@bleed + \@t@yOffset) \pgfkeys{/Quote/#2/xOffset/.get=\@val} \setlength{\@t@xOffset}{\@val} \pgfkeys{/Quote/#2/yOffset/.get=\@val} \setlength{\@t@yOffset}{\@val} \JoinCoffins*\@wall@photoPageWrap[l,t]\@wall@quote[l,t](\@t@xOffset, \@t@yOffset) \fi % Calendar is aligned to the top of the notes page. \JoinCoffins*\@wall@notesPageWrap[hc,t]\@wall@calendar[hc,t](0pt, 0pt) % Notepad is aligned to the bottom of the notes page. \JoinCoffins*\@wall@notesPageWrap[hc,b]\@wall@notepad[hc,b](0pt, 0pt) \makeatother % *** Typeset \ifPhotoEnabled \clearpage \TypesetCoffin\@wall@photoPageWrap% \fi \clearpage \TypesetCoffin\@wall@notesPageWrap% }% \@wall@photoAndNotesLayout % *** Tikz calendar % #1 = number of month with leading zero \newcommand*{\tikzMonthCalendar@photoAndNotes}[1]{% \pgfkeys{/Events/\monthName{#1}/marks/.get=\@eventmarks}% \calendar (cal#1) [rigel, dates=\CalendarYear-#1-01 to \CalendarYear-#1-last] \@eventmarks;% } % ** Large Calendar, \textbackslash @wall@largeCalendarLayout % *** Setup formatting hooks \newcommand\largeCalendarFmt{% \renewcommand*\monthFmt{\LARGE}% \renewcommand*\yearFmt{\LARGE}% \renewcommand*\dayLetterColor{}% \renewcommand*\dayLetterFmt{\small}% \renewcommand*\dayLetterTextFmt[1]{\tiny\textls*{\MakeUppercase{##1}}}% \renewcommand*\dayTextFmt{\small}% \renewcommand*\quoteFmt{}% \renewcommand*\headingFmt{\centering}% \renewcommand*\calendarFmt{\centering}% \renewcommand*\eventsFmt{\setlength{\parindent}{0pt}\raggedright\fontsize{6}{8}\selectfont}% \setlength{\@t@calendar@minimumHeight}{112mm}% \setlength{\@t@calendar@hmargin}{20pt}% % white space to allow: % - month and year label % - notepad area % - extra white space \setlength{\@t@calendar@verticalSpacing}{30mm}% } % *** Init \newcommand\@wall@largeCalendarLayout[2][]{% \makeatletter \renewcommand*\theMonthName{#2} \@wall@layout@reset \largeCalendarFmt % *** Lengths and sizes % Bleed: \pgfkeys{/Photo/#2/bleed/.get=\@val} \setlength{\@t@bleed}{\@val} \def\@t@monthnum{\monthToNum{#2}} % Determine if this month needs six rows: \settowidth{\@tmp@z}{% \begin{tikzpicture} \calendar [ dates=\CalendarYear-\@t@monthnum-01 to \CalendarYear-\@t@monthnum-last, execute at begin day scope={ \ifdate{six rows month}{\global\sixrowsmonthtrue}{\global\sixrowsmonthfalse} \ifdate{four rows month}{\global\fourrowsmonthtrue}{} \ifdate{day of month=29}{\global\fourrowsmonthfalse}{} }, ]; \end{tikzpicture} } % Calendar height: % % Default height to fit: % % - day headings % - days in a grid, 6 rows % - events % - bottom bleed \setlength{\@t@calendar@height}{\@t@calendar@minimumHeight + \@t@bleed} % See if there was a height given in the options \pgfkeys{/Calendar/#2/minimum height/.get=\@val} \ifx\@val\empty \relax \else \setlength{\@t@calendar@height}{\@val + \@t@bleed} \fi % Calculate offsets: \setlength{\@tmp@a}{\@t@calendar@verticalSpacing} \setlength{\@tmp@b}{\@t@calendar@height -\@tmp@a} \setlength{\@t@calendar@dayYshift}{0.1666\@tmp@b}% 1/6 = 0.1666 \setlength{\@t@calendar@gridHeightSixRows}{\@tmp@b} \setlength{\@t@calendar@gridHeightFiveRows}{\@tmp@b -0.1666\@tmp@b} \setlength{\@t@calendar@gridHeightFourRows}{\@tmp@b -0.3332\@tmp@b} % NOTE: the -4pt and -2pt offset is somehow necessary for the sides to align % with the edges \setlength{\@t@rightOffset}{\@t@bleed +\@t@calendar@hmargin -4pt} \setlength{\@t@minipageWidth}{\calPaperWidth -2\@t@calendar@hmargin -2pt} \setlength{\@t@calendar@dayXshift}{0.1428\@t@minipageWidth}% 1/7 = 0.1428 % *** Set the coffin contents % Photo wrap: \SetHorizontalCoffin\@wall@pageWrap{% \color{white}% \rule{\textwidth}{0pt}% \rule{0pt}{\textheight}% } % Photo: \pgfkeys{/Photo/#2/file/.get=\@t@file} \SetHorizontalCoffin\@wall@photo{% % Varnishmask placeholder is in 'put photo/left' and 'put photo/right'. \@wall@photo@putPhoto{\@t@file}% } % Quote: \SetHorizontalCoffin\@wall@quote{% \ifvarnishmask\relax \else \placeholder[fill=quote-frame]{}{% \pgfkeys{/Quote/#2/text/.get=\@val}% \@wall@quote@putQuote{\@val}% }% \fi } % Calendar: \SetHorizontalCoffin\@wall@calendar{% \ifvarnishmask\relax \else \begin{tikzpicture} \node (bg) [ fill = calendarbg, opacity = 1, minimum width = {\calPaperWidth + 2\@t@bleed}, anchor=north west, /Calendar/#2/bg, % override the style, in case bleed was set above minimum height = {\@t@calendar@height}, ] at (0,0) {}; \node (heading) [ below right=2pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=heading-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \headingFmt {\monthFmt\@tr@monthNumName{\@t@monthnum}} \hfill \strcmpblank{\CalendarAltYear}{% {\yearFmt\CalendarYear}% }{% {\yearFmt\CalendarYear/\CalendarAltYear}% }% \end{minipage}% }% }; \node (calendar) [ below right=35pt and {\@t@rightOffset} of bg.north west, anchor=north west, ] {% \placeholder[fill=calendar-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \calendarFmt \hspace*{-5pt}% FIXME \tikz{\tikzMonthCalendar@largeCalendar{\@t@monthnum};}% \end{minipage}% }% }; \node (events) [ below=105mm of bg.north, anchor=north, ] {% \placeholder[fill=events-frame]{}{% \begin{minipage}{\@t@minipageWidth}% \eventsFmt \pgfkeys{/Events/#2/text/.get=\@val}% \@val% \end{minipage}% }% }; \end{tikzpicture}% \fi }% \SetHorizontalCoffin % *** Join the coffins \@wall@photo@setYOffset \pgfkeys{/Photo/#2/xOffset/.get=\@val} \addtolength{\@t@xOffset}{\@val} \pgfkeys{/Photo/#2/yOffset/.get=\@val} \addtolength{\@t@yOffset}{\@val} \JoinCoffins*\@wall@pageWrap[l,t]\@wall@photo[l,t](-\spinemargin -\@t@bleed + \@t@xOffset, \uppermargin + \@t@bleed + \@t@yOffset) \pgfkeys{/Quote/#2/xOffset/.get=\@val} \setlength{\@t@xOffset}{\@val} \pgfkeys{/Quote/#2/yOffset/.get=\@val} \setlength{\@t@yOffset}{\@val} \JoinCoffins*\@wall@pageWrap[l,t]\@wall@quote[l,t](-\spinemargin -\@t@bleed + \@t@xOffset, \uppermargin + \@t@bleed + \@t@yOffset) \JoinCoffins*\@wall@pageWrap[l,b]\@wall@calendar[l,t](-\spinemargin -\@t@bleed, \textheight +\uppermargin -\paperheight -\@t@bleed +\@t@calendar@height +10mm) \makeatother % *** Typeset \clearpage \TypesetCoffin\@wall@pageWrap% }% \@wall@largeCalendarLayout % *** Tikz calendar % #1 = number of month with leading zero \newcommand*{\tikzMonthCalendar@largeCalendar}[1]{% \pgfkeys{/Events/\monthName{#1}/marks/.get=\@eventmarks}% \calendar (cal#1) [rigel, dates=\CalendarYear-#1-01 to \CalendarYear-#1-last] \@eventmarks;% } % ** Tikz styles % *** day letter headings \tikzstyle{day letter headings}=[% day heading/.style={black!90}, execute before day scope={% \ifdate{day of month=1}{% \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}% \pgfmathsetlength\pgf@ya{\tikz@lib@cal@yshift}% \foreach \d in {0,1,2,3,4,5,6} {% \pgf@xa=\d\pgf@xa% \pgftransformxshift{\pgf@xa}% \pgftransformyshift{\pgf@ya}% \pgftransformyshift{4pt}% \node (d\d) [anchor=base, day heading] {\dayLetterFmt\@tr@columnDayLetter{\d}};% };% }{}% },% ] % *** day fullday headings \tikzstyle{day fullday headings}=[% day heading/.style={black!90}, execute before day scope={% \ifdate{day of month=1}{% \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}% \pgfmathsetlength\pgf@ya{\tikz@lib@cal@yshift}% \foreach \d in {0,1,2,3,4,5,6} {% \pgf@xa=\d\pgf@xa% \pgftransformxshift{\pgf@xa}% \pgftransformyshift{\pgf@ya}% \pgftransformyshift{4pt}% \node (d\d) [anchor=base, day heading] {\dayLetterTextFmt{\@tr@columnDayName{\d}}};% };% }{}% },% ] % *** days grid \newcount\gridRows \newcount\gridLines \newcount\n \tikzstyle{days grid}=[% execute before day scope={% \ifdate{day of month=1}{% % % Determine if the grid is five or six rows % % 31 day months \ifdate{between=01-01 and 01-31, between=03-01 and 03-31, between=05-01 and 05-31, between=07-01 and 07-31, between=08-01 and 08-31, between=10-01 and 10-31, between=12-01 and 12-31}{% % Monday-first: 6 rows if 1st is Sat or Sun. Sunday-first: 6 rows if 1st is Fri or Sat. \ifsundayFirst \ifdate{Friday,Saturday}{% \gridRows=6% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightSixRows}% }{% \gridRows=5% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightFiveRows}% } \else \ifdate{Saturday,Sunday}{% \gridRows=6% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightSixRows}% }{% \gridRows=5% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightFiveRows}% } \fi }{ % 30 day months and February \ifdate{between=02-01 and 02-last}{% % 4-row February: non-leap year where Feb 1 is the week-start day. % Monday-first: 4 rows if 1st is Mon. Sunday-first: 4 rows if 1st is Sun. \ifsundayFirst \ifdate{Sunday}{% \luadirect{ local date = require("wallcalendar-date.lua") if not date.isleapyear(\CalendarYear) then tex.sprint("\\gridRows=4\\relax") tex.sprint("\\setlength\\@t@calendar@gridHeight{\\@t@calendar@gridHeightFourRows}") else tex.sprint("\\gridRows=5\\relax") tex.sprint("\\setlength\\@t@calendar@gridHeight{\\@t@calendar@gridHeightFiveRows}") end }% }{% \gridRows=5% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightFiveRows}% }% \else \ifdate{Monday}{% \luadirect{ local date = require("wallcalendar-date.lua") if not date.isleapyear(\CalendarYear) then tex.sprint("\\gridRows=4\\relax") tex.sprint("\\setlength\\@t@calendar@gridHeight{\\@t@calendar@gridHeightFourRows}") else tex.sprint("\\gridRows=5\\relax") tex.sprint("\\setlength\\@t@calendar@gridHeight{\\@t@calendar@gridHeightFiveRows}") end }% }{% \gridRows=5% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightFiveRows}% }% \fi }{% % Monday-first: 6 rows if 1st is Sun. Sunday-first: 6 rows if 1st is Sat. \ifsundayFirst \ifdate{Saturday}{% \gridRows=6% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightSixRows}% }{% \gridRows=5% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightFiveRows}% } \else \ifdate{Sunday}{% \gridRows=6% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightSixRows}% }{% \gridRows=5% \setlength\@t@calendar@gridHeight{\@t@calendar@gridHeightFiveRows}% } \fi } } % % Horizontal lines % \gridLines=\gridRows \ifgridSurround \advance\gridLines by 1 \n=0 \draw [ gridcolor, line width=0.3pt, xshift=-0.5\@t@calendar@dayXshift, yshift=0.5\@t@calendar@dayYshift, ] (0,{-\n\@t@calendar@dayYshift}) -- (7\@t@calendar@dayXshift,{-\n\@t@calendar@dayYshift}); \fi \foreach \n in {1,2,3,4,5,6} { \ifnum\n<\gridLines \draw [ gridcolor, line width=0.3pt, xshift=-0.5\@t@calendar@dayXshift, yshift=0.5\@t@calendar@dayYshift, ] (0,{-\n\@t@calendar@dayYshift}) -- (7\@t@calendar@dayXshift,{-\n\@t@calendar@dayYshift}); \fi } % % Vertical lines % \gridLines=7 \ifgridSurround \advance\gridLines by 1 \n=0 \draw [ gridcolor, line width=0.3pt, xshift=-0.5\@t@calendar@dayXshift, yshift=0.5\@t@calendar@dayYshift, ] ({\n\@t@calendar@dayXshift},0) -- ({\n\@t@calendar@dayXshift},{-\gridRows\@t@calendar@dayYshift}); \fi \foreach \n in {1,2,3,4,5,6,7} { \ifnum\n<\gridLines \draw [ gridcolor, line width=0.3pt, xshift=-0.5\@t@calendar@dayXshift, yshift=0.5\@t@calendar@dayYshift, ] ({\n\@t@calendar@dayXshift},0) -- ({\n\@t@calendar@dayXshift},{-\gridRows\@t@calendar@dayYshift}); \fi } % % If we are not drawing the surrounding lines, it looks better to hide % some of the top and bottom edges % \ifgridSurround\relax \else \draw [ color=white, line width=6pt, xshift=-0.5\@t@calendar@dayXshift, yshift={0.5\@t@calendar@dayYshift -1pt}, ] (0,0) -- (7\@t@calendar@dayXshift,0); \draw [ color=white, line width=6pt, xshift=-0.5\@t@calendar@dayXshift, yshift={0.5\@t@calendar@dayYshift +1pt}, ] (0,-\gridRows\@t@calendar@dayYshift) -- (7\@t@calendar@dayXshift,-\gridRows\@t@calendar@dayYshift); \fi }{}% } ] % *** headings background rule \tikzstyle{headings background rule}=[ background rule/.style={black!90, line width=0.3pt, yshift={0.3\@t@calendar@dayYshift -3pt}}, execute before day scope={% \ifdate{day of month=1}{% \draw [ xshift=-0.5\@t@calendar@dayXshift, yshift=0.5\@t@calendar@dayYshift, background rule, ] (0,0) -- (7\@t@calendar@dayXshift,0); }{}% } ] % *** headings background bar \tikzstyle{headings background bar}=[ headings background rule, background rule/.style={black!20, line width=10pt, yshift={0.3\@t@calendar@dayYshift +3.5pt}}, ] % ** week list sunday % % A variant of TikZ's =week list= that starts weeks on Sunday instead of Monday. % Sunday (weekday 6 in TikZ) is placed in column 0, Monday to Saturday in columns % 1 to 6. The row advances after Saturday. % % Based on https://texample.net/tikz/examples/changing-the-default-calendar-layout/ % week list sunday: a variant of TikZ's week list that starts weeks on Sunday. \tikzstyle{week list sunday}=[ execute before day scope={% \ifdate{day of month=1}{\ifdate{equals=\pgfcalendarbeginiso}{}{% \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@month@yshift}% \pgftransformyshift{-\pgf@y}% }}{}% }, execute at begin day scope={% \pgfmathsetlength\pgf@x{\tikz@lib@cal@xshift}% \ifnum\pgfcalendarcurrentweekday=6 \c@pgf@counta=0 \else \c@pgf@counta=\pgfcalendarcurrentweekday \advance\c@pgf@counta by 1 \fi \pgf@x=\c@pgf@counta\pgf@x \pgftransformxshift{\pgf@x}% }, execute after day scope={% \ifdate{Saturday}{% \pgfmathsetlength{\pgf@y}{\tikz@lib@cal@yshift}% \pgftransformyshift{-\pgf@y}% }{}% }, tikz@lib@cal@width=7 ] % ** Tikz calendar styles % *** Betelgeuse, days in a grid % (Betelgeuse is Alpha Orionis) \tikzstyle{betelgeuse}=[ days grid, \@wall@weekListStyle, day xshift=\@t@calendar@dayXshift, day yshift=\@t@calendar@dayYshift, headings background bar, day letter headings, day heading/.style={black!90, yshift={-0.3\@t@calendar@dayYshift}}, every day/.append style={anchor=base, inner xsep=0pt, yshift={-0.25\baselineskip}}, day text={\dayTextFmt\%d-}, ] % *** Rigel, days in a grid, inline notes % % (Rigel is Beta Orionis) % Command to print day number, so that it can be reused outside the day code block: % % #1 : day node name to position at, \pgfcalendarsuggestedname in the day code block % #2 : this node name postfix, -daynumber in the day code block % #3 : day number, use \tikzdaytext in the day code block \newcommand*\calDayNumberNode[3]{% \node (#1#2) [ below right=3.5pt and 8pt of #1.north west, anchor=north west, inner sep=0pt, ] {#3}; } \tikzstyle{rigel}=[ days grid, \@wall@weekListStyle, day xshift=\@t@calendar@dayXshift, day yshift=\@t@calendar@dayYshift, day fullday headings, day heading/.style={black!90, yshift={-0.3\@t@calendar@dayYshift}}, every day/.append style={anchor=base, inner xsep=0pt, yshift={-0.25\baselineskip}}, execute at begin day scope={ \ifdate{Sunday}{\def\dayLetterColor{\color{sunday}}}{\def\dayLetterColor{\color{weekday}}}% }, day text={\dayTextFmt\dayLetterColor\%d-}, day code={% \node [ minimum width=\@t@calendar@dayXshift, minimum height=\@t@calendar@dayYshift, name=\pgfcalendarsuggestedname, every day, ] {};% \calDayNumberNode{\pgfcalendarsuggestedname}{-daynumber}{\tikzdaytext}% }, ] % *** Aldebaran, like Rigel but without heading bg bar \tikzstyle{aldebaran}=[ days grid, \@wall@weekListStyle, day xshift=\@t@calendar@dayXshift, day yshift=\@t@calendar@dayYshift, day letter headings, day heading/.style={black!90, yshift={-0.3\@t@calendar@dayYshift}}, every day/.append style={anchor=base, inner xsep=0pt, yshift={-0.25\baselineskip}}, day text={\dayTextFmt\%d-}, ] % *** Alnitak, days in one line % % (Alnitak is Zeta Orionis) \tikzstyle{alnitak}=[ day list right, day xshift={0pt}, every month/.append style={anchor=base, inner xsep=0pt, yshift=4mm, xshift=-\widthof{\space}}, day text={\dayTextFmt\%d-}, every day/.append style={anchor=base, inner xsep=0pt}, execute before day scope={ % % === Moving the day number === % % Uniform cell width with half-cell negative offset so days reach closer % to the bounding box edges. Cell width = linewidth / (lastday - 0.5). \pgfcalendarjuliantodate{\pgfcalendarendjulian}{\currentyear}{\currentmonth}{\lastday}% \pgfmathparse{\linewidth / (\lastday - 0.5)}% \ifnum\pgfcalendarcurrentday=1\relax% \pgftransformxshift{0}% \else% \pgftransformxshift{\pgfmathresult}% \fi% % % === Weekday letter above the day === % \ifdate{weekend}{\def\dayLetterColor{\color{weekend}}}{\def\dayLetterColor{\color{weekday}}}% \node[anchor=base,yshift=5.5mm,inner sep=0pt]{% \dayLetterColor\dayLetterFmt\@tr@dayLetter{\pgfcalendarcurrentweekday}% };% }, ] % * Year Planner % ** Tikz calendar styles % *** Year Planner Portrait \newcommand\plannerPortraitMonthFmt{\fontsize{13}{13}\selectfont\color{darkgold}} \newcommand\plannerPortraitDayFmt{\fontsize{12}{12}\selectfont\color{plannerdatenum}} \tikzstyle{year planner portrait}=[ \@wall@weekListStyle, day xshift=20pt, day yshift=18pt, month text={\plannerPortraitMonthFmt\@tr@monthNumName{\pgfcalendarcurrentmonth}}, day text={\plannerPortraitDayFmt\%d-}, every month/.append style={% anchor=south, inner xsep=0pt, yshift=5mm, xshift=2.5mm, }, day letter headings, day heading/.style={gray, xshift=0pt, scale=0.85}, month label above centered, every day/.style={anchor=mid}, ] % *** Year Planner Landscape \newcommand\plannerLandscapeDateDayFont{} \newcommand\plannerLandscapeDayFont{} \newcommand\plannerLandscapeMonthFont{} \newcommand\plannerLandscapeMonthFmt{% \plannerLandscapeMonthFont% \fontsize{15}{18}\selectfont% \color{gold}\bfseries% } \newcommand\plannerLandscapeDayFmt{% \plannerLandscapeDayFont% \fontsize{11}{12}\selectfont% } \newcommand*\plannerLandscapeDateDayFormat[1]{% \plannerLandscapeDateDayFont% \fontsize{8}{11}\selectfont% #1% } \newcommand\plannerLandscapeBeginDayScopeHook{% \ifdate{weekend}{\color{black!60}}{} } \newlength\plannerLandscapeDayXShift \newlength\plannerLandscapeMonthYShift % Assuming 25mm to fit 'September' \setlength{\@tmp@a}{\calPaperWidth - \@wall@leftMargin - \@wall@rightMargin - 25mm} % Max week shift is 6 = Sunday. 31 days + 6 = 37. 1/37 = 0.027 \setlength{\plannerLandscapeDayXShift}{0.027\@tmp@a} % Assuming 10mm for day headings (M T W...) and some padding \setlength{\@tmp@a}{\calPaperHeight - \@wall@topMargin - \@wall@bottomMargin - 10mm} % 1/12 = 0.0833 \setlength{\plannerLandscapeMonthYShift}{0.0833\@tmp@a} \tikzstyle{year planner landscape}=[ month list, day xshift=\plannerLandscapeDayXShift, month yshift=\plannerLandscapeMonthYShift, every month/.append style={anchor=base, inner xsep=0pt}, month text={\plannerLandscapeMonthFmt \%mt}, day text={\plannerLandscapeDayFmt \%d-}, every day/.append style={anchor=base, inner xsep=0pt}, month label left, execute at begin day scope={ \plannerLandscapeBeginDayScopeHook % Week divider line at end of week as a thin rectangle % Sunday-first: divider after Saturday (weekday 5). Monday-first: after Sunday (weekday 6). \ifsundayFirst \n=5\else \n=6\fi \ifnum\pgfcalendarcurrentweekday=\n \node[ rectangle, inner sep=0pt, minimum width={0.4pt}, minimum height={\plannerLandscapeMonthYShift}, xshift={0.5\plannerLandscapeDayXShift}, yshift=2pt, draw=none, fill=black!80, ]{};% \fi % Weekday headers in January \ifdate{between=01-01 and 01-31}{ \def\l{\ifcase\pgfcalendarcurrentweekday M\or T\or W\or T\or F\or S\or S\fi}% \ifdate{weekend}{\def\daylabelcolor{weekend}}{\def\daylabelcolor{weekday}}% \node[anchor=south,yshift=5mm,inner sep=0pt]{\color{\daylabelcolor}\plannerLandscapeDateDayFormat{\l}};% }{} % Weekday headers in December \ifdate{between=12-01 and 12-31}{ \pgftransformyshift{-3mm}% \def\l{\ifcase\pgfcalendarcurrentweekday M\or T\or W\or T\or F\or S\or S\fi}% \ifdate{weekend}{\def\daylabelcolor{weekend}}{\def\daylabelcolor{weekday}}% \node[anchor=south,yshift=5mm,inner sep=0pt]{\color{\daylabelcolor}\plannerLandscapeDateDayFormat{\l}};% }{} } ] % *** Year Planner Landscape Grid \newcommand\plannerGridMonthFont{} \newcommand\plannerGridDateDayFont{} \newcommand\plannerGridNotesFont{} \newcommand\plannerGridDayFont{} \newcommand\plannerGridYearNumberFont{} \newcommand\plannerGridYearNumberFmt{% \plannerGridYearNumberFont% \fontsize{11}{11}\selectfont% \color{white}% } \newcommand\plannerGridMonthFmt{% \plannerGridMonthFont% \fontsize{9.5}{9.5}\selectfont% \color{white}% } \newcommand\plannerGridDayFmt{% \plannerGridDayFont% \fontsize{10.5}{10.5}\selectfont% } \newcommand\plannerGridDateDayFmt{% \plannerGridDateDayFont% \fontsize{8.5}{8.5}\selectfont% \color{black!80}% } \newcommand{\plannerGridNotesFmt}{% \plannerGridNotesFont% \fontsize{9}{9}\selectfont% } \newcommand\plannerGridBeginDayScopeHook{% \ifdate{weekend}{\color{black!60}}{} } \newlength\plannerGridColXShift \newlength\plannerGridRowYShift \newlength\plannerGridCalendarWidth \newlength\plannerGridCalendarHeight \newlength\plannerGridDayHeadingsHeight \newlength\plannerGridMonthNamesWidth \newlength\plannerGridNotesHeight \setlength{\plannerGridNotesHeight}{7mm} \setlength{\plannerGridDayHeadingsHeight}{5mm} \setlength{\plannerGridMonthNamesWidth}{5mm} \setlength{\plannerGridCalendarWidth}{\calPaperWidth - \@wall@leftMargin - \@wall@rightMargin - \plannerGridMonthNamesWidth} \setlength{\plannerGridCalendarHeight}{\calPaperHeight - \@wall@topMargin - \@wall@bottomMargin - \plannerGridNotesHeight} \setlength{\@tmp@a}{\plannerGridCalendarWidth - \plannerGridMonthNamesWidth} % 37 columns. 1/37 = 0.027. Max week shift is 6 = Sunday. 31 days + 6 = 37. \setlength{\plannerGridColXShift}{0.027\@tmp@a} \setlength{\@tmp@a}{\plannerGridCalendarHeight - 2\plannerGridDayHeadingsHeight} % 12 rows. 1/12 = 0.0833 \setlength{\plannerGridRowYShift}{0.0833\@tmp@a} \newcounter{verticalCount} \tikzstyle{year planner landscape grid days}=[ month list, day xshift=\plannerGridColXShift, month yshift=\plannerGridRowYShift, day text={\plannerGridDayFmt \%d-}, every day/.append style={anchor=base, yshift=-4pt, inner xsep=0pt}, execute at begin day scope={% % White fill to cover the page background color \node (cell) [ rectangle, fill = white, minimum height = \plannerGridRowYShift - 1pt, minimum width = \plannerGridColXShift - 1pt, xshift = -0.5\plannerGridColXShift, yshift = 4.5pt, ] {};% % % Week start marker (left triangle). Monday-first: Monday (0). Sunday-first: Sunday (6). \ifsundayFirst \n=6\else \n=0\fi \ifnum\pgfcalendarcurrentweekday=\n \node (a) [above left = 10pt and -3.5pt of cell.west] {}; \node (b) [below left = 10pt and -3.5pt of cell.west] {}; \node (c) [right = 5pt of cell.west] {}; \path [on layer = one, fill = pagebgcolor] (a.south) -- (b.north) -- (c.west) -- (a.south);% \fi % % Week end marker (right triangle). Monday-first: Sunday (6). Sunday-first: Saturday (5). \ifsundayFirst \n=5\else \n=6\fi \ifnum\pgfcalendarcurrentweekday=\n \node (a) [above left = 10pt and {-3.5pt + 0.6pt} of cell.east] {}; \node (b) [below left = 10pt and {-3.5pt + 0.6pt} of cell.east] {}; \node (c) [right = {5pt - 0.6pt} of cell.east] {}; \path [on layer = two, fill = white] (a.south) -- (b.north) -- (c.west) -- (a.south);% \fi % \plannerGridBeginDayScopeHook% }, ] % *** Year Planner Compact \newcommand\pf{\fontsize{8}{8}\selectfont} \newcommand\plannerCompactDayFmt{\fontsize{9}{9}\selectfont} \newcommand\plannerCompactMonthFmt{\bfseries\fontsize{10}{10}\selectfont\color{month}} \newcommand\plannerCompactYearFmt{\plannerCompactMonthFmt} \newcommand\plannerCompactWeekNumFmt{\itshape\fontsize{7}{7}\selectfont\color{plannerdatenum}} \newcommand*\plannerCompactDateDayFormat[1]{\fontsize{8}{11}\selectfont #1} \newcommand\plannerCompactBeginDayScopeHook{% \ifdate{weekend}{\color{weekend}}{\color{weekday}} } \newcount\weeknum \newif\ifstartswithlastyear \luadirect{ require("wallcalendar-helpers.lua") setStartsWithLastYear(\luastring{\CalendarYear})} \tikzstyle{year planner compact}=[ \@wall@weekListStyle, month yshift=0pt, day text={\plannerCompactDayFmt\%d-}, every day/.style={anchor=mid},% % execute before day scope={% % % Month corner node % \ifdate{day of month=1}{% \node (month-\pgfcalendarcurrentmonth-top-left) {}; }{} % % Year number % \ifdate{equals=01-01}{% \node [ above left = \tikz@lib@cal@yshift and 35pt of month-01-top-left.north west, inner sep = 0pt, anchor = south east, ] {\plannerCompactYearFmt\CalendarYear};% }{} % % Weekday headers in January % \ifdate{equals=01-01}{% \weeknum=1 \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift}% \pgfmathsetlength\pgf@ya{\tikz@lib@cal@yshift}% \foreach \d in {0,1,2,3,4,5,6} {% \pgf@xa=\d\pgf@xa% \pgftransformxshift{\pgf@xa}% \pgftransformyshift{\pgf@ya}% \pgftransformyshift{4pt}% \node (d\d) [anchor=base, inner sep=0pt] {% \ifsundayFirst % Sunday-first: column 0 = Sunday (weekend), column 6 = Saturday (weekend) \ifnum\d=0 \plannerCompactDateDayFormat{\color{weekend}\@tr@columnDayLetter{\d}}% \else \ifnum\d=6 \plannerCompactDateDayFormat{\color{weekend}\@tr@columnDayLetter{\d}}% \else \plannerCompactDateDayFormat{\@tr@columnDayLetter{\d}}% \fi \fi \else % Monday-first: columns 5,6 = Saturday,Sunday (weekend) \ifnum\d=5 \plannerCompactDateDayFormat{\color{weekend}\@tr@columnDayLetter{\d}}% \else \ifnum\d=6 \plannerCompactDateDayFormat{\color{weekend}\@tr@columnDayLetter{\d}}% \else \plannerCompactDateDayFormat{\@tr@columnDayLetter{\d}}% \fi \fi \fi };% };% }{}% % % Week number % Determine the weekday that starts a new week row \ifsundayFirst \n=6\else \n=0\fi \ifnum\pgfcalendarcurrentweekday=\n \node [ anchor = east, xshift = -13pt, yshift = -0.5pt, inner sep = 0pt, ] {\parbox{6mm}{\centering\plannerCompactWeekNumFmt \the\weeknum.}}; \advance\weeknum by 1 \fi % When first week doesn't start on the first day of the week \ifdate{equals=01-01}{% \ifnum\pgfcalendarcurrentweekday=\n\relax \else \ifstartswithlastyear \node [ anchor = east, xshift = -13pt, yshift = -0.5pt, inner sep = 0pt, ] {\parbox{6mm}{\centering\plannerCompactWeekNumFmt 53.}}; \else \node [ anchor = east, xshift = -13pt, yshift = -0.5pt, inner sep = 0pt, ] {\parbox{6mm}{\centering\plannerCompactWeekNumFmt \the\weeknum.}}; \advance\weeknum by 1 \fi \fi }{}% },% % execute at begin day scope={% % % Month name % \ifdate{day of month=1}{% \node [ below left = 0pt and 35pt of month-\pgfcalendarcurrentmonth-top-left.north west, inner sep = 0pt, anchor = north west, rotate = -90, ] {% \plannerCompactMonthFmt\@tr@monthNumName{\pgfcalendarcurrentmonth}% }; }{} % % Draw border lines between months % \ifdate{day of month=1}{% \ifdate{equals=01-01}{% % Don't draw border in January }{% \pgfmathsetlength\pgf@xa{\tikz@lib@cal@xshift} \pgfmathsetlength\pgf@ya{\tikz@lib@cal@yshift} % % Compute column index from weekday \ifsundayFirst \ifnum\pgfcalendarcurrentweekday=6 \n=0\else \n=\pgfcalendarcurrentweekday \advance\n by 1 \fi \else \n=\pgfcalendarcurrentweekday \fi % No bottom and left edge when day is in the first column \ifnum\n=0\relax \else % % Bottom border, from left side to the number \draw [ gridcolor, line width = 0.5pt, ] ({-\n\pgf@xa -0.5\pgf@xa}, -0.5\pgf@ya) -- (-0.5\pgf@xa, -0.5\pgf@ya); % Vertical edge on the left side of the number \draw [ gridcolor, line width = 0.5pt, ] (-0.5\pgf@xa, 0.5\pgf@ya + 0.25pt) -- (-0.5\pgf@xa, -0.5\pgf@ya - 0.25pt); \fi % % Top border, from the number to the right side \advance \n by -6 \draw [ gridcolor, line width = 0.5pt, ] (-0.5\pgf@xa, 0.5\pgf@ya) -- ({-\n\pgf@xa +0.5\pgf@xa}, 0.5\pgf@ya); }% }{}% % \plannerCompactBeginDayScopeHook }, ] % ** Helpers \newcommand\plannerMarksDayTextCSV{\@wall@eventsCsv} \newcommand\plannerMarksNoteCSV{\@wall@eventsCsv} \newcommand\plannerMoonsCSV{\@wall@moonsCsv} \newcommand\plannerMarkDefaultsCsv{} \newcommand\@wall@plm[1]{% \luadirect{ require("wallcalendar-helpers.lua") monthMarksDayText(\luastring{#1}, nil, \luastring{\plannerMarksDayTextCSV}) monthMarksDayText(\luastring{#1}, nil, \luastring{\plannerMoonsCSV}) tex.sprint(';') }} \newcommand\@wall@plmYear{% \luadirect{ require("wallcalendar-helpers.lua") yearMarksDayText(tonumber(\CalendarYear), nil, \luastring{\plannerMarksDayTextCSV}) yearMarksDayText(tonumber(\CalendarYear), nil, \luastring{\plannerMoonsCSV}) tex.sprint(';') if isEqual(\luastring{\@wall@dateAnnotationsStr}, "true") then drawAnnotations(tonumber(\CalendarYear), nil, \luastring{\plannerMarksDayTextCSV}) end }} \newcommand\@wall@plNotes{% \luadirect{ require("wallcalendar-helpers.lua") yearMarksNote(tonumber(\CalendarYear), nil, \luastring{\plannerMarksNoteCSV}, \luastring{\plannerMarkDefaultsCsv}, false) }} \newcommand\@wall@plNotesOneCalendar{% \luadirect{ require("wallcalendar-helpers.lua") yearMarksNote(tonumber(\CalendarYear), nil, \luastring{\plannerMarksNoteCSV}, \luastring{\plannerMarkDefaultsCsv}, true) }} \newcommand\plannerEvents{% \parseYearEvents[filter pred = hasFootnote]% } \newcommand\plannerWeeklyNotes{% \luadirect{ require("wallcalendar-helpers.lua") plannerWeeklyNotes(tonumber(\CalendarYear), nil, \luastring{\plannerMarksDayTextCSV}) }} \newcommand\plannerWeeklyImages{% \luadirect{ require("wallcalendar-helpers.lua") plannerWeeklyImages(tonumber(\CalendarYear), nil, \luastring{\plannerMarksDayTextCSV}) }} % \varul[below-depth][line-thickness]{text} % https://tex.stackexchange.com/questions/36894/underline-omitting-the-descenders \ExplSyntaxOn \cs_new:Npn \white_text:n #1 { \fp_set:Nn \l_tmpa_fp {#1 * .01} \llap{\textcolor{white}{\the\SOUL@syllable}\hspace{\fp_to_decimal:N \l_tmpa_fp em}} \llap{\textcolor{white}{\the\SOUL@syllable}\hspace{-\fp_to_decimal:N \l_tmpa_fp em}} } \NewDocumentCommand{\whiten}{ m } { \int_step_function:nnnN {1}{1}{#1} \white_text:n } \ExplSyntaxOff \NewDocumentCommand{ \varul }{ D<>{5} O{0.3ex} O{0.1ex} +m } {% \begingroup \setul{#2}{#3}% \def\SOUL@uleverysyllable{% \setbox0=\hbox{\the\SOUL@syllable}% \ifdim\dp0>\z@ \SOUL@ulunderline{\phantom{\the\SOUL@syllable}}% \whiten{#1}% \llap{% \the\SOUL@syllable \SOUL@setkern\SOUL@charkern }% \else \SOUL@ulunderline{% \the\SOUL@syllable \SOUL@setkern\SOUL@charkern }% \fi}% \ul{#4}% \endgroup } \def\@wall@oneWeekNotes@fontSize{9} \def\@wall@oneWeekNotes@lineHeight{14.55} \newcommand\oneWeekNotesSize{\@setfontsize\oneWeekNotesSize{\@wall@oneWeekNotes@fontSize}{\@wall@oneWeekNotes@lineHeight}} \newlength\oneNoteSkip \newlength\oneImageSkip \setlength{\oneNoteSkip}{\@wall@oneWeekNotes@lineHeight pt} \setlength{\oneImageSkip}{\oneNoteSkip} \newcommand\oneWeekNotesSep{} \newcommand\oneWeekImagesSep{} % #1 = (opt) color % #2 = text \newcommand*\colorUL[2][textbody]{% \setulcolor{#1}% \varul{#2}% \setulcolor{textbody}% } % #1 = color % #2 = week number % #3 = date string % #4 = text \newcommand\oneNote[4]{% \ifstrequal{#3}{}{% #4\quad% }{% \colorUL[#1]{#3} #4\quad% }% } % #1 = week number % #2 = combined text \newcommand\oneWeekNotes[2]{% \node [ below left = {#1\oneNoteSkip} and 0pt of bg.north east, anchor = north east, inner sep = 0pt, ] {% \begin{minipage}{\linewidth}% \raggedright% \setlength{\parindent}{0pt}% \oneWeekNotesSize\selectfont% #2% \end{minipage}% };% } % #1 = (opt) image options % #2 = week number % #3 = image path \newcommand\oneImage[3][width=20mm]{% \node [ below left = {#2\oneImageSkip} and 0pt of bg.north east, anchor = north east, inner sep = 0pt, ] {% \includegraphics[#1]{#3}% };% } % ** \textbackslash YearPlannerPortrait \newcommand\YearPlannerPortrait{% \@wall@useDefaultMoons% \begin{tikzpicture}[every calendar/.style={year planner portrait}]% \matrix[column sep=1.5em, row sep=5mm] { \calendar(cal01)[dates=\CalendarYear-01-01 to \CalendarYear-01-last] \@wall@plm{January}; \pgfmatrixnextcell \calendar(cal02)[dates=\CalendarYear-02-01 to \CalendarYear-02-last] \@wall@plm{February}; \pgfmatrixnextcell \calendar(cal03)[dates=\CalendarYear-03-01 to \CalendarYear-03-last] \@wall@plm{March}; \\ \calendar(cal04)[dates=\CalendarYear-04-01 to \CalendarYear-04-last] \@wall@plm{April}; \pgfmatrixnextcell \calendar(cal05)[dates=\CalendarYear-05-01 to \CalendarYear-05-last] \@wall@plm{May}; \pgfmatrixnextcell \calendar(cal06)[dates=\CalendarYear-06-01 to \CalendarYear-06-last] \@wall@plm{June}; \\ \calendar(cal07)[dates=\CalendarYear-07-01 to \CalendarYear-07-last] \@wall@plm{July}; \pgfmatrixnextcell \calendar(cal08)[dates=\CalendarYear-08-01 to \CalendarYear-08-last] \@wall@plm{August}; \pgfmatrixnextcell \calendar(cal09)[dates=\CalendarYear-09-01 to \CalendarYear-09-last] \@wall@plm{September}; \\ \calendar(cal10)[dates=\CalendarYear-10-01 to \CalendarYear-10-last] \@wall@plm{October}; \pgfmatrixnextcell \calendar(cal11)[dates=\CalendarYear-11-01 to \CalendarYear-11-last] \@wall@plm{November}; \pgfmatrixnextcell \calendar(cal12)[dates=\CalendarYear-12-01 to \CalendarYear-12-last] \@wall@plm{December}; \\ }; \@wall@plNotes \end{tikzpicture}% } % ** \textbackslash YearPlannerLandscape \newcommand\YearPlannerLandscape{% \@wall@usePlannerMoons% \begin{tikzpicture}% \calendar (cal) [ year planner landscape, dates=\CalendarYear-01-01 to \CalendarYear-12-31, ] \@wall@plmYear; \@wall@plNotesOneCalendar \end{tikzpicture}% } % ** \textbackslash YearPlannerLandscapeGrid \newcommand\YearPlannerLandscapeGrid{% \@wall@usePlannerMoons% \begin{tikzpicture} % Background frame \node (bg) [ rectangle, inner sep = 0pt, minimum width = \plannerGridCalendarWidth, minimum height = \plannerGridCalendarHeight, ] {}; \foreach \x/\m in {1/\xJanShort, 2/\xFebShort, 3/\xMarShort, 4/\xAprShort, 5/\xMayShort, 6/\xJunShort, 7/\xJulShort, 8/\xAugShort, 9/\xSepShort, 10/\xOctShort, 11/\xNovShort, 12/\xDecShort} { \setlength{\@tmp@a}{\x\plannerGridRowYShift + \plannerGridDayHeadingsHeight} % Month labels \node [ below = \@tmp@a of bg.north west, yshift = 0.5\plannerGridRowYShift - 2pt, xshift = 0.5\plannerGridColXShift - 2pt, anchor = base, rotate = 90, ] {\plannerGridMonthFmt\MakeUppercase{\textls*{\m}}}; % Horizontal lines \addtolength{\@tmp@a}{-\plannerGridRowYShift} \node (h-a-\x) [below = \@tmp@a of bg.north west] {}; \node (h-b-\x) [below = \@tmp@a of bg.north east] {}; \draw [gridcolor] (h-a-\x) -- (h-b-\x); } % 13th line \setlength{\@tmp@a}{12\plannerGridRowYShift + \plannerGridDayHeadingsHeight} \node (h-a-13) [below = \@tmp@a of bg.north west] {}; \node (h-b-13) [below = \@tmp@a of bg.north east] {}; \draw [gridcolor] (h-a-13) -- (h-b-13); % Year number in the corner \node [ below right = -1pt and -5pt of bg.north west, xshift = 0.5\plannerGridMonthNamesWidth, yshift = -0.5\plannerGridDayHeadingsHeight, anchor = north west, inner sep = 0pt, ] {\plannerGridYearNumberFmt\CalendarYear}; \setcounter{verticalCount}{1} \foreach \i in {0,1,2,3,4,5} { \foreach \j/\d in { 0/\xMondayDayLetter, 1/\xTuesdayDayLetter, 2/\xWednesdayDayLetter, 3/\xThursdayDayLetter, 4/\xFridayDayLetter, 5/\xSaturdayDayLetter, 6/\xSundayDayLetter} { \addtocounter{verticalCount}{1} \ifnumgreater{\value{verticalCount}}{38}{\relax}{ \setlength{\@tmp@a}{7\plannerGridColXShift} \setlength{\@tmp@a}{\i\@tmp@a + \j\plannerGridColXShift + \plannerGridMonthNamesWidth} % Day headings (top and bottom) \node [ right = \@tmp@a of bg.north west, xshift = 0.5\plannerGridColXShift + 4pt, yshift = -0.5\plannerGridDayHeadingsHeight - 5pt, anchor = base, ] {\plannerGridDateDayFmt \d}; \node [ right = \@tmp@a of bg.south west, xshift = 0.5\plannerGridColXShift + 4pt, yshift = 0.5\plannerGridDayHeadingsHeight - 5pt, anchor = base, ] {\plannerGridDateDayFmt \d}; % % Vertical lines % \node (v-a-\i-\j) [right = \@tmp@a of bg.north west] {}; % \node (v-b-\i-\j) [right = \@tmp@a of bg.south west] {}; % \draw [gridcolor] (v-a-\i-\j) -- (v-b-\i-\j); } } } \calendar (cal) [ year planner landscape grid days, dates=\CalendarYear-01-01 to \CalendarYear-12-31, below right = 0pt and 0pt of bg.north west, anchor = north west, yshift = -\plannerGridDayHeadingsHeight - 3mm, xshift = \plannerGridMonthNamesWidth + 0.5\plannerGridColXShift + 4pt, ] \@wall@plmYear; \@wall@plNotesOneCalendar \end{tikzpicture}% } % ** \textbackslash YearPlannerLandscapeGridPage \newcommand{\YearPlannerLandscapeGridPage}{% \pagecolor{pagebgcolor}% \AddToShipoutPictureFG*{\put(\LenToUnit{\@wall@leftMargin},\LenToUnit{\@wall@bottomMargin})% {\begin{minipage}[b]{\plannerGridCalendarWidth}% \YearPlannerLandscapeGrid \begin{minipage}[b][10mm][c]{\plannerGridCalendarWidth}% \plannerGridNotesFmt \hspace*{2mm}% \parseYearEvents[% filter pred = hasFootnote, format cmd = {\textsuperscript{\eIdx}~\eMonthShort~\eDay:~\textit{\eFootnote}\ifnumless{\eIdx}{\eMaxIdx}{,\space}{.}}, ]% \end{minipage}% \end{minipage}% }}} % ** \textbackslash YearPlannerCompact \newcommand\YearPlannerCompact{% \@wall@usePlannerMoons% \begin{tikzpicture}% \calendar (cal) [ year planner compact, dates=\CalendarYear-01-01 to \CalendarYear-12-31, ] \@wall@plmYear; \@wall@plNotesOneCalendar \end{tikzpicture}% } % * Title page % % ** \textbackslash TitlePage % #1 : image path % #3 : background overlay height % #3 : title text \newcommand{\TitlePage}[3]{% \mbox{} \thispagestyle{empty} \AddToShipoutPictureFG*{% \put(\LenToUnit{-3mm},\LenToUnit{-3mm}){% \begin{tikzpicture} \node (bg) [ minimum width=\calPaperWidth + 6mm, minimum height=\calPaperHeight + 6mm, ] {% \includegraphics[height={\calPaperHeight + 6mm}]{#1}% }; \node (title-bg) [ minimum width=\calPaperWidth + 6mm, minimum height=#2, above left=0pt and 0pt of bg.center, anchor=center, fill=white, opacity=0.4, ] {}; \node (title-text) [ above left=0pt and 0pt of bg.center, anchor=center, ] {% \begin{minipage}{\calPaperWidth + 6mm}% \centering #3% \par \end{minipage}% }; \end{tikzpicture}% }% }% } % * Translation keys % Load internal translations \InputIfFileExists{i18n/wallcalendar-\@wall@calendarLanguage.tex}{}% {\ClassError{wallcalendar}{File Not Found: i18n/wallcalendar-\@wall@calendarLanguage.tex}{}} % Load user translations if the option was set and translationsAutoload is true \newcommand\LoadTranslations{% \InputIfFileExists{\@wall@translationsInputFile}{}% {\ClassWarning{wallcalendar}{File Not Found: \@wall@translationsInputFile}{}}} \notblank{\@wall@translationsInputFile}{% \iftranslationsAutoload \LoadTranslations \fi} % Use =\ifcase= instead of a =\luadirect= array lookup, otherwise Portuguese day % headings such as =\def\xMondayDayLetter{{2\textsuperscript{a}}}= cause an error. % #1 : month number, returns the translation \newcommand*\@tr@monthNumName[1]{% \ifcase#1 \relax\or \xJanuary\or \xFebruary\or \xMarch\or \xApril\or \xMay\or \xJune\or \xJuly\or \xAugust\or \xSeptember\or \xOctober\or \xNovember\or \xDecember\fi} % #1 : weekday number, returns the one letter translation \newcommand*\@tr@dayLetter[1]{% \ifcase#1 \xMondayDayLetter\or \xTuesdayDayLetter\or \xWednesdayDayLetter\or \xThursdayDayLetter\or \xFridayDayLetter\or \xSaturdayDayLetter\or \xSundayDayLetter\fi} \newcommand*\@tr@dayName[1]{% \ifcase#1 \xMonday\or \xTuesday\or \xWednesday\or \xThursday\or \xFriday\or \xSaturday\or \xSunday\fi} % Column-to-day mapping for headings. When =sundayFirst= is active, column 0 is % Sunday; otherwise column 0 is Monday (matching TikZ weekday numbering). These % are used by heading styles where the loop variable is a column index, not a % weekday number. % Column-to-day mapping for headings. When sundayFirst is active, column 0 is % Sunday; otherwise column 0 is Monday (matching TikZ weekday numbering). \newcommand*\@tr@columnDayLetter[1]{% \ifsundayFirst \ifcase#1 \xSundayDayLetter\or \xMondayDayLetter\or \xTuesdayDayLetter\or \xWednesdayDayLetter\or \xThursdayDayLetter\or \xFridayDayLetter\or \xSaturdayDayLetter\fi \else \@tr@dayLetter{#1}% \fi} \newcommand*\@tr@columnDayName[1]{% \ifsundayFirst \ifcase#1 \xSunday\or \xMonday\or \xTuesday\or \xWednesday\or \xThursday\or \xFriday\or \xSaturday\fi \else \@tr@dayName{#1}% \fi} % * Helper macros % Doing this in Lua to make blasted sure the result is just a string % #1 : month name in English, returns zero padded number \newcommand*{\monthToNum}[1]{% \luadirect{ local monthToNum = { january = '01', february = '02', march = '03', april = '04', may = '05', june = '06', july = '07', august = '08', september = '09', october = '10', november = '11', december = '12', } local key = string.lower('#1') tex.sprint(monthToNum[key]) }} % #1 : month number, returns the name in English \newcommand*\monthName[1]{% % \ifcase might be just fine here \luadirect{ local monthName = { 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', } local key = tonumber('#1') tex.sprint(monthName[key]) }} % * Epilogue % % Running the calendar commands with empty arguments to make sure necessary % pgfkeys are defined. % % This also avoids the problem that the user doesn't have to remember to declare % empty parts, such as having to call =\SetQuote{January}{}= when he doesn't have % a quote. % % Otherwise results in =Missing number= error when the user is building up the % calendar piece by piece. % % : ! Missing number, treated as zero. % : % : \@val % : l.19 ...out=full page, put photo=full page]{January} % % Repeating the months manually, =\foreach= doesn't seem to work to set the month keys. \SetPhoto{January} \SetCalendar{January} \SetQuote{January}{} \SetEvents{January}{}{} \SetPhoto{February} \SetCalendar{February} \SetQuote{February}{} \SetEvents{February}{}{} \SetPhoto{March} \SetCalendar{March} \SetQuote{March}{} \SetEvents{March}{}{} \SetPhoto{April} \SetCalendar{April} \SetQuote{April}{} \SetEvents{April}{}{} \SetPhoto{May} \SetCalendar{May} \SetQuote{May}{} \SetEvents{May}{}{} \SetPhoto{June} \SetCalendar{June} \SetQuote{June}{} \SetEvents{June}{}{} \SetPhoto{July} \SetCalendar{July} \SetQuote{July}{} \SetEvents{July}{}{} \SetPhoto{August} \SetCalendar{August} \SetQuote{August}{} \SetEvents{August}{}{} \SetPhoto{September} \SetCalendar{September} \SetQuote{September}{} \SetEvents{September}{}{} \SetPhoto{October} \SetCalendar{October} \SetQuote{October}{} \SetEvents{October}{}{} \SetPhoto{November} \SetCalendar{November} \SetQuote{November}{} \SetEvents{November}{}{} \SetPhoto{December} \SetCalendar{December} \SetQuote{December}{} \SetEvents{December}{}{} % Set the time so that showtrims headers print the same date and time. \newcommand\setTestDateTime{% \day=01% \month=01% \year=2016% % \time is minutes since midnight, so 14:30 = 14*60 + 30 = 870 \time=870% } % End of wallcalendar.cls