Cambiando la apariencia de GTK+ con CSS

Carlos Garnacho: “A partir de GTK+ 3.0, la vieja capa de theming va a ser reemplazada por una más moderna, potente e inmediata para el diseñador, y también más intuitiva para las masas.”

 

¿Qué hay de nuevo?

A partir de GTK+ 3.0, la vieja capa de theming va a ser reemplazada por una más moderna, potente e inmediata para el diseñador, y también más intuitiva para las masas.

Esta nueva infraestructura ha sido desarrollada en los últimos meses en una rama independiente de GTK+, aunque ya esta totalmente integrada en la rama master, introduciendo características que empiezan a ser habituales en los toolkit gráficos más modernos:

  • Mayor expresividad en un lenguaje que los diseñadores entienden. Si bien, no todo es modificable a través de CSS, la mayor parte de la información de estilo se puede expresar en este lenguaje, y posterga a los theming engines (y por tanto al trabajo de desarrolladores) a un rol secundario.
  • Mayor facilidad a los desarrolladores para replicar completamente el look de un elemento del interfaz de usuario. A la hora del renderizado, los widgets de GTK+ que usen el mismo conjunto de de clases de CSS tendrán la misma apariencia.
  • Es más, esta infraestructura puede ser usada fuera de GTK+, debido a que la búsqueda de estilo sucede sobre representaciones de un widget, que puede ser imitado sin siquiera tener una instancia de un GtkWidget.
  • Facilita incrustar un estilo propio. Ya sea una applicacion con una apariencia personalizada, o una librería de widgets ofreciendo un estilo por defecto para sus widgets, ahora es posible enganchar tu hoja de estilo en cualquier punto en la cascada.
  • Permite a los “theme engines” implementar animaciones implícitas. Los cambios de estado pueden ser completamente animados, por lo que el theme engine sólo necesita obtener el progreso para un estado determinado con el fin de modificar el resultado. Los widgets complejos también pueden animar diferentes regiones de forma independiente.

Selectores CSS en GTK+

Asumiendo que sabes ya algo de CSS, será rapido comprender los detalles. Asi es el selector universal en CSS:

    * {
    }

Este selector coincidiría con cualquier GtkWidget. Si quieres un selector que coincida con un tipo de widget determinado, necesitar especificar el nombre de su tipo:

    GtkButton {
    }

Este selector coincidiría con cualqiuer GtkButton, o cualquier widget derivado de el. Por supuesto también puedes poner un nombre al widget para que pueda aplicársele otro estilo:

    #some-widget-name,
    GtkLabel#title-label {
    }

Como ya se mencionó antes, los widgets tambien pueden usar determinadas clases de CSS para dar pistas acerca del estilo necesitado para un elemento que se pinta en pantalla. Los siguientes selectores coincidirían respectivamente con entradas de texto, botones, y los botones de un GtkSpinButton:

    .entry {
    }

    .button {
    }

    GtkSpinButton.button {
    }

Los widgets complejos pueden también asignar regiones a los elementos que se pintan, que se verían en el selector como identificadores en minusculas:

    GtkTreeView row {
    }

    GtkNotebook tab {
    }

Pero el widget puede también aportar información adicional a esas regiones, que pueden resolverse en CSS a través de la pseudo-clase :nth-child. De esta manera, el coloreado de filas pares/impares de un treeview podría hacerse con:

    GtkTreeView row:nth-child(even) {
    }

    GtkTreeView row:nth-child(odd) {
    }

Estas clases/regiones que un widget añade pueden ser completamente
arbitrarias, pero GTK+ provee de un conjunto de estas para que
puedan reutilizarse en diferentes widgets:
http://library.gnome.org/devel/gtk/2.91/GtkStyleContext.html#gtkstylecontext-classesEl estado de un widget puede también definirse como una pseudo-clase en CSS:

    /* Estos son equivalentes */
    .button:prelight,
    .button:hover {
    }

    .entry:focused {
    }

Y por supuesto, todo esto puede combinarse para formar selectores más complejos y específicos:

    GtkWindow > .entry:selected {
    }

    GtkTreeview column-header .button {
    }

    GtkWindow#my-window GtkCheckButton.check:prelight {
    }

Propiedades soportadas

GTK+ soporta actualmente un subconjunto de propiedades CSS:

  • background-color
  • background-image
  • color
  • border-color
  • border-image
  • border-radius
  • border-width
  • border-style
  • padding
  • margin
  • transition

Las propiedades “background-color”, “color” y “border-color” toman un color (ya sea simbólico, un nombre, cadenas hexadecimales o cadenas del tipo rgb()/rbga(), y cualquier combinación de estos mediante las funciones soportadas:

    * {
      background-color: red;
      border-color: shade (mix (rgb (34, 255, 120), #fff, 0.5), 0.9);
    }

    .entry:selected {
      color: darker (@selected_fg_color);
      background-color: lighter (rgba (50%, 32%, 35%, 0.9));
    }

De forma parecida a CSS3, la propiedad “background-image” puede usarse para especificar gradientes lineales o radiales como el fondo de un elemento:

    .button {
      background-image: -gtk-gradient (linear,
                                       left top,
       left bottom,
       from (@bg_color),
       color-stop (0.5, darker (@bg_color)),
       to (@bg_color));
    }

    .entry {
      background-image: -gtk-gradient (radial,
                                       0.5 0.5 0.2,
       0.6 0.6 1,
       from (@bg_color),
       to (shade (@bg_color, 0.9)));
    }

En estos gradientes, cualquier número de color-stop()s puede definirse, y cualquier definición de color puede usarse, como en las propiedades mencionadas anteriormente.Los bordes pueden modificarse a través de varias propiedades, el ancho del borde en sí esta definido por la propiedad “border-width”.

La propiedad “border-radius” especifica el radio en pixels para las esquinas de un marco que esté siendo pintado en pantalla. Normalmente, los GtkWidgets proveerán información acerca de cómo un marco conecta visualmente con otros elementos en la interfaz de usuario, de forma que las esquinas redondeadas sólo se aplican a las esquinas que no conectan con ningún elemento.

La propiedad “border-style” accepta los valores “none”, “solid”, “inset” y “outset”. “inset” y “outset” podrían típicamente usarse para hacer sencillas simulaciones pseudo-3D cuando un botón es pulsado:

    .button {
      border-style: outset;
    }

    .button:active {
      border-style: inset;
    }

También se ofrece soporte para animaciones implícitas, aunque de una forma distinta al CSS standard. En el CSS de GTK+, sólo la duración de la animación y la función de progreso pueden especificarse. Por ejemplo, de esta forma se puede decir a un botón que cambie de blanco a amarillo cuando el ratón pasa por encima:

    GtkButton {
      background-color: white;
    }

    GtkButton:hover {
      transition: 300ms ease-in-out;
      background-color: yellow;
    }

Poniendo esto en práctica

El GTK+ que puedes obtener por defecto tiene un aspecto conservativo, aburrido si quieres, tomemos una aplicación bien conocida de GNOME, gedit:

gedit styled with default GTK

Muy bien, ¿muy cuadrado para tu gusto? Intentemos arreglar eso, creamos un archivo ~/.config/gtk-3.0/gtk.css y escribimos:

  /* Hacer algunas cosas redondeadas */
  .notebook,
  .button,
  .entry {
    border-radius: 3;
    border-style: solid;
    border-width: 1;
  }

Ya empieza a tener mejor aspecto:used CSS to round some things

Ahora usemos algunos gradientes para dar un aspecto más suave:

  .menubar,
  .toolbar {
    border-width: 0;
    background-image: -gtk-gradient (linear,
                                     left top, left bottom,
                                     from (@bg_color),
                                     to (shade (@bg_color, 0.95)));
  }

  .button:hover,
  .menu:hover,
  .menubar:hover {
    background-image: -gtk-gradient (linear,
                                     left top, left bottom,
                                     from (shade (@selected_bg_color, 1.1)),
                                     color-stop (0.55, shade (@selected_bg_color, 1.0)),
                                     color-stop (0.55, shade (@selected_bg_color, 0.8)),
                                     to (shade (@selected_bg_color, 0.9)));
  }

Tiene mejor aspecto? Hmm, pero esas scrollbars son un poco feas todavia, hagamos algo al respecto:

  /* Gradiente para scrollbars verticales,
   * de izquierda a derecha
   */
  .slider.vertical {
    background-image: -gtk-gradient (linear,
                                     left top, right top,
                                     from (mix (shade (@bg_color, 0.9), @selected_bg_color, 0.3)),
                                     to (mix (@bg_color, @selected_bg_color, 0.3)));
  }

  .slider.vertical:hover {
    background-image: -gtk-gradient (linear,
                                     left top, right top,
                                     from (shade (@selected_bg_color, 0.9)),
                                     to (@selected_bg_color));
  }

  /* Ahora los scrollbars horizontales,
   * de arriba a abajo
   */
  .slider.horizontal {
    background-image: -gtk-gradient (linear,
                                     left top, left bottom,
                                     from (shade (@bg_color, 0.9)),
                                     to (@bg_color));
  }

  .slider.horizontal:hover {
    background-image: -gtk-gradient (linear,
                                     left top, left bottom,
                                     from (shade (@selected_bg_color, 0.9)),
                                     to (@selected_bg_color));
  }

  /* Un gradiente radial para la parte hundida */
  .trough {
    background-image: -gtk-gradient (radial,
                                     center center, 0,
                                     center center, 1,
                                     from (@bg_color),
                                     to (shade (@bg_color, 0.8)));
  }

  GtkScrollbar.button {
    border-width: 0;

    /* Asegurar un fondo transparente
     */
    background-image: none;
    background-color: rgba (0, 0, 0, 0);
}

Si queremos que el tema sea un poco más vivo, también podemos hacer:

  GtkButton:hover {
    transition: 100ms linear;
  }

  GtkCheckButton:active {
    transition: 250ms ease-in-out;
  }

De forma que esos estados tengan una animación de transición. Tras otros cambios menores, tenemos algo como esto:improved look with gradients and other tweaks

Con un archivo CSS relativamente simple hemos conseguido mejorar la apariencia de las aplicaciones, pero esto da mucho más de sí.

Si has estado al tanto del desarrollo de gnome-shell, ya sea compilándolo o a través de los paquetes inestables de tu distro favorita, hay muchas posibilidades de que ya tengas GTK+ 2.99.x en tu sistema, asi que no dudes en bajarte el CSS resultado de este artículo y ¡empieza a experimentar ya!

Carlos Garnacho es un desarrollador de GTK.

Discuss this story with other readers on the GNOME forums.

Advertisements

Posted on March 15, 2011, in March 2011. Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: