Remove ShellButtonBox, button.js; Use St.Clickable in panel.js

StClickable replaces ShellButtonBox.  Reduce the number of
button-like things by deleting button.js.

To do so, add CSS style for the actitivies button.

https://bugzilla.gnome.org/show_bug.cgi?id=602131
This commit is contained in:
Colin Walters 2009-11-16 14:16:22 -05:00
parent 93f3412f70
commit 2f1ca7bf28
9 changed files with 28 additions and 544 deletions

View File

@ -287,6 +287,16 @@ StTooltip {
spacing: 4px; spacing: 4px;
} }
/* Panel */
#panelActivities {
color: #ffffff;
}
#panelActivities:pressed {
background-color: rgba(50,76,111,0.98);
}
/* Calendar popup */ /* Calendar popup */
#calendarPopup { #calendarPopup {

View File

@ -5,7 +5,6 @@ dist_jsui_DATA = \
appDisplay.js \ appDisplay.js \
appFavorites.js \ appFavorites.js \
appIcon.js \ appIcon.js \
button.js \
calendar.js \ calendar.js \
chrome.js \ chrome.js \
dash.js \ dash.js \

View File

@ -440,16 +440,18 @@ SwitcherList.prototype = {
addItem : function(item) { addItem : function(item) {
// We want the St.Bin's padding to be clickable (since it will // We want the St.Bin's padding to be clickable (since it will
// be part of the highlighted background color), so we put the // be part of the highlighted background color), so we put the
// bin inside the ButtonBox rather than vice versa. // bin inside the Clickable rather than vice versa.
let bin = new St.Bin({ style_class: 'item-box' }); let bin = new St.Bin({ style_class: 'item-box' });
let bbox = new Shell.ButtonBox({ reactive: true }); let bbox = new St.Clickable({ reactive: true,
x_fill: true,
y_fill: true });
bin.add_actor(item); bin.add_actor(item);
bbox.append(bin, Big.BoxPackFlags.NONE); bbox.set_child(bin);
this._list.add_actor(bbox); this._list.add_actor(bbox);
let n = this._items.length; let n = this._items.length;
bbox.connect('activate', Lang.bind(this, function () { bbox.connect('clicked', Lang.bind(this, function () {
this._itemActivated(n); this._itemActivated(n);
})); }));
bbox.connect('enter-event', Lang.bind(this, function () { bbox.connect('enter-event', Lang.bind(this, function () {
@ -681,7 +683,7 @@ AppSwitcher.prototype = {
this.icons.push(appIcon); this.icons.push(appIcon);
this.addItem(appIcon.actor); this.addItem(appIcon.actor);
// SwitcherList creates its own Shell.ButtonBox; we want to // SwitcherList creates its own St.Clickable; we want to
// avoid intercepting the events it wants. // avoid intercepting the events it wants.
appIcon.actor.reactive = false; appIcon.actor.reactive = false;

View File

@ -1,172 +0,0 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
const Big = imports.gi.Big;
const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Tweener = imports.ui.tweener;
const DEFAULT_BUTTON_COLOR = new Clutter.Color();
DEFAULT_BUTTON_COLOR.from_pixel(0xeeddcc66);
const DEFAULT_PRESSED_BUTTON_COLOR = new Clutter.Color();
DEFAULT_PRESSED_BUTTON_COLOR.from_pixel(0xccbbaa66);
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;
function Button(widget, buttonColor, pressedButtonColor, textColor, font) {
this._init(widget, buttonColor, pressedButtonColor, textColor, font);
}
Button.prototype = {
_init : function(widgetOrText, buttonColor, pressedButtonColor, textColor, font) {
this._buttonColor = buttonColor
if (buttonColor == null)
this._buttonColor = DEFAULT_BUTTON_COLOR;
this._pressedButtonColor = pressedButtonColor
if (pressedButtonColor == null)
this._pressedButtonColor = DEFAULT_PRESSED_BUTTON_COLOR;
this._textColor = textColor;
if (textColor == null)
this._textColor = DEFAULT_TEXT_COLOR;
this._font = font;
if (font == null)
this._font = DEFAULT_FONT;
this._isBetweenPressAndRelease = false;
this._mouseIsOverButton = false;
this.actor = new Shell.ButtonBox({ reactive: true,
corner_radius: 5,
padding_left: SIDE_PADDING,
padding_right: SIDE_PADDING,
orientation: Big.BoxOrientation.HORIZONTAL,
y_align: Big.BoxAlignment.CENTER
});
if (typeof widgetOrText == 'string') {
this._widget = new Clutter.Text({ font_name: this._font,
color: this._textColor,
text: widgetOrText });
} else {
this._widget = widgetOrText;
}
this.actor.append(this._widget, Big.BoxPackFlags.EXPAND);
this.actor.connect('notify::hover', Lang.bind(this, this._updateColors));
this.actor.connect('notify::pressed', Lang.bind(this, this._updateColors));
this.actor.connect('notify::active', Lang.bind(this, this._updateColors));
},
_updateColors : function() {
if (this.actor.active || this.actor.pressed)
this.actor.backgroundColor = this._pressedButtonColor;
else if (this.actor.hover)
this.actor.backgroundColor = this._buttonColor;
else
this.actor.backgroundColor = null;
}
};
Signals.addSignalMethods(Button.prototype);
/* 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)
*/
function IconButton(parent, size, texture) {
this._init(parent, size, texture);
}
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(event.get_related()) != -1)
return;
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(event.get_related()) != -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() {
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" });
}
};

View File

@ -16,7 +16,6 @@ const AppDisplay = imports.ui.appDisplay;
const DocDisplay = imports.ui.docDisplay; const DocDisplay = imports.ui.docDisplay;
const PlaceDisplay = imports.ui.placeDisplay; const PlaceDisplay = imports.ui.placeDisplay;
const GenericDisplay = imports.ui.genericDisplay; const GenericDisplay = imports.ui.genericDisplay;
const Button = imports.ui.button;
const Main = imports.ui.main; const Main = imports.ui.main;
const DEFAULT_PADDING = 4; const DEFAULT_PADDING = 4;

View File

@ -13,7 +13,6 @@ const Signals = imports.signals;
const Gettext = imports.gettext.domain('gnome-shell'); const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext; const _ = Gettext.gettext;
const Button = imports.ui.button;
const Calendar = imports.ui.calendar; const Calendar = imports.ui.calendar;
const Main = imports.ui.main; const Main = imports.ui.main;
const StatusMenu = imports.ui.statusMenu; const StatusMenu = imports.ui.statusMenu;
@ -274,11 +273,12 @@ Panel.prototype = {
/* Button on the left side of the panel. */ /* Button on the left side of the panel. */
/* Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". */ /* Translators: If there is no suitable word for "Activities" in your language, you can use the word for "Overview". */
this.button = new Button.Button(_("Activities"), PANEL_BUTTON_COLOR, PRESSED_BUTTON_BACKGROUND_COLOR, let label = new St.Label({ text: _("Activities") });
PANEL_FOREGROUND_COLOR, DEFAULT_FONT); this.button = new St.Clickable({ name: 'panelActivities' });
this.button.actor.height = PANEL_HEIGHT; this.button.set_child(label);
this.button.height = PANEL_HEIGHT;
this._leftBox.append(this.button.actor, Big.BoxPackFlags.NONE); this._leftBox.append(this.button, Big.BoxPackFlags.NONE);
// We use this flag to mark the case where the user has entered the // We use this flag to mark the case where the user has entered the
// hot corner and has not left both the hot corner and a surrounding // hot corner and has not left both the hot corner and a surrounding
@ -402,8 +402,9 @@ Panel.prototype = {
// We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably // We get into the Overview mode on button-press-event as opposed to button-release-event because eventually we'll probably
// have the Overview act like a menu that allows the user to release the mouse on the activity the user wants // have the Overview act like a menu that allows the user to release the mouse on the activity the user wants
// to switch to. // to switch to.
this.button.actor.connect('button-press-event', Lang.bind(this, function(b, e) { this.button.connect('clicked', Lang.bind(this, function(b) {
if (e.get_button() == 1 && e.get_click_count() == 1 && !Main.overview.animationInProgress) { let event = Clutter.get_current_event();
if (!Main.overview.animationInProgress) {
this._maybeToggleOverviewOnClick(); this._maybeToggleOverviewOnClick();
return true; return true;
} else { } else {
@ -414,10 +415,10 @@ Panel.prototype = {
// pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered // pressing the System key, Alt+F1 or Esc. We want the button to be pressed in when the Overview is entered
// and to be released when it is exited regardless of how it was triggered. // and to be released when it is exited regardless of how it was triggered.
Main.overview.connect('showing', Lang.bind(this, function() { Main.overview.connect('showing', Lang.bind(this, function() {
this.button.actor.active = true; this.button.active = true;
})); }));
Main.overview.connect('hiding', Lang.bind(this, function() { Main.overview.connect('hiding', Lang.bind(this, function() {
this.button.actor.active = false; this.button.active = false;
})); }));
Main.chrome.addActor(this.actor, { visibleInOverview: true }); Main.chrome.addActor(this.actor, { visibleInOverview: true });

View File

@ -63,8 +63,6 @@ libgnome_shell_la_SOURCES = \
shell-app-usage.h \ shell-app-usage.h \
shell-arrow.c \ shell-arrow.c \
shell-arrow.h \ shell-arrow.h \
shell-button-box.c \
shell-button-box.h \
shell-drawing.c \ shell-drawing.c \
shell-drawing.h \ shell-drawing.h \
shell-embedded-window.c \ shell-embedded-window.c \

View File

@ -1,317 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* SECTION:shell-button-box
* @short_description: A box with properties useful for implementing buttons
*
* A #BigBox subclass which translates lower-level Clutter button events
* into higher level properties which are useful for implementing "button-like"
* actors.
*/
#include "shell-button-box.h"
G_DEFINE_TYPE(ShellButtonBox, shell_button_box, BIG_TYPE_BOX);
struct _ShellButtonBoxPrivate {
gboolean active;
gboolean held;
gboolean hover;
gboolean pressed;
};
/* Signals */
enum
{
ACTIVATE,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_ACTIVE,
PROP_HOVER,
PROP_PRESSED,
};
static guint shell_button_box_signals [LAST_SIGNAL] = { 0 };
static void
set_active (ShellButtonBox *box,
gboolean active)
{
if (box->priv->active == active)
return;
box->priv->active = active;
g_object_notify (G_OBJECT (box), "active");
}
static void
set_hover (ShellButtonBox *box,
gboolean hover)
{
if (box->priv->hover == hover)
return;
box->priv->hover = hover;
g_object_notify (G_OBJECT (box), "hover");
}
static void
set_pressed (ShellButtonBox *box,
gboolean pressed)
{
if (box->priv->pressed == pressed)
return;
box->priv->pressed = pressed;
g_object_notify (G_OBJECT (box), "pressed");
}
static gboolean
shell_button_box_contains (ShellButtonBox *box,
ClutterActor *actor)
{
while (actor != NULL && actor != (ClutterActor*)box)
{
actor = clutter_actor_get_parent (actor);
}
return actor != NULL;
}
static gboolean
shell_button_box_enter_event (ClutterActor *actor,
ClutterCrossingEvent *event)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (shell_button_box_contains (box, event->related))
return TRUE;
if (!shell_button_box_contains (box, event->source))
return TRUE;
g_object_freeze_notify (G_OBJECT (actor));
if (box->priv->held)
set_pressed (box, TRUE);
set_hover (box, TRUE);
g_object_thaw_notify (G_OBJECT (actor));
return TRUE;
}
static gboolean
shell_button_box_leave_event (ClutterActor *actor,
ClutterCrossingEvent *event)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (shell_button_box_contains (box, event->related))
return TRUE;
set_hover (box, FALSE);
set_pressed (box, FALSE);
return TRUE;
}
static gboolean
shell_button_box_button_press_event (ClutterActor *actor,
ClutterButtonEvent *event)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (event->button != 1 || event->click_count != 1)
return FALSE;
if (box->priv->held)
return TRUE;
if (!shell_button_box_contains (box, event->source))
return FALSE;
box->priv->held = TRUE;
clutter_grab_pointer (CLUTTER_ACTOR (box));
set_pressed (box, TRUE);
return TRUE;
}
static gboolean
shell_button_box_button_release_event (ClutterActor *actor,
ClutterButtonEvent *event)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (actor);
if (event->button != 1 || event->click_count != 1)
return FALSE;
if (!box->priv->held)
return TRUE;
box->priv->held = FALSE;
clutter_ungrab_pointer ();
if (!shell_button_box_contains (box, event->source))
return FALSE;
set_pressed (box, FALSE);
g_signal_emit (G_OBJECT (box), shell_button_box_signals[ACTIVATE], 0, event);
return TRUE;
}
/**
* shell_button_box_fake_release:
* @box:
*
* If this button box is holding a pointer grab, this function will
* will ungrab it, and reset the pressed state. The effect is
* similar to if the user had released the mouse button, but without
* emitting the activate signal.
*
* This function is useful if for example you want to do something after the user
* is holding the mouse button for a given period of time, breaking the
* grab.
*/
void
shell_button_box_fake_release (ShellButtonBox *box)
{
if (!box->priv->held)
return;
box->priv->held = FALSE;
clutter_ungrab_pointer ();
set_pressed (box, FALSE);
}
static void
shell_button_box_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (object);
switch (prop_id)
{
case PROP_ACTIVE:
set_active (box, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
shell_button_box_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
ShellButtonBox *box = SHELL_BUTTON_BOX (object);
switch (prop_id)
{
case PROP_ACTIVE:
g_value_set_boolean (value, box->priv->active);
break;
case PROP_PRESSED:
g_value_set_boolean (value, box->priv->pressed);
break;
case PROP_HOVER:
g_value_set_boolean (value, box->priv->hover);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
shell_button_box_class_init (ShellButtonBoxClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
gobject_class->get_property = shell_button_box_get_property;
gobject_class->set_property = shell_button_box_set_property;
actor_class->enter_event = shell_button_box_enter_event;
actor_class->leave_event = shell_button_box_leave_event;
actor_class->button_press_event = shell_button_box_button_press_event;
actor_class->button_release_event = shell_button_box_button_release_event;
/**
* ShellButtonBox::activate
* @box: The #ShellButtonBox
* @event: Release event which triggered the activation
*
* This signal is emitted when the button should take the action
* associated with button click+release.
*/
shell_button_box_signals[ACTIVATE] =
g_signal_new ("activate",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 1, CLUTTER_TYPE_EVENT);
/**
* ShellButtonBox:active
*
* The property allows the button to be used as a "toggle button"; it's up to the
* application to update the active property in response to the activate signal;
* it doesn't happen automatically.
*/
g_object_class_install_property (gobject_class,
PROP_ACTIVE,
g_param_spec_boolean ("active",
"Active",
"Whether the button persistently active",
FALSE,
G_PARAM_READWRITE));
/**
* ShellButtonBox:hover
*
* This property tracks whether the mouse is over the button; note this
* state is independent of whether the button is pressed.
*/
g_object_class_install_property (gobject_class,
PROP_HOVER,
g_param_spec_boolean ("hover",
"Hovering state",
"Whether the mouse is over the button",
FALSE,
G_PARAM_READABLE));
/**
* ShellButtonBox:pressed
*
* This property tracks whether the button should have a "pressed in"
* effect.
*/
g_object_class_install_property (gobject_class,
PROP_PRESSED,
g_param_spec_boolean ("pressed",
"Pressed state",
"Whether the button is currently pressed",
FALSE,
G_PARAM_READABLE));
g_type_class_add_private (gobject_class, sizeof (ShellButtonBoxPrivate));
}
static void
shell_button_box_init (ShellButtonBox *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, SHELL_TYPE_BUTTON_BOX,
ShellButtonBoxPrivate);
}

View File

@ -1,36 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef __SHELL_BUTTON_BOX_H__
#define __SHELL_BUTTON_BOX_H__
#include <clutter/clutter.h>
#include "big/box.h"
#define SHELL_TYPE_BUTTON_BOX (shell_button_box_get_type ())
#define SHELL_BUTTON_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SHELL_TYPE_BUTTON_BOX, ShellButtonBox))
#define SHELL_BUTTON_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SHELL_TYPE_BUTTON_BOX, ShellButtonBoxClass))
#define SHELL_IS_BUTTON_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SHELL_TYPE_BUTTON_BOX))
#define SHELL_IS_BUTTON_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SHELL_TYPE_BUTTON_BOX))
#define SHELL_BUTTON_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SHELL_TYPE_BUTTON_BOX, ShellButtonBoxClass))
typedef struct _ShellButtonBox ShellButtonBox;
typedef struct _ShellButtonBoxClass ShellButtonBoxClass;
typedef struct _ShellButtonBoxPrivate ShellButtonBoxPrivate;
struct _ShellButtonBox
{
BigBox parent;
ShellButtonBoxPrivate *priv;
};
struct _ShellButtonBoxClass
{
BigBoxClass parent_class;
};
GType shell_button_box_get_type (void) G_GNUC_CONST;
void shell_button_box_fake_release (ShellButtonBox *box);
#endif /* __SHELL_BUTTON_BOX_H__ */