Inconsistent handling of Dynamic option values; intended, omission, or bug?

In answering Dynamic ClipPlanes calculated from current ViewPoint Kuba and I got into a brief exchange regarding how Option values wrapped in Dynamic should be handled. For background John Fultz wrote:

Front end options, which includes all box options, can take Dynamic heads. That basically means that the FE will compute the value of the Dynamic and use it for the option. And that it will be updated whenever a Dynamic dependency updates.

It would therefore appear advantageous for Option values that become Box options to preserve a Dynamic head, and indeed many do, however some do not. For example:

gr3D = Graphics3D[{}, MapAt[Dynamic, 2] /@ Options @ Graphics3DBox];

Tally[Head /@ Values @ Options @ ToBoxes @ gr3D]

{{Dynamic, 51}, {DynamicBox, 6}}


All but six Options pass their Dynamic values; these six allow conversion to DynamicBox:

Cases[Options @ ToBoxes @ gr3D, _[op_, _DynamicBox] :> op]

{AxesLabel, AxesStyle, ClipPlanes, Epilog, PlotLabel, Prolog}


Should these six Options also pass Dynamic values or is there a design intent that they do not?

(Observations in 10.1.0 under Windows, in case this behavior is version dependent.)

Further consideration

It is worth noting that in the case of expressions which are explicitly displayed a DynamicBox "works" because it is an active element in the front end, therefore e.g. a dynamic value of PlotLabel updates appropriately:

Slider[Dynamic[x], {0, 1}]

Graphics3D[Ball[], PlotLabel -> Dynamic[x]]


However something that is not explicitly displayed, such as a style directive, would seem an inappropriate place for a DynamicBox expression, and it does indeed produce an error message:

x = Red;

Graphics[Disk[], AxesStyle -> Dynamic[x]]


(* shown by clicking the "+" next to the error frame *)

An improperly formatted directive with head DynamicBox was encountered.

In the case of AxesStyle I think conversion to DynamicBox is simply a mistake.

This can be bypassed by use of a RawBoxes wrapper, which if respected prevents processing during Box conversion.

(* Thanks to Kuba for the concise example *)

ColorSlider @ Dynamic[x]

Graphics[
Disk[],
Axes -> True,
BaseStyle -> AbsoluteThickness[3],
AxesStyle -> RawBoxes @ Dynamic[x]
]


The case of AxesLabel is somewhat ambiguous as its elements are explicitly displayed, therefore individual Dynamic labels being converted into DynamicBox expressions might be appropriate. However there are problems.

In version 10.1.0 under Windows this initially works but closing the Notebook in which it resides hangs the FrontEnd:

(*  THIS CODE MAY HANG THE FRONT-END

ColorSlider @ Dynamic[x]

Graphics[Disk[],
Axes -> True,
AxesLabel -> Dynamic[x]
]

*)


This likewise works initially but hangs the FrontEnd on close:

(*  THIS CODE MAY HANG THE FRONT-END

ColorSlider @ Dynamic[x]

Graphics[Disk[],
Axes -> True,
AxesLabel -> {Dynamic[x]}
]

*)


Adding RawBoxes to a bare Dynamic does not work right:

ColorSlider @ Dynamic[x]

Graphics[Disk[],
Axes -> True,
AxesLabel -> RawBoxes @ Dynamic[x]
]


An unknown box name (RGBColor) was sent as the BoxForm for the expression. Check the format rules for the expression.

This implies an explanation for Box conversion: in GraphicsBox the value of AxesLabel needs to be in Box form. Attempting this conversion inside our force-fed Dynamic once again produces an initial result but hangs on close:

(*  THIS CODE MAY HANG THE FRONT-END

ColorSlider @ Dynamic[x]

Graphics[Disk[],
Axes -> True,
AxesLabel -> RawBoxes @ Dynamic @ ToBoxes @ x
]

*)


There clearly seems to be a bug (in 10.1.0) with the use of dynamic values in AxesLabel.

• None of the examples are hanging the front end in 10.4.1 on Windows, though all other observations match. – Simon Woods Jun 17 '16 at 21:11
• @Simon Thanks. I guess that bug is fixed. What do you think of the handling of AxesStyle and ClipPlanes? – Mr.Wizard Jun 18 '16 at 6:33
• It certainly seems inconsistent - why is AxesStyle handled differently to FrameStyle for example? – Simon Woods Jun 18 '16 at 12:49
• The conversion of options to boxes is done by SystemDumpGraphicsOptionsToBoxes which in turn calls TypesetMakeBoxes on each option. TypesetMakeBoxes has a huge list of downvalues, including a special case for AxesStyle, essentially MakeBoxes[AxesStyle -> stuff] becomes AxesStyle -> MakeBoxes[stuff]. There is no such special case for FrameStyle (you end up with TypesetHold[FrameStyle -> stuff]`). I suppose there are good reasons for this, which perhaps have nothing to do with Dynamic. – Simon Woods Jun 18 '16 at 12:50