panel上有三个组成部分:
- _leftBox: 放两个组件: ActivitiesButton, AppButton
- _centerBox: 放一个组件: dateMenu
- _rightBox: 存放系统indicator
this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
if (global.session_type == Shell.SessionType.USER) {
this._activitiesButton = new ActivitiesButton();
this._activities = this._activitiesButton.actor;
this._leftBox.add(this._activities);
// The activities button has a pretend menu, so as to integrate
// more cleanly with the rest of the panel
this._menus.addMenu(this._activitiesButton.menu);
this._appMenu = new AppMenuButton(this._menus);
this._leftBox.add(this._appMenu.actor);
}
上面代码给出了_leftBox的创建及添加ActivitiesButton和appMenu的过程。
定义在 panel.js 中。 label和hotcorner通过下面语句实现。
this._label = new St.Label({ text: _("Activities") });
container.add_actor(this._label);
this.actor.label_actor = this._label;
this._hotCorner = new Layout.HotCorner();
container.add_actor(this._hotCorner.actor);
activitiesButton的press/release事件需要重新定义,因为其实现的功能不同于一般的menuButton.所以通过以下语句实现:
this.menu.open = Lang.bind(this, this._onMenuOpenRequest);
this.menu.close = Lang.bind(this, this._onMenuCloseRequest);
this.menu.toggle = Lang.bind(this, this._onMenuToggleRequest);
button click/key press事件通过以下语句定义:
this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
回调函数中调用 Main.overview.toggle(); 用来触发overview。
定义在 panel.js 文件中。作用是跟踪当前应用程序。同时提供launchApp时的notification。注意在overview状态时是不显示此button的,所以在代码中可以看到这两行:
Main.overview.connect('hiding', Lang.bind(this, function () {
this.show();
}));
Main.overview.connect('showing', Lang.bind(this, function () {
this.hide();
}));
_centerBox的创建
this._centerBox = new St.BoxLayout({ name: 'panelCenter' });
this.actor.add_actor(this._centerBox);
_centerBox button的添加
this._centerBox.add(this._dateMenu.actor, { y_fill: true });
this._menus.addMenu(this._dateMenu.menu);
_rightBox的创建
略
_rightBox indicator的添加: 首先在 panel.js 文件首部定义了一些系统indicator常量,如下所示:
const STANDARD_STATUS_AREA_ORDER = ['a11y', 'keyboard', 'volume', 'bluetooth', 'network', 'battery', 'userMenu'];
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'userMenu': imports.ui.userMenu.UserMenuButton
};
其后,在function : startStatusArea 中用for循环将这些indicator添加到_rightBox中,所以具体的函数调用如下图所示:
添加流程大致如此,startStatusArea会在main.js中被下面这条语句执行。
panel.startStatusArea();
panelMenu.js 定义了panel menu button。其中先后定义了ButtonBox/Button/SystemStatusButton/三个对象,ButtonBox作为基类,Button继承ButtonBox,SystemStatusButton继承Button, panel.js 中_rightBox添加的indicator都属于SystemStatusButton。
在 panelMenu.js Button对象的定义中,引入了menu成员对象,如下代码所示:
if (dontCreateMenu)
this.menu = null;
else
this.setMenu(new PopupMenu.PopupMenu(this.actor, menuAlignment, St.Side.TOP, 0));
然后在button press事件的回调中执行如下语句:
_onButtonPress: function(actor, event) {
if (!this.menu)
return;
this.menu.toggle();
},
在 popupMenu.js PopupMenuBase基类中toggle函数如下所示:
toggle: function() {
if (this.isOpen)
this.close(true);
else
this.open(true);
},
这样,调用open函数show出菜单,那么菜单是什么组件?答案是BoxPointer, 也就是说status indicator 点击打开的菜单控件和messageTray上通知icon点击打开的messageInfo是一个组件,可以通过 PopupMenu 对象的”constructor”中得到证明。代码如下:
this._boxPointer = new BoxPointer.BoxPointer(arrowSide,
{ x_fill: true,
y_fill: true,
x_align: St.Align.START });
this.actor = this._boxPointer.actor;
所以open函数的实现也就不难理解,关键代码如下:
this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
this._boxPointer.show(animate);
各种 menuItem 定义也在在 popupMenu.js ,主要的类型如下表:
Name | description | |||
---|---|---|---|---|
PopupBaseMenuItem | MenuItem基类 | |||
PopupMenuItem | 类似一个label,创建此对象会在popupMenu中创建一个label,如volume indicator的第一行“Volume”就是一个PopupMenuItem | |||
PopupSeparatorMenuItem | menuItem之间的分割空间,用于UI美化 | |||
PopupAlternatingMenuItem | item label可选择,有DEFAULT/ALTERNATIVE两块label可供选择 | |||
PopupSliderMenuItem | 离散划动控件,典型: 音量控制 | |||
Switch | 二进制开关控件的基类 | |||
PopupSwitchMenuItem | 二进制开关控件 | |||
PopupImageMenuItem | ||||
PopupMenuBase | ||||
PopupMenu | ||||
PopupSubMenu | ||||
PopupMenuSection | ||||
PopupSubMenuMenuItem | ||||
PopupComboMenu | ||||
PopupComboBoxMenuItem | ||||
RemoteMenu | ||||
PopupMenuManager |
popupMenu.js/还定义了一个辅助function: /addSettingsAction 直接添加一个PopupMenuItem将之与对应app的desktop相关联。
对statusBar以及上面的控件的结构大致如此。