4

I am currently trying to write a custom command that helps me display a bunch of icons on the side of a section text, right below the section heading. There is always the same amount of icons (in my case it will be 5), but basically there will be an on/off option for each of the icons. Depending on the option, the icon will look slightly different and will be displayed in another column. There should be one column for each type of option (on/off). The icon size is around 24x24 px.

To illustrate what I want to achieve, here is a picture: Custom icons below section header

To be honest, I have tried quite some things (\makebox, etc), but I couldn't get my desired result without destroying the rest of the layout (e.g. did \makebox cause the text to have no indent anymore). I also found a way of switching content based on a parameter with \numif for example, but I'm not sure if doing both a content switching and changing the alignment is possible.

So my question is if anyone could give me a tip in which direction I should go and try and if doing everything in one command is actually doable (and also feasible)? It is no problem for me if I have to use one command per icon, for example.


Edit:

To better illustrate my problem, I created an MWE:

\documentclass[11pt,fleqn,openany]{book}

\usepackage[top=3cm,bottom=3cm,left=2.5cm,right=2.5cm]{geometry}

\usepackage{lipsum}
\usepackage{mwe}

\usepackage[table,xcdraw]{xcolor}
\definecolor{colcustom}{RGB}{13,211,155}

% styling of section numbering
\makeatletter
\renewcommand{\@seccntformat}[1]{\llap{\textcolor{colcustom}{\csname the#1\endcsname}\hspace{1em}}}                    
\renewcommand{\section}{\@startsection{section}{1}{\z@}
    {-4ex \@plus -1ex \@minus -.4ex}
    {1ex \@plus.2ex }
    {\normalfont\large\sffamily\bfseries}}
\renewcommand{\subsection}{\@startsection {subsection}{2}{\z@}
    {-3ex \@plus -0.1ex \@minus -.4ex}
    {0.5ex \@plus.2ex }
    {\normalfont\sffamily\bfseries}}

% styling of icons on the side of text
\newcommand{\includedinpackages}{\makebox[-1.5cm]{\includegraphics[width=20px]{example-image-a}}}

\begin{document}

\chapter{Main Chapter}

\section{First Section}
\includedinpackages
\lipsum[3-4]

\subsection{First Subsection}
\lipsum[1]

\end{document}

When using \makebox[-1.5cm]{\includegraphics[width=20px]{example-image-a}} to add an image below the section numbering, the section text is not indented anymore but starts somewhere near the image. I tried fixing it with adding \hspace before the text, but it seems ugly and is hard to properly align the text.

Can someone give me a hint on what I'm doing wrong?

I also found syntax information about \makebox in the internet where it was said that you can use \makebox(x,y){content} to position the box in x and y direction accordingly. But I could only get \makebox[x]{content} to work. Do I lack a special package/option or is this wrong info?

  • In principle, this should be possible, but a solution depends, at least in part, on what class and packages you use to achieve the shown layout. So please provide a MWE. It should also show, what you tried so far. – Mike May 3 '18 at 20:50
4

So here's a start:

enter image description here

\documentclass[11pt,fleqn,openany]{book}

\usepackage[top=3cm,bottom=3cm,left=2.5cm,right=2.5cm]{geometry}

\usepackage{lipsum}
\usepackage{mwe}

\usepackage[table,xcdraw]{xcolor}
\definecolor{colcustom}{RGB}{13,211,155}

\newsavebox\iconbox
\savebox\iconbox{}
\newcommand{\seticons}[1]{%
  \savebox\iconbox{{\makebox[\iconboxwidth]{\includegraphics[width=\iconboxwidth]{#1}}}}}
\newlength{\iconboxwidth}
\setlength{\iconboxwidth}{0.5in}
\newlength{\iconsep}
\setlength{\iconsep}{4pt}
\makeatletter
\renewcommand{\@seccntformat}[1]{%
  \llap{\parbox[t][0pt]{\iconboxwidth}{\hfill\textcolor{colcustom}{\csname the#1\endcsname}\\[\iconsep]\usebox{\iconbox}}\hspace{0.5em}}}
\renewcommand{\section}{\@startsection{section}{1}{\z@}
    {-4ex \@plus -1ex \@minus -.4ex}
    {1ex \@plus.2ex }
    {\normalfont\large\sffamily\bfseries}}
\renewcommand{\subsection}{\@startsection {subsection}{2}{\z@}
    {-3ex \@plus -0.1ex \@minus -.4ex}
    {0.5ex \@plus.2ex }
    {\normalfont\sffamily\bfseries}}

\begin{document}

\chapter{Main Chapter}

\seticons{example-image-a}

\section{First Section}
\lipsum[3-4]

\setlength{\iconboxwidth}{0.75in}
\seticons{example-image-b}

\subsection{First Subsection}
\lipsum[1]

\end{document}

Basically we offer this user-interface:

  • \seticons{<image-file>} sets the NEXT icon image that will be printed.
  • \setlength{\iconwidth}{<length>} sets the width of the image
  • \setlength{\iconsep}{<length>} sets the separation between icons and section number

If you want to change the size, you need to do that before the \seticons command. I rather assume you won't need to anyway, but might as well have the ability to do so.

This assumes that the relevant image of the icons is a single separate image file. A more sophisticate method would allow you to identify individual icon files for inclusion in two columns, but I haven't tried that.

You might need to UNSET the icons. In that event, you will probably want another command:

  • \newcommand{\noicons}{\savebox{\iconbox}{}}

The technique here is to put the icobox in \@seccntformat, which prints the section number. Basically, we print the number (as you had it) and then a newline and a space all in a parbox. We "trick" LaTeX into thinking the box has zero height in order to make sure that the following text doesn't have a gap. If you didn't want them set in the margin (but I gather from your example that you do), the technique would be a bit different and easier, and we wouldn't need the \llap or to set the box to have zero height.

Edited to add: The zero height trick will probably cause problems if the section title appears near the bottom of the page, because there might be insufficient space. I guess it's one of those times when, if that happens, you may have to intervene manually.

UPDATE

You asked how you might construct the columns of icons automatically. Here's one idea. I'm assuming two things: you want two columns of icons. You will decide which get placed in which column. There will be no more than 5 in a column. The code could quite easily be changed to accommodate different requirements: this is more to give you an idea.

I first have to add two packages, which are really just laziness, and there would be many alternative approaches.

\usepackage{etoolbox}% for easy looping and boolean tests
\usepackage{listofitems}% for easy access to list items

Then we define a new length, which is only used internally

\newlength{\iconcolwidth}

Then we define a command to output an icon. This is designed to allow us safely to include something blank. I think as I have finally ended up with the code it is superfluous, but it does no harm.

\newcommand{\outputicon}[2][]{%
  \ifblank{#2}
  {}
  {\includegraphics[#1]{#2}}}

The the critical command

\newcommand{\iconarrangement}[2]{%
  \begingroup
  \setsepchar{,}%
  \readlist*\licons{#1}%left hand
  \readlist*\ricons{#2}%right hand
  \setlength{\tabcolsep}{2pt}%
  \setlength{\iconcolwidth}{\dimexpr \numexpr (\iconboxwidth - \tabcolsep) / 2\relax sp \relax}%
  \renewcommand{\arraystretch}{1}%
  \renewcommand*{\do}[1]{%
    \ifboolexpr{%
      test {\ifnumcomp{\liconslen}{<}{##1}}
      and test {\ifnumcomp{\riconslen}{<}{##1}}}% PRINT NEITHER
    {}%
    {\ifnumless{\liconslen}{##1}
      {&}%
      {\outputicon[width=\iconcolwidth]{\licons[##1]}&}%
    \ifnumless{\riconslen}{##1}
      {\\}%
      {\outputicon[width=\iconcolwidth]{\ricons[##1]}\\}}}%
  \begin{tabular}{@{}cc@{}}
    \docsvlist{1,2,3,4,5}%
  \end{tabular}%
  \endgroup}

So we give \iconarrangement two comma separated lists of image files. The first is the left hand list, and the second is the right hand list. It iterates over the lizt and places them in a tabular. I think the code is largely self-explanatory.

Finally, if we want to use this for our icons, we redefine \seticons to use it.

\renewcommand\seticons[2]{%
  \savebox{\iconbox}{\iconarrangement{#1}{#2}}}

And now

\seticons{example-image-a, example-image-a}{example-image-b,example-image-b,example-image-b}

\section{New section}

\lipsum[1]

\seticons{example-image-b}{example-image-a, example-image-a}

\section{New section}

\lipsum[1]

Produces

revised version

Probably you need to fiddle with the detail to get it right, but it offers a general idea.

  • Very very good. +1. After I will remove this comment. – Sebastiano May 4 '18 at 10:14
  • Thank you, that already looks very nice! Interestingly, the icons were slightly shifted compared to your image when I tried your code, but changing the \iconsep was no issue. -- Although it does help me out quite a lot already, I wonder if there is a way to assign multiple consecutive icons to this icon box - like multiple image files and not one image containing all the icons pre-aligned. If this isn't possible, I'll have to create quite some image variations myself (worst case 2^5 = 32 images, but I will not need all variations). Is this possible? Issuing multiple boxes didn't work. – Namoshek May 4 '18 at 12:21
  • I don't see why one could not do that. Basically, all you need is a command which produces an appropriate box saved in \iconbox, and substitute that for \seticons. In principle \iconbox can contain anything that can be placed in a box. You'd want to think about the interface, which may depend on exactly what you plan to do. Personally, I think this might be better as a separate question, aimed simply at constructing a suitable \iconbox: this code will then place that box! – Paul Stanley May 4 '18 at 13:06
  • I updated the answer to offer a suggestion in lone with your request. – Paul Stanley May 4 '18 at 16:10
  • That is awesome, thank you so much! I still have minor issues with getting it to work within my actual document (and not the MWE), but I'm quite confident I'll find the way from here myself. Again, thanks a lot! – Namoshek May 4 '18 at 16:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.