From e00398e2ac7d5b4b0ed15ec85313b66e27a73771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 22 Jul 2010 01:29:02 +0200 Subject: [PATCH] dash: Reimplement the dash based on AppWell code The new dash implementation is a single-column vertical sidebar, whose items are scaled dynamically to fit the available height. If the height is still exceeded after scaling down to a minimum item size, excess items are cut off. The now unused old dash implementation is renamed to OldDash, as its code will be used as a base for the new view selector element. https://bugzilla.gnome.org/show_bug.cgi?id=634948 --- data/Makefile.am | 1 + data/theme/gnome-shell.css | 24 ++--- data/theme/running-indicator.svg | 89 +++++++++++++++++ js/ui/appDisplay.js | 144 ++------------------------- js/ui/dash.js | 165 ++++++++++++++++++++++++++++++- js/ui/overview.js | 14 +-- 6 files changed, 276 insertions(+), 161 deletions(-) create mode 100644 data/theme/running-indicator.svg diff --git a/data/Makefile.am b/data/Makefile.am index 68dcc1d04..e17b0e7f7 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -32,6 +32,7 @@ dist_theme_DATA = \ theme/move-window-on-new.svg \ theme/process-working.png \ theme/remove-workspace.svg \ + theme/running-indicator.svg \ theme/scroll-button-down-hover.png \ theme/scroll-button-down.png \ theme/scroll-button-up-hover.png \ diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css index 8c5c0d2f0..d2ce60d23 100644 --- a/data/theme/gnome-shell.css +++ b/data/theme/gnome-shell.css @@ -371,7 +371,12 @@ StTooltip StLabel { #dash { color: #5f5f5f; font-size: 12px; - padding: 0px 14px; + padding: 12px; + spacing: 6px; + background-color: rgba(0, 0, 0, 0.5); + border: 2px solid rgba(128, 128, 128, 0.4); + border-left: 0px; + border-radius: 0px 9px 9px 0px; } #dashSections { @@ -558,31 +563,26 @@ StTooltip StLabel { } .app-well-app { - border: 1px solid #181818; border-radius: 4px; padding: 4px; - width: 70px; - height: 70px; font-size: 10px; + color: white; transition-duration: 100; text-align: center; } .app-well-app.running { - background-gradient-direction: vertical; - background-gradient-start: #3d3d3d; - background-gradient-end: #181818; + text-shadow: black 0px 2px 2px; + background-image: url("running-indicator.svg"); } .app-well-app.selected { - border: 1px solid #666666; + background: rgba(255,255,255,0.33); } .app-well-app:hover { - border: 1px solid #666666; - background-gradient-direction: vertical; - background-gradient-start: rgba(61,61,61,0.8); - background-gradient-end: rgba(24,24,24,0.2); + background: rgba(255,255,255,0.33); + text-shadow: black 0px 2px 2px; transition-duration: 100; } diff --git a/data/theme/running-indicator.svg b/data/theme/running-indicator.svg new file mode 100644 index 000000000..d721e6444 --- /dev/null +++ b/data/theme/running-indicator.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js index 8c3330e19..b9a339992 100644 --- a/js/ui/appDisplay.js +++ b/js/ui/appDisplay.js @@ -375,7 +375,9 @@ AppIcon.prototype = { let label = this.app.get_name(); - IconGrid.BaseIcon.prototype._init.call(this, label); + IconGrid.BaseIcon.prototype._init.call(this, + label, + { setSizeManually: true }); }, createIcon: function(iconSize) { @@ -396,8 +398,8 @@ AppWellIcon.prototype = { y_fill: true }); this.actor._delegate = this; - this._icon = new AppIcon(app); - this.actor.set_child(this._icon.actor); + this.icon = new AppIcon(app); + this.actor.set_child(this.icon.actor); this.actor.connect('clicked', Lang.bind(this, this._onClicked)); @@ -581,13 +583,13 @@ AppWellIcon.prototype = { }, getDragActor: function() { - return this.app.create_icon_texture(this._icon.iconSize); + return this.app.create_icon_texture(this.icon.iconSize); }, // Returns the original actor that should align with the actor // we show as the item is being dragged. getDragActorSource: function() { - return this._icon.icon; + return this.icon.icon; } }; Signals.addSignalMethods(AppWellIcon.prototype); @@ -756,135 +758,3 @@ AppIconMenu.prototype = { } }; Signals.addSignalMethods(AppIconMenu.prototype); - -function AppWell() { - this._init(); -} - -AppWell.prototype = { - _init : function() { - this._placeholderText = null; - this._menus = []; - this._menuDisplays = []; - - this._favorites = []; - - this._grid = new IconGrid.IconGrid(); - this.actor = this._grid.actor; - this.actor._delegate = this; - - this._workId = Main.initializeDeferredWork(this.actor, Lang.bind(this, this._redisplay)); - - this._tracker = Shell.WindowTracker.get_default(); - this._appSystem = Shell.AppSystem.get_default(); - - this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay)); - AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay)); - this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay)); - }, - - _appIdListToHash: function(apps) { - let ids = {}; - for (let i = 0; i < apps.length; i++) - ids[apps[i].get_id()] = apps[i]; - return ids; - }, - - _queueRedisplay: function () { - Main.queueDeferredWork(this._workId); - }, - - _redisplay: function () { - this._grid.removeAll(); - - let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); - - /* hardcode here pending some design about how exactly desktop contexts behave */ - let contextId = ''; - - let running = this._tracker.get_running_apps(contextId); - let runningIds = this._appIdListToHash(running); - - let nFavorites = 0; - for (let id in favorites) { - let app = favorites[id]; - let display = new AppWellIcon(app); - this._grid.addItem(display.actor); - nFavorites++; - } - - for (let i = 0; i < running.length; i++) { - let app = running[i]; - if (app.get_id() in favorites) - continue; - let display = new AppWellIcon(app); - this._grid.addItem(display.actor); - } - if (this._placeholderText) { - this._placeholderText.destroy(); - this._placeholderText = null; - } - - if (running.length == 0 && nFavorites == 0) { - this._placeholderText = new St.Label({ text: _("Drag here to add favorites") }); - this.actor.add_actor(this._placeholderText); - } - }, - - handleDragOver : function(source, actor, x, y, time) { - let app = null; - if (source instanceof AppWellIcon) - app = this._appSystem.get_app(source.getId()); - else if (source instanceof Workspace.WindowClone) - app = this._tracker.get_window_app(source.metaWindow); - - // Don't allow favoriting of transient apps - if (app == null || app.is_transient()) - return DND.DragMotionResult.NO_DROP; - - let id = app.get_id(); - - let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); - - let srcIsFavorite = (id in favorites); - - if (srcIsFavorite) - return DND.DragMotionResult.NO_DROP; - - return DND.DragMotionResult.COPY_DROP; - }, - - // Draggable target interface - acceptDrop : function(source, actor, x, y, time) { - let app = null; - if (source instanceof AppWellIcon) { - app = this._appSystem.get_app(source.getId()); - } else if (source instanceof Workspace.WindowClone) { - app = this._tracker.get_window_app(source.metaWindow); - } - - // Don't allow favoriting of transient apps - if (app == null || app.is_transient()) { - return false; - } - - let id = app.get_id(); - - let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); - - let srcIsFavorite = (id in favorites); - - if (srcIsFavorite) { - return false; - } else { - Mainloop.idle_add(Lang.bind(this, function () { - AppFavorites.getAppFavorites().addFavorite(id); - return false; - })); - } - - return true; - } -}; - -Signals.addSignalMethods(AppWell.prototype); diff --git a/js/ui/dash.js b/js/ui/dash.js index 530962bba..a8f5cd8d7 100644 --- a/js/ui/dash.js +++ b/js/ui/dash.js @@ -4,11 +4,13 @@ const Clutter = imports.gi.Clutter; const Mainloop = imports.mainloop; const Signals = imports.signals; const Lang = imports.lang; +const Shell = imports.gi.Shell; const St = imports.gi.St; const Gettext = imports.gettext.domain('gnome-shell'); const _ = Gettext.gettext; const AppDisplay = imports.ui.appDisplay; +const AppFavorites = imports.ui.appFavorites; const DND = imports.ui.dnd; const DocDisplay = imports.ui.docDisplay; const PlaceDisplay = imports.ui.placeDisplay; @@ -16,6 +18,7 @@ const Main = imports.ui.main; const Overview = imports.ui.overview; const Search = imports.ui.search; const Tweener = imports.ui.tweener; +const Workspace = imports.ui.workspace; // 25 search results (per result type) should be enough for everyone const MAX_RENDERED_SEARCH_RESULTS = 25; @@ -689,11 +692,11 @@ Section.prototype = { } }; -function Dash() { +function OldDash() { this._init(); } -Dash.prototype = { +OldDash.prototype = { _init : function() { // dash and the popup panes need to be reactive so that the clicks in unoccupied places on them // are not passed to the transparent background underneath them. This background is used for the workspaces area when @@ -911,3 +914,161 @@ Dash.prototype = { } }; Signals.addSignalMethods(Dash.prototype); + + +function Dash() { + this._init(); +} + +Dash.prototype = { + _init : function() { + this._placeholderText = null; + this._menus = []; + this._menuDisplays = []; + this._maxHeight = -1; + + this._favorites = []; + + this._box = new St.BoxLayout({ name: 'dash', + vertical: true, + clip_to_allocation: true }); + this._box._delegate = this; + + this.actor = new St.Bin({ y_align: St.Align.START, child: this._box }); + this.actor.connect('notify::height', Lang.bind(this, + function() { + if (this._maxHeight != this.actor.height) + this._queueRedisplay(); + this._maxHeight = this.actor.height; + })); + + this._workId = Main.initializeDeferredWork(this._box, Lang.bind(this, this._redisplay)); + + this._tracker = Shell.WindowTracker.get_default(); + this._appSystem = Shell.AppSystem.get_default(); + + this._appSystem.connect('installed-changed', Lang.bind(this, this._queueRedisplay)); + AppFavorites.getAppFavorites().connect('changed', Lang.bind(this, this._queueRedisplay)); + this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay)); + }, + + _appIdListToHash: function(apps) { + let ids = {}; + for (let i = 0; i < apps.length; i++) + ids[apps[i].get_id()] = apps[i]; + return ids; + }, + + _queueRedisplay: function () { + Main.queueDeferredWork(this._workId); + }, + + _redisplay: function () { + this._box.hide(); + this._box.remove_all(); + + let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); + + /* hardcode here pending some design about how exactly desktop contexts behave */ + let contextId = ''; + + let running = this._tracker.get_running_apps(contextId); + let runningIds = this._appIdListToHash(running); + + for (let id in favorites) { + let app = favorites[id]; + let display = new AppDisplay.AppWellIcon(app); + this._box.add(display.actor); + } + + for (let i = 0; i < running.length; i++) { + let app = running[i]; + if (app.get_id() in favorites) + continue; + let display = new AppDisplay.AppWellIcon(app); + this._box.add(display.actor); + } + if (this._placeholderText) { + this._placeholderText.destroy(); + this._placeholderText = null; + } + + let children = this._box.get_children(); + if (children.length == 0) { + this._placeholderText = new St.Label({ text: _("Drag here to add favorites") }); + this._box.add_actor(this._placeholderText); + } else if (this._maxHeight > -1) { + let iconSizes = [ 48, 32, 24, 22, 16 ]; + + for (let i = 0; i < iconSizes.length; i++) { + let minHeight, natHeight; + + for (let j = 0; j < children.length; j++) + children[j]._delegate.icon.setIconSize(iconSizes[i]); + + [minHeight, natHeight] = this.actor.get_preferred_height(-1); + + if (natHeight <= this._maxHeight) + break; + } + } + this._box.show(); + }, + + handleDragOver : function(source, actor, x, y, time) { + let app = null; + if (source instanceof AppDisplay.AppWellIcon) + app = this._appSystem.get_app(source.getId()); + else if (source instanceof Workspace.WindowClone) + app = this._tracker.get_window_app(source.metaWindow); + + // Don't allow favoriting of transient apps + if (app == null || app.is_transient()) + return DND.DragMotionResult.NO_DROP; + + let id = app.get_id(); + + let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); + + let srcIsFavorite = (id in favorites); + + if (srcIsFavorite) + return DND.DragMotionResult.NO_DROP; + + return DND.DragMotionResult.COPY_DROP; + }, + + // Draggable target interface + acceptDrop : function(source, actor, x, y, time) { + let app = null; + if (source instanceof AppDisplay.AppWellIcon) { + app = this._appSystem.get_app(source.getId()); + } else if (source instanceof Workspace.WindowClone) { + app = this._tracker.get_window_app(source.metaWindow); + } + + // Don't allow favoriting of transient apps + if (app == null || app.is_transient()) { + return false; + } + + let id = app.get_id(); + + let favorites = AppFavorites.getAppFavorites().getFavoriteMap(); + + let srcIsFavorite = (id in favorites); + + if (srcIsFavorite) { + return false; + } else { + Mainloop.idle_add(Lang.bind(this, function () { + AppFavorites.getAppFavorites().addFavorite(id); + return false; + })); + } + + return true; + } +}; + +Signals.addSignalMethods(Dash.prototype); diff --git a/js/ui/overview.js b/js/ui/overview.js index 3c398d0e8..d9f2695ad 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -319,15 +319,12 @@ Overview.prototype = { this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width)); if (rtl) { - this._dash.actor.set_position(primary.width - displayGridColumnWidth, contentY); + this._dash.actor.set_position(primary.width - displayGridColumnWidth - WORKSPACE_GRID_PADDING / 2, + this._workspacesY); } else { - this._dash.actor.set_position(0, contentY); + this._dash.actor.set_position(0, this._workspacesY); } - - this._dash.actor.set_size(displayGridColumnWidth, contentHeight); - this._dash.searchArea.height = this._workspacesY - contentY; - this._dash.sectionArea.height = this._workspacesHeight; - this._dash.searchResults.actor.height = this._workspacesHeight; + this._dash.actor.height = this._workspacesHeight; // place the 'Add Workspace' button in the bottom row of the grid this._workspacesBarX = this._workspacesX; @@ -445,8 +442,6 @@ Overview.prototype = { this.visible = true; this.animationInProgress = true; - this._dash.show(); - /* TODO: make this stuff dynamic */ this._workspacesManager = new WorkspacesView.WorkspacesManager(this._workspacesWidth, @@ -615,7 +610,6 @@ Overview.prototype = { this._workspacesManager = null; - this._dash.hide(); this._desktopFade.hide(); this._background.hide(); this._group.hide();