1

I have the following MWE for the note command I'm working on.

\documentclass{article}
\usepackage[a5paper,marginparwidth=15mm]{geometry}
\usepackage{tikzpagenodes}
\usetikzlibrary{calc}
\newcommand\note[2][0pt]{
  \tikz[overlay,remember picture,baseline=-1ex] \coordinate (e);
  \begin{tikzpicture}[remember picture, overlay]
  \path let \p1 = (e), \p2 = (current page marginpar area.west) in node[yshift=-#1,text width=\marginparwidth,align=left,anchor=north west,inner ysep=0pt,inner xsep=0pt,font=\normalfont\tiny\color{red}] at (\x2,\y1) {#2};
  \end{tikzpicture}
}
\usepackage{everypage}
\AddEverypageHook{
    \tikz[remember picture,overlay] {\draw [blue] (current page text area.south west) rectangle (current page text area.north east);}
    \tikz[remember picture,overlay] {\draw [green] (current page marginpar area.south west) rectangle (current page marginpar area.north east);}
}
\begin{document}
\section{\note{Note A}A Test Section}
Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec \note{Note B - pretty long one} vehicula augue eu neque. Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra
metus rhoncus sem. \note{Note C} Nulla et lectus vestibulum urna fringilla \note{Note D} ultrices. Phasellus
eu tellus sit \note{Note E} amet tortor gravida placerat. Integer sapien est, iaculis in, pretium
quis, viverra ac, nunc.tus a mi. Morbi ac orci et nisl hendrerit mollis.
\end{document}

I would like the Note E to be shifted below Note D. Currently I could do that manually by precising yshift, but I think it can be easily done without the need of hand-tuning.

I could think of an algorithm

  1. Save bottom of the note position
  2. When placing next note check if top position is less than previous bottom
  3. Calculate required yshift

However as a beginner I have no idea how to implement that behavior in tikz. Any help appreciated :)

Update

There is also a secondary question here - if I try to remove the optional argument (just to make it \newcommand\note[1]{) I end up with the error

! Use of \use@tikzlibrary doesn't match its definition.
\pgfutil@ifnextchar ...1\def \pgfutil@reserved@a { #2}\def \pgfutil@reserved@...
l.20 \section{\note{Note A}A Test Section}

Of course I remember about changing references. What's going on?

Test code

To show what happens with align and tabu

\documentclass{article}
\usepackage[a5paper,marginparwidth=15mm]{geometry}
\usepackage{tikzpagenodes}
\tikzset{
  marginpar node/.style={
    text width=\marginparwidth,
    align=left,
    inner sep=+0pt,
    font=\normalfont\tiny,
    text=red}}
\makeatletter
\def\tikz@marginpar@node@page{-1}%
\protected\def\note#1{%
  \tikzpicture[remember picture, overlay]
    \pgfutil@ifundefined{pgf@sh@ns@tikz@marginpar@node}{%
      \coordinate (@tikz@marginpar@node@c)at (0pt, 1ex-|current page marginpar area.west);
    }{%
      \ifnum\tikz@marginpar@node@page=\c@page\relax
        \pgfpointdiff{\pgfpointanchor{tikz@marginpar@node}{south west}}
                     {\pgfpoint{+0pt}{+1ex}}
        \ifdim\pgf@y<-3pt\relax
          \coordinate (@tikz@marginpar@node@c)
            at (0pt,1ex-|current page marginpar area.west);
        \else
          \coordinate (@tikz@marginpar@node@c)
            at ([yshift=-3pt]tikz@marginpar@node.south west);
        \fi
      \else
        \coordinate (@tikz@marginpar@node@c)
            at (0pt,1ex-|current page marginpar area.west);
      \fi
    }
    \node [marginpar node/.try, anchor=north west, alias=tikz@marginpar@node]
            at (@tikz@marginpar@node@c) {\setlength\baselineskip{0pt}#1};
    \xdef\tikz@marginpar@node@page{\the\c@page}%
  \endtikzpicture}
\makeatother
\usepackage{everypage}
\AddEverypageHook{%
  \tikz[remember picture,overlay]{
    \draw[blue]  (current page text area.south west) rectangle
                    (current page text area.north east);
    \draw[green] (current page marginpar area.south west) rectangle
                    (current page marginpar area.north east);}%
}
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}
\fancyhf[HL]{\def\note##1{}\leftmark}
\renewcommand{\sectionmark}[1]{\markboth{\thesection\ #1}{}}
\usepackage{tabu}
\usepackage{multicol}
\usepackage{amsmath}
\begin{document}
{\def\note#1{}\tableofcontents}

\section{\note{Note A}A Test Section}
Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec \note{Note B - pretty long one} vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra
metus rhoncus sem. \note{Note C} Nulla et lectus vestibulum urna fringilla
\note{Note D} ultrices. Phasellus eu tellus sit \note{Note E} amet tortor
gravida placerat. Integer sapien est, iaculis in, pretium quis, viverra ac,
nunc.tus a mi. Morbi ac orci et nisl hendrerit mollis.

\newpage
\section{\note{Note A}A Test Section}
Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec \note{Note B - pretty long one} vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra
metus rhoncus sem. \note{Note C} Nulla et lectus vestibulum urna fringilla
\note{Note D} ultrices. Phasellus eu tellus sit \note{Note E} amet tortor
gravida placerat. \note{Note F} Integer sapien est, iaculis in, pretium quis, 
viverra ac, nunc.tus a mi. Morbi ac orci et nisl hendrerit mollis.

\newpage
Morbi dolor\note{More testing} nulla, malesuada eu, pulvinar at, mollis ac, nulla. 
Cur-abitur auctor semper nulla. Donec varius orci eget risus. 
\begin{center}
Duis nibh mi, congue \note{center}
eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci dignissim
rutrum.
\end{center}
\begin{displaymath}
a+b+c =\note{display math} d+e+f
\end{displaymath}
Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, \note{Test} lobortis vitae, 
ultricies et, tellus. Donec aliquet, tortor sed accumsan bibendum, erat ligula 
aliquet magna, vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis.
\begin{multicols}{2}
Erat ligula aliquet magna,
vitae ornare odio metus a mi. Morbi nisl \note{Something is wrong here} mollis. 
Donec aliquet, tortor sed accumsan bibendum. Suspendisse
ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna. 
Nulla ullamcorper vestibulum turpis. Nulla ullamcorper 
$f(x)=\note{This requires special attention}f(-x)$ vestibulum turpis. 
Pellentesque cursus luctus mauris.
\end{multicols}

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae, 
ultricies et, tellus.

\begin{center}
\begin{tabular}{|c|c|c|c|c|}
\hline
Strop&Spag&H&Symbol&Nazwa\\\hline
0&4.05&\note{Table comment?}4.05&$Ps$&Piasek sredni\\\hline
4.05&5.30&1.25&$T$&Torf\\\hline
5.30&7.60&2.30&$Gz$&Glina zwiezla\\\hline
7.60&$\infty$&$\infty$&$P \pi$&Piasek pylasty\\\hline
\end{tabular}
\end{center}

\newpage
Morbi dolor\note{More testing} nulla, malesuada eu, pulvinar at, mollis ac, nulla. 
Cur-abitur auctor semper nulla. Donec varius orci eget risus. 
\begin{center}
Duis nibh mi, congue \note{center}
eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci dignissim
rutrum.
\end{center}
\begin{align}
a+b+c &= d+e+f \\
&\note{Rly equal?}= g +h \\
&= i.
\end{align}
Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, \note{Test} 
lobortis vitae, ultricies et,
tellus. Donec aliquet, tortor sed accumsan bibendum, erat ligula aliquet magna,
vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis.
\begin{multicols}{2}
Erat ligula aliquet magna, vitae ornare odio 
metus a mi. Morbi ac orci et nisl \note{Something is wrong here} mollis. 
Donec aliquet, tortor sed accumsan bibendum. Suspendisse
ut massa. Cras nec ante. Pellentesque a nulla. Cum sociis natoque penatibus et
magnis dis parturient montes, nascetur ridiculus mus. Aliquam tincidunt urna. 
Nulla ullamcorper vestibulum turpis. Nulla ullamcorper 
$f(x)=\note{This requires special attention}f(-x)$ vestibulum turpis. 
Pellentesque cursus luctus mauris.
\end{multicols}

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae, 
ultricies et, tellus.

\begin{center}
\begin{tabu}{|c|c|c|c|c|}
\hline
Strop&Spag&H&Symbol&Nazwa\\\hline
0&4.05&\note{Table comment?}4.05&$Ps$&Piasek sredni\\\hline
4.05&5.30&1.25&$T$&Torf\\\hline
5.30&7.60&2.30&$Gz$&Glina zwiezla\\\hline
7.60&$\infty$&$\infty$&$P \pi$&Piasek pylasty\\\hline
\end{tabu}
\end{center}

\newpage
Restart?\note{restart}

\end{document}
ShreevatsaR
  • 45,428
  • 10
  • 117
  • 149
Pawel
  • 515
  • Secondary question: You need to use \protect\note in the \section or \protected\def\note#1{ instead of \newcommand\node[1]. See What is the difference between Fragile and Robust commands? – Qrrbrbirlbel Sep 28 '13 at 13:01
  • @Qrrbrbirlbel thanks for the comment, pretty useful and in fact did the trick. Anyway I am still working on the first part of my question, could you enlighten me please how to use \ifthenelse to compare two tikz \coordinate's? Or simply return greater y of two. – Pawel Sep 28 '13 at 13:29
  • See my answer, but please be aware that if you use \tableofcontents this will also have the notes, you should do something along the lines of {\def\note#1{}\tableofcontents} then. – Qrrbrbirlbel Sep 28 '13 at 13:42

1 Answers1

2

A calc-less solution.

First we check whether a node tikz@marginpar@node exists. If some exist we calculate the difference between (tikz@marginpar@node.south west) and (0pt, 1ex) (unless the previous note was on a different page). If the y part less than 0, (0pt, 1ex) is too high and thus the previous tikz@marginpar@node is used to position the new node.

Code

\documentclass{article}
\usepackage[a5paper,marginparwidth=15mm]{geometry}
\usepackage{tikzpagenodes}
\tikzset{
  marginpar node/.style={
    text width=\marginparwidth,
    align=left,
    inner sep=+0pt,
    font=\normalfont\tiny,
    text=red}}
\makeatletter
\def\tikz@marginpar@node@page{-1}%
\protected\def\note#1{%
  \tikzpicture[remember picture, overlay]
    \pgfutil@ifundefined{pgf@sh@ns@tikz@marginpar@node}{%
      \coordinate (@tikz@marginpar@node@c)at (0pt, 1ex-|current page marginpar area.west);
    }{%
      \ifnum\tikz@marginpar@node@page=\c@page\relax
        \pgfpointdiff{\pgfpointanchor{tikz@marginpar@node}{south west}}
                     {\pgfpoint{+0pt}{+1ex}}
        \ifdim\pgf@y<0pt\relax
          \coordinate (@tikz@marginpar@node@c)
                                          at (0pt,1ex-|current page marginpar area.west);
        \else
          \coordinate (@tikz@marginpar@node@c)
                                      at ([yshift=-.75ex]tikz@marginpar@node.south west);
        \fi
      \else
        \coordinate (@tikz@marginpar@node@c)
                                          at (0pt,1ex-|current page marginpar area.west);
      \fi
    }
    \node [marginpar node/.try, anchor=north west, alias=tikz@marginpar@node]
                                                 at (@tikz@marginpar@node@c) {#1};
    \xdef\tikz@marginpar@node@page{\the\c@page}%
  \endtikzpicture}
\makeatother
\usepackage{everypage}
\AddEverypageHook{%
  \tikz[remember picture,overlay]{
    \draw[blue]  (current page text area.south west)      rectangle
                                                     (current page text area.north east);
    \draw[green] (current page marginpar area.south west) rectangle
                                             (current page marginpar area.north east);}%
}
\begin{document}
{\def\note#1{}\tableofcontents}

\section{\note{Note A}A Test Section}
Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec \note{Note B - pretty long one} vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra
metus rhoncus sem. \note{Note C} Nulla et lectus vestibulum urna fringilla
\note{Note D} ultrices. Phasellus eu tellus sit \note{Note E} amet tortor
gravida placerat. Integer sapien est, iaculis in, pretium quis, viverra ac,
nunc.tus a mi. Morbi ac orci et nisl hendrerit mollis.

\newpage
\section{\note{Note A}A Test Section}
Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec \note{Note B - pretty long one} vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus
et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra
metus rhoncus sem. \note{Note C} Nulla et lectus vestibulum urna fringilla
\note{Note D} ultrices. Phasellus eu tellus sit \note{Note E} amet tortor
gravida placerat. Integer sapien est, iaculis in, pretium quis, viverra ac,
nunc.tus a mi. Morbi ac orci et nisl hendrerit mollis.
\end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
  • Thanks for the answer, however could you expain me a few things? 1. ...(0pt, 1ex-|current page margin... whats does that 1ex-| do? 2. If in {\pgfpoint{+0pt}{+1ex}} 1ex is a minimal allowed distance between notes why do you use [yshift=-.75ex] instead of [yshift=-1ex]? 3. \tableofcontents is fine now, but what about \sectionmark - section title in the header (using fancyhdr)? 4. How could one modify \baselineskip in the note content? – Pawel Sep 28 '13 at 14:15
  • @Paul 1. The -| (as well as the |-) is the explicit version of the perpendicular cs: and denotes the coordinate horizontal through 0pt, 1ex and vertical through current page margin area.west, i.e. the same coordinate that you used let … in for. 2. No, \pgfpoint{0pt}{1ex} is the PGF version of (0pt, 1ex). The 1ex are the same 1ex you use to denote the coordinate (e) which vertical part you use to place the node (at its north west anchor). We check if the new north west anchor would be higher then the south west anchor of the previous node. cont. – Qrrbrbirlbel Sep 28 '13 at 16:15
  • The .75ex is simply the distance between the old south west and the new north west anchor, i.e. the vertical distance between the nodes if the new one would overlap the previous one. 3. No idea at the moment. Though \label works the same way (you can use it in \sections and \captions without a problem), maybe there is a related Q on TeX.sx. 4. As always in LaTeX: Either with \fontsize or \setlength\baselineskip. – Qrrbrbirlbel Sep 28 '13 at 16:19
  • 1. I understand that is tikz way to get the coordinate (marginpar.X, here.Y + 1ex) 2. Then we have to test diff against .75ex, because it might happen that two notes do not overlap, but are still too close example, assuming .75ex=3pt \ifdim\pgf@y<-3pt\relax fixes the issue. I assumed 3pt because I guess .75ex won't work out of the node scope. 3. I adapted your solution for \tableofcontents: \fancyhf[HL]{\def\note##1{}\leftmark} and it's fine 4. I want to change spacing between lines {\setlength\baselineskip{0pt}#1} doesn't work. – Pawel Sep 28 '13 at 18:02
  • Moreover putting \note{...} into more elaborate environments like align (amsmath) or tabu (table) results in note dissappearing altogether with each further on the page. What is even more weird displaymath and tabular works fine. Original code works in all cases. I edited question to give an example of what I am talking about. – Pawel Sep 28 '13 at 18:29