Note: The code below requires version 12.0.
Problem Overview: I am having some strange behavior with an ActionMenu, where the items in the menu don't show up until the mouse passes over them, as shown below. I would welcome any insights into how to fix this problem.
Background: This is part of a package I am developing to allow sophisticated label/symbol notation for both input cells and output cells. My specific application is Chemistry, but the approach should be more generally applicable. The main notion is to have a list of string notations and associate them with internal symbols, and have those string notations inside a TemplateBox with an assigned tag that helps with style. I want the user to be able to define these notations on-the-fly, because this is a general tool I use in teaching. Using this approach for output cells is easy, but is a bit more challenging for input cells, because I need a way to enter the string notation already associated with the TemplateBox tag. I have a way to do it using palettes, but am exploring a way to do it using an escape-alias and an ActionMenuBox. That is where I am running into this strange problem.
Setup Code: The following loads the Notation package, specifies the stylesheet and adds a custom style that helps with formatting, and defines a function that takes a list of label/symbol pairs and generates the notation associations.
<< Notation`
SetOptions[EvaluationNotebook[],
StyleDefinitions ->
Notebook[
{Cell[
StyleData[StyleDefinitions ->
FrontEnd`FileName[{"Report"}, "StandardReport.nb",
CharacterEncoding -> "UTF-8"]]],
Cell[StyleData["chemical"], StyleMenuListing -> None,
TagBoxOptions -> {SyntaxForm -> "symbol"},
ShowStringCharacters -> False, ShowAutoStyles -> False,
ZeroWidthTimes -> True,
TemplateBoxOptions ->
{DisplayFunction -> (RowBox[{#}] &),
SyntaxForm -> "symbol"}]}]]
AssignLabels[list_] :=
Block[{},
Do[Notation[DoubleLongLeftRightArrow[
ParsedBoxWrapper@TemplateBox[{"\""<>list[[i,1]]<>"\""},
"chemical", Editable -> False, Selectable -> False],
ParsedBoxWrapper@SymbolName[list[[i, 2]]]]],
{i, Length[list]}];]
The Palette Version that Works: To give you an idea of what I am trying to accomplish, here is how I make a palette to insert the tagged labels:
ChemPalette[name_, list_, width_] :=
CreatePalette[Multicolumn[PasteButton @@@ list, width],
WindowTitle -> name]
Example Usage: The following code assigns eight example labels and generates a palette for their entry.
assignments = {{"\!\(\*SubscriptBox[\(C\), \\(6\)]\)\!\
(\*SubscriptBox[\(H\), \(6\)]\)O", C6H6O}, {"(\!\
(\*SubscriptBox[\(NH\), \(4\)]\)\!\(\*SubscriptBox[\
\()\), \(2\)]\)\!\(\*SubscriptBox[\(SO\), \(4\)]\)",
AmmoniumSulfate}, {"\!\(\*SubsuperscriptBox[\(SO\), \(4\), \
\(\(2\)\(-\)\)]\)", Sulfate}, {"\!\(\*SubscriptBox[\(H\), \
(2\)]\)O (g)", WaterVapor}, {"\!\(\*SubscriptBox[\(\
[CapitalDelta]\), \(f\)]\)\!\\(\*SubsuperscriptBox[\(H\),
\(\*SubscriptBox[\(H\), \(2\)] O \((g)\)\\), \(o\)]\)",
\[CapitalDelta]fHWaterVapor}, \{"\!\(\*SubsuperscriptBox[
\(k\), \(sq\), SubscriptBox[\(C\), \(60\)]]\\)", ksqC60},
{"\!\(\*SubsuperscriptBox[\(\[Null]\), \(6\), \\(12\)]\)C",
Carbon12}, {"[\!\(\*SuperscriptBox[\(H\),
\(+\)]\)]",HplusConc}};
In Mathematica, that code looks like this:
And then:
AssignLabels[assignments];
ChemPalette["Example", assignments, 3];
This generates a palette that looks like this:
And I can then use this palette to enter any of my labels and have my input cells (and the resulting output cells) look like perfectly chemistry-standard notation.
The ActionMenu Version: Because I tend to prefer keyboard entry to palette entry, I have been exploring ways to do the same thing in a more keyboard-centric manner. Based on a suggestion by Carl Woll on this thread, I tried the following:
EscMenu[shortcut_, title_, list_] :=
AddInputAlias[
shortcut ->
ParsedBoxWrapper[ActionMenuBox[title,
(ToBoxes[#2] :> NotebookWrite[EvaluationBox[],
ToBoxes@#2]) & @@@ list,
Appearance -> "PopupMenu", AutoAction -> True]]]
EscMenu["chem", "Example", assignments]
This does exactly what I want (well, mostly... bonus question to refine it further below), except that all of the menu entries appear blank until the mouse passes over them (as shown at the top of this question). Any ideas?
Bonus Question: This approach still requires the mouse. What would be really nice is if the Esc-chem-Esc sequences could then be followed by arrow key selection of the options rather than having to use the mouse. Any ideas on how to implement that?
Context: The application is a set of code to be distributed to students in a chemistry class. They will execute the code, and then on-the-fly generate the label/symbol associations they need for the particular problem they are trying to solve from a small set of simple function calls. They should be able to generate one palette or ActionMenu for one problem (on, say, an exam or homework), and then generate a different one with completely different labels/symbols for a second problem without having to restart the kernel. The code they take from my materials they will copy-and-paste in to use; that code can be sophisticated and even obscure, because all they will do is copy-and-paste. Their usage of it, however, needs to be simple. They understand a bit of Mathematica notation, but not a huge amount, because Mathematica is emphatically not the focus of the class.
Edited to Add: A suggestion was made to write boxes directly. I will explain here why I don't think that works in this case. Let us look at a particular example notation I am using: . I can enter that in a string by typing the following key sequence: "EscDEscCtrl-fCtrlSpaceHCtrl-HCtrl-2CtrlSpaceO(g)Ctrl%oCtrlSpace". My students already (for other purposes) know all of the Ctrl sequences in that, and it gets formatted correctly. They have the skills to generate such a string, but do not have the skills to generate box representations, especially with AdjustmentBoxes. If I do not enclose that in a string, the formatting gets screwed up: . I found a way using the Notation package to assign aliases (detailed above) that lets me take that string and make it (with an embedded TemplateBox tax) the box representation displayed. This is the code that accomplishes this:
ParsedBoxWrapper@TemplateBox[{"\""<>list[[i,1]]<>"\""},
"chemical", Editable -> False, Selectable -> False]
And unfortunately, that approach doesn't seem to work when placed into the ActionMenuBox context.
However, in trying a bunch of things to provide this clarification, I may have hit on a solution. I will update shortly.