使用样式表
根据笔记本界面所提供的任意或全部可用选项,Wolfram 系统使用样式表控制笔记本的行为和外观. 样式表是笔记本的各种特殊单元的集合,它被其他笔记本引用,或者作为笔记本选项的一部分应用. 在后一种情形中,我们称样式表作为私有或本地样式表在笔记本内部“嵌入”.
StyleDefinitions | 笔记本选项,指定具有样式定义的文件能够在笔记本中使用 |
StyleData["style"] | 样式定义单元的内容的低层表示 |
样式表是包含 StyleData 单元的笔记本. 一个简单的样式表笔记本表达式可以像下面所展示的这个例子这么简单.
Notebook[{
Cell[StyleData["Section"],
FontColor->Gray],
Cell[StyleData["Subsection"],
FontFamily->"Helvetica"]
}]
上例仅定义了两种样式:Section 和 Subsection. 两者的定义仅使用了一个选项. 在没有更多信息的情况下,Section 和 Subsection 单元在工作笔记本中没有任何不同. 它们的大小相同(正常文本),并具有相同的边幅,一个将是灰色的,另一个将是黑色的,并且它们的字体也将不同.
变化的缺乏是由于缺乏更广泛的格式化信息. 通常情况下,这些格式的详细信息来自默认的样式表,在菜单和对话框中被命名为“默认”,并在笔记本表达式中用 StyleDefinitions->"Default.nb" 指定. 在编辑样式表时,默认样式将总是作为起始参照点被包括,以对所定义的样式进行改变. 这在编辑界面的样式表中是可见的,同时也作为第一个单元出现在样式表笔记本表达式中,不同的是 StyleData 添加了一个参数,来表明这是一个样式表,而不是样式名称.
Notebook[{
Cell[StyleData[StyleDefinitions -> "Default.nb"]],
Cell[StyleData["Section"],
FontColor->Gray],
Cell[StyleData["Subsection"],
FontFamily->"Georgia"]
}]
这个样式表中定义的每个样式将继承顶部指定的样式表的各种命名样式,在本例情况下是 Default.nb. 多个样式表可作为相似的单个单元的堆栈进行指定,并且对选项设置的继承将按顺序向下级联. 通过这个简单示例的设置,Section 和 Subsection 现在已经在很多方面互不相同了,正如在默认样式表中所定义的一样,只有灰色和其他字体族除外,这些在新编辑的样式定义中应用.
首先,选择 格式 ▶ 编辑样式表. 如果您的文档尚未包含样式表的话,这将立即在文档中嵌入一个全新的样式表. 这里所做的样式变化仅影响包含此个人样式表的笔记本. 下图显示的是该样式表、工具栏及其下方的主要编辑区(编辑区的开始是一个引用已有样式表 Default.nb 的单元,并且必须保持在原位).
样式表实际上是一个含有特殊类型单元的笔记本,这些特殊类型的单元能够被系统识别为样式定义. 在此添加的具有某种类型的任何单元均会影响实际文档中设置为同一样式名称的单元的外观或行为. 本例中所编辑的的是 Section,这是在 选择样式 弹出菜单中可选的常用样式:
从菜单中选择 Section,相应的样式单元将插入主编辑区,并标记为“样式 Section 的局部定义”. “局部”是指它将作为样式表的一部分(该样式表相对于文档是本地的),而不是从应用布局中被引用.
如果文档中的单元已经具有相似类型的自定义格式,这种方法则不会生效. 究其原因,是因为继承,这是一个与级联样式表相关的概念——从不同层次的引用所获得的格式设置. 这个样式表的第一个单元引用的是 Default.nb,通过点击这个笔记本您可以看到它引用的是 Core.nb. 引用链将您的新的本地样式表置于 Default 和实际文档内容之间. 因此,在您的文档中对单元所做的任何改变都会覆盖样式表中相同类型的设置.
除文档界面菜单外,另一个更为详细的更改设置的方法是使用 选项设置 菜单. 如要对 Section 单元上方的线条进行修改,这是唯一可用的界面. 在样式单元仍处于选中状态的同时,选择 格式 ▶ 选项设置 菜单下的 单元选项 和CellFrame.
CellFrame 选项所取的值是列表的列表,在这个例子中最后一个值为1,这意味着单元上方框架的边是1个像素:
应用 Section 的新设置并关闭样式表窗口,然后用快捷键或者通过 格式 ▶ 样式 ▶ Section 菜单在您的文档中开始一个新的 Section 单元,并在这个单元中键入一些文本,可以看到文本颜色现在变成了黑色,并且上方的线条不见了.
继承是一个与级联样式表相关的概念——从不同层次的引用所获得的格式设置. 样式表中的第一个单元通常引用已有的样式表,如 Default.nb,点击它可以看到它引用的是 Core.nb. 只要任何特定的选项设置位于所引用的样式表堆栈中,样式控制着实际文档内容的最终结果. 该累积效应堆栈的最终是工作文档的实际单元. 如果它应用了一个选项,如 FontColor->Red,该选项将覆盖整个继承堆栈的 FontColor 的其他设置.
$FrontEnd | 笔记本界面中所有选项的默认设置 |
Core.nb | 定义低层单元外观和行为的基础样式表 |
Default.nb | 可供用户选择的样式表,对于新文档通常是 Default.nb |
个人样式表 (如果存在) | 编辑文档样式表的结果 |
样式表中"Notebook"的局部样式定义 | 应用于笔记本层次的选项的样式表的特殊样式定义 |
样式表中的样式环境设置 | 下节中讨论的环境 |
笔记本层次的选项设置 | 应用于笔记本层次的设置 |
单元层次的选项设置 | 应用于单元层次的设置 |
StyleData["style","environment"] | 表示在样式环境 "environment" 中样式定义单元的内容 |
StyleData 的第二个参数通常是设置所应用的环境名称.
样式环境提供了一种无需更换样式表即可切换文档设置的方法. 典型的环境包括 SlideShow 和 Printout. 许多专门的行为依赖于文档的环境设置. 例如,幻灯片放映能够工作是由于分页设置,而分页设置在其他情况下与正常工作环境无关. 相似地,打印操作也受这些相同的分页符的影响,但 Printout 环境将待打印页面中所有内容按比例缩放至一个更合适的尺寸. 字体也被设置为打印所需的较高分辨率.
显示屏和打印环境的设置可以不同,方法是使用两种不同的菜单:格式 ▶ 显示屏环境 和 文件 ▶ 打印设置 ▶ 打印环境. 在默认情况下,文档界面将显示屏环境设置为 Working,将打印环境设置为 Printout. 因此,一定要注意这不是一个“所见即所得”的配置. 也就是说,在任何情况下,您“所看到的”不是“您所得到的”,但这可以由用户通过所介绍的菜单改变.
探索默认的样式表,了解其他环境是如何组织的. 选择编辑一个新文档的样式表,然后单击编辑区下方第一个单元中的 Default.nb 链接. 打开任何一个章节查找样式定义,在大多数情况下也是单元组,因为 Working 环境的样式定义单元(在 StyleData 中无环境定义)总是将样式定义单元编组,以用于相同样式名称的其他环境.
一个尤为有趣的技术开发环境是将除特定单元所在环境之外的其他环境设置为 CellOpen->False. 这样就可能为相同内容的不用语言译文创建环境,实现不同语言之间环境的切换. 另一种用途是显示或隐藏功用单元,如由 幻灯片 面板插入的幻灯片分页符. 这些分页符与分页符设置一起定义,创建在 SlideShow 环境中的单张幻灯片视图,同时在相同的观看模式中“消失”,原因是 CellOpen->False 的设置也在此处得到了应用.
开发自定义的样式表可以是一个快速、简单的过程,也可以是一个长期、复杂的过程,这要取决于具体有多少内容需要自定义. 如果样式表将用于技术文章或教科书的独特文档设计,可以预见开发上百个或更多的样式定义,并对每个样式定义设置自定义的选项设置值是可能的,并且根据有关部署要求,这些样式定义可能用于多种环境.
在这种情况下,推荐的步骤是先创建一个笔记本,将需要定义的单元的各种例子纳入,并具有适当的样式名称. 这些名称可能与文档界面当前所用的名称一样,也可以是您所希望的任何名称. 从一个完整的模板笔记本开始编辑样式表,并保证它仅由模板笔记本私用。在文档作为一个整体的前提下,设置将立即显示在模板笔记本中.
除了在“基本编辑过程”中介绍的应用单元选项的方法外, 另一种有时会非常有效的方法是使用 单元 ▶ 显示表达式 对样式定义单元的表达式进行去格式化. 这将显示单元表达式的底层语法,如果您对笔记本编程和一般单元选项有所熟悉的话,应该可以比较快地在这种模式下进行选项的设置.
一旦完成个人样式表的定义,您可以使用编辑界面工具栏中的 安装样式表 按钮,把它保存在应用布局中. 另一种方法是选中所有的样式定义单元,复制到新的笔记本中,因为样式表不过就是由这些特殊单元组成的笔记本. 使用 格式 ▶ 样式表 ▶ 其它 菜单将它保存至一个位置,以供任何文档使用,或者将它保存至特殊的样式表路径下,使之在前端重启时能在样式表菜单中列出.
FrontEnd`FileName[{$UserBaseDirectory,"SystemFiles","FrontEnd","StyleSheets"}]
FrontEnd`FileName[{$InstallationDirectory,"SystemFiles", "FrontEnd","StyleSheets"}]
单元分组行为通常在样式表层次得以控制,并影响文档的整体分层结构. 试着从 单元 ▶ 分组 菜单对模板笔记本内容的设置进行改变,从而探索各种可能的效果. 检查单元表达式以快速了解将被应用到您的自定义样式定义中的选项语法. 关于单元分组的更多信息,请参阅帮助系统中的控制单元编组.
自动编号是在样式表中定义的另一种典型设置,特别是对技术文件而言. 从 文件 ▶ 新建 ▶ 笔记本模板 中选择新模板Journal Article 或 Preprint 来了解这些设置. 首先选择编辑样式表,然后单击所引用的样式表,并打开随后的章节,以访问自动编号样式的一些范例的编号列表项.
开发样式的大多数设置可在 单元选项 类别下的选项设置中找到. 尤为有趣的选项是 CellFrame 和 CellFrameLabels,后者与 CellDingbat 相似,可接受任何单元表达式,这使得标记或者“装饰”单元内容存在很多有趣的方式. 使用 CellFrameLabels 的一个极端的例子是 Demonstrations 样式表. 在这个样式表中,模板文件的所有初始显示内容都来自样式表设置. 选择 文件 ▶ 新建 ▶ 演示项目,然后对所有单元表达式进行去格式化,可以看到这些单元的内容都是空的.
Demonstration 样式表同时强调了从其他不同样式定义继承设置的方法. StyleData 接受一个额外参数,该参数的形式与列在自己样式表顶部的所引用的样式表的形式相同. 该参数指向一个不同样式来继承设置,而不是指向一个样式表.
Cell[StyleData["Section", StyleDefinitions->StyleData["Title"]],
FontColor->Gray]
Cell[StyleData["Section", "Printout", StyleDefinitions->StyleData["Title", "Printout"]],
FontColor->Gray]
最后需要提到的是使用公式,这可能是指定单元选项的最有趣也最强大的一种方法. 这可能是因为前端包含它自己的计算内核,支持 Wolfram 语言的许多函数. 这些可在键入所需要的函数名称的同时,使用 FEPrivate` 语境查看通过指令补全所能提供的函数时发现. 试试看,比如 FEPrivate`If 或 FEPrivate`SameQ. 另外,或许也可以利用任意选项的 CurrentValue[] 作为公式的一部分,来动态控制其他选项的设置. 这种方法可在幻灯片放映样式表中找到,例如在下面的设置中,窗口宽度值乘以系数0.135,作为左侧单元边距的设置.
CellMargins->{{
0.135 FrontEnd`AbsoluteCurrentValue[{WindowSize, 1}],
0.03 FrontEnd`AbsoluteCurrentValue[{WindowSize, 1}]},
{1.5 Inherited, 1.5 Inherited}}
有个小小的警告:前端对样式表的解析,发生在对文档的方方面面进行编辑和处理的任何时候,所以谨慎处理选项设置的公式是非常重要的,尤其是在它们保持高效计算方面. 使用 Dynamic[] 也是可以的,但由于前端对样式表的迭代解析,建议尽量避免使用,除非您在实现自己的格式化目标时没有其他方法可用时再考虑使用。