From b8647cc00e0e20dae679e4dca2fe1f36813dc5a5 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Tue, 30 Mar 2010 10:32:15 -0400 Subject: [PATCH] Remove sidebar --- data/gnome-shell.schemas | 57 ------ js/ui/Makefile.am | 3 - js/ui/main.js | 3 - js/ui/sidebar.js | 264 -------------------------- js/ui/statusMenu.js | 13 -- js/ui/widget.js | 364 ------------------------------------ js/ui/widgetBox.js | 395 --------------------------------------- 7 files changed, 1099 deletions(-) delete mode 100644 js/ui/sidebar.js delete mode 100644 js/ui/widget.js delete mode 100644 js/ui/widgetBox.js diff --git a/data/gnome-shell.schemas b/data/gnome-shell.schemas index 06ce650aa..7c17afe7b 100644 --- a/data/gnome-shell.schemas +++ b/data/gnome-shell.schemas @@ -57,63 +57,6 @@ - - /schemas/desktop/gnome/shell/sidebar/visible - /desktop/gnome/shell/sidebar/visible - gnome-shell - bool - false - - Whether or not to display the sidebar - - Determines whether or not the sidebar is visible. - - - - - - /schemas/desktop/gnome/shell/sidebar/expanded - /desktop/gnome/shell/sidebar/expanded - gnome-shell - bool - true - - Whether the sidebar should be in the expanded (wide) mode - - Controls the expanded/collapsed state of the sidebar. - - - - - - /schemas/desktop/gnome/shell/sidebar/autohide - /desktop/gnome/shell/sidebar/autohide - gnome-shell - bool - true - - Whether the sidebar should automatically hide itself in compact mode - - Controls the autohide state of the sidebar. - - - - - - /schemas/desktop/gnome/shell/sidebar/widgets - /desktop/gnome/shell/sidebar/widgets - gnome-shell - list - string - [imports.ui.widget.ClockWidget,imports.ui.widget.AppsWidget,imports.ui.widget.RecentDocsWidget] - - The widgets to display in the sidebar - - The widgets to display in the sidebar, in order from top to bottom. Each widget "name" is actually a JavaScript expression referring to a widget constructor object. - - - - /schemas/desktop/gnome/shell/disabled_extensions /desktop/gnome/shell/disabled_extensions diff --git a/js/ui/Makefile.am b/js/ui/Makefile.am index 974cc6043..7cd7cc9ea 100644 --- a/js/ui/Makefile.am +++ b/js/ui/Makefile.am @@ -24,11 +24,8 @@ dist_jsui_DATA = \ runDialog.js \ search.js \ shellDBus.js \ - sidebar.js \ statusMenu.js \ tweener.js \ - widget.js \ - widgetBox.js \ windowAttentionHandler.js \ windowManager.js \ workspacesView.js \ diff --git a/js/ui/main.js b/js/ui/main.js index bb837a3bd..677e58776 100644 --- a/js/ui/main.js +++ b/js/ui/main.js @@ -24,7 +24,6 @@ const LookingGlass = imports.ui.lookingGlass; const NotificationDaemon = imports.ui.notificationDaemon; const WindowAttentionHandler = imports.ui.windowAttentionHandler; const ShellDBus = imports.ui.shellDBus; -const Sidebar = imports.ui.sidebar; const WindowManager = imports.ui.windowManager; const DEFAULT_BACKGROUND_COLOR = new Clutter.Color(); @@ -32,7 +31,6 @@ DEFAULT_BACKGROUND_COLOR.from_pixel(0x2266bbff); let chrome = null; let panel = null; -let sidebar = null; let placesManager = null; let overview = null; let runDialog = null; @@ -109,7 +107,6 @@ function start() { overview = new Overview.Overview(); chrome = new Chrome.Chrome(); panel = new Panel.Panel(); - sidebar = new Sidebar.Sidebar(); wm = new WindowManager.WindowManager(); notificationDaemon = new NotificationDaemon.NotificationDaemon(); windowAttentionHandler = new WindowAttentionHandler.WindowAttentionHandler(); diff --git a/js/ui/sidebar.js b/js/ui/sidebar.js deleted file mode 100644 index 6d12db3dc..000000000 --- a/js/ui/sidebar.js +++ /dev/null @@ -1,264 +0,0 @@ -/* -*- 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 Mainloop = imports.mainloop; - -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; - -// 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; - -function Sidebar() { - this._init(); -} - -Sidebar.prototype = { - _init : function() { - // 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 }); - - // 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, - padding_right: 0, - padding_left: 0, - spacing: SIDEBAR_SPACING }); - this.actor.add_actor(this.box); - - this._gconf = Shell.GConf.get_default(); - - this._expanded = this._gconf.get_boolean ("sidebar/expanded"); - if (!this._expanded) - this.actor.width = SIDEBAR_COLLAPSED_WIDTH; - - this._visible = this._gconf.get_boolean ("sidebar/visible"); - if (this._visible) - Main.chrome.addActor(this.actor); - - this._hidden = false; - this._hideTimeoutId = 0; - this._widgets = []; - this.addWidget(new ToggleWidget()); - - let default_widgets = this._gconf.get_string_list("sidebar/widgets"); - for (let i = 0; i < default_widgets.length; i++) - this.addWidget(default_widgets[i]); - - this._gconf.connect('changed::sidebar/expanded', - Lang.bind(this, this._expandedChanged)); - this._gconf.connect('changed::sidebar/visible', - Lang.bind(this, this._visibleChanged)); - this._gconf.connect('changed::sidebar/autohide', - Lang.bind(this, this._autohideChanged)); - - this.actor.connect('enter-event',Lang.bind(this,this._restoreHidden)); - this.actor.connect('leave-event',Lang.bind(this,this._startHideTimeout)); - - this._adjustPosition(); - this._autohideChanged(); - }, - - addWidget: function(widget) { - let widgetBox; - try { - widgetBox = new WidgetBox.WidgetBox(widget, this._expanded); - } catch(e) { - logError(e, "Failed to add widget '" + widget + "'"); - return; - } - - this.box.append(widgetBox.actor, Big.BoxPackFlags.NONE); - this._widgets.push(widgetBox); - this._adjustPosition(); - }, - - _adjustPosition: function() { - let primary=global.get_primary_monitor(); - - this.actor.y = Math.floor(Math.max(primary.y + Panel.PANEL_HEIGHT,primary.height/2 - this.actor.height/2)); - this.actor.x = primary.x; - }, - - _visibleChanged: function() { - let visible = this._gconf.get_boolean("sidebar/visible"); - if (visible == this._visible) - return; - - this._visible = visible; - if (visible) - Main.chrome.addActor(this.actor); - else - Main.chrome.removeActor(this.actor); - }, - - _expandedChanged: function() { - let expanded = this._gconf.get_boolean("sidebar/expanded"); - if (expanded == this._expanded) - return; - - this._expanded = expanded; - if (expanded) - this._expand(); - else - this._collapse(); - }, - - _autohideChanged: function() { - let autohide = this._gconf.get_boolean("sidebar/autohide"); - if (autohide == this._autohide) - return; - - this._autohide = autohide; - if (autohide) { - this.actor.set_reactive(true); - this._hide(); - } else { - this.actor.set_reactive(false); - this._restore(); - } - }, - - _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(); - - // Update the strut/stage area after the animation completes - Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME, - onComplete: Lang.bind(this, function () { - this.actor.width = SIDEBAR_COLLAPSED_WIDTH; - }) }); - }, - - _hide: function() { - if (!this._expanded) { - this._hidden = true; - for (let i = 0; i < this._widgets.length; i++) - this._widgets[i].hide(); - - // Update the strut/stage area after the animation completes - Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME / 2, - onComplete: Lang.bind(this, function () { - this.actor.width = Math.floor(WidgetBox.WIDGETBOX_PADDING * 2 + SIDEBAR_PADDING); - }) }); - } - }, - - _restore: function() { - if (!this._expanded) { - this._hidden = false; - for (let i = 0; i < this._widgets.length; i++) - this._widgets[i].restore(); - - // Updated the strut/stage area after the animation completes - Tweener.addTween(this, { time: WidgetBox.ANIMATION_TIME / 2, - onComplete: function () { - this.actor.width = SIDEBAR_COLLAPSED_WIDTH; - } }); - } - }, - - _restoreHidden: function(actor, event) { - this._cancelHideTimeout(); - if (this._hidden) - this._restore(); - return false; - }, - - _startHideTimeout: function(actor, event) { - if (!this._expanded) { - this._cancelHideTimeout(); - this._hideTimeoutId = Mainloop.timeout_add_seconds(2, Lang.bind(this,this._hideTimeoutFunc)); - } - return false; - }, - - _cancelHideTimeout: function() { - if (this._hideTimeoutId != 0) { - Mainloop.source_remove(this._hideTimeoutId); - this._hideTimeoutId = 0; - } - }, - - _hideTimeoutFunc: function() { - this._hide(); - return false; - }, - - 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() { - this._init(); -} - -ToggleWidget.prototype = { - __proto__ : Widget.Widget.prototype, - - _init : function() { - this._gconf = Shell.GConf.get_default(); - - 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, this._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, this._expand)); - }, - - _collapse : function () { - this._gconf.set_boolean ("sidebar/expanded", false); - }, - - _expand : function () { - this._gconf.set_boolean ("sidebar/expanded", true); - } -}; diff --git a/js/ui/statusMenu.js b/js/ui/statusMenu.js index e8e66d9da..1cf0c411e 100644 --- a/js/ui/statusMenu.js +++ b/js/ui/statusMenu.js @@ -18,8 +18,6 @@ const Panel = imports.ui.panel; // Copyright (C) 2004-2005 James M. Cape . // Copyright (C) 2008,2009 Red Hat, Inc. -const SIDEBAR_VISIBLE_KEY = 'sidebar/visible'; - function StatusMenu() { this._init(); } @@ -128,17 +126,6 @@ StatusMenu.prototype = { this._menu.append(item); item.show(); - let gconf = Shell.GConf.get_default(); - item = new Gtk.CheckMenuItem({ label: _("Sidebar"), - active: gconf.get_boolean(SIDEBAR_VISIBLE_KEY) }); - item.connect('activate', Lang.bind(this, - function() { - gconf.set_boolean(SIDEBAR_VISIBLE_KEY, this._sidebarItem.active); - })); - this._menu.append(item); - item.show(); - this._sidebarItem = item; - item = this._createImageMenuItem(_("System Preferences..."), 'preferences-desktop'); item.connect('activate', Lang.bind(this, this._onPreferencesActivate)); this._menu.append(item); diff --git a/js/ui/widget.js b/js/ui/widget.js deleted file mode 100644 index 0d50a1926..000000000 --- a/js/ui/widget.js +++ /dev/null @@ -1,364 +0,0 @@ -/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ - -const Big = imports.gi.Big; -const Clutter = imports.gi.Clutter; -const Gio = imports.gi.Gio; -const Gtk = imports.gi.Gtk; -const Mainloop = imports.mainloop; -const Lang = imports.lang; -const Pango = imports.gi.Pango; -const Shell = imports.gi.Shell; -const Signals = imports.signals; -const St = imports.gi.St; -const Gettext = imports.gettext.domain('gnome-shell'); -const _ = Gettext.gettext; - -const AppFavorites = imports.ui.appFavorites; -const DocInfo = imports.misc.docInfo; - -const COLLAPSED_WIDTH = 24; -const EXPANDED_WIDTH = 200; - -const STATE_EXPANDED = 0; -const STATE_COLLAPSING = 1; -const STATE_COLLAPSED = 2; -const STATE_EXPANDING = 3; -const STATE_POPPING_OUT = 4; -const STATE_POPPED_OUT = 5; -const STATE_POPPING_IN = 6; - -function Widget() { -} - -Widget.prototype = { - // _init(): - // - // Your widget constructor. Your constructor function should look - // like: - // - // function MyWidgetType() { - // this._init.apply(this, arguments); - // } - // - // and your _init method should start by doing: - // - // Widget.Widget.prototype._init.apply(this, arguments); - // - // The _init method must define a field named "actor" containing - // the Clutter.Actor to show in expanded mode. This actor will be - // clipped to Widget.EXPANDED_WIDTH. Most widgets will also define - // a field named "title" containing the title string to show above - // the widget in the sidebar. - // - // If you want to have a separate collapsed view, you can define a - // field "collapsedActor" containing the Clutter.Actor to show in - // that mode. (It may be the same actor.) This actor will be - // clipped to Widget.COLLAPSED_WIDTH, and will normally end up - // having the same height as the main actor. - // - // If you do not set a collapsedActor, then you must set a title, - // since that is what will be displayed in collapsed mode, and - // in this case (and only in this case), the widget will support - // pop-out, meaning that if the user hovers over its title while - // the sidebar is collapsed, the widget's expanded view will pop - // out of the sidebar until either the cursor moves out of it, - // or else the widget calls this.activated() on itself. - _init: function (initialState) { - this.state = initialState; - }, - - // destroy(): - // - // Optional. Will be called when the widget is removed from the - // sidebar. (Note that you don't need to destroy the actors, - // since they will be destroyed for you.) - - // collapse(): - // - // Optional. Called during the sidebar collapse process, at the - // point when the expanded sidebar has slid offscreen, but the - // collapsed sidebar has not yet slid onscreen. - - // expand(): - // - // Optional. Called during the sidebar expand process, at the - // point when the collapsed sidebar has slid offscreen, but the - // expanded sidebar has not yet slid onscreen. - - // activated(): - // - // Emits the "activated" signal for you, which will cause pop-out - // to end. - activated: function() { - this.emit('activated'); - } - - // state: - // - // A field set on your widget by the sidebar. Will contain one of - // the Widget.STATE_* values. (Eg, Widget.STATE_EXPANDED). -}; - -Signals.addSignalMethods(Widget.prototype); - - -function ClockWidget() { - this._init.apply(this, arguments); -} - -ClockWidget.prototype = { - __proto__ : Widget.prototype, - - _init: function() { - Widget.prototype._init.apply(this, arguments); - - this.actor = new Clutter.Text({ font_name: "Sans Bold 16px", - text: "", - // Give an explicit height to ensure - // it's the same in both modes - height: COLLAPSED_WIDTH }); - - this.collapsedActor = new St.DrawingArea({ width: COLLAPSED_WIDTH, - height: COLLAPSED_WIDTH }); - this.collapsedActor.connect('repaint', Lang.bind(this, this._repaintClock)); - - this._update(); - }, - - destroy: function() { - if (this.timer) - Mainloop.source_remove(this.timer); - }, - - expand: function() { - this._update(); - }, - - collapse: function() { - this._update(); - }, - - _update: function() { - this.currentTime = new Date(); - let msec_remaining = 60000 - (1000 * this.currentTime.getSeconds() + - this.currentTime.getMilliseconds()); - if (msec_remaining < 500) { - this.currentTime.setMinutes(this.currentTime.getMinutes() + 1); - msec_remaining += 60000; - } - - if (this.state == STATE_COLLAPSED || this.state == STATE_COLLAPSING) - this.collapsedActor.queue_repaint(); - else - this._updateText(); - - if (this.timer) - Mainloop.source_remove(this.timer); - this.timer = Mainloop.timeout_add(msec_remaining, Lang.bind(this, this._update)); - return false; - }, - - _updateText: function(time) { - // Translators: This is a time format. - this.actor.set_text(this.currentTime.toLocaleFormat(_("%H:%M"))); - }, - - _repaintClock: function(area) { - Shell.draw_clock(area, - this.currentTime.getHours() % 12, - this.currentTime.getMinutes()); - } -}; - - -const ITEM_ICON_SIZE = 48; -const ITEM_PADDING = 1; -const ITEM_SPACING = 4; - -const ITEM_BG_COLOR = new Clutter.Color(); -ITEM_BG_COLOR.from_pixel(0x00000000); -const ITEM_NAME_COLOR = new Clutter.Color(); -ITEM_NAME_COLOR.from_pixel(0x000000ff); - -function LauncherWidget() { - this._init.apply(this, arguments); -} - -LauncherWidget.prototype = { - __proto__ : Widget.prototype, - - addItem : function(info) { - let item = new Big.Box({ orientation: Big.BoxOrientation.HORIZONTAL, - width: EXPANDED_WIDTH, - height: ITEM_ICON_SIZE, - padding: ITEM_PADDING, - spacing: ITEM_SPACING, - reactive: true }); - item._info = info; - item.append(info.createIcon(ITEM_ICON_SIZE), Big.BoxPackFlags.NONE); - item.append(new Clutter.Text({ color: ITEM_NAME_COLOR, - font_name: "Sans 14px", - ellipsize: Pango.EllipsizeMode.END, - text: info.name }), - Big.BoxPackFlags.NONE); - - this.actor.append(item, Big.BoxPackFlags.NONE); - item.connect('button-press-event', Lang.bind(this, this._buttonPress)); - item.connect('button-release-event', Lang.bind(this, this._buttonRelease)); - item.connect('leave-event', Lang.bind(this, this._leave)); - item.connect('enter-event', Lang.bind(this, this._enter)); - - if (!this.collapsedActor) - return; - - item = new Big.Box({ width: COLLAPSED_WIDTH, - height: COLLAPSED_WIDTH, - padding: ITEM_PADDING, - reactive: true }); - item._info = info; - item.append(info.createIcon(COLLAPSED_WIDTH - 2 * ITEM_PADDING), - Big.BoxPackFlags.NONE); - - this.collapsedActor.append(item, Big.BoxPackFlags.NONE); - item.connect('button-press-event', Lang.bind(this, this._buttonPress)); - item.connect('button-release-event', Lang.bind(this, this._buttonRelease)); - item.connect('leave-event', Lang.bind(this, this._leave)); - item.connect('enter-event', Lang.bind(this, this._enter)); - }, - - clear : function() { - let children, i; - - children = this.actor.get_children(); - for (i = 0; i < children.length; i++) - children[i].destroy(); - - if (this.collapsedActor) { - children = this.collapsedActor.get_children(); - for (i = 0; i < children.length; i++) - children[i].destroy(); - } - }, - - _buttonPress : function(item) { - Clutter.grab_pointer(item); - item._buttonDown = true; - item._inItem = true; - this._updateItemState(item); - return true; - }, - - _leave : function(item, evt) { - if (evt.get_source() == item && item._buttonDown) { - item._inItem = false; - this._updateItemState(item); - } - return false; - }, - - _enter : function(item, evt) { - if (evt.get_source() == item && item._buttonDown) { - item._inItem = true; - this._updateItemState(item); - } - return false; - }, - - _buttonRelease : function(item) { - Clutter.ungrab_pointer(item); - item._buttonDown = false; - this._updateItemState(item); - - if (item._inItem) { - item._info.launch(); - this.activated(); - } - return true; - }, - - _updateItemState : function(item) { - if (item._buttonDown && item._inItem) { - item.padding_top = item.padding_left = 2 * ITEM_PADDING; - item.padding_bottom = item.padding_right = 0; - } else - item.padding = ITEM_PADDING; - } -}; - -function AppsWidgetInfo(appInfo) { - this._init(appInfo); -} - -AppsWidgetInfo.prototype = { - _init : function(appInfo) { - this._info = appInfo; - this.name = appInfo.get_name(); - }, - - createIcon : function(size) { - return this._info.create_icon_texture(size); - }, - - launch : function() { - this._info.launch(); - } -}; - -function AppsWidget() { - this._init.apply(this, arguments); -} - -AppsWidget.prototype = { - __proto__ : LauncherWidget.prototype, - - _init : function() { - Widget.prototype._init.apply(this, arguments); - - this.title = _("Applications"); - this.actor = new Big.Box({ spacing: 2 }); - this.collapsedActor = new Big.Box({ spacing: 2}); - - let appSystem = Shell.AppSystem.get_default(); - let apps = AppFavorites.getAppFavorites().getFavorites(); - for (let i = 0; i < apps.length; i++) { - this.addItem(new AppsWidgetInfo(apps[i])); - } - } -}; - -function RecentDocsWidget() { - this._init.apply(this, arguments); -} - -RecentDocsWidget.prototype = { - __proto__ : LauncherWidget.prototype, - - _init : function() { - Widget.prototype._init.apply(this, arguments); - - this.title = _("Recent Documents"); - this.actor = new Big.Box({ spacing: 2 }); - - this._recentManager = Gtk.RecentManager.get_default(); - this._recentManager.connect('changed', Lang.bind(this, this._recentChanged)); - this._recentChanged(); - }, - - _recentChanged: function() { - let i; - - this.clear(); - - let items = []; - let docs = this._recentManager.get_items(); - for (i = 0; i < docs.length; i++) { - let docInfo = new DocInfo.DocInfo (docs[i]); - - items.push(docInfo); - } - - items.sort(function (a,b) { return b.timestamp - a.timestamp; }); - for (i = 0; i < Math.min(items.length, 5); i++) - this.addItem(items[i]); - } -}; diff --git a/js/ui/widgetBox.js b/js/ui/widgetBox.js deleted file mode 100644 index 10cb362b4..000000000 --- a/js/ui/widgetBox.js +++ /dev/null @@ -1,395 +0,0 @@ -/* -*- 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 Mainloop = imports.mainloop; - -const Main = imports.ui.main; -const Tweener = imports.ui.tweener; -const Widget = imports.ui.widget; - -const WIDGETBOX_BG_COLOR = new Clutter.Color(); -WIDGETBOX_BG_COLOR.from_pixel(0xf0f0f0ff); -const BLACK = new Clutter.Color(); -BLACK.from_pixel(0x000000ff); - -const WIDGETBOX_PADDING = 2; -const ANIMATION_TIME = 0.5; -const POP_IN_LAG = 250; /* milliseconds */ - -function WidgetBox(widget, expanded) { - this._init(widget, expanded); -} - -WidgetBox.prototype = { - _init: function(widget, expanded) { - this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED; - - if (widget instanceof Widget.Widget) { - this._widget = widget; - this._widget.state = this.state; - } else { - let ctor = this._ctorFromName(widget); - this._widget = new ctor(this.state); - } - - if (!this._widget.actor) - throw new Error("widget has no actor"); - else if (!this._widget.title && !this._widget.collapsedActor) - throw new Error("widget has neither title nor collapsedActor"); - - this.state = expanded ? Widget.STATE_EXPANDED : Widget.STATE_COLLAPSED; - - // The structure of a WidgetBox: - // - // The top level is a Clutter.Group, which exists to make - // pop-out work correctly; when another widget pops out, its - // width will increase, which will in turn cause the sidebar's - // width to increase, which will cause the sidebar to increase - // the width of each of its children (the WidgetBoxes). But we - // don't want the non-popped-out widgets to expand, so we make - // the top-level actor be a Clutter.Group, which will accept - // the new width from the Sidebar, but not impose it on its - // own child. - // - // Inside the toplevel group is a horizontal Big.Box - // containing 2 Clutter.Groups; one for the collapsed state - // (cgroup) and one for the expanded state (egroup). Each - // group contains a single vertical Big.Box (cbox and ebox - // respectively), which have the appropriate fixed width. The - // cbox contains either the collapsed widget actor or else the - // rotated title. The ebox contains the horizontal title (if - // any), separator line, and the expanded widget actor. (If - // the widget doesn't have a collapsed actor, and therefore - // supports pop-out, then it will also have a vertical line - // between the two groups, which will only be shown during - // pop-out.) - // - // In the expanded view, cgroup is hidden and egroup is shown. - // When animating to the collapsed view, first the ebox is - // slid offscreen by giving it increasingly negative x - // coordinates within egroup. Then once it's fully offscreen, - // we hide egroup, show cgroup, and slide cbox back in in the - // same way. - // - // The pop-out view works similarly to the second half of the - // collapsed-to-expanded transition, except that the - // horizontal title gets hidden to avoid duplication. - - this.actor = new Clutter.Group(); - this._hbox = new Big.Box({ background_color: WIDGETBOX_BG_COLOR, - padding_top: WIDGETBOX_PADDING, - padding_bottom: WIDGETBOX_PADDING, - padding_right: WIDGETBOX_PADDING, - // Left padding is here to make up for - // the X offset used for the sidebar - // to hide its rounded corners - padding_left: 2 * WIDGETBOX_PADDING, - spacing: WIDGETBOX_PADDING, - corner_radius: WIDGETBOX_PADDING, - orientation: Big.BoxOrientation.HORIZONTAL, - reactive: true }); - this.actor.add_actor(this._hbox); - - this._cgroup = new Clutter.Group({ clip_to_allocation: true }); - this._hbox.append(this._cgroup, Big.BoxPackFlags.NONE); - - this._cbox = new Big.Box({ width: Widget.COLLAPSED_WIDTH, - clip_to_allocation: true }); - this._cgroup.add_actor(this._cbox); - - if (this._widget.collapsedActor) { - if (this._widget.collapsedActor == this._widget.actor) - this._singleActor = true; - else { - this._cbox.append(this._widget.collapsedActor, - Big.BoxPackFlags.NONE); - } - } else { - let vtitle = new Clutter.Text({ font_name: "Sans 16px", - text: this._widget.title, - rotation_angle_z: -90.0 }); - let signalId = vtitle.connect('notify::allocation', - function () { - vtitle.disconnect(signalId); - vtitle.set_anchor_point(vtitle.natural_width, 0); - vtitle.set_size(vtitle.natural_height, - vtitle.natural_width); - }); - this._vtitle = vtitle; - this._cbox.append(this._vtitle, Big.BoxPackFlags.NONE); - - this._vline = new Clutter.Rectangle({ color: BLACK, width: 1 }); - this._hbox.append(this._vline, Big.BoxPackFlags.NONE); - this._vline.hide(); - - // Set up pop-out - this._eventHandler = this._hbox.connect('captured-event', - Lang.bind(this, this._popEventHandler)); - this._activationHandler = this._widget.connect('activated', - Lang.bind(this, this._activationHandler)); - } - - this._egroup = new Clutter.Group({ clip_to_allocation: true }); - this._hbox.append(this._egroup, Big.BoxPackFlags.NONE); - - this._ebox = new Big.Box({ spacing: WIDGETBOX_PADDING, - width: Widget.EXPANDED_WIDTH, - clip_to_allocation: true }); - this._egroup.add_actor(this._ebox); - - if (this._widget.title) { - this._htitle = new Clutter.Text({ font_name: "Sans 16px", - text: this._widget.title }); - this._ebox.append(this._htitle, Big.BoxPackFlags.NONE); - - this._hline = new Clutter.Rectangle({ color: BLACK, height: 1 }); - this._ebox.append(this._hline, Big.BoxPackFlags.NONE); - } - - this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE); - - if (expanded) - this._setWidgetExpanded(); - else - this._setWidgetCollapsed(); - }, - - // Given a name like "imports.ui.widget.ClockWidget", turn that - // into a constructor function - _ctorFromName: function(name) { - // Make sure it's a valid import - if (!name.match(/^imports(\.[a-zA-Z0-9_]+)+$/)) - throw new Error("widget name must start with 'imports.'"); - if (name.match(/^imports\.gi\./)) - throw new Error("cannot import widget from GIR"); - - let ctor = eval(name); - - // Make sure it's really a constructor - if (!ctor || typeof(ctor) != "function") - throw new Error("widget name is not a constructor"); - - // Make sure it's a widget - let proto = ctor.prototype; - while (proto && proto != Widget.Widget.prototype) - proto = proto.__proto__; - if (!proto) - throw new Error("widget does not inherit from Widget prototype"); - - return ctor; - }, - - expand: function() { - Tweener.addTween(this._cbox, { x: -Widget.COLLAPSED_WIDTH, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad", - onComplete: this._expandPart1Complete, - onCompleteScope: this }); - this.state = this._widget.state = Widget.STATE_EXPANDING; - }, - - _setWidgetExpanded: function() { - this._cgroup.hide(); - this._egroup.show(); - - if (this._singleActor) { - this._widget.actor.get_parent().remove_actor(this._widget.actor); - this._ebox.append(this._widget.actor, Big.BoxPackFlags.NONE); - } - - if (this._htitle) { - this._htitle.show(); - this._hline.show(); - } - }, - - _expandPart1Complete: function() { - this._cbox.x = 0; - this._setWidgetExpanded(); - - if (this._widget.expand) { - try { - this._widget.expand(); - } catch (e) { - logError(e, 'Widget failed to expand'); - } - } - - this._ebox.x = -Widget.EXPANDED_WIDTH; - Tweener.addTween(this._ebox, { x: 0, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad", - onComplete: this._expandComplete, - onCompleteScope: this }); - }, - - _expandComplete: function() { - this.state = this._widget.state = Widget.STATE_EXPANDED; - }, - - collapse: function() { - Tweener.addTween(this._ebox, { x: -Widget.EXPANDED_WIDTH, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad", - onComplete: this._collapsePart1Complete, - onCompleteScope: this }); - this.state = this._widget.state = Widget.STATE_COLLAPSING; - }, - - _setWidgetCollapsed: function() { - this._egroup.hide(); - this._cgroup.show(); - - if (this._singleActor) { - this._widget.actor.get_parent().remove_actor(this._widget.actor); - this._cbox.append(this._widget.actor, Big.BoxPackFlags.NONE); - } - - if (this._htitle) { - this._htitle.hide(); - this._hline.hide(); - } - - if (this._vtitle) - this._cbox.height = this._ebox.height; - }, - - _collapsePart1Complete: function() { - this._ebox.x = 0; - this._setWidgetCollapsed(); - - if (this._widget.collapse) { - try { - this._widget.collapse(); - } catch (e) { - logError(e, 'Widget failed to collapse'); - } - } - - this._cbox.x = -Widget.COLLAPSED_WIDTH; - Tweener.addTween(this._cbox, { x: 0, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad", - onComplete: this._collapseComplete, - onCompleteScope: this }); - }, - - _collapseComplete: function() { - this.state = this._widget.state = Widget.STATE_COLLAPSED; - }, - - _popEventHandler: function(actor, event) { - let type = event.type(); - - if (type == Clutter.EventType.ENTER) { - this._clearPopInTimeout(); - if (this.state == Widget.STATE_COLLAPSED || - this.state == Widget.STATE_COLLAPSING) { - this._popOut(); - return false; - } - } else if (type == Clutter.EventType.LEAVE && - (this.state == Widget.STATE_POPPED_OUT || - this.state == Widget.STATE_POPPING_OUT)) { - // If moving into another actor within this._hbox, let the - // event be propagated - let into = event.get_related(); - while (into) { - if (into == this._hbox) - return false; - into = into.get_parent(); - } - - // Else, moving out of this._hbox - this._setPopInTimeout(); - return false; - } - - return false; - }, - - _activationHandler: function() { - if (this.state == Widget.STATE_POPPED_OUT) - this._popIn(); - }, - - _popOut: function() { - if (this.state != Widget.STATE_COLLAPSED && - this.state != Widget.STATE_COLLAPSING) - return; - - this._vline.show(); - this._egroup.show(); - this._ebox.x = -Widget.EXPANDED_WIDTH; - Tweener.addTween(this._ebox, { x: 0, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad", - onComplete: this._popOutComplete, - onCompleteScope: this }); - this.state = this._widget.state = Widget.STATE_POPPING_OUT; - - Main.chrome.trackActor(this._hbox, { affectsStruts: false }); - }, - - _popOutComplete: function() { - this.state = this._widget.state = Widget.STATE_POPPED_OUT; - }, - - _setPopInTimeout: function() { - this._clearPopInTimeout(); - this._popInTimeout = Mainloop.timeout_add(POP_IN_LAG, Lang.bind(this, function () { this._popIn(); return false; })); - }, - - _clearPopInTimeout: function() { - if (this._popInTimeout) { - Mainloop.source_remove(this._popInTimeout); - delete this._popInTimeout; - } - }, - - _popIn: function() { - this._clearPopInTimeout(); - - if (this.state != Widget.STATE_POPPED_OUT && - this.state != Widget.STATE_POPPING_OUT) - return; - - Tweener.addTween(this._ebox, { x: -Widget.EXPANDED_WIDTH, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad", - onComplete: this._popInComplete, - onCompleteScope: this }); - }, - - _popInComplete: function() { - this.state = this._widget.state = Widget.STATE_COLLAPSED; - this._vline.hide(); - this._egroup.hide(); - this._ebox.x = 0; - - Main.chrome.untrackActor(this._hbox); - }, - - hide: function() { - if (this.state == Widget.STATE_COLLAPSED) - Tweener.addTween(this._cbox, { x: -Widget.COLLAPSED_WIDTH, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad" }); - }, - - restore: function() { - if (this.state == Widget.STATE_COLLAPSED) - Tweener.addTween(this._cbox, { x: 0, - time: ANIMATION_TIME / 2, - transition: "easeOutQuad" }); - }, - - destroy: function() { - if (this._widget.destroy) - this._widget.destroy(); - } -}; -