[gnome-shell/overview-relayout: 15/15] dash: Improve DND to dash and allow reordering
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/overview-relayout: 15/15] dash: Improve DND to dash and allow reordering
- Date: Thu, 11 Nov 2010 15:41:51 +0000 (UTC)
commit f9ec93a0c6e1596151d077dbfb6f35125af0b908
Author: Florian Müllner <fmuellner gnome org>
Date: Mon Nov 8 02:51:02 2010 +0100
dash: Improve DND to dash and allow reordering
Show a positional indicator where a new favorite will be added and
make the favorites re-orderable. Also allow the removal of favorites
using drag-and-drop according to the mockups.
data/Makefile.am | 1 +
data/theme/dash-placeholder.svg | 84 +++++++++++++++++++
data/theme/gnome-shell.css | 14 +++-
js/ui/appDisplay.js | 174 ++++++++++++++++++++++++++++++++++++---
js/ui/appFavorites.js | 30 ++++++-
js/ui/overview.js | 2 +
6 files changed, 284 insertions(+), 21 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index e17b0e7..8c04198 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -25,6 +25,7 @@ dist_theme_DATA = \
theme/close-window.svg \
theme/close.svg \
theme/corner-ripple.png \
+ theme/dash-placeholder.svg \
theme/dialog-error.svg \
theme/gnome-shell.css \
theme/mosaic-view-active.svg \
diff --git a/data/theme/dash-placeholder.svg b/data/theme/dash-placeholder.svg
new file mode 100644
index 0000000..cbae148
--- /dev/null
+++ b/data/theme/dash-placeholder.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="76"
+ height="27"
+ id="svg11252"
+ version="1.1">
+ <defs
+ id="defs11254">
+ <radialGradient
+ xlink:href="#linearGradient39563-4-2"
+ id="radialGradient68155-2-3"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.3486842,0,317.8421)"
+ cx="49"
+ cy="488"
+ fx="49"
+ fy="488"
+ r="38" />
+ <linearGradient
+ id="linearGradient39563-4-2">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop39565-1-4" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop39567-7-9" />
+ </linearGradient>
+ <radialGradient
+ xlink:href="#linearGradient39573-6-1"
+ id="radialGradient68157-0-8"
+ gradientUnits="userSpaceOnUse"
+ cx="50.5"
+ cy="487.5"
+ fx="50.5"
+ fy="487.5"
+ r="10.5" />
+ <linearGradient
+ id="linearGradient39573-6-1">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop39575-5-6" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop39577-1-2" />
+ </linearGradient>
+ </defs>
+ <g
+ id="layer1"
+ transform="translate(-337,-518.86218)">
+ <g
+ id="g99967"
+ style="display:inline"
+ transform="translate(326,44.862171)">
+ <rect
+ style="opacity:0.49375;color:#000000;fill:url(#radialGradient68155-2-3);fill-opacity:1;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect99969"
+ width="76"
+ height="2"
+ x="11"
+ y="487"
+ rx="0"
+ ry="0" />
+ <path
+ style="opacity:0.43125;color:#000000;fill:url(#radialGradient68157-0-8);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path99971"
+ d="M 61,487.5 C 61,493.29899 56.29899,498 50.5,498 44.70101,498 40,493.29899 40,487.5 40,481.70101 44.70101,477 50.5,477 c 5.79899,0 10.5,4.70101 10.5,10.5 z"
+ transform="matrix(1.2857143,0,0,1.2857143,-14.428572,-139.28571)" />
+ <path
+ transform="matrix(0.43589747,0,0,0.43589747,28.487179,275)"
+ d="M 61,487.5 C 61,493.29899 56.29899,498 50.5,498 44.70101,498 40,493.29899 40,487.5 40,481.70101 44.70101,477 50.5,477 c 5.79899,0 10.5,4.70101 10.5,10.5 z"
+ id="path99973"
+ style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+ </g>
+</svg>
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 30f9210..d4c87ff 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -365,6 +365,11 @@ StTooltip {
border-radius: 0px 9px 9px 0px;
}
+.dash-placeholder {
+ background-image: url("dash-placeholder.svg");
+ height: 27px;
+}
+
#ViewSelector {
spacing: 16px;
}
@@ -554,14 +559,17 @@ StTooltip {
padding: 6px 12px;
}
+.overview-icon {
+ color: white;
+ font-size: 10px;
+ text-align: center;
+}
+
.app-well-app > .overview-icon,
.dash-search-result-content > .overview-icon {
border-radius: 4px;
padding: 4px;
- font-size: 10px;
- color: white;
transition-duration: 100;
- text-align: center;
}
.app-well-app.running > .overview-icon {
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index cc14127..0a71d35 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -260,6 +260,52 @@ PrefsSearchProvider.prototype = {
}
};
+function RemoveFavoriteIcon() {
+ this._init();
+}
+
+RemoveFavoriteIcon.prototype = {
+ __proto__: IconGrid.BaseIcon.prototype,
+
+ _init: function() {
+ IconGrid.BaseIcon.prototype._init.call(this,
+ "Remove from Favorites",
+ { setSizeManually: true });
+ this.actor._delegate = this;
+ },
+
+ createIcon: function(size) {
+ return St.TextureCache.get_default().load_icon_name('user-trash',
+ St.IconType.DOCUMENT,
+ size);
+ },
+
+ // Rely on the dragged item being a favorite
+ handleDragOver: function(source, actor, x, y, time) {
+ return DND.DragMotionResult.MOVE_DROP;
+ },
+
+ acceptDrop: function(source, actor, x, y, time) {
+ let app = null;
+ if (source instanceof AppWellIcon) {
+ let appSystem = Shell.AppSystem.get_default();
+ app = appSystem.get_app(source.getId());
+ } else if (source instanceof Workspace.WindowClone) {
+ let tracker = Shell.WindowTracker.get_default();
+ app = tracker.get_window_app(source.metaWindow);
+ }
+
+ let id = app.get_id();
+
+ Mainloop.idle_add(Lang.bind(this, function () {
+ AppFavorites.getAppFavorites().removeFavorite(id);
+ return false;
+ }));
+
+ return true;
+ }
+};
+
function AppIcon(app) {
this._init(app);
}
@@ -658,6 +704,11 @@ AppWell.prototype = {
this._menus = [];
this._menuDisplays = [];
this._maxHeight = -1;
+ this._iconSize = 48;
+
+ this._dragPlaceholder = null;
+ this._dragPlaceholderPos = -1;
+ this._favRemoveTarget = null;
this._favorites = [];
@@ -684,6 +735,63 @@ AppWell.prototype = {
this._tracker.connect('app-state-changed', Lang.bind(this, this._queueRedisplay));
},
+ show: function() {
+ this._itemDragBeginId = Main.overview.connect('item-drag-begin',
+ Lang.bind(this, this._onItemDragBegin));
+ this._itemDragEndId = Main.overview.connect('item-drag-end',
+ Lang.bind(this, this._onItemDragEnd));
+ },
+
+ hide: function() {
+ Main.overview.disconnect(this._itemDragBeginId);
+ Main.overview.disconnect(this._itemDragEndId);
+ },
+
+ _onItemDragBegin: function() {
+ this._dragMonitor = {
+ dragMotion: Lang.bind(this, this._onDragMotion)
+ };
+ DND.addDragMonitor(this._dragMonitor);
+ },
+
+ _onItemDragEnd: function() {
+ this._clearDragPlaceholder();
+ if (this._favRemoveTarget) {
+ this._favRemoveTarget.actor.destroy();
+ this._favRemoveTarget = null;
+ }
+ DND.removeMonitor(this._dragMonitor);
+ },
+
+ _onDragMotion: function(dragEvent) {
+ let app = null;
+ if (dragEvent.source instanceof AppWellIcon)
+ app = this._appSystem.get_app(dragEvent.source.getId());
+ else if (dragEvent.source instanceof Workspace.WindowClone)
+ app = this._tracker.get_window_app(dragEvent.source.metaWindow);
+ else
+ return DND.DragMotionResult.CONTINUE;
+
+ let id = app.get_id();
+
+ let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
+
+ let srcIsFavorite = (id in favorites);
+
+ if (srcIsFavorite && this._favRemoveTarget == null) {
+ this._favRemoveTarget = new RemoveFavoriteIcon();
+ this._favRemoveTarget.setIconSize(this._iconSize);
+ this._box.add(this._favRemoveTarget.actor);
+ }
+
+ if (!this._box.contains(dragEvent.targetActor) ||
+ (this._favRemoveTarget &&
+ this._favRemoveTarget.actor.contains(dragEvent.targetActor)))
+ this._clearDragPlaceholder();
+
+ return DND.DragMotionResult.CONTINUE;
+ },
+
_appIdListToHash: function(apps) {
let ids = {};
for (let i = 0; i < apps.length; i++)
@@ -695,6 +803,19 @@ AppWell.prototype = {
Main.queueDeferredWork(this._workId);
},
+ _addApp: function(app) {
+ let display = new AppWellIcon(app);
+ display._draggable.connect('drag-begin',
+ Lang.bind(this, function() {
+ display.actor.opacity = 50;
+ }));
+ display._draggable.connect('drag-end',
+ Lang.bind(this, function() {
+ display.actor.opacity = 255;
+ }));
+ this._box.add(display.actor);
+ },
+
_redisplay: function () {
this._box.hide();
this._box.remove_all();
@@ -709,16 +830,14 @@ AppWell.prototype = {
for (let id in favorites) {
let app = favorites[id];
- let display = new AppWellIcon(app);
- this._box.add(display.actor);
+ this._addApp(app);
}
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._box.add(display.actor);
+ this._addApp(app);
}
if (this._placeholderText) {
this._placeholderText.destroy();
@@ -735,8 +854,9 @@ AppWell.prototype = {
for (let i = 0; i < iconSizes.length; i++) {
let minHeight, natHeight;
+ this._iconSize = iconSizes[i];
for (let j = 0; j < children.length; j++)
- children[j]._delegate.icon.setIconSize(iconSizes[i]);
+ children[j]._delegate.icon.setIconSize(this._iconSize);
[minHeight, natHeight] = this.actor.get_preferred_height(-1);
@@ -747,6 +867,14 @@ AppWell.prototype = {
this._box.show();
},
+ _clearDragPlaceholder: function() {
+ if (this._dragPlaceholder) {
+ this._dragPlaceholder.destroy();
+ this._dragPlaceholder = null;
+ this._dragPlaceholderPos = -1;
+ }
+ },
+
handleDragOver : function(source, actor, x, y, time) {
let app = null;
if (source instanceof AppWellIcon)
@@ -758,6 +886,17 @@ AppWell.prototype = {
if (app == null || app.is_transient())
return DND.DragMotionResult.NO_DROP;
+ let numChildren = this._box.get_children().length;
+ let numFavorites = AppFavorites.getAppFavorites().getFavorites().length;
+ let pos = Math.floor(y * numChildren / this._box.height);
+ if (pos != this._dragPlaceholderPos && pos <= numFavorites) {
+ this._dragPlaceholderPos = pos;
+ if (this._dragPlaceholder)
+ this._dragPlaceholder.destroy();
+ this._dragPlaceholder = new St.Bin({ style_class: 'dash-placeholder' });
+ this._box.insert_actor(this._dragPlaceholder, pos);
+ }
+
let id = app.get_id();
let favorites = AppFavorites.getAppFavorites().getFavoriteMap();
@@ -765,7 +904,7 @@ AppWell.prototype = {
let srcIsFavorite = (id in favorites);
if (srcIsFavorite)
- return DND.DragMotionResult.NO_DROP;
+ return DND.DragMotionResult.MOVE_DROP;
return DND.DragMotionResult.COPY_DROP;
},
@@ -790,15 +929,24 @@ AppWell.prototype = {
let srcIsFavorite = (id in favorites);
- if (srcIsFavorite) {
- return false;
- } else {
- Mainloop.idle_add(Lang.bind(this, function () {
- AppFavorites.getAppFavorites().addFavorite(id);
- return false;
- }));
+ let favPos = 0;
+ let children = this._box.get_children();
+ for (let i = 0; i < this._dragPlaceholderPos; i++) {
+ let childId = children[i]._delegate.app.get_id();
+ if (childId == id)
+ continue;
+ if (childId in favorites)
+ favPos++;
}
+ Mainloop.idle_add(Lang.bind(this, function () {
+ if (srcIsFavorite)
+ AppFavorites.getAppFavorites().moveFavoriteToPos(id, favPos);
+ else
+ AppFavorites.getAppFavorites().addFavoriteAtPos(id, favPos);
+ return false;
+ }));
+
return true;
}
};
diff --git a/js/ui/appFavorites.js b/js/ui/appFavorites.js
index 9c050ee..30116de 100644
--- a/js/ui/appFavorites.js
+++ b/js/ui/appFavorites.js
@@ -63,7 +63,7 @@ AppFavorites.prototype = {
return appId in this._favorites;
},
- _addFavorite: function(appId) {
+ _addFavorite: function(appId, pos) {
if (appId in this._favorites)
return false;
@@ -73,14 +73,17 @@ AppFavorites.prototype = {
return false;
let ids = this._getIds();
- ids.push(appId);
+ if (pos == -1)
+ ids.push(appId);
+ else
+ ids.splice(pos, 0, appId);
global.settings.set_strv(this.FAVORITE_APPS_KEY, ids);
this._favorites[appId] = app;
return true;
},
- addFavorite: function(appId) {
- if (!this._addFavorite(appId))
+ addFavoriteAtPos: function(appId, pos) {
+ if (!this._addFavorite(appId, pos))
return;
let app = Shell.AppSystem.get_default().get_app(appId);
@@ -90,6 +93,15 @@ AppFavorites.prototype = {
}));
},
+ addFavorite: function(appId) {
+ this.addFavoriteAtPos(appId, -1);
+ },
+
+ moveFavoriteToPos: function(appId, pos) {
+ this._removeFavorite(appId);
+ this._addFavorite(appId, pos);
+ },
+
_removeFavorite: function(appId) {
if (!appId in this._favorites)
return false;
@@ -100,13 +112,21 @@ AppFavorites.prototype = {
},
removeFavorite: function(appId) {
+ let ids = this._getIds();
+ let pos = -1;
+ for (let i = 0; i < ids.length; i++)
+ if (ids[i] == appId) {
+ pos = i;
+ break;
+ }
+
let app = this._favorites[appId];
if (!this._removeFavorite(appId))
return;
Main.overview.shellInfo.setMessage(_("%s has been removed from your favorites.").format(app.get_name()),
Lang.bind(this, function () {
- this._addFavorite(appId);
+ this._addFavorite(appId, pos);
}));
}
};
diff --git a/js/ui/overview.js b/js/ui/overview.js
index 1ffa5b7..525b8b7 100644
--- a/js/ui/overview.js
+++ b/js/ui/overview.js
@@ -290,6 +290,7 @@ Overview.prototype = {
this.viewSelector.show();
this._workspacesDisplay.show();
+ this._appWell.show();
this.workspaces = this._workspacesDisplay.workspacesView;
this._group.add_actor(this.workspaces.actor);
@@ -423,6 +424,7 @@ Overview.prototype = {
this._workspacesDisplay.hide();
this.viewSelector.hide();
+ this._appWell.hide();
this._desktop.hide();
this._group.hide();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]