第15章 定义应用程式的预设选项 -- Resources
大多数的X程式接受命令列选项,以便让你指定前景和背景的颜色、字型
、起始位置等等。这种需求是有必要的,因为如果你在程式内硬性规定使用某
种字型,而在执行此程式的机器上并没有这种字型,则将使得程式无法执行,
所以你不应硬性规定某些参数。 当你每次执行程式时不太可能在命令列中指定所有需要的选项,因为有太多种
可能的组合了,所以X提供了一个叫做resources 的一般性结构,用来传递预
设的设定给应用程式。当你阅读指南页时,你可能已经注意到要你参照resources
,但却不知道什麽是resources ,我们将在此解释。 你在系统中几乎所有的定制动作都将运用到resources ,事实上你为一
个应用程式所选择的每一个选项的设定都要用到resources ,从简单的项目例
如色彩或字型,到定制你的键盘或管理你的显示器如何工作,它非常的方便,
而且在系统中到处都用得到。 本章我们描述什麽是resources ,及关於它们是如何发展的资讯,接下来
我们描述X Toolkit(工具),它完全地使用到了resources 的结构;然後
告诉你一些resources 工作的细节,你该如何设定它们,及你能用它们设定哪些
型态。 这是相当长的一章,有几个新的观念被加进来,一开始会有些困难,但不
需太担心,原则上resources 结构非常地简单,只是第一眼看起来好像有许多
"魔术符号" 而已,也许你应该先很快地浏览一遍,然後再详细地重读一遍。
15.1 什麽是resources ? 在X的文献中,”resources ”有两种意义。第一种是相当低阶的,意指
被server管理或建立而被应用程式使用的东西。视窗、游标、字型等均属於这
种意义。 另一种意义也就是通常你在指南页中常看到”resources ”的意义:它是
一种传递预设设定、参数和其它值给应用程式的方法。在本章中我们局限於
讨论此种意义之resources 。在解释现行系统如何工作前,先回顾一下X的早
期版本是如何掌握这些功能的,因为现行的结构由此产生。
15.1.1 ”预设”的背景 在X较早的版本,对於像视窗背景颜色、视窗边界的颜色、应用程式所使
用的字型这类项目你可以轻易地设定其预设值。 预设值的设定方式很直接,你只需指定一个视窗的属性和它的预设值。例如: .Border : red 意即所有的视窗均为红色的边(除非你在命令列中重新设定边的颜色),你也
可以把程式的名称放在属性之前,则只有被指名的程式才会改变,所以把以下
这个规格 xclock.Border:blue 和先前的规格结合在一起的意义为:预设所有视窗均为红色的边,只有xclock
的视窗为蓝色的边。 每当你设定预设值,程式会自动取用该值,所以你□需每次均指定你的选
择,它让你依照适合你的工作习惯来使用字型,不论是你要用较小的字型以获
得更多的资讯显示,或是用较大的字型以便阅读,它让你为特定的应用程式选
择颜色,你可以定义应用程式的起始位置,所以你可以自行设计一些启始萤
幕的布置,因为许多的预设值(字型、色彩等)实际上精确的意义为”resources”
,所以”resources ”的意义逐渐扩增为”预设值设定(default setting) ”
或”设定预设选项(setting default options) ”。
15.1.2 Resources 传递资讯到应用程式 随著X的发展,应用程式也随之扩增,需要有一个设施传递大量的资讯到应
用程式以定制或指定它们的行为,而不再只是有关色彩和字型的资讯而已,
例如你可以告诉 xbiff检查信件的频率,或定义 xterm的功能键(function-key)
12为插入某一特定的字串,或在 xedit中连续碰触两次滑鼠中按钮代表选择目
前这段本文等等。 所以逐渐地,resource及预设设施已遂一被发展出来,直到目前对於传递
任何资讯到一个应用程式已是一个一般性的结构。你可以像文字串一样地指定
资讯,应用程式会在内部解释它:例如把这字串当作一个滑鼠按钮的名称,或一种颜
色,或由应用程式所发出的一个功能和 "resources"是如何指定的。 这个结构也逐渐地复杂起来以便让你能正确地指定在何处应用预设值。在
以前,你只能指定所有的程式或某一个特定的程式。现在的系统你可以设定的
预设值如:”终端机视窗的选单选项”或”在所有视窗的标签”或甚至”除了
xterm以外的所有编辑器视窗按钮盒中的功能按钮”。 X Toolkit, 使得resources在使用上有很大的包容性并且增进了应用的
精确度。你需要先了解 Toolkit是什麽,才能适当地使用resource 结构,我
们将在下一节讨论。
15.2 X Toolkit 我们先前曾提过,X并不决定使用者介面,它只是提供一些结构,让应用
程式设计者能组合成任何形式的介面。理论上这是非常合乎需求的 -- 它使得
系统拥有一个一般性目的的工具且没有使用上的限制,但从另外的角度来看,
它有很大的缺点: .对一个使用者而言,不同的应用程式有不同的介面,不只是难学难记,
且应用程式无法平顺地 (smoothly) 相互协调工作(例如无法在视窗之间
做剪贴),你得到的是一群个别的、独立的程式,而不是一个一致的、
合作无间的系统。 .从程式设计师的立场,意味著基本视窗系统上的每一件事均需从头做起,
选单、卷动棒、时钟、功能钮等等都必须一一生产。甚至在单一的产品,
不同的程式师做了一点稍有不同的事,便会导致许多不相容的情况。 为了克服上述的问题,Toolkit(工具)的方式应运而生。 在某些□围,Toolkit 会决定使用者介面的形式,但是无论如何,它会尽
量减少这种影响,并让使用者介面发展者有更多选择的可能性,Toolkit 被分
为两个部份: 1. 一组基本的结构和函数用以建构使用者介面的元素,被称为Toolkit
Intrinsics(内部的工具)。不论是什麽样的介面,任何工具均需使
用到它,所以我们可以把Toolkit Intrinsics视为”固定的”,也就
是无可替代的。 2. 一组提供特定的使用者介面(或介面的形式)的元素,这些元素被称
为 widgets (小工具),而Toolkit 的第二部份称为 widget set (小
工具组),我们认为这是可以替换的,不同的介面提供不同的Widget
Sets ,甚至它们都使用Intrinsics。 下面两个小节更详细地说明这两个部份。
15.2.1 Toolkit 的第一个部份 -- Intrinsics Intrinsics定义的实体称为widgets,并提供了所有建立、管理和毁坏widget
所需的设施。理论上,一个widget是一个处理特定动作的使用者介面的元素,实际
上一个widget是X视窗加上规则和功能以决定它的输入和输出的动作,也就是
说,它如何对使用者有所反应。 为了帮助解释widget的观念,我们将给一点□例,但是请注意!它们并不
是Intrinsics的一部份,而是我们将於下一小节讨论的一个特定的widget组的
一部份,在此提出目的只是为了方便。 Command Widget(命令widget):这是一个在萤幕上含有一些文字的长方
形”按钮”(也就是一个小视窗)。当指标在这个按钮之上时,它的边会呈现
高亮度,当一个滑鼠按钮在这个widget被碰触时,一个被程式师指定的软体常
式(routine) 便会被执行。 你已经使用过command widget好几次了:在xedit 的命令选单和在xman的
主选项视窗。 Scrollbar Widget(卷动棒widget):同样的,你也已经使用过了好几次,
在xterm 和xedit 中卷动本文,在xman中卷动本文和目录列。 Intrinsic 提供了基本的结构,任何一个提供介面的较高阶软体均需要使
用到它,它提供了以下的功能: .建立和毁坏widget。 .把一群widget当成一个单元(unit)来管理。 .掌握geometry,也就是说位置,包括从最高阶(也就是应用程式的 -geometry
选项)到最低阶(管理应用程式用到的sub-widget的位置(例如选单按钮
的位置))。 .掌握”事件”,例如在一个widget中, 当滑鼠按钮被碰触时呼叫适当的程
序、管理视窗的曝光 (exposure)和掌握键盘的输入。 .管理给resources 和预设的每一个widget。
15.2.2 Toolkit 的第二部份 -- Widget Sets 广义来说,Intrinsics只提供你建造一个使用者介面的骨架,Widget Set则
实际地提供了一个既定的介面,且不同的widget组提供不同形式的介面,虽然
对任何□围的需求并无法预防混用widget,但一般仍希望一个系统固定在
一致性的widget set上。 在X core 版上只有一个widget set提供,我们描述於下: Athena Widget Set (雅典娜widget set) 大部份的MIT core版的应用程式使用Toolkit 和Athena Widget Set.(名
称的来源是X由MIT 的Athena计画产生出来)。这些widget的定义你已在许多
的应用程式用过。 我们在前节提过了Command Widget和Scrollbar Widget,至於Athena Widget
Set 的其它部份包含: Label Widget:这个你可以想像 -- 在视窗中显示的一个字串或图。(例
如在xman主选项选单中的”Manual Browser”的标题) Text Widget :我们在第10章描述xedit 时提过的”building block”。
它提供我们所使用的编辑功能。 Viewport Widget :一个具有卷动棒的视窗,让你可以卷动视埠(viewport)
的内容,xman使用其中之一用以显示指南页之目录。 Box Widget:它以一个指定大小的盒管理sub-widget的布置,且试著将 sub-
widget尽量集中在一起,例如xmh 的Reply 、Forward 等命
令钮即是由Box Widget布置。 VPaned Widget :它管理sub-widget,将它们保存在垂直堆叠中,且显示了
在两个sub-widget之间的分隔线上的”把手”(grip),把手
可以选择性的让你改变一个widget的大小,而且另一个相
关的widget大小亦伴随变化,例如我们在图10-12 看到的
xman的视窗的主要的元素是被VPaned Widget 管理的。 Form Widget :另一种管理一组sub-widget的方法,但对位置的选择有更多
的弹性。 List Widget :它管理一群字串,将它们安排在行列中,任何的字串藉
著於其上碰触的动作而被选择:字串会转为高亮度,且呼叫
一个指定的函数以完成特定的动作。xman使用一个List
Widget来掌握在一个指南章节中指南页的表列。 我们现在来看一下如何组合widget以获得所需要功能,我们仍然以xman为
例。xman的指南页之目录在它的低阶是list widget ,管理目录页名称的表列
以及它本身的内容是用viewport widget (让使用者卷动至表列中所需的位置
),将指南页的widget聚集在一起,它们是包含在一个VPaned Widget 中,所
以事实上这是一个阶层状(hierarchy) 的widget,每一个可以完成它的专门
功能,而所有的应用程式所使用的Toolkit 均含有这三个widget结构。
15.2.3 widget:名称和类别 (Names and Classes) resource和预设结构是在widget名称的基础下工作,所以我们将以对名称
的处理做一个概观方式来结束对Toolkit 的观察,并回到先前讨论的resource。 Toolkit 提供一个物件导向程式系统(object-oriented programming system)
给程式设计师。它定义物件的类别(class) ,也就是指定何时物件被建立或如
何操作等等的物件性质。这些物件即是widget,系统将确保它们和其它的widget
以及其它部份的应用软体以定义明确的方式交谈。 当一个程式设计师建立一个特定类别的widget,它被称为该类别的成员
(instance)(概括的说,一个类别是一个抽象的定义,而一个成员在某些地方
实际地符合这些定义。)建立widget有必须一个名称,由程式设计师指定,(
例如:程式码的实际型式为”Creat a widget, of the class Box Widget,
and call it topBox ”)在某些环境下widget的类别名称也会被参考到。总
结来说,一个widget有一个成员名称和类别名称;更简单的说,一个名称和一
个类别。
15.3 Resources 如何被管理 -- Resource管理器 让我们提醒自己一下我们试图用resource来做什麽?我们要能传递资讯给
一个应用程式,告诉它以某些方式改变它的一般性动作,例如,将视窗的边
以粉红色取代原来的黑色,或使用一些特别的字型。 X用下述的方式掌握这些需求。你设定一个包含许多项resource规格的资
料库,每一个resource规格以一个应用程式的某些特徵命名,且设定一个值给
这个特徵当预设值,也就是说,一个规格 (spec) 的形式为: characteristic : value (特徵:值) 当应用程式开始执行时,它会先询问资料库是否有任何特徵符合自己所要
的设定,或使用相关的值,例如: xclock*foreground:blue 意为将值blue设定给特徵xclock*foreground 。用以决定一个程式的需求
是否符合在资料库中之规格的系统部份,被称作Resource管理器。 Resource预设值能被应用到一个应用程式中的物件(通常是widget),就
如同设计整个程式一般,(例如你可以对一个特定的子视窗在某一个命令按钮
的背景色设定预设值,而不是只能针对所有应用程式的视窗背景)。为了能达
到这一点,我们需要一些严谨的命名方法,以设定物件应用预设值。
15.3.1 指定一个Resource预定应用到何处 Resource管理器根据特徵值(characteristic)决定一个预设规格是否能应
用在特别的情况,我们可将特徵值分为三个部份。 1. 你用以设定预设值的程式属性,例如:背景色、字型等。 你必需指定属性 (attribute) -- 意即你设定什麽值给它。给定一个
resource的规格 而不说明它的值是无意义的。 注意:在X的文献和手册中,属性通常被称为”resource”或
”resource name”,”Resource”也通常被用来当作我们称为特徵值。 特徵值的其它两个部份指定预设值在何处使用。例如只在特定的程式
使用或在特定型态的物件,或两者均是。 2. 应用到这个规格的应用程式的名称,如果你省略它,规格将应用到
所有的应用程式。 3. 一连串的限定(restrictions)条件:当物件符合限定条件时,才会产
生指定的应用。限定通常为widget的名称,你可以指定从零开始任何
数目的限定。例如: xclock*foreground:blue
xedit*row1*Command*Cursor:Cntr_ptr 第一个例子没有任何限定,第二个例子有两个限定(row1 和Command) 三个部份依序排列 [<program name>] [<restrictions>] <attribute> 并以特殊的分隔符号分开,我们将於稍後说明分隔符号的细节,但我
们先看一些特徵值的□例(为了简单起见,我们在□例中只用到颜色
属性)。
一些说明Resource规格的□例 .指定在任何地方中的前景色预设值为黄色。 *foreground:yellow 我们未指定任何应用程式的名称,所以此规格可应用到所有的应用程式;
我们也未指定任何限制,所以对一个应用程式在任何地方都适用。("*" 这个
符号就是我们方才提及的特殊分隔号的一种) .指定只有在xclock应用程式中的前景色预设值为粉红色。 xclock*foreground:pink 这个规格仅能在xclock适用,但是只要项目中的属性叫做
”foreground”的均适用。 .现在,针对一个特定应用程式的特定地方: xman*topBox*foreground:blue 这个规格仅能在xman适用,而且只能在xman主选项选单中名为topBox的
物件适用。(应该适用於xman中所有叫topBox的物件,但实际上只有一个
topBox物件) .在第二个□例(粉红色)中我们包含了应用程式名称,但忽略了任何限
制,现在我们反过来: *command*foreground:green 也就是说,我们指定在任何应用程式中物件名称为command 的前景色预
设值为绿色。
15.3.2 用类别名称一般化规格说明 前述的例子说明了我们对预设值结构所需的大部份功能,但它们有一个限
制:你必须知道应用程式设计师设计在每一个应用程式中的widget名称,这
些资讯有时包含在程式的指南页中的一部份,但通常被省略。 无论如何,Resource管理器有一个尽量减低这个问题的方式:当你在特徵
中不论何处用到一个应用程式名称、限制或属性名称,你均可类别名称(class
name)来代替它。 应用程式类别名称(Application class name):描述程式的型态,例如
xterm 可以是Term Emu