Use a fading icon button in genericDisplay
Add a new icon button in button.js that fades in/out with a short delay when the mouse enters/leaves its parent. Use it for the information button of genericDisplay.
This commit is contained in:
parent
7a0ce6c57b
commit
3852176e80
107
js/ui/button.js
107
js/ui/button.js
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
const Big = imports.gi.Big;
|
const Big = imports.gi.Big;
|
||||||
const Clutter = imports.gi.Clutter;
|
const Clutter = imports.gi.Clutter;
|
||||||
|
const Lang = imports.lang;
|
||||||
|
const Mainloop = imports.mainloop;
|
||||||
|
|
||||||
|
const Shell = imports.gi.Shell;
|
||||||
|
const Tweener = imports.ui.tweener;
|
||||||
|
|
||||||
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
|
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
|
||||||
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
|
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
|
||||||
@ -112,3 +117,105 @@ Button.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Delay before the icon should appear, in seconds after the pointer has entered the parent */
|
||||||
|
const SHOW_ICON_DELAY = 250; // 0.25 second
|
||||||
|
const ANIMATION_TIME = 0.25;
|
||||||
|
|
||||||
|
/* This is an icon button that fades in/out when mouse enters/leaves the parent.
|
||||||
|
* A delay is used before the fading starts. You can force it to be shown if needed.
|
||||||
|
*
|
||||||
|
* parent -- used to show/hide the button depending on mouse entering/leaving it
|
||||||
|
* size -- size in pixels of both the button and the icon it contains
|
||||||
|
* texture -- optional, must be used if the texture for the icon is already created (else, use setIconFromName)
|
||||||
|
*/
|
||||||
|
function iconButton(parent, size, icon) {
|
||||||
|
this._init(parent, size, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
iconButton.prototype = {
|
||||||
|
_init : function(parent, size, texture) {
|
||||||
|
this._size = size;
|
||||||
|
if(texture)
|
||||||
|
this.actor = texture;
|
||||||
|
else
|
||||||
|
this.actor = new Clutter.Texture({ width: this._size, height: this._size });
|
||||||
|
this.actor.set_reactive(true);
|
||||||
|
this.actor.set_opacity(0);
|
||||||
|
parent.connect("enter-event", Lang.bind(this, function(actor, event) {
|
||||||
|
this._shouldHide = false;
|
||||||
|
|
||||||
|
// Nothing to do if the cursor has come back from a child of the parent actor
|
||||||
|
if(actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._sourceId = Mainloop.timeout_add(SHOW_ICON_DELAY,
|
||||||
|
Lang.bind(this, this._fadeIn));
|
||||||
|
}));
|
||||||
|
parent.connect("leave-event", Lang.bind(this, function(actor, event) {
|
||||||
|
// Nothing to do if the cursor has merely entered a child of the parent actor
|
||||||
|
if(actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remember that we should not be visible to hide the button if forceShow is unset
|
||||||
|
if(this._forceShow) {
|
||||||
|
this._shouldHide = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._fadeOut()
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Private methods ///
|
||||||
|
|
||||||
|
setIconFromName : function(iconName) {
|
||||||
|
let iconTheme = Gtk.IconTheme.get_default();
|
||||||
|
let iconInfo = iconTheme.lookup_icon(iconName, this._size, 0);
|
||||||
|
if (!iconInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let iconPath = iconInfo.get_filename();
|
||||||
|
this.actor.set_from_file(iconPath);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Useful if we want to show the button immediately,
|
||||||
|
// e.g. in case the mouse is already in the parent when the button is created
|
||||||
|
show : function() {
|
||||||
|
this.actor.set_opacity(255);
|
||||||
|
},
|
||||||
|
|
||||||
|
// If show is true, prevents the button from fading out
|
||||||
|
forceShow : function(show) {
|
||||||
|
this._forceShow = show;
|
||||||
|
// Hide the button if it should have been hidden under normal conditions
|
||||||
|
if(!this._forceShow && this._shouldHide) {
|
||||||
|
this._fadeOut();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Private methods ///
|
||||||
|
|
||||||
|
_fadeIn : function() {
|
||||||
|
if(this._sourceId) {
|
||||||
|
Mainloop.source_remove(this._sourceId);
|
||||||
|
this._sourceId = null;
|
||||||
|
}
|
||||||
|
Tweener.removeTweens(this.actor);
|
||||||
|
Tweener.addTween(this.actor, { opacity: 255,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition :"easeInQuad" });
|
||||||
|
},
|
||||||
|
|
||||||
|
_fadeOut : function() {
|
||||||
|
if(this._sourceId) {
|
||||||
|
Mainloop.source_remove(this._sourceId);
|
||||||
|
this._sourceId = null;
|
||||||
|
}
|
||||||
|
Tweener.removeTweens(this.actor);
|
||||||
|
Tweener.addTween(this.actor, { opacity: 0,
|
||||||
|
time: ANIMATION_TIME,
|
||||||
|
transition :"easeOutQuad" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ const Signals = imports.signals;
|
|||||||
const Shell = imports.gi.Shell;
|
const Shell = imports.gi.Shell;
|
||||||
const Tidy = imports.gi.Tidy;
|
const Tidy = imports.gi.Tidy;
|
||||||
|
|
||||||
|
const Button = imports.ui.button;
|
||||||
const DND = imports.ui.dnd;
|
const DND = imports.ui.dnd;
|
||||||
const Link = imports.ui.link;
|
const Link = imports.ui.link;
|
||||||
|
|
||||||
@ -84,33 +85,30 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
let global = Shell.Global.get();
|
let global = Shell.Global.get();
|
||||||
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
let infoIconUri = "file://" + global.imagedir + "info.svg";
|
||||||
|
let infoIcon = Shell.TextureCache.get_default().load_uri_sync(infoIconUri,
|
||||||
this._informationButton = Shell.TextureCache.get_default().load_uri_sync(infoIconUri,
|
INFORMATION_BUTTON_SIZE,
|
||||||
INFORMATION_BUTTON_SIZE,
|
INFORMATION_BUTTON_SIZE);
|
||||||
INFORMATION_BUTTON_SIZE);
|
this._informationButton = new Button.iconButton(this.actor, INFORMATION_BUTTON_SIZE, infoIcon);
|
||||||
|
this._informationButton.actor.x = availableWidth - ITEM_DISPLAY_PADDING_RIGHT - INFORMATION_BUTTON_SIZE;
|
||||||
this._informationButton.x = availableWidth - ITEM_DISPLAY_PADDING_RIGHT - INFORMATION_BUTTON_SIZE;
|
this._informationButton.actor.y = ITEM_DISPLAY_HEIGHT / 2 - INFORMATION_BUTTON_SIZE / 2;
|
||||||
this._informationButton.y = ITEM_DISPLAY_HEIGHT / 2 - INFORMATION_BUTTON_SIZE / 2;
|
|
||||||
this._informationButton.reactive = true;
|
|
||||||
|
|
||||||
// Connecting to the button-press-event for the information button ensures that the actor,
|
// Connecting to the button-press-event for the information button ensures that the actor,
|
||||||
// which is a draggable actor, does not get the button-press-event and doesn't initiate
|
// which is a draggable actor, does not get the button-press-event and doesn't initiate
|
||||||
// the dragging, which then prevents us from getting the button-release-event for the button.
|
// the dragging, which then prevents us from getting the button-release-event for the button.
|
||||||
this._informationButton.connect('button-press-event',
|
this._informationButton.actor.connect('button-press-event',
|
||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
this._informationButton.connect('button-release-event',
|
this._informationButton.actor.connect('button-release-event',
|
||||||
Lang.bind(this,
|
Lang.bind(this,
|
||||||
function() {
|
function() {
|
||||||
// Selects the item by highlighting it and displaying its details
|
// Selects the item by highlighting it and displaying its details
|
||||||
this.emit('select');
|
this.emit('select');
|
||||||
return true;
|
return true;
|
||||||
}));
|
}));
|
||||||
this._informationButton.hide();
|
this.actor.add_actor(this._informationButton.actor);
|
||||||
this.actor.add_actor(this._informationButton);
|
this._informationButton.actor.lower_bottom();
|
||||||
this._informationButton.lower_bottom();
|
|
||||||
|
|
||||||
this._name = null;
|
this._name = null;
|
||||||
this._description = null;
|
this._description = null;
|
||||||
@ -118,9 +116,6 @@ GenericDisplayItem.prototype = {
|
|||||||
this._previewIcon = null;
|
this._previewIcon = null;
|
||||||
|
|
||||||
this.dragActor = null;
|
this.dragActor = null;
|
||||||
|
|
||||||
this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
|
|
||||||
this.actor.connect('leave-event', Lang.bind(this, this._onLeave));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//// Draggable object interface ////
|
//// Draggable object interface ////
|
||||||
@ -162,10 +157,14 @@ GenericDisplayItem.prototype = {
|
|||||||
// if isSelected is true, removes the highlighting otherwise.
|
// if isSelected is true, removes the highlighting otherwise.
|
||||||
markSelected: function(isSelected) {
|
markSelected: function(isSelected) {
|
||||||
let color;
|
let color;
|
||||||
if (isSelected)
|
if (isSelected) {
|
||||||
color = ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR;
|
color = ITEM_DISPLAY_SELECTED_BACKGROUND_COLOR;
|
||||||
else
|
this._informationButton.forceShow(true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
color = ITEM_DISPLAY_BACKGROUND_COLOR;
|
color = ITEM_DISPLAY_BACKGROUND_COLOR;
|
||||||
|
this._informationButton.forceShow(false);
|
||||||
|
}
|
||||||
this._bg.background_color = color;
|
this._bg.background_color = color;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -308,21 +307,11 @@ GenericDisplayItem.prototype = {
|
|||||||
|
|
||||||
//// Private methods ////
|
//// Private methods ////
|
||||||
|
|
||||||
// Performs actions on mouse enter event for the item. Currently, shows the information button for the item.
|
|
||||||
_onEnter: function(actor, event) {
|
|
||||||
this._informationButton.show();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Performs actions on mouse leave event for the item. Currently, hides the information button for the item.
|
|
||||||
_onLeave: function(actor, event) {
|
|
||||||
this._informationButton.hide();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hides the information button once the item starts being dragged.
|
// Hides the information button once the item starts being dragged.
|
||||||
_onDragBegin : function (draggable, time) {
|
_onDragBegin : function (draggable, time) {
|
||||||
// For some reason, we are not getting leave-event signal when we are dragging an item,
|
// For some reason, we are not getting leave-event signal when we are dragging an item,
|
||||||
// so we should remove the link manually.
|
// so we should remove the link manually.
|
||||||
this._informationButton.hide();
|
this._informationButton.actor.hide();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user