dash: Move labels beside the app icon upon hovering
Instead of using an St.Tooltip to show the app's name under the icon, manually position a new St.Label ourselves. Make sure to keep the label hidden when right-clicking so it doesn't get in the way of the popup menu. Only one tooltip/label will be displayed at a time. https://bugzilla.gnome.org/show_bug.cgi?id=666166
This commit is contained in:
parent
7b9c9b2f7d
commit
2b9561fcbb
@ -645,6 +645,17 @@ StTooltip StLabel {
|
|||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dash-label {
|
||||||
|
border-radius: 7px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
color: #ffffff;
|
||||||
|
font-size: 0.9em;
|
||||||
|
font-weight: bold;;
|
||||||
|
text-align: center;
|
||||||
|
-x-offset: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Apps */
|
/* Apps */
|
||||||
|
|
||||||
.icon-grid {
|
.icon-grid {
|
||||||
|
@ -470,6 +470,7 @@ const AppWellIcon = new Lang.Class({
|
|||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
this._onStateChanged));
|
this._onStateChanged));
|
||||||
this._onStateChanged();
|
this._onStateChanged();
|
||||||
|
this.isMenuUp = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDestroy: function() {
|
_onDestroy: function() {
|
||||||
@ -551,8 +552,8 @@ const AppWellIcon = new Lang.Class({
|
|||||||
this._menuManager.addMenu(this._menu);
|
this._menuManager.addMenu(this._menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isMenuUp = true;
|
||||||
this.actor.set_hover(true);
|
this.actor.set_hover(true);
|
||||||
this.actor.show_tooltip();
|
|
||||||
this._menu.popup();
|
this._menu.popup();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -568,6 +569,7 @@ const AppWellIcon = new Lang.Class({
|
|||||||
|
|
||||||
_onMenuPoppedDown: function() {
|
_onMenuPoppedDown: function() {
|
||||||
this.actor.sync_hover();
|
this.actor.sync_hover();
|
||||||
|
this.isMenuUp = false;
|
||||||
},
|
},
|
||||||
|
|
||||||
_onActivate: function (event) {
|
_onActivate: function (event) {
|
||||||
|
@ -6,6 +6,7 @@ const Lang = imports.lang;
|
|||||||
const Meta = imports.gi.Meta;
|
const Meta = imports.gi.Meta;
|
||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const St = imports.gi.St;
|
const St = imports.gi.St;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
const AppDisplay = imports.ui.appDisplay;
|
const AppDisplay = imports.ui.appDisplay;
|
||||||
const AppFavorites = imports.ui.appFavorites;
|
const AppFavorites = imports.ui.appFavorites;
|
||||||
@ -16,6 +17,9 @@ const Tweener = imports.ui.tweener;
|
|||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
|
|
||||||
const DASH_ANIMATION_TIME = 0.2;
|
const DASH_ANIMATION_TIME = 0.2;
|
||||||
|
const DASH_ITEM_LABEL_SHOW_TIME = 0.15;
|
||||||
|
const DASH_ITEM_LABEL_HIDE_TIME = 0.1;
|
||||||
|
const DASH_ITEM_HOVER_TIMEOUT = 300;
|
||||||
|
|
||||||
// A container like StBin, but taking the child's scale into account
|
// A container like StBin, but taking the child's scale into account
|
||||||
// when requesting a size
|
// when requesting a size
|
||||||
@ -32,6 +36,8 @@ const DashItemContainer = new Lang.Class({
|
|||||||
Lang.bind(this, this._allocate));
|
Lang.bind(this, this._allocate));
|
||||||
this.actor._delegate = this;
|
this.actor._delegate = this;
|
||||||
|
|
||||||
|
this._label = null;
|
||||||
|
|
||||||
this.child = null;
|
this.child = null;
|
||||||
this._childScale = 1;
|
this._childScale = 1;
|
||||||
this._childOpacity = 255;
|
this._childOpacity = 255;
|
||||||
@ -84,6 +90,60 @@ const DashItemContainer = new Lang.Class({
|
|||||||
alloc.natural_size = natWidth * this.child.scale_y;
|
alloc.natural_size = natWidth * this.child.scale_y;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showLabel: function() {
|
||||||
|
if (this._label == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._label.opacity = 0;
|
||||||
|
this._label.show();
|
||||||
|
|
||||||
|
let [stageX, stageY] = this.actor.get_transformed_position();
|
||||||
|
|
||||||
|
let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
|
||||||
|
|
||||||
|
let labelHeight = this._label.get_height();
|
||||||
|
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
|
||||||
|
|
||||||
|
let y = stageY + yOffset;
|
||||||
|
|
||||||
|
let node = this._label.get_theme_node();
|
||||||
|
let xOffset = node.get_length('-x-offset');
|
||||||
|
|
||||||
|
let x;
|
||||||
|
if (St.Widget.get_default_direction () == St.TextDirection.RTL)
|
||||||
|
x = stageX - this._label.get_width() - xOffset;
|
||||||
|
else
|
||||||
|
x = stageX + this.actor.get_width() + xOffset;
|
||||||
|
|
||||||
|
this._label.set_position(x, y);
|
||||||
|
Tweener.addTween(this._label,
|
||||||
|
{ opacity: 255,
|
||||||
|
time: DASH_ITEM_LABEL_SHOW_TIME,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setLabelText: function(text) {
|
||||||
|
if (this._label == null)
|
||||||
|
this._label = new St.Label({ style_class: 'dash-label'});
|
||||||
|
|
||||||
|
this._label.set_text(text);
|
||||||
|
Main.layoutManager.addChrome(this._label);
|
||||||
|
this._label.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
hideLabel: function () {
|
||||||
|
this._label.opacity = 255;
|
||||||
|
Tweener.addTween(this._label,
|
||||||
|
{ opacity: 0,
|
||||||
|
time: DASH_ITEM_LABEL_HIDE_TIME,
|
||||||
|
transition: 'easeOutQuad',
|
||||||
|
onComplete: Lang.bind(this, function() {
|
||||||
|
this._label.hide();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setChild: function(actor) {
|
setChild: function(actor) {
|
||||||
if (this.child == actor)
|
if (this.child == actor)
|
||||||
return;
|
return;
|
||||||
@ -238,6 +298,7 @@ const Dash = new Lang.Class({
|
|||||||
this._dragPlaceholderPos = -1;
|
this._dragPlaceholderPos = -1;
|
||||||
this._animatingPlaceholdersCount = 0;
|
this._animatingPlaceholdersCount = 0;
|
||||||
this._favRemoveTarget = null;
|
this._favRemoveTarget = null;
|
||||||
|
this._labelTimeoutId = 0;
|
||||||
|
|
||||||
this._box = new St.BoxLayout({ name: 'dash',
|
this._box = new St.BoxLayout({ name: 'dash',
|
||||||
vertical: true,
|
vertical: true,
|
||||||
@ -371,16 +432,37 @@ const Dash = new Lang.Class({
|
|||||||
Lang.bind(this, function() {
|
Lang.bind(this, function() {
|
||||||
display.actor.opacity = 255;
|
display.actor.opacity = 255;
|
||||||
}));
|
}));
|
||||||
display.actor.set_tooltip_text(app.get_name());
|
|
||||||
|
|
||||||
let item = new DashItemContainer();
|
let item = new DashItemContainer();
|
||||||
item.setChild(display.actor);
|
item.setChild(display.actor);
|
||||||
|
|
||||||
display.icon.setIconSize(this.iconSize);
|
item.setLabelText(app.get_name());
|
||||||
|
|
||||||
|
display.icon.setIconSize(this.iconSize);
|
||||||
|
display.actor.connect('notify::hover',
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
this._onHover(item, display)
|
||||||
|
}));
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onHover: function (item, display) {
|
||||||
|
if (display.actor.get_hover() && !display.isMenuUp) {
|
||||||
|
if (this._labelTimeoutId == 0) {
|
||||||
|
this._labelTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
|
||||||
|
Lang.bind(this, function() {
|
||||||
|
item.showLabel();
|
||||||
|
return false;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this._labelTimeoutId > 0)
|
||||||
|
Mainloop.source_remove(this._labelTimeoutId);
|
||||||
|
this._labelTimeoutId = 0;
|
||||||
|
item.hideLabel();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_adjustIconSize: function() {
|
_adjustIconSize: function() {
|
||||||
// For the icon size, we only consider children which are "proper"
|
// For the icon size, we only consider children which are "proper"
|
||||||
// icons (i.e. ignoring drag placeholders) and which are not
|
// icons (i.e. ignoring drag placeholders) and which are not
|
||||||
|
Loading…
x
Reference in New Issue
Block a user