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
This commit is contained in:
Florian Müllner 2010-07-22 01:29:02 +02:00
parent 2d2ac5b3f6
commit 3e4f744e56
6 changed files with 279 additions and 161 deletions

View File

@ -32,6 +32,7 @@ dist_theme_DATA = \
theme/move-window-on-new.svg \ theme/move-window-on-new.svg \
theme/process-working.png \ theme/process-working.png \
theme/remove-workspace.svg \ theme/remove-workspace.svg \
theme/running-indicator.svg \
theme/scroll-button-down-hover.png \ theme/scroll-button-down-hover.png \
theme/scroll-button-down.png \ theme/scroll-button-down.png \
theme/scroll-button-up-hover.png \ theme/scroll-button-up-hover.png \

View File

@ -339,7 +339,17 @@ StTooltip StLabel {
#dash { #dash {
color: #5f5f5f; color: #5f5f5f;
font-size: 12px; 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;
}
#dash:empty {
height: 100px;
width: 60px;
} }
#dashSections { #dashSections {
@ -526,31 +536,26 @@ StTooltip StLabel {
} }
.app-well-app { .app-well-app {
border: 1px solid #181818;
border-radius: 4px; border-radius: 4px;
padding: 4px; padding: 4px;
width: 70px;
height: 70px;
font-size: 10px; font-size: 10px;
color: white;
transition-duration: 100; transition-duration: 100;
text-align: center; text-align: center;
} }
.app-well-app.running { .app-well-app.running {
background-gradient-direction: vertical; text-shadow: black 0px 2px 2px;
background-gradient-start: #3d3d3d; background-image: url("running-indicator.svg");
background-gradient-end: #181818;
} }
.app-well-app.selected { .app-well-app.selected {
border: 1px solid #666666; background: rgba(255,255,255,0.33);
} }
.app-well-app:hover { .app-well-app:hover {
border: 1px solid #666666; background: rgba(255,255,255,0.33);
background-gradient-direction: vertical; text-shadow: black 0px 2px 2px;
background-gradient-start: rgba(61,61,61,0.8);
background-gradient-end: rgba(24,24,24,0.2);
transition-duration: 100; transition-duration: 100;
} }

View File

@ -0,0 +1,89 @@
<?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="74.01342"
height="74.006706"
id="svg7355"
version="1.1">
<defs
id="defs7357">
<radialGradient
xlink:href="#linearGradient36429"
id="radialGradient7461"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0525552,0,0,1.0525552,-2.5162753,-9.0000838)"
cx="47.878681"
cy="171.25"
fx="47.878681"
fy="171.25"
r="37" />
<linearGradient
id="linearGradient36429">
<stop
id="stop36431"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop36433"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<radialGradient
xlink:href="#linearGradient36471"
id="radialGradient7463"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.1891549,0,0,0.55513246,-9.281289,36.12653)"
cx="49.067139"
cy="242.50381"
fx="49.067139"
fy="242.50381"
r="37.00671" />
<linearGradient
id="linearGradient36471">
<stop
id="stop36473"
offset="0"
style="stop-color:#ffffff;stop-opacity:1;" />
<stop
id="stop36475"
offset="1"
style="stop-color:#ffffff;stop-opacity:0;" />
</linearGradient>
<radialGradient
r="37.00671"
fy="242.50381"
fx="49.067139"
cy="242.50381"
cx="49.067139"
gradientTransform="matrix(1.1891549,0,0,0.55513246,-9.281289,36.12653)"
gradientUnits="userSpaceOnUse"
id="radialGradient7488"
xlink:href="#linearGradient36471" />
</defs>
<g
id="layer1"
transform="translate(-266.21629,-168.11809)">
<g
style="display:inline"
id="g30864"
transform="translate(255.223,70.118091)">
<rect
ry="3.5996203"
rx="3.5996203"
y="98"
x="11"
height="74"
width="74"
id="rect14000"
style="opacity:0.371875;fill:url(#radialGradient7461);fill-opacity:1;stroke:none" />
<path
id="rect34520"
d="m 84.506708,167.95508 c 6e-6,1.96759 -1.584022,3.55162 -3.551629,3.55163 l -65.910146,0 c -1.967608,-1e-5 -3.551648,-1.58402 -3.551643,-3.55164"
style="opacity:0.2;fill:none;stroke:url(#radialGradient7488);stroke-width:1;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -375,7 +375,9 @@ AppIcon.prototype = {
let label = this.app.get_name(); 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) { createIcon: function(iconSize) {
@ -396,8 +398,8 @@ AppWellIcon.prototype = {
y_fill: true }); y_fill: true });
this.actor._delegate = this; this.actor._delegate = this;
this._icon = new AppIcon(app); this.icon = new AppIcon(app);
this.actor.set_child(this._icon.actor); this.actor.set_child(this.icon.actor);
this.actor.connect('clicked', Lang.bind(this, this._onClicked)); this.actor.connect('clicked', Lang.bind(this, this._onClicked));
@ -581,13 +583,13 @@ AppWellIcon.prototype = {
}, },
getDragActor: function() { 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 // Returns the original actor that should align with the actor
// we show as the item is being dragged. // we show as the item is being dragged.
getDragActorSource: function() { getDragActorSource: function() {
return this._icon.icon; return this.icon.icon;
} }
}; };
Signals.addSignalMethods(AppWellIcon.prototype); Signals.addSignalMethods(AppWellIcon.prototype);
@ -756,135 +758,3 @@ AppIconMenu.prototype = {
} }
}; };
Signals.addSignalMethods(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);

View File

@ -4,11 +4,13 @@ const Clutter = imports.gi.Clutter;
const Mainloop = imports.mainloop; const Mainloop = imports.mainloop;
const Signals = imports.signals; const Signals = imports.signals;
const Lang = imports.lang; const Lang = imports.lang;
const Shell = imports.gi.Shell;
const St = imports.gi.St; const St = imports.gi.St;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
const AppDisplay = imports.ui.appDisplay; const AppDisplay = imports.ui.appDisplay;
const AppFavorites = imports.ui.appFavorites;
const DND = imports.ui.dnd; const DND = imports.ui.dnd;
const DocDisplay = imports.ui.docDisplay; const DocDisplay = imports.ui.docDisplay;
const PlaceDisplay = imports.ui.placeDisplay; const PlaceDisplay = imports.ui.placeDisplay;
@ -16,6 +18,7 @@ const Main = imports.ui.main;
const Overview = imports.ui.overview; const Overview = imports.ui.overview;
const Search = imports.ui.search; const Search = imports.ui.search;
const Tweener = imports.ui.tweener; const Tweener = imports.ui.tweener;
const Workspace = imports.ui.workspace;
// 25 search results (per result type) should be enough for everyone // 25 search results (per result type) should be enough for everyone
const MAX_RENDERED_SEARCH_RESULTS = 25; const MAX_RENDERED_SEARCH_RESULTS = 25;
@ -689,11 +692,11 @@ Section.prototype = {
} }
}; };
function Dash() { function OldDash() {
this._init(); this._init();
} }
Dash.prototype = { OldDash.prototype = {
_init : function() { _init : function() {
// dash and the popup panes need to be reactive so that the clicks in unoccupied places on them // 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 // are not passed to the transparent background underneath them. This background is used for the workspaces area when
@ -911,3 +914,159 @@ Dash.prototype = {
} }
}; };
Signals.addSignalMethods(Dash.prototype); Signals.addSignalMethods(Dash.prototype);
function Dash() {
this._init();
}
Dash.prototype = {
_init : function() {
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);
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);
}
let children = this._box.get_children();
if (children.length == 0) {
this._box.add_style_pseudo_class('empty');
} else {
this._box.remove_style_pseudo_class('empty');
if (this._maxHeight > -1) {
let iconSizes = [ 48, 32, 24, 22, 16 ];
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(this._iconSize);
[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);

View File

@ -319,15 +319,12 @@ Overview.prototype = {
this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width)); this._workspacesY = Math.floor(displayGridRowHeight + WORKSPACE_GRID_PADDING * (primary.height / primary.width));
if (rtl) { 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 { } else {
this._dash.actor.set_position(0, contentY); this._dash.actor.set_position(0, this._workspacesY);
} }
this._dash.actor.height = this._workspacesHeight;
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;
// place the 'Add Workspace' button in the bottom row of the grid // place the 'Add Workspace' button in the bottom row of the grid
this._workspacesBarX = this._workspacesX; this._workspacesBarX = this._workspacesX;
@ -445,8 +442,6 @@ Overview.prototype = {
this.visible = true; this.visible = true;
this.animationInProgress = true; this.animationInProgress = true;
this._dash.show();
/* TODO: make this stuff dynamic */ /* TODO: make this stuff dynamic */
this._workspacesManager = this._workspacesManager =
new WorkspacesView.WorkspacesManager(this._workspacesWidth, new WorkspacesView.WorkspacesManager(this._workspacesWidth,
@ -615,7 +610,6 @@ Overview.prototype = {
this._workspacesManager = null; this._workspacesManager = null;
this._dash.hide();
this._desktopFade.hide(); this._desktopFade.hide();
this._background.hide(); this._background.hide();
this._group.hide(); this._group.hide();