A similar question has been asked before, with no answers. I would love to have a way to easily reference objects associated with counters. To provide such a capability for things like figures, tables, etc., it would be great if it was possible to automatically create tags as part of a Stylesheet definition. Can this be done?
For example, I have a Stylesheet definition for my figure captions that reads like this:
Cell[StyleData["FigureCaption", StyleDefinitions -> StyleData["SmallText"]],
TextAlignment->Center,
TextJustification->0.,
CounterIncrements->"Figure",
MenuSortingValue->10000,
FontFamily->"Source Sans Pro",
FontSize->12,
FontWeight->"Plain",
FontSlant->"Plain",
FontVariations->{"StrikeThrough"->False,
"Underline"->False},
FontProperties->{"ScreenResolution"->Automatic}]
Is it possible to add to this some code that will automatically create a tag of the form, say, "figctr
", where ctr
would be the value of the counter associated with the caption?
CLARIFICATION: Suppose I have a document that includes many FigureCaption cells that reference the counter above. Is it possible to programmatically create CellTags that reference the current value of the counter on each of these cells?
For example, I would like the 5th FigureCaption cell in notebook to have the CellTag "fig'ctr'", where 'ctr' is 5.
I use CellTags for navigation in a lecture notebook. It would very helpful to have the ability to add and delete FigureCaption cells in the notebook and then have some code that would update the cell tags to their appropriate values. Here is a related question I asked.
Note: As outlined in my comment, updating cell tags after having inserted more figures cannot be done in isolation: If we update the tags, the question comes up as to what happens to links after you edit the notebook. The part that's problematic about this is of course not the updating of the CellTags, but the fact that if we simply update the tags so they correspond to the counters, then existing references will point to the wrong cells. This means that we also need to search for and update the references to all of the tags.
Answer
Here's a solution. The inspiration for much of the code came from Eric Schulz's lecture on "Wisdom Gained from Publishing a CDF ebook" as well as as some code from this post. Below are the components for creating automatic cell tags for FigureCaption cells, but the idea can be extended to more than one type. The following are the components needed to keep everything updated for the cell type "FigureCaption" but can be used for multiple cell types.
A custom stylesheet that includes a definition for a "FigureCaption" cell. Make sure to setup the counters as shown.
Cell[StyleData["FigureCaption"], CellMargins->{{54, 24}, {10, -5}}, TextAlignment->Center, LineSpacing->{1, 2}, ParagraphSpacing->{0, 5}, LanguageCategory->"NaturalLanguage", ScriptLevel->1, CounterIncrements->"FigureCaption", FontFamily->"Times New Roman", FontSize->12]
A notebook that contains some FigureCaption cells. This is the notebook we will be manipulating I will refer to as the lecture notebook.
A function that builds the cell tags for the lecture notebook. The function is located in the Action Menu below.
DynamicModule[{found}, celltagdialog = Tooltip[Dynamic[ ActionMenu[ "C", {"Build Cell Tags" :> {SelectionMove[InputNotebook[], Before, Notebook]; found = NotebookFind[InputNotebook[], "FigureCaption", Next, CellStyle]; While[! FailureQ[found], SetOptions[NotebookSelection[], CellTags -> "Figure " <> ToString[ CurrentValue[ NotebookSelection[InputNotebook[]], {"CounterValue", "FigureCaption"}]]]; found = NotebookFind[InputNotebook[], "FigureCaption", Next, CellStyle];];}}, Appearance -> "Palette", FrameMargins -> None, Alignment -> Center, BaselinePosition -> Axis, ImageSize -> {24, 24}]], "Show Gridbox Dialog", TooltipDelay -> 0]]
- A function that creates the links to the cell tags in the lecture notebook. These are basically pointers that point to updated tags so that you can hyperlink to them... and them opens and closes groups to make it look nice.
CreateLinks[nb_] := Module[{tagLis = {}, data, imax, i}, SelectionMove[nb, Before, Notebook]; SelectionMove[nb, Next, Cell]; data = NotebookRead[nb]; While[data =!= {}, tagLis = Join[tagLis, Cases[data, Rule[CellTags, tg_] :> tg]]; SelectionMove[nb, Next, Cell]; data = NotebookRead[nb]]; MapThread[ Which[StringContainsQ[#1, "Figure"], " " <> #1, True, Style[#1, Bold]] :> {FrontEndExecute[FrontEndToken["SelectAll"]]; FrontEndExecute[{FrontEndToken[InputNotebook[], "SelectionCloseAllGroups"]}]; NotebookLocate[#1], FrontEndExecute[{FrontEndToken[ "SelectionOpenAllGroups"]}];} &, {tagLis}]]
Applying the functions given in 3 will keep the cell tags automatically generated so that even when you insert a new cell, the cell tags are renamed using 3. The function in 4 will rebuild the links which can be used for hyperlinking. These need to be rebuilt whenever we add or remove or move cells that have cell tags in the notebook or they won't match up. Let me know if you would like to see more code.
Below is a short gif I made to illustrating how we can do this in pratice. I have many cells with tags and some of them with counters that I reference in the tags. As you can see, I used a docked cell with a dropdown menu to rebuild the celltags.
The pointers created in 4 can be used for hyperlinks to any celltag in the notebook. Below is a gif illustrating how this can be implemented. Make sure to rebuild the docked cell to keep these pointers updated. I prefer to update the docked cell at the same time as I build the celltags, so it's one click instead of two. Again I used a dropdown menu and use the CreateLinks function above for its content.
Comments
Post a Comment