2008-12-01 19:51:43 +00:00
|
|
|
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2008-11-15 00:44:11 +00:00
|
|
|
|
2009-02-04 18:45:38 +00:00
|
|
|
const Big = imports.gi.Big;
|
2009-02-10 16:12:58 +00:00
|
|
|
const Clutter = imports.gi.Clutter;
|
2009-07-02 16:35:34 +00:00
|
|
|
const Lang = imports.lang;
|
|
|
|
const Mainloop = imports.mainloop;
|
|
|
|
|
|
|
|
const Shell = imports.gi.Shell;
|
|
|
|
const Tweener = imports.ui.tweener;
|
2008-11-15 00:44:11 +00:00
|
|
|
|
|
|
|
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
|
2009-02-04 18:45:38 +00:00
|
|
|
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
|
2008-11-15 00:44:11 +00:00
|
|
|
|
|
|
|
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
|
2009-02-04 18:45:38 +00:00
|
|
|
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaa66);
|
2008-11-15 00:44:11 +00:00
|
|
|
|
2009-07-13 16:49:06 +00:00
|
|
|
const DEFAULT_TEXT_COLOR = new Clutter.Color();
|
|
|
|
DEFAULT_TEXT_COLOR.from_pixel(0x000000ff);
|
|
|
|
|
|
|
|
const DEFAULT_FONT = 'Sans Bold 16px';
|
|
|
|
|
|
|
|
// Padding on the left and right side of the button.
|
|
|
|
const SIDE_PADDING = 14;
|
|
|
|
|
2009-08-11 22:10:25 +00:00
|
|
|
function Button(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
|
|
|
|
this._init(widget, buttonColor, pressedButtonColor, textColor, staysPressed, font);
|
2008-11-15 00:44:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Button.prototype = {
|
2009-08-11 22:10:25 +00:00
|
|
|
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, staysPressed, font) {
|
2008-12-01 19:51:43 +00:00
|
|
|
let me = this;
|
2008-11-15 00:44:11 +00:00
|
|
|
|
2008-12-01 19:51:43 +00:00
|
|
|
this._buttonColor = buttonColor
|
|
|
|
if (buttonColor == null)
|
|
|
|
this._buttonColor = DEFAULT_BUTTON_COLOR;
|
2008-11-15 00:44:11 +00:00
|
|
|
|
2008-12-01 19:51:43 +00:00
|
|
|
this._pressedButtonColor = pressedButtonColor
|
|
|
|
if (pressedButtonColor == null)
|
|
|
|
this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
|
2008-11-15 00:44:11 +00:00
|
|
|
|
2009-07-13 16:49:06 +00:00
|
|
|
this._textColor = textColor;
|
|
|
|
if (textColor == null)
|
|
|
|
this._textColor = DEFAULT_TEXT_COLOR;
|
|
|
|
|
2009-05-08 20:27:14 +00:00
|
|
|
this._staysPressed = staysPressed
|
2008-12-01 19:51:43 +00:00
|
|
|
if (staysPressed == null)
|
2009-05-08 20:27:14 +00:00
|
|
|
this._staysPressed = false;
|
|
|
|
|
2009-07-13 16:49:06 +00:00
|
|
|
this._font = font;
|
|
|
|
if (font == null)
|
|
|
|
this._font = DEFAULT_FONT;
|
|
|
|
|
2009-05-08 20:27:14 +00:00
|
|
|
// if this._staysPressed is true, this._active will be true past the first release of a button, until a subsequent one (the button
|
|
|
|
// is unpressed) or until release() is called explicitly
|
2008-12-01 19:51:43 +00:00
|
|
|
this._active = false;
|
|
|
|
this._isBetweenPressAndRelease = false;
|
|
|
|
this._mouseIsOverButton = false;
|
|
|
|
|
2009-02-04 18:45:38 +00:00
|
|
|
this.button = new Big.Box({ reactive: true,
|
|
|
|
corner_radius: 5,
|
2009-07-13 16:49:06 +00:00
|
|
|
padding_left: SIDE_PADDING,
|
|
|
|
padding_right: SIDE_PADDING,
|
2009-02-04 18:45:38 +00:00
|
|
|
orientation: Big.BoxOrientation.HORIZONTAL,
|
|
|
|
y_align: Big.BoxAlignment.CENTER
|
|
|
|
});
|
|
|
|
if (typeof widgetOrText == 'string') {
|
2009-07-13 16:49:06 +00:00
|
|
|
this._widget = new Clutter.Text({ font_name: this._font,
|
|
|
|
color: this._textColor,
|
2009-02-23 19:42:00 +00:00
|
|
|
text: widgetOrText });
|
2009-02-04 18:45:38 +00:00
|
|
|
} else {
|
|
|
|
this._widget = widgetOrText;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.button.append(this._widget, Big.BoxPackFlags.EXPAND);
|
|
|
|
|
2008-12-01 19:51:43 +00:00
|
|
|
this.button.connect('button-press-event',
|
|
|
|
function(o, event) {
|
|
|
|
me._isBetweenPressAndRelease = true;
|
2009-02-04 18:45:38 +00:00
|
|
|
me.button.backgroundColor = me._pressedButtonColor;
|
2008-12-01 19:51:43 +00:00
|
|
|
return false;
|
|
|
|
});
|
|
|
|
this.button.connect('button-release-event',
|
|
|
|
function(o, event) {
|
|
|
|
me._isBetweenPressAndRelease = false;
|
2009-05-08 20:27:14 +00:00
|
|
|
if (!me._staysPressed || me._active) {
|
2008-12-01 19:51:43 +00:00
|
|
|
me.release();
|
|
|
|
} else {
|
|
|
|
me._active = true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
this.button.connect('enter-event',
|
|
|
|
function(o, event) {
|
|
|
|
me._mouseIsOverButton = true;
|
|
|
|
if (!me._active) {
|
2009-02-04 18:45:38 +00:00
|
|
|
me.button.backgroundColor = me._buttonColor;
|
2008-12-01 19:51:43 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
this.button.connect('leave-event',
|
|
|
|
function(o, event) {
|
|
|
|
me._isBetweenPressAndRelease = false;
|
|
|
|
me._mouseIsOverButton = false;
|
|
|
|
if (!me._active) {
|
2009-02-04 18:45:38 +00:00
|
|
|
me.button.backgroundColor = null;
|
2008-12-01 19:51:43 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2009-05-08 20:27:14 +00:00
|
|
|
pressIn : function() {
|
|
|
|
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
|
|
|
this._active = true;
|
|
|
|
this.button.backgroundColor = this._pressedButtonColor;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2008-12-01 19:51:43 +00:00
|
|
|
release : function() {
|
2009-05-08 20:27:14 +00:00
|
|
|
if (!this._isBetweenPressAndRelease && this._staysPressed) {
|
2008-12-01 19:51:43 +00:00
|
|
|
this._active = false;
|
|
|
|
if (this._mouseIsOverButton) {
|
2009-02-04 18:45:38 +00:00
|
|
|
this.button.backgroundColor = this._buttonColor;
|
2008-11-15 00:44:11 +00:00
|
|
|
} else {
|
2009-02-04 18:45:38 +00:00
|
|
|
this.button.backgroundColor = null;
|
2008-11-15 00:44:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-01 19:51:43 +00:00
|
|
|
};
|
2009-07-02 16:35:34 +00:00
|
|
|
|
|
|
|
/* Delay before the icon should appear, in seconds after the pointer has entered the parent */
|
|
|
|
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)
|
|
|
|
*/
|
2009-07-11 16:44:21 +00:00
|
|
|
function iconButton(parent, size, texture) {
|
|
|
|
this._init(parent, size, texture);
|
2009-07-02 16:35:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
iconButton.prototype = {
|
|
|
|
_init : function(parent, size, texture) {
|
|
|
|
this._size = size;
|
2009-07-11 16:44:21 +00:00
|
|
|
if (texture)
|
2009-07-02 16:35:34 +00:00
|
|
|
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
|
2009-07-11 16:44:21 +00:00
|
|
|
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
2009-07-02 16:35:34 +00:00
|
|
|
return;
|
|
|
|
|
2009-07-08 00:02:47 +00:00
|
|
|
this._fadeIn();
|
2009-07-02 16:35:34 +00:00
|
|
|
}));
|
|
|
|
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
|
2009-07-11 16:44:21 +00:00
|
|
|
if (actor.get_children().indexOf(Shell.get_event_related(event)) != -1)
|
2009-07-02 16:35:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Remember that we should not be visible to hide the button if forceShow is unset
|
2009-07-11 16:44:21 +00:00
|
|
|
if (this._forceShow) {
|
2009-07-02 16:35:34 +00:00
|
|
|
this._shouldHide = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-11 16:44:21 +00:00
|
|
|
this._fadeOut();
|
2009-07-02 16:35:34 +00:00
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
|
|
|
/// 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
|
2009-07-11 16:44:21 +00:00
|
|
|
if (!this._forceShow && this._shouldHide) {
|
2009-07-02 16:35:34 +00:00
|
|
|
this._fadeOut();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/// Private methods ///
|
|
|
|
|
|
|
|
_fadeIn : function() {
|
|
|
|
Tweener.removeTweens(this.actor);
|
|
|
|
Tweener.addTween(this.actor, { opacity: 255,
|
|
|
|
time: ANIMATION_TIME,
|
|
|
|
transition :"easeInQuad" });
|
|
|
|
},
|
|
|
|
|
|
|
|
_fadeOut : function() {
|
|
|
|
Tweener.removeTweens(this.actor);
|
|
|
|
Tweener.addTween(this.actor, { opacity: 0,
|
|
|
|
time: ANIMATION_TIME,
|
|
|
|
transition :"easeOutQuad" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|