2009-04-24 14:01:34 +00:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
|
|
|
|
|
|
const Big = imports.gi.Big;
|
|
|
|
const Clutter = imports.gi.Clutter;
|
|
|
|
const Shell = imports.gi.Shell;
|
|
|
|
const Lang = imports.lang;
|
|
|
|
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
const Panel = imports.ui.panel;
|
|
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
const Widget = imports.ui.widget;
|
|
|
|
const WidgetBox = imports.ui.widgetBox;
|
|
|
|
|
|
|
|
const SIDEBAR_SPACING = 4;
|
|
|
|
const SIDEBAR_PADDING = 4;
|
|
|
|
|
2009-06-20 14:51:07 +00:00
|
|
|
// The total sidebar width is the widget width plus the widget padding
|
|
|
|
// (counted twice for the widget box, and once again for the
|
|
|
|
// out-of-screen padding), plus the empty space between the border of
|
|
|
|
// the bar and of the windows
|
|
|
|
const SIDEBAR_COLLAPSED_WIDTH = Widget.COLLAPSED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
|
|
|
const SIDEBAR_EXPANDED_WIDTH = Widget.EXPANDED_WIDTH + 3 * WidgetBox.WIDGETBOX_PADDING + SIDEBAR_PADDING;
|
2009-04-24 14:01:34 +00:00
|
|
|
|
|
|
|
// The maximum height of the sidebar would be extending from just
|
|
|
|
// below the panel to just above the taskbar. Since the taskbar is
|
|
|
|
// just a temporary hack and it would be too hard to do this the right
|
|
|
|
// way, we just hardcode its size.
|
|
|
|
const HARDCODED_TASKBAR_HEIGHT = 24;
|
|
|
|
const MAXIMUM_SIDEBAR_HEIGHT = Shell.Global.get().screen_height - Panel.PANEL_HEIGHT - HARDCODED_TASKBAR_HEIGHT;
|
|
|
|
|
|
|
|
// FIXME, needs to be configurable, obviously
|
|
|
|
const default_widgets = [
|
|
|
|
"imports.ui.widget.ClockWidget",
|
|
|
|
"imports.ui.widget.AppsWidget",
|
|
|
|
"imports.ui.widget.DocsWidget"
|
|
|
|
];
|
|
|
|
|
|
|
|
function Sidebar() {
|
|
|
|
this._init();
|
|
|
|
}
|
|
|
|
|
|
|
|
Sidebar.prototype = {
|
|
|
|
_init : function() {
|
|
|
|
let global = Shell.Global.get();
|
|
|
|
|
|
|
|
// The top-left corner of the sidebar is fixed at:
|
|
|
|
// x = -WidgetBox.WIDGETBOX_PADDING, y = Panel.PANEL_HEIGHT.
|
|
|
|
// (The negative X is so that we don't see the rounded
|
|
|
|
// WidgetBox corners on the screen edge side.)
|
|
|
|
this.actor = new Clutter.Group({ x: -WidgetBox.WIDGETBOX_PADDING,
|
|
|
|
y: Panel.PANEL_HEIGHT,
|
|
|
|
width: SIDEBAR_EXPANDED_WIDTH });
|
|
|
|
Main.chrome.addActor(this.actor);
|
|
|
|
|
|
|
|
// The actual widgets go into a Big.Box inside this.actor. The
|
|
|
|
// box's width will vary during the expand/collapse animations,
|
|
|
|
// but this.actor's width will remain constant until we adjust
|
|
|
|
// it at the end of the animation, because we don't want the
|
|
|
|
// wm strut to move and cause windows to move multiple times
|
|
|
|
// during the animation.
|
|
|
|
this.box = new Big.Box ({ padding_top: SIDEBAR_PADDING,
|
|
|
|
padding_bottom: SIDEBAR_PADDING,
|
2009-06-20 14:51:07 +00:00
|
|
|
padding_right: 0,
|
2009-04-24 14:01:34 +00:00
|
|
|
padding_left: 0,
|
|
|
|
spacing: SIDEBAR_SPACING });
|
|
|
|
this.actor.add_actor(this.box);
|
|
|
|
|
|
|
|
this._visible = this.expanded = true;
|
|
|
|
|
|
|
|
this._widgets = [];
|
|
|
|
this.addWidget(new ToggleWidget(this));
|
|
|
|
for (let i = 0; i < default_widgets.length; i++)
|
|
|
|
this.addWidget(default_widgets[i]);
|
|
|
|
},
|
|
|
|
|
|
|
|
addWidget: function(widget) {
|
|
|
|
let widgetBox;
|
|
|
|
try {
|
|
|
|
widgetBox = new WidgetBox.WidgetBox(widget);
|
|
|
|
} catch(e) {
|
|
|
|
logError(e, "Failed to add widget '" + widget + "'");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.box.append(widgetBox.actor, Big.BoxPackFlags.NONE);
|
|
|
|
this._widgets.push(widgetBox);
|
|
|
|
},
|
|
|
|
|
|
|
|
show: function() {
|
|
|
|
this._visible = true;
|
|
|
|
this.actor.show();
|
|
|
|
},
|
|
|
|
|
|
|
|
hide: function() {
|
|
|
|
this._visible = false;
|
|
|
|
this.actor.hide();
|
|
|
|
},
|
|
|
|
|
|
|
|
expand: function() {
|
|
|
|
this.expanded = true;
|
|
|
|
for (let i = 0; i < this._widgets.length; i++)
|
|
|
|
this._widgets[i].expand();
|
|
|
|
|
|
|
|
// Updated the strut/stage area after the animation completes
|
|
|
|
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
|
|
|
|
onComplete: function () {
|
|
|
|
this.actor.width = SIDEBAR_EXPANDED_WIDTH;
|
|
|
|
} });
|
|
|
|
},
|
|
|
|
|
|
|
|
collapse: function() {
|
|
|
|
this.expanded = false;
|
|
|
|
for (let i = 0; i < this._widgets.length; i++)
|
|
|
|
this._widgets[i].collapse();
|
|
|
|
|
|
|
|
// Updated the strut/stage area after the animation completes
|
|
|
|
Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME,
|
|
|
|
onComplete: function () {
|
|
|
|
this.actor.width = SIDEBAR_COLLAPSED_WIDTH;
|
|
|
|
} });
|
|
|
|
},
|
|
|
|
|
|
|
|
destroy: function() {
|
|
|
|
this.hide();
|
|
|
|
|
|
|
|
for (let i = 0; i < this._widgets.length; i++)
|
|
|
|
this._widgets[i].destroy();
|
|
|
|
this.actor.destroy();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const LEFT_DOUBLE_ARROW = "\u00AB";
|
|
|
|
const RIGHT_DOUBLE_ARROW = "\u00BB";
|
|
|
|
|
|
|
|
function ToggleWidget(sidebar) {
|
|
|
|
this._init(sidebar);
|
|
|
|
}
|
|
|
|
|
|
|
|
ToggleWidget.prototype = {
|
|
|
|
__proto__ : Widget.Widget.prototype,
|
|
|
|
|
|
|
|
_init : function(sidebar) {
|
|
|
|
this._sidebar = sidebar;
|
|
|
|
this.actor = new Clutter.Text({ font_name: "Sans Bold 16px",
|
|
|
|
text: LEFT_DOUBLE_ARROW,
|
|
|
|
reactive: true });
|
|
|
|
this.actor.connect('button-release-event',
|
|
|
|
Lang.bind(this._sidebar, this._sidebar.collapse));
|
|
|
|
this.collapsedActor = new Clutter.Text({ font_name: "Sans Bold 16px",
|
|
|
|
text: RIGHT_DOUBLE_ARROW,
|
|
|
|
reactive: true });
|
|
|
|
this.collapsedActor.connect('button-release-event',
|
|
|
|
Lang.bind(this._sidebar, this._sidebar.expand));
|
|
|
|
}
|
|
|
|
};
|