Style sheet primer
- To: mathgroup at smc.vnet.net
- Subject: [mg76590] Style sheet primer
- From: John Fultz <jfultz at wolfram.com>
- Date: Thu, 24 May 2007 06:11:31 -0400 (EDT)
- Reply-to: jfultz at wolfram.com
I've been thinking about how to address the stylesheet issues. I could= write an extremely long email on the topic addressing all questions to date, but I've= decided it might be more manageable to begin with a primer on the concepts,= then address the applications by addressing the various unanswered questions on= this group in separate emails. Sorry for those who've been waiting for several days for a response like= this on the stylesheet issue. Responding to these questions takes considerable time= free from the distractions of work and life which have seemed to come up frequently for me, lately. Some new concepts in the version 6 stylesheet mechanism... * Inherited stylesheets - A stylesheet may inherit from other stylesheets.= If stylesheet B inherits from stylesheet A, then B gets all of A's styles plus= any defined in B. B can override A in several ways... + It can add new options to an existing style + It can add new styles + It can completely replace an existing style + It can't remove a style, but it can replace it with a null style that doesn't appear on the menus. A stylesheet can inherit from multiple stylesheets, in which case they are simply combined with earlier stylesheets taking priority (this is very= similar, incidentally, to what has always happened if you have multiple definitions= of a named style in a single stylesheet). Note that in 5.2, there was an= extremely limited inheritance model...all stylesheets inherited from Default.nb. * Inherited styles - A named style may inherit from any other named style. = Similarly, a named environment may inherit from any other named environment.= This inheritance only takes place within the current stylesheet (or its ancestors), though...you cannot inherit from a style from a completely= different stylesheet. * Private or embedded stylesheets - This is not a new concept, but it's done= differently now. This is a one-off stylesheet which is embedded in the= notebook. Previously, this was done by embedding an entire copy of the stylesheet in a= notebook. This is no longer necessary in a world of inherited stylesheets. = You can now embed a very tiny stylesheet which inherits from a canonical= stylesheet and contains only the changes (i.e. new styles, changed existing styles). * Core.nb - The Core stylesheet is very nice example of what inherited stylesheets allow. Core doesn't contain enough styles to constitute a= useful stylesheet. But it does contain those styles which really ought to be at= the core of every other stylesheet. For example, it contains all of the style information which supports default syntax coloring. Without this= information, all of the syntax coloring will appear styleless (i.e. black, plain). Reproducing this in every single stylesheet is unnecessary, and creates more= opportunities for mistakes to happen in any individual stylesheet. But that= doesn't mean that a certain stylesheet might not add to or override a few of= the syntax styles. Every stylesheet we ship inherits from Core (although not= always directly...a stylesheet might inherit from Default, which in turn inherits= from Core). * MenuPosition - Since we now have stylesheets like Core which are only= useful as parents of other stylesheets, we should hide them from the menus. = Therefore, stylesheets have a MenuPosition option which is set at the notebook level. = Setting the MenuPosition->None removes it from the menu entirely. Any= positive number allows you to specify specifically where the stylesheet should be in= the menu. Stylesheets with equivalent positive numbers are sorted= alphabetically. This mechanism of removing stylesheets from the menu is also being used when= we want to stop supporting some stylesheets, but keep them around for backward= compatibility. The MenuPosition option also works for individual styles, serving a very= similar purpose (this replaces the StyleMenuListing option for 5.2). The interfaces= provided for creating new styles will always put your styles at the bottom= fo the Styles menu. * MenuCommandKey - This option applies to styles and allows you to set the command key for a style to be "1"-"9". The command-key assignments are no longer order-sensitive. However, for the moment, conflict management is= left up to you. The behavior of a stylesheet with multiple styles assigned to the= same MenuCommandKey is undefined. * Legacy stylesheets - The front end enters a slightly different mode when reading a stylesheet created by 5.2 and earlier. For example, in new stylesheets, it respects only the MenuCommandKey and MenuPosition options= when constructing the Style menu, whereas in legacy stylesheet it respects the StyleMenuListing option and assigns command keys according to the order of= the styles (i.e. 5.2 behavior). Now, let me go over some problems with the previous design, and how we deal= with those problems in v6.... * Installed stylesheets can be modified and saved (i.e. the old Edit Stylesheet->Shared). This is bad because there is simply no guarantee that= you can even write to the installation directory. Also, somebody could change a= stylesheet like Default.nb in such a way as to permanently damage the system= and necessitate a re-install. Built-in stylesheets are no longer editable or savable. * Creating new stylesheets (embedded or public) freezes your stylesheet at= the version of Mathematica you're using. For example, anybody who created a 5.2= stylesheet based upon a copy of Default.nb will find that many things appear= broken (graphics don't appear the same, syntax coloring might not show up correctly) because you are essentially using a 5.2 version of Default.nb. = By using inherited stylesheets, you are now inheriting from the canonical stylesheet. If you make a stylesheet which inherits from Default.nb in 6.0,= and then open the notebook in Mathematica 7, it will inherit the Mathematica 7 stylesheet, and any new features in that stylesheet. * Creating a stylesheet from scratch is a heavyweight process, but that's= the only option that was really available in 5.2. Very few people have the resources or desire to create a stylesheet from scratch. Much more= typically, people want to tweak existing stylesheets. In fact, very commonly, all= people want to do is to just add or change a very small number of styles. The inherited stylesheet mechanism is perfect for this. So here's a few of the interesting implications of the new mechanism which= may not be immediately obvious... * Embedded stylesheets are now very small and manageable. * Your modification of a system stylesheet need not have a different name. = For example, if you want to change the behavior of Default.nb, make a new= Default.nb which inherits from Default.nb and put it in $BaseDirectory or $UserBaseDirectory. The copy in $[User]BaseDirectory will inherit from the= one in the layout, and you'll only see the one instance in the menu. * This allows us to create custom interfaces which streamline the most= common stylesheet tasks users wish to do. Now, here comes the rough part. All of the underlying technologies have a= solid implementation, but some of the user interface could still use some work,= and it's largely undocumented. For example, I think we have a very good= beginning to an interface for working with embedded stylesheets, although it could certainly use a style inspector. Creating named stylesheets is considerably= awkward right now. Finalizing the interfaces would have required delaying Mathematica. We= decided not to do this because, frankly, the whole of Mathematica 6 is really good= and we were eager to get it out the door. Also, except for the lack of documentation, the situation really isn't any worse than 5.2, which was also= undocumented and considerably awkward in every aspect of stylesheet= editing. Finally, before I go onto answering specific questions, let me outline the syntax for the style data cells. As a review, a 5.2 style cells look like this... (* defines a style *) Cell[StyleData[stylename_String], opts] (* defines an environment *) Cell[StyleData[All, environment_String], opts] (* defines an environment-specific tweak to a style *) Cell[StyleData[style_String, environment_String], opts] (* Set notebook-level options *) Cell[StyleData["Notebook"], opts] 6.0 now allows the following new StyleData forms as the first argument of= a Cell: (* Inherit from another stylesheet. This should always appear before any= style definitions *) StyleData[StyleDefinitions->stylesheet_String] (* This defines how a style or environment is inherited...*) StyleData[stylename_String, StyleDefinitions->source] StyleData[All, environmentname_String, StyleDefinitions->source] StyleData[stylename_String, environment_String, StyleDefinitions->source] Possible values of source: =09Inherited: Inherit from the style named 'stylename' in the parent= stylesheet (this is the default) =09None: Do *not* inherit the style from anywhere =09StyleData[style_String]: Inherit from 'style' as defined in the current or= parent stylesheet =09StyleData[All, environment_String]: Inherit from 'environment' =09StyleData[style_String, environment_String]: Inherit from the environment-specific definition of style More followup to specific questions coming shortly. Sincerely, John Fultz jfultz at wolfram.com User Interface Group Wolfram Research, Inc.