Panel: clean up button construction code

We already could build the right part of the panel declaratively according
to the session mode. Extend that to handle the left and center parts.
Also, move the mapping from the roles to the classes in panel.js, as it shared
by all modes.

https://bugzilla.gnome.org/show_bug.cgi?id=682546
This commit is contained in:
Giovanni Campagna 2012-08-28 23:10:44 +02:00
parent e0ca572572
commit e5534e86ab
3 changed files with 84 additions and 128 deletions

View File

@ -222,8 +222,7 @@ function start() {
sessionMode.createSession(); sessionMode.createSession();
panel.startStatusArea(); panel.init();
layoutManager.init(); layoutManager.init();
keyboard.init(); keyboard.init();
overview.init(); overview.init();

View File

@ -14,13 +14,14 @@ const St = imports.gi.St;
const Signals = imports.signals; const Signals = imports.signals;
const Atk = imports.gi.Atk; const Atk = imports.gi.Atk;
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab; const CtrlAltTab = imports.ui.ctrlAltTab;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const Layout = imports.ui.layout; const Layout = imports.ui.layout;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu; const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu; const PanelMenu = imports.ui.panelMenu;
const DateMenu = imports.ui.dateMenu;
const Main = imports.ui.main; const Main = imports.ui.main;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
@ -221,14 +222,14 @@ const AppMenuButton = new Lang.Class({
Name: 'AppMenuButton', Name: 'AppMenuButton',
Extends: PanelMenu.Button, Extends: PanelMenu.Button,
_init: function(menuManager) { _init: function(panel) {
this.parent(0.0, null, true); this.parent(0.0, null, true);
this.actor.accessible_role = Atk.Role.MENU; this.actor.accessible_role = Atk.Role.MENU;
this._startingApps = []; this._startingApps = [];
this._menuManager = menuManager; this._menuManager = panel.menuManager;
this._targetApp = null; this._targetApp = null;
this._appMenuNotifyId = 0; this._appMenuNotifyId = 0;
this._actionGroupNotifyId = 0; this._actionGroupNotifyId = 0;
@ -899,6 +900,29 @@ const PanelCorner = new Lang.Class({
} }
}); });
const PANEL_ITEM_IMPLEMENTATIONS = {
'activities': ActivitiesButton,
'appMenu': AppMenuButton,
'dateMenu': imports.ui.dateMenu.DateMenuButton,
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
PANEL_ITEM_IMPLEMENTATIONS['bluetooth'] =
imports.ui.status.bluetooth.Indicator;
try {
PANEL_ITEM_IMPLEMENTATIONS['network'] =
imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const Panel = new Lang.Class({ const Panel = new Lang.Class({
Name: 'Panel', Name: 'Panel',
@ -919,7 +943,7 @@ const Panel = new Lang.Class({
Main.screenShield.connect('lock-status-changed', Lang.bind(this, this._onLockStateChanged)); Main.screenShield.connect('lock-status-changed', Lang.bind(this, this._onLockStateChanged));
this._menus = new PopupMenu.PopupMenuManager(this); this.menuManager = new PopupMenu.PopupMenuManager(this);
this._leftBox = new St.BoxLayout({ name: 'panelLeft' }); this._leftBox = new St.BoxLayout({ name: 'panelLeft' });
this.actor.add_actor(this._leftBox); this.actor.add_actor(this._leftBox);
@ -946,27 +970,6 @@ const Panel = new Lang.Class({
this.actor.connect('allocate', Lang.bind(this, this._allocate)); this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress)); this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
/* Button on the left side of the panel. */
if (Main.sessionMode.hasOverview) {
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);
}
if (Main.sessionMode.hasAppMenu) {
this._appMenu = new AppMenuButton(this._menus);
this._leftBox.add(this._appMenu.actor);
}
/* center */
this._dateMenu = new DateMenu.DateMenuButton();
this._centerBox.add(this._dateMenu.actor, { y_fill: true });
this._menus.addMenu(this._dateMenu.menu);
Main.layoutManager.panelBox.add(this.actor); Main.layoutManager.panelBox.add(this.actor);
Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here-symbolic', Main.ctrlAltTabManager.addGroup(this.actor, _("Top Bar"), 'start-here-symbolic',
{ sortGroup: CtrlAltTab.SortGroup.TOP }); { sortGroup: CtrlAltTab.SortGroup.TOP });
@ -1086,75 +1089,70 @@ const Panel = new Lang.Class({
}, },
openAppMenu: function() { openAppMenu: function() {
let menu = this._appMenu.menu; let indicator = this.statusArea.appMenu;
if (!this._appMenu.actor.reactive || menu.isOpen) if (!indicator) // appMenu not supported by current session mode
return;
let menu = indicator.menu;
if (!indicator.actor.reactive || menu.isOpen)
return; return;
menu.open(); menu.open();
menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false); menu.actor.navigate_focus(null, Gtk.DirectionType.TAB_FORWARD, false);
}, },
startStatusArea: function() { init: function() {
for (let i = 0; i < Main.sessionMode.statusArea.order.length; i++) { let panel = Main.sessionMode.panel;
let role = Main.sessionMode.statusArea.order[i]; this._initBox(panel.left, this._leftBox);
let constructor = Main.sessionMode.statusArea.implementation[role]; this._initBox(panel.center, this._centerBox);
this._initBox(panel.right, this._rightBox);
},
_initBox: function(elements, box) {
for (let i = 0; i < elements.length; i++) {
let role = elements[i];
let constructor = PANEL_ITEM_IMPLEMENTATIONS[role];
if (!constructor) { if (!constructor) {
// This icon is not implemented (this is a bug) // panel icon is not supported (can happen for
// bluetooth or network)
continue; continue;
} }
let indicator = new constructor(); let indicator = new constructor(this);
this.addToStatusArea(role, indicator, i); this._addToPanelBox(role, indicator, i, box);
} }
}, },
_insertStatusItem: function(actor, position) { _addToPanelBox: function(role, indicator, position, box) {
let children = this._rightBox.get_children(); box.insert_child_at_index(indicator.actor, position);
let i; if (indicator.menu)
for (i = children.length - 1; i >= 0; i--) { this.menuManager.addMenu(indicator.menu);
let rolePosition = children[i]._rolePosition; this.statusArea[role] = indicator;
if (position > rolePosition) { let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) {
this._rightBox.insert_child_at_index(actor, i + 1); delete this.statusArea[role];
break; emitter.disconnect(destroyId);
} }));
}
if (i == -1) {
// If we didn't find a position, we must be first
this._rightBox.insert_child_at_index(actor, 0);
}
actor._rolePosition = position;
}, },
addToStatusArea: function(role, indicator, position) { addToStatusArea: function(role, indicator, position, box) {
if (this.statusArea[role]) if (this.statusArea[role])
throw new Error('Extension point conflict: there is already a status indicator for role ' + role); throw new Error('Extension point conflict: there is already a status indicator for role ' + role);
if (!(indicator instanceof PanelMenu.Button)) if (!(indicator instanceof PanelMenu.Button))
throw new TypeError('Status indicator must be an instance of PanelMenu.Button'); throw new TypeError('Status indicator must be an instance of PanelMenu.Button');
if (!position) position = position || 0;
position = 0; let boxes = {
this._insertStatusItem(indicator.actor, position); left: this._leftBox,
if (indicator.menu) center: this._centerBox,
this._menus.addMenu(indicator.menu); right: this._rightBox
};
this.statusArea[role] = indicator; let boxContainer = boxes[box] || this._rightBox;
let destroyId = indicator.connect('destroy', Lang.bind(this, function(emitter) { this._addToPanelBox(role, indicator, position, boxContainer);
delete this.statusArea[role];
emitter.disconnect(destroyId);
}));
return indicator; return indicator;
}, },
_onLockStateChanged: function(shield, locked) { _onLockStateChanged: function(shield, locked) {
if (this._activitiesButton)
this._activitiesButton.setLockedState(locked);
if (this._appMenu)
this._appMenu.setLockedState(locked);
if (this._dateMenu)
this._dateMenu.setLockedState(locked);
for (let id in this.statusArea) for (let id in this.statusArea)
this.statusArea[id].setLockedState(locked); this.statusArea[id].setLockedState(locked);
}, },

View File

@ -2,37 +2,13 @@
const Lang = imports.lang; const Lang = imports.lang;
const Config = imports.misc.config;
const Main = imports.ui.main; const Main = imports.ui.main;
const Params = imports.misc.params; const Params = imports.misc.params;
const STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION = {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'userMenu': imports.ui.userMenu.UserMenuButton
};
if (Config.HAVE_BLUETOOTH)
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['bluetooth'] =
imports.ui.status.bluetooth.Indicator;
try {
STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION['network'] =
imports.ui.status.network.NMApplet;
} catch(e) {
log('NMApplet is not supported. It is possible that your NetworkManager version is too old');
}
const DEFAULT_MODE = 'user'; const DEFAULT_MODE = 'user';
const _modes = { const _modes = {
'gdm': { hasOverview: false, 'gdm': { hasOverview: false,
hasAppMenu: false,
showCalendarEvents: false, showCalendarEvents: false,
allowSettings: false, allowSettings: false,
allowExtensions: false, allowExtensions: false,
@ -42,24 +18,15 @@ const _modes = {
createSession: Main.createGDMSession, createSession: Main.createGDMSession,
createUnlockDialog: Main.createGDMLoginDialog, createUnlockDialog: Main.createGDMLoginDialog,
extraStylesheet: null, extraStylesheet: null,
statusArea: { panel: {
order: [ left: [],
'a11y', 'display', 'keyboard', center: ['dateMenu'],
'volume', 'battery', 'lockScreen', 'powerMenu' right: ['a11y', 'display', 'keyboard',
], 'volume', 'battery', 'lockScreen', 'powerMenu']
implementation: {
'a11y': imports.ui.status.accessibility.ATIndicator,
'volume': imports.ui.status.volume.Indicator,
'battery': imports.ui.status.power.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
'powerMenu': imports.gdm.powerMenu.PowerMenuButton
}
} }
}, },
'initial-setup': { hasOverview: false, 'initial-setup': { hasOverview: false,
hasAppMenu: false,
showCalendarEvents: false, showCalendarEvents: false,
allowSettings: false, allowSettings: false,
allowExtensions: false, allowExtensions: false,
@ -68,21 +35,14 @@ const _modes = {
hasWorkspaces: false, hasWorkspaces: false,
createSession: Main.createInitialSetupSession, createSession: Main.createInitialSetupSession,
extraStylesheet: null, extraStylesheet: null,
statusArea: { panel: {
order: [ left: [],
'a11y', 'keyboard', 'volume', 'lockScreen', center: ['dateMenu'],
], right: ['a11y', 'keyboard', 'volume', 'lockScreen']
implementation: { }
'a11y': imports.ui.status.accessibility.ATIndicator, },
'keyboard': imports.ui.status.keyboard.XKBIndicator,
'volume': imports.ui.status.volume.Indicator,
'lockScreen': imports.ui.status.lockScreenMenu.Indicator,
}
}
},
'user': { hasOverview: true, 'user': { hasOverview: true,
hasAppMenu: true,
showCalendarEvents: true, showCalendarEvents: true,
allowSettings: true, allowSettings: true,
allowExtensions: true, allowExtensions: true,
@ -92,12 +52,11 @@ const _modes = {
createSession: Main.createUserSession, createSession: Main.createUserSession,
createUnlockDialog: Main.createSessionUnlockDialog, createUnlockDialog: Main.createSessionUnlockDialog,
extraStylesheet: null, extraStylesheet: null,
statusArea: { panel: {
order: [ left: ['activities', 'appMenu'],
'input-method', 'a11y', 'keyboard', 'volume', 'bluetooth', center: ['dateMenu'],
'network', 'battery', 'lockScreen', 'userMenu' right: ['a11y', 'keyboard', 'volume', 'bluetooth',
], 'network', 'battery', 'lockScreen', 'userMenu']
implementation: STANDARD_STATUS_AREA_SHELL_IMPLEMENTATION
} }
} }
}; };