Traduzca

Translate to EnglishÜbersetzen Sie zum Deutsch/GermanΜεταφράστε στα ελληνικά/GreekПереведите к русскому/RussianOversetter til Norsk/NorwegianÖversätta till Svensk/Swedishहिनà¥à¤¦à¥€ अनà¥à¤µà¤¾à¤¦ करने के लिà¤/Hindi
Tradueix al català/CatalanTulkot uz latviešu/LatvianPreložiť do slovenčiny/SlovakVertaal aan het Nederlands/Dutchترجمة الى العربية/ArabicTraduzca al Español/SpanishTraduisez au Français/French
Traduca ad Italiano/ItalianTraduza ao Português/Portuguese日本語に翻訳しなさい /Japanese한국어에게 번역하십시오/Korean中文翻译/Chinese Simplified中文翻译/Chinese TraditionalПереклад на українську/Ukrainian
Imagen del desarrollo del núcleo del linux (3ro edición)
La imagen de RHCE Red Hat certificó la guía del estudio del linux del ingeniero (examen RH302) (la prensa de la certificación)
Imagen de los conceptos del sistema operativo
Imagen de XSLT 2.0 y de la referencia de programador de XPath 2.0 (programador al programador)

Cambio del botón de las actividades en el GNOMO Shell 3.2

En la versión original del GNOMO Shell (3.0) era muy fácil alterar el texto de las actividades abotona o agrega un icono por medio de una extensión simple de Shell del GNOMO.

Por ejemplo, aquí está el código para una extensión simple de Shell del GNOMO que publiqué poco después del lanzamiento del GNOMO 3.0 que permite a un usuario hacer apenas eso.

const St = imports.gi.St;
const Main = imports.ui.main;
const Panel = imports.ui.panel;

const Gettext = imports.gettext.domain('gnome-shell');
const _ = Gettext.gettext;

function main() {

   let hotCornerButton = Main.panel.button;

   let box = new St.BoxLayout({ style_class: 'activities_box'});

   // change the text string if you want to display different text
   // for the activities button
   let label = new St.Label({ text: _("Activities"),
                              style_class: 'activities_text' });

   // change the icon_name if you want to display a different icon
   // the icon must exist in the appropriate directory
   let logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
                            icon_size: hotCornerButton.height,
                            icon_name: 'fedora-logo-icon' });

   // comment out this line if you do not want an icon displayed
   box.add_actor(logo);

   // comment out this line if you do not want the label displayed
   box.add_actor(label);

   Main.panel.button.set_child(box);
}


Esta extensión de Shell del GNOMO se podría modificar para requisitos particulares fácilmente para exhibir o un icono, una secuencia de texto o ambas para las actividades abotonan. Todo lo que usted tuvo que hacer era comentar u o uncomment las líneas apropiadas en el código fuente.

Con el lanzamiento del GNOMO 3.2, que el GNOMO incluido Shell 3.2, en septiembre de 2011, el código antedicho trabaja no más. La vida llegó a ser mucho más complicada para los reveladores de la extensión de Shell del GNOMO debido a nuevos requisitos de apoyar tres funciones: el init, permite e inhabilita al cifrar una nueva extensión de Shell del GNOMO o aumentando una extensión existente al GNOMO Shell 3.2 de la ayuda. Vea este poste, que escribí hace uces par de meses, para una descripción detallada de los cambios a la infraestructura de la extensión de Shell del GNOMO.

Además, el código del Javascript referente a las actividades abotona cambiado perceptiblemente entre el GNOMO Shell 3.0 y 3.2. Aquí está el código relevante de /usr/share/gnome-shell/js/ui/panel.js con los comentarios quitados para reducir el número de líneas.

function ActivitiesButton() {
    this._init.apply(this, arguments);
}

ActivitiesButton.prototype = {
    __proto__: PanelMenu.Button.prototype,

    _init: function() {
        PanelMenu.Button.prototype._init.call(this, 0.0);

        let container = new Shell.GenericContainer();
        container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
        container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
        container.connect('allocate', Lang.bind(this, this._containerAllocate));
        this.actor.add_actor(container);
        this.actor.name = 'panelActivities';

        this._label = new St.Label({ text: _("Activities") });
        container.add_actor(this._label);

        this._hotCorner = new Layout.HotCorner();
        container.add_actor(this._hotCorner.actor);

        this.menu.open = Lang.bind(this, this._onMenuOpenRequest);
        this.menu.close = Lang.bind(this, this._onMenuCloseRequest);
        this.menu.toggle = Lang.bind(this, this._onMenuToggleRequest);

        this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
        this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
        this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));

        Main.overview.connect('showing', Lang.bind(this, function() {
            this.actor.add_style_pseudo_class('overview');
            this._escapeMenuGrab();
        }));
        Main.overview.connect('hiding', Lang.bind(this, function() {
            this.actor.remove_style_pseudo_class('overview');
            this._escapeMenuGrab();
        }));

        this._xdndTimeOut = 0;
    },
    _containerGetPreferredWidth: function(actor, forHeight, alloc) {
        [alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight);
    },

    _containerGetPreferredHeight: function(actor, forWidth, alloc) {
        [alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth);
    },

    _containerAllocate: function(actor, box, flags) {
        this._label.allocate(box, flags);

        let primary = Main.layoutManager.primaryMonitor;
        let hotBox = new Clutter.ActorBox();
        let ok, x, y;
        if (actor.get_direction() == St.TextDirection.LTR) {
            [ok, x, y] = actor.transform_stage_point(primary.x, primary.y)
        } else {
            [ok, x, y] = actor.transform_stage_point(primary.x + primary.width, primary.y);
        }

        hotBox.x1 = Math.round(x);
        hotBox.x2 = hotBox.x1 + this._hotCorner.actor.width;
        hotBox.y1 = Math.round(y);
        hotBox.y2 = hotBox.y1 + this._hotCorner.actor.height;
        this._hotCorner.actor.allocate(hotBox, flags);
    },


Observe el uso de Shell.GenericContainer y de sus tratantes asociados de la señal. Volveré a discutir este objeto y éstos señalan a tratantes más adelante en el poste.

El resto de este poste describe por medio de un número de ejemplos cómo modificar el código antedicho vía una extensión de Shell del GNOMO para cambiar la etiqueta (del texto) exhibida, exhibir un icono en vez de una etiqueta o exhibir un icono y una etiqueta simultáneamente. Este poste asume que usted es familiar con el desarrollo de extensión de Shell del GNOMO; no intenta explicar los fundamentos de escribir una extensión.

Ejemplo 1:

Esta extensión de Shell del GNOMO exhibe simplemente una etiqueta alternativa para las actividades abotona cuando está permitida e invierte de nuevo a la etiqueta original, es decir actividades, cuando está inhabilitada. La ayuda de la localización para la etiqueta alternativa no es incluida sino puede ser agregada fácilmente.

const Main = imports.ui.main;

// Replace this string constant with your text
const ACTIVITIES_BUTTON_TEXT = "Change Me";

function ChangeActivitiesButtonText() {
    this._init();
}

ChangeActivitiesButtonText.prototype = {

    _init: function() {
        this._label = Main.panel._activitiesButton._label;
        this._originalText = this._label.get_text();
    },

    enable: function() {
        this._label.set_text(ACTIVITIES_BUTTON_TEXT);
    },

    disable: function() {
        this._label.set_text(this._originalText);
    }
};

function init(extensionMeta) {
    return new ChangeActivitiesButtonText();
}


Como usted puede ver, el código para esta extensión de Shell del GNOMO sigue siendo bastante simple. Cuando la extensión está instalada, se invoca el _init. Cuando se permite la extensión, permita se invoca y la etiqueta en el botón de las actividades se cambia al contenido del constante de ACTIVITIES_BUTTON_TEXT. Cuando la extensión es lisiada, se exhibe la etiqueta original, es decir actividades.

Alguna gente prefiere la manera de escritura no-prototípica una extensión de Shell del GNOMO. Si usted es uno de esa gente, aquí es lo que parece esta extensión cuando está escrito para proporcionar las tres funciones obligatorias:

const Main = imports.ui.main;

// Replace this string constant with your text
const ACTIVITIES_BUTTON_TEXT = "Change Me";

let _label;
let _originalText;

function init() {
    _label = Main.panel._activitiesButton._label;
    _originalText = _label.get_text();
}

function enable() {
    _label.set_text(ACTIVITIES_BUTTON_TEXT);
}

function disable() {
    _label.set_text(this._originalText);
}

Ejemplo 2:

Las cosas consiguen más complicadas cuando usted quiere agregar un icono al botón de las actividades o substituir el texto por un icono. Esto es debido al hecho el código para ejecutar las actividades que el botón fue cambiado en el GNOMO Shell 3.2 para utilizar un objeto de Shell GenericContainer. Aquí está el código fuente de C para este objeto.

/**
 * SECTION:shell-generic-container
 * @short_description: A container class with signals for allocation
 *
 * #ShellGenericContainer is mainly a workaround for the current
 * lack of GObject subclassing + vfunc overrides in gjs.  We
 * implement the container interface, but proxy the virtual functions
 * into signals, which gjs can catch.
 *
 * #ShellGenericContainer is an #StWidget, and automatically takes its
 * borders and padding into account during size request and allocation.
 */

#include "config.h"

#include "shell-generic-container.h"

#include <clutter/clutter.h>
#include <gtk/gtk.h>
#include <girepository.h>

static void shell_generic_container_iface_init (ClutterContainerIface *iface);

G_DEFINE_TYPE_WITH_CODE(ShellGenericContainer,
                        shell_generic_container,
                        ST_TYPE_CONTAINER,
                        G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
                                               shell_generic_container_iface_init));

struct _ShellGenericContainerPrivate {
  GHashTable *skip_paint;
};

/* Signals */
enum
{
  GET_PREFERRED_WIDTH,
  GET_PREFERRED_HEIGHT,
  ALLOCATE,
  LAST_SIGNAL
};

static guint shell_generic_container_signals [LAST_SIGNAL] = { 0 };

static gpointer
shell_generic_container_allocation_ref (ShellGenericContainerAllocation *alloc)
{
  alloc->_refcount++;
  return alloc;
}

static void
shell_generic_container_allocation_unref (ShellGenericContainerAllocation *alloc)
{
  if (--alloc->_refcount == 0)
    g_slice_free (ShellGenericContainerAllocation, alloc);
}

static void
shell_generic_container_allocate (ClutterActor           *self,
                                  const ClutterActorBox  *box,
                                  ClutterAllocationFlags  flags)
{
  StThemeNode *theme_node;
  ClutterActorBox content_box;

  CLUTTER_ACTOR_CLASS (shell_generic_container_parent_class)->allocate (self, box, flags);

  theme_node = st_widget_get_theme_node (ST_WIDGET (self));
  st_theme_node_get_content_box (theme_node, box, &content_box);

  g_signal_emit (G_OBJECT (self), shell_generic_container_signals[ALLOCATE], 0,
                 &content_box, flags);
}

static void
shell_generic_container_get_preferred_width (ClutterActor *actor,
                                             gfloat        for_height,
                                             gfloat       *min_width_p,
                                             gfloat       *natural_width_p)
{
  ShellGenericContainerAllocation *alloc = g_slice_new0 (ShellGenericContainerAllocation);
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));

  st_theme_node_adjust_for_height (theme_node, &for_height);

  alloc->_refcount = 1;
  g_signal_emit (G_OBJECT (actor), shell_generic_container_signals[GET_PREFERRED_WIDTH], 0,
                 for_height, alloc);
  if (min_width_p)
    *min_width_p = alloc->min_size;
  if (natural_width_p)
    *natural_width_p = alloc->natural_size;
  shell_generic_container_allocation_unref (alloc);

  st_theme_node_adjust_preferred_width (theme_node, min_width_p, natural_width_p);
}

static void
shell_generic_container_get_preferred_height (ClutterActor *actor,
                                              gfloat        for_width,
                                              gfloat       *min_height_p,
                                              gfloat       *natural_height_p)
{
  ShellGenericContainerAllocation *alloc = g_slice_new0 (ShellGenericContainerAllocation);
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));

  st_theme_node_adjust_for_width (theme_node, &for_width);

  alloc->_refcount = 1;
  g_signal_emit (G_OBJECT (actor), shell_generic_container_signals[GET_PREFERRED_HEIGHT], 0,
                 for_width, alloc);
  if (min_height_p)
    *min_height_p = alloc->min_size;
  if (natural_height_p)
    *natural_height_p = alloc->natural_size;
  shell_generic_container_allocation_unref (alloc);

  st_theme_node_adjust_preferred_height (theme_node, min_height_p, natural_height_p);
}

static void
shell_generic_container_paint (ClutterActor  *actor)
{
  ShellGenericContainer *self = (ShellGenericContainer*) actor;
  GList *iter, *children;

  CLUTTER_ACTOR_CLASS (shell_generic_container_parent_class)->paint (actor);

  children = st_container_get_children_list (ST_CONTAINER (actor));
  for (iter = children; iter; iter = iter->next)
    {
      ClutterActor *child = iter->data;

      if (g_hash_table_lookup (self->priv->skip_paint, child))
        continue;

      clutter_actor_paint (child);
    }
}

static void
shell_generic_container_pick (ClutterActor        *actor,
                              const ClutterColor  *color)
{
  ShellGenericContainer *self = (ShellGenericContainer*) actor;
  GList *iter, *children;

  CLUTTER_ACTOR_CLASS (shell_generic_container_parent_class)->pick (actor, color);

  children = st_container_get_children_list (ST_CONTAINER (actor));
  for (iter = children; iter; iter = iter->next)
    {
      ClutterActor *child = iter->data;

      if (g_hash_table_lookup (self->priv->skip_paint, child))
        continue;

      clutter_actor_paint (child);
    }
}

static GList *
shell_generic_container_get_focus_chain (StContainer *container)
{
  ShellGenericContainer *self = SHELL_GENERIC_CONTAINER (container);
  GList *children, *focus_chain;

  focus_chain = NULL;
  for (children = st_container_get_children_list (container); children; children = children->next)
    {
      ClutterActor *child = children->data;

      if (CLUTTER_ACTOR_IS_VISIBLE (child) &&
          !shell_generic_container_get_skip_paint (self, child))
        focus_chain = g_list_prepend (focus_chain, child);
    }

  return g_list_reverse (focus_chain);
}

/**
 * shell_generic_container_get_n_skip_paint:
 * @self:  A #ShellGenericContainer
 *
 * Returns: Number of children which will not be painted.
 */
guint
shell_generic_container_get_n_skip_paint (ShellGenericContainer  *self)
{
  return g_hash_table_size (self->priv->skip_paint);
}

/**
 * shell_generic_container_get_skip_paint:
 * @self: A #ShellGenericContainer
 * @child: Child #ClutterActor
 *
 * Gets whether or not @actor is skipped when painting.
 *
 * Return value: %TRUE or %FALSE
 */
gboolean
shell_generic_container_get_skip_paint (ShellGenericContainer  *self,
                                        ClutterActor           *child)
{
  return g_hash_table_lookup (self->priv->skip_paint, child) != NULL;
}

/**
 * shell_generic_container_set_skip_paint:
 * @self: A #ShellGenericContainer
 * @child: Child #ClutterActor
 * @skip: %TRUE if we should skip painting
 *
 * Set whether or not we should skip painting @actor.  Workaround for
 * lack of gjs ability to override _paint vfunc.
 */
void
shell_generic_container_set_skip_paint (ShellGenericContainer  *self,
                                        ClutterActor           *child,
                                        gboolean                skip)
{
  gboolean currently_skipping;

  currently_skipping = g_hash_table_lookup (self->priv->skip_paint, child) != NULL;
  if (!!skip == currently_skipping)
    return;

  if (!skip)
    g_hash_table_remove (self->priv->skip_paint, child);
  else
    g_hash_table_insert (self->priv->skip_paint, child, child);

  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}

static void
shell_generic_container_finalize (GObject *object)
{
  ShellGenericContainer *self = (ShellGenericContainer*) object;

  g_hash_table_destroy (self->priv->skip_paint);

  G_OBJECT_CLASS (shell_generic_container_parent_class)->finalize (object);
}

static void
shell_generic_container_class_init (ShellGenericContainerClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
  StContainerClass *container_class = ST_CONTAINER_CLASS (klass);

  gobject_class->finalize = shell_generic_container_finalize;

  actor_class->get_preferred_width = shell_generic_container_get_preferred_width;
  actor_class->get_preferred_height = shell_generic_container_get_preferred_height;
  actor_class->allocate = shell_generic_container_allocate;
  actor_class->paint = shell_generic_container_paint;
  actor_class->pick = shell_generic_container_pick;

  container_class->get_focus_chain = shell_generic_container_get_focus_chain;

  /**
   * ShellGenericContainer::get-preferred-width:
   * @self: the #ShellGenericContainer
   * @for_height: as in clutter_actor_get_preferred_width()
   * @alloc: a #ShellGenericContainerAllocation to be filled in
   *
   * Emitted when clutter_actor_get_preferred_width() is called
   * on @self. You should fill in the fields of @alloc with the
   * your minimum and natural widths. #ShellGenericContainer
   * will deal with taking its borders and padding into account
   * for you.
   *
   * @alloc's fields are initialized to 0, so unless you have a fixed
   * width specified (via #ClutterActor:width or CSS), you must
   * connect to this signal and fill in the values.
   */
  shell_generic_container_signals[GET_PREFERRED_WIDTH] =
    g_signal_new ("get-preferred-width",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  gi_cclosure_marshal_generic,
                  G_TYPE_NONE, 2, G_TYPE_FLOAT, SHELL_TYPE_GENERIC_CONTAINER_ALLOCATION);

  /**
   * ShellGenericContainer::get-preferred-height:
   * @self: the #ShellGenericContainer
   * @for_width: as in clutter_actor_get_preferred_height()
   * @alloc: a #ShellGenericContainerAllocation to be filled in
   *
   * Emitted when clutter_actor_get_preferred_height() is called
   * on @self. You should fill in the fields of @alloc with the
   * your minimum and natural heights. #ShellGenericContainer
   * will deal with taking its borders and padding into account
   * for you.
   *
   * @alloc's fields are initialized to 0, so unless you have a fixed
   * height specified (via #ClutterActor:height or CSS), you must
   * connect to this signal and fill in the values.
   */
  shell_generic_container_signals[GET_PREFERRED_HEIGHT] =
    g_signal_new ("get-preferred-height",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  gi_cclosure_marshal_generic,
                  G_TYPE_NONE, 2, G_TYPE_FLOAT, SHELL_TYPE_GENERIC_CONTAINER_ALLOCATION);

  /**
   * ShellGenericContainer::allocate:
   * @self: the #ShellGenericContainer
   * @box: @self's content box
   * @flags: the allocation flags.
   *
   * Emitted when @self is allocated, after chaining up to the parent
   * allocate method.
   *
   * Note that @box is @self's content box (qv
   * st_theme_node_get_content_box()), NOT its allocation.
   */
  shell_generic_container_signals[ALLOCATE] =
    g_signal_new ("allocate",
                  G_TYPE_FROM_CLASS (klass),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  gi_cclosure_marshal_generic,
                  G_TYPE_NONE, 2, CLUTTER_TYPE_ACTOR_BOX, CLUTTER_TYPE_ALLOCATION_FLAGS);

  g_type_class_add_private (gobject_class, sizeof (ShellGenericContainerPrivate));
}

static void
shell_generic_container_actor_removed (ClutterContainer *container,
                                       ClutterActor     *actor)
{
  ShellGenericContainerPrivate *priv = SHELL_GENERIC_CONTAINER (container)->priv;

  g_hash_table_remove (priv->skip_paint, actor);
}

static void
shell_generic_container_iface_init (ClutterContainerIface *iface)
{
  iface->actor_removed = shell_generic_container_actor_removed;
}

static void
shell_generic_container_init (ShellGenericContainer *area)
{
  area->priv = G_TYPE_INSTANCE_GET_PRIVATE (area, SHELL_TYPE_GENERIC_CONTAINER,
                                            ShellGenericContainerPrivate);
  area->priv->skip_paint = g_hash_table_new (NULL, NULL);
}

GType
shell_generic_container_allocation_get_type (void)
{
  static GType gtype = G_TYPE_INVALID;
  if (gtype == G_TYPE_INVALID)
    {
      gtype = g_boxed_type_register_static ("ShellGenericContainerAllocation",
         (GBoxedCopyFunc)shell_generic_container_allocation_ref,
         (GBoxedFreeFunc)shell_generic_container_allocation_unref);
    }
  return gtype;
}

Una forma a trabajar alrededor de la edición de Shell GenericContainer es utilizar el CSS al restyle que las actividades abotonan para exhibir un icono en vez de la etiqueta del defecto como se muestra abajo:

const St = imports.gi.St;
const Shell = imports.gi.Shell;
const Main = imports.ui.main;

function ThemeActivitiesButton(meta) {
    this._init(meta)
}

ThemeActivitiesButton.prototype = {
    _init: function(meta) {
        this._defaultStylesheet = Main._defaultCssStylesheet;
        this._patchStylesheet = meta.path + '/activitiesbutton.css';
        this._themeContext = St.ThemeContext.get_for_stage(global.stage);
    },

    enable: function() {
        let theme = new St.Theme ({ application_stylesheet: this._patchStylesheet,
                                    theme_stylesheet: this._defaultStylesheet });
        try {
            this._themeContext.set_theme(theme);
        } catch (e) {
            global.logError('Stylesheet parse error: ' + e);
        }
    },

    disable: function() {
        let theme = new St.Theme ({ theme_stylesheet: this._defaultStylesheet });
        try {
            this._themeContext.set_theme(theme);
        } catch (e) {
            global.logError('Stylesheet parse error: ' + e);
        }
    }

};

function init(meta) {
    return new ThemeActivitiesButton(meta);
}


Aquí es el stylesheet.css la correspondencia

/* activitiesbutton.png should be 24x24 PNG icon */

#panelActivities {
    border: none;
    background-image: url("activitiesbutton.png");
    background-position: 4 0;
    width: 24px;
    height: 24px;
    padding-left: 12px;
    padding-right: 0px;
    color: rgba(0,0,0,0.0);
    transition-duration: 100;
}

#panelActivities:hover {
    border-image: url("activitiesbutton-border.svg") 10 10 0 2;
}


Los problemas con este acercamiento son (1) usted no pueden exhibir el texto y un icono en las actividades abotona, y (2) allí es potencial para labrar del GNOMO Shell vencer confuso a los stylesheets múltiples en las extensiones múltiples de Shell del GNOMO. Esto es un problema sabido en el GNOMO Shell. Es algo que puede ocurrir fácilmente con las extensiones gravemente escritas de Shell que hacen asunciones injustificables sobre lo que él puede y no puede hacer.

El mejor acercamiento es entender cómo Shell GenericContainer trabaja. Probablemente la cosa más importante a entender sobre este objeto es que usted no puede asignar una altura o una anchura cuando usted está creando un caso de este objeto. En lugar usted tiene que utilizar tres señales separadas según las indicaciones del ejemplo siguiente:

// create the new shell generic container object
let container = new Shell.GenericContainer();

// set up the three signals
container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
container.connect('allocate', Lang.bind(this, this._containerAllocate));

// signal code
_containerGetPreferredWidth: function(actor, forHeight, alloc) {
    [alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight);
},

_containerGetPreferredHeight: function(actor, forWidth, alloc) {
    [alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth);
},

_containerAllocate: function(actor, box, flags) {
    this._label.allocate(box, flags);
    ....
},


Aquí está un extension.js completo que exhibe la insignia del proyecto de Fedora en las actividades abotona cuando está permitido. Todos los ejemplos restantes en este poste se basan en este código.

const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
const Layout = imports.ui.layout;
const PanelMenu = imports.ui.panelMenu;
const Main = imports.ui.main;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;

// ------------ change to suit -----------
const ACTIVITIES_BUTTON_ICON_SIZE    = 20;
const ACTIVITIES_BUTTON_ICON_NAME    = 'fedora-logo-icon';  

function ActivitiesButtonIcon() {
    this._init.apply(this, arguments);
}

// ----- most of this code came straight from panel.js
ActivitiesButtonIcon.prototype = {
    __proto__: PanelMenu.Button.prototype,

    _init: function() {
        PanelMenu.Button.prototype._init.call(this, 0.0);

        this.actor.name = 'panelActivities';

        let container = new Shell.GenericContainer();
        container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
        container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
        container.connect('allocate', Lang.bind(this, this._containerAllocate));
        this.actor.add_actor(container);

        // ---------------- icon code -----------------
        this._iconBox = new St.Bin({ width: ACTIVITIES_BUTTON_ICON_SIZE,
                                     height: ACTIVITIES_BUTTON_ICON_SIZE,
                                     x_fill: true,
                                     y_fill: true });
        this._logo = new St.Icon({ icon_type: St.IconType.FULLCOLOR,
                                   icon_size: ACTIVITIES_BUTTON_ICON_SIZE,
                                   icon_name: ACTIVITIES_BUTTON_ICON_NAME });
        this._iconBox.child = this._logo;
        container.add_actor(this._iconBox);

        this._hotCorner = new Layout.HotCorner();
        container.add_actor(this._hotCorner.actor);

        // Hack up our menu...
        this.menu.open = Lang.bind(this, this._onMenuOpenRequest);
        this.menu.close = Lang.bind(this, this._onMenuCloseRequest);
        this.menu.toggle = Lang.bind(this, this._onMenuToggleRequest);

        this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
        this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
        this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));

        Main.overview.connect('showing', Lang.bind(this, function() {
            this.actor.add_style_pseudo_class('overview');
            this._escapeMenuGrab();
        }));
        Main.overview.connect('hiding', Lang.bind(this, function() {
            this.actor.remove_style_pseudo_class('overview');
            this._escapeMenuGrab();
        }));

        this._xdndTimeOut = 0;
    },

    _containerGetPreferredWidth: function(actor, forHeight, alloc) {
        [alloc.min_size, alloc.natural_size] = this._iconBox.get_preferred_width(forHeight);
    },

    _containerGetPreferredHeight: function(actor, forWidth, alloc) {
        [alloc.min_size, alloc.natural_size] = this._iconBox.get_preferred_height(forWidth);
    },

    _containerAllocate: function(actor, box, flags) {
        this._iconBox.allocate(box, flags);

        let primary = Main.layoutManager.primaryMonitor;
        let hotBox = new Clutter.ActorBox();
        let ok, x, y;
        if (actor.get_direction() == St.TextDirection.LTR) {
            [ok, x, y] = actor.transform_stage_point(primary.x, primary.y)
        } else {
            [ok, x, y] = actor.transform_stage_point(primary.x + primary.width, primary.y);
        }

        hotBox.x1 = Math.round(x);
        hotBox.x2 = hotBox.x1 + this._hotCorner.actor.width;
        hotBox.y1 = Math.round(y);
        hotBox.y2 = hotBox.y1 + this._hotCorner.actor.height;
        this._hotCorner.actor.allocate(hotBox, flags);
    },

    handleDragOver: function(source, actor, x, y, time) {
        if (source != Main.xdndHandler)
            return;

        if (this._xdndTimeOut != 0)
            Mainloop.source_remove(this._xdndTimeOut);
        this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT,
                                                 Lang.bind(this, this._xdndShowOverview, actor));
    },

    _escapeMenuGrab: function() {
        if (this.menu.isOpen)
            this.menu.close();
    },

    _onCapturedEvent: function(actor, event) {
        if (event.type() == Clutter.EventType.BUTTON_PRESS) {
            if (!this._hotCorner.shouldToggleOverviewOnClick())
                return true;
        }
        return false;
    },

    _onMenuOpenRequest: function() {
        this.menu.isOpen = true;
        this.menu.emit('open-state-changed', true);
    },

    _onMenuCloseRequest: function() {
        this.menu.isOpen = false;
        this.menu.emit('open-state-changed', false);
    },

    _onMenuToggleRequest: function() {
        this.menu.isOpen = !this.menu.isOpen;
        this.menu.emit('open-state-changed', this.menu.isOpen);
    },

    _onButtonRelease: function() {
        if (this.menu.isOpen) {
            this.menu.close();
            Main.overview.toggle();
        }
    },

    _onKeyRelease: function(actor, event) {
        let symbol = event.get_key_symbol();
        if (symbol == Clutter.KEY_Return || symbol == Clutter.KEY_space) {
            if (this.menu.isOpen)
                this.menu.close();
            Main.overview.toggle();
        }
    },

    _xdndShowOverview: function(actor) {
        let [x, y, mask] = global.get_pointer();
        let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);

        if (pickedActor == this.actor) {
            if (!Main.overview.visible && !Main.overview.animationInProgress) {
                Main.overview.showTemporarily();
                Main.overview.beginItemDrag(actor);
            }
        }

        Mainloop.source_remove(this._xdndTimeOut);
        this._xdndTimeOut = 0;
    }

};

function ChangeActivitiesButton() {
    this._init();
}

ChangeActivitiesButton.prototype = {

    _init: function() {
        this._myActivitiesButton = new ActivitiesButtonIcon();
        this._orgActivitiesButton = Main.panel._activitiesButton;
    },

    enable: function() {
        Main.panel._leftBox.remove_actor(this._orgActivitiesButton.actor);
        Main.panel._leftBox.insert_actor(this._myActivitiesButton.actor, 0);
    },

    disable: function() {
        Main.panel._leftBox.remove_actor(this._myActivitiesButton.actor);
        Main.panel._leftBox.insert_actor(this._orgActivitiesButton.actor, 0);
    }
};

function init(extensionMeta) {
    return new ChangeActivitiesButton();
}


En el GNOMO Shell 3.0, habríamos podido utilizar el mono que remendaba para remendar el código del prototipo de ActivitiesButton en /usr/share/gnome-shell/js/ui/panel.js. Esto es no más posible en el GNOMO Shell 3.2 debido a un cambio en cuando se cargan y se permiten las extensiones de Shell del GNOMO. Por lo tanto la necesidad de proporcionar un prototipo completo de ActivitiesButton en la extensión.

Este código se puede utilizar para exhibir cualquier icono que esté disponible en los lugares generalmente en una plataforma del linux según lo especificado por la especificación del directorio bajo de XDG. Usted puede también poner un icono de encargo en $HOME/.icons y exhibido por la extensión de Shell del GNOMO. El ejemplo antedicho utiliza un SVG para el icono pero se aceptan otros tipos de archivo.

Ejemplo 3:

En este ejemplo, nuestra nueva extensión de Shell del GNOMO del ejemplo 2 se modifica para leer un archivo que contiene un icono y el icono contenido en esto se exhiba en el botón de las actividades.

const ACTIVITIES_BUTTON_ICON_FILENAME = 'activities_button_icon.svg';  

function ActivitiesButtonIcon() {
    this._init.apply(this, arguments);
}

// ----- most of this code came straight from panel.js
ActivitiesButtonIcon.prototype = {
    __proto__: PanelMenu.Button.prototype,

    _init: function(iconpath) {
        PanelMenu.Button.prototype._init.call(this, 0.0);

        this.actor.name = 'panelActivities';

        // ---------------- icon code -----------------
        let textureCache = St.TextureCache.get_default();
        this._iconActivitiesButton = textureCache.load_uri_async("file://" + iconpath + "/" + ACTIVITIES_BUTTON_ICON_FILENAME, -1, -1);

        this._iconBox = new St.Bin({ style_class: 'activities-button-icon',
                                     child: this._iconActivitiesButton });
        container.add_actor(this._iconBox);
        ....
    },

    _containerGetPreferredWidth: function(actor, forHeight, alloc) {
        [alloc.min_size, alloc.natural_size] = this._iconBox.get_preferred_width(forHeight);
    },

    _containerGetPreferredHeight: function(actor, forWidth, alloc) {
        [alloc.min_size, alloc.natural_size] = this._iconBox.get_preferred_height(forWidth);
    },

    _containerAllocate: function(actor, box, flags) {
        this._iconBox.allocate(box, flags);
        ...
    },

    ...
};

function init(extensionMeta) {
    return new ChangeActivitiesButton(extensionMeta.path);
}


En el ejemplo antedicho, el archivo del icono se debe situar en el mismo directorio que el código de extensión. Ciertos meta datos se pasan a una extensión de Shell del GNOMO cuando se carga. La trayectoria llena a donde se localiza el código de extensión es un componente de los meta datos disponibles. En el ejemplo antedicho, esta trayectoria se recupera usando extensionMeta.path.

Ejemplo 4:

En este ejemplo final, nuestra nueva extensión de Shell del GNOMO del ejemplo 2 se modifica para exhibir un icono y el texto.

Aquí están los cambios relevantes del código:

        // ---------------- icon and text code -----------------
        let textureCache = St.TextureCache.get_default();
        this._iconActivitiesButton = textureCache.load_uri_async("file://" + iconpath + "/" + ACTIVITIES_BUTTON_ICON_FILENAME, -1, -1);

        this._boxIconText = new St.BoxLayout({ vertical: false });
        this._boxIconText.add_actor( new St.Bin({ style_class: 'activities-button-icon',
                                                  child: this._iconActivitiesButton }));
        this._boxIconText.add_actor(new St.Label({ text: _("Activities"),
                                                   style_class: 'activities-button-text' }));
        container.add_actor(this._boxIconText);

    ....

    _containerGetPreferredWidth: function(actor, forHeight, alloc) {
        [alloc.min_size, alloc.natural_size] = this._boxIconText.get_preferred_width(forHeight);
    },

    _containerGetPreferredHeight: function(actor, forWidth, alloc) {
        [alloc.min_size, alloc.natural_size] = this._boxIconText.get_preferred_height(forWidth);
    },

    _containerAllocate: function(actor, box, flags) {
        this._boxIconText.allocate(box, flags);
    ...


La ayuda para un ruleset adicional del CSS, actividad-botón-texto, fue agregada para permitir que la etiqueta del botón de las actividades sea labrada.

.activities-button-text {
    font-style: italic;
    font-size: 75%;
}


Si usted examina el screenshot antedicho, usted verá que la etiqueta de las actividades está exhibida en una fuente puesta en letra itálica más pequeña. No hay razón que tal ayuda no se podría agregar a la extensión de Shell del GNOMO del ejemplo 1. Me iré que como ejercicio para que usted haga.

Bien, los ejemplos antedichos deben haber proveído de usted todo el conocimiento y habilidades necesarios para permitirle desarrollar su propia extensión de Shell del GNOMO 3.2 para modificar su botón de las actividades para requisitos particulares en cualquier manera de que usted tiene gusto. Todos los ejemplos antedichos se pueden transferir de mi Web page de las extensiones de Shell del GNOMO como extensiones de trabajo.

P.S. Sienta por favor libre de enviarme por correo electrónico con sus sugerencias de asuntos adicionales referente ampliar al GNOMO Shell que usted quisiera que escribiera alrededor.

1 comentario a cambiar el botón de las actividades en el GNOMO Shell 3.2

  • Awolf

    ¿instalé bien esto la manera que se recomienda im usando el ubuntu 11.10 donde estoy supuse para poner el icono quiero fijar mientras que las actividades abotonan? ¿Conozco im supuesto para cambiar el nombre de los iconos en el código de extensión pero qué sobre donde debe el icono ser? puedo fijar la localización del icono en
    const ACTIVITIES_BUTTON_ICON_NAME = sombrero de ala-insignia-icon' del `

    Picosegundo: No soy ninguÌn programador y no sé la codificación im que trabaja en ella uno mismo-que estudia realmente Thnx para ninguna ayuda

Deje una contestación