COLORI IN GTK

Nel sistema Xwindow il colore di ogni pixel viene ottenuto mescolando in qualche rapporto luce Rossa Verde e Blu .

In relazione all’ hardware disponibile ciascun pixel può essere rappresentato da un numero più o meno ampio di bit così la capacità di colore di un pixel viene definita profondità.

In un display primitivo che supporta soltanto due colori, ogni pixel è acceso o spento, dunque lo stato del pixel stesso è descritto da un solo bit che può trovarsi nello stato di “on” o di “off”.

Questo tipo di display viene chiamato ad “un bit per pixel” ( 1 bpp ) e ha profondità di colore 1, i moderni display invece supportano fino a 24 o 32 bpp.

Per quanto detto nel caso di un display a 32 bpp il numero di pixel differenti per ogni finestra sarà uguale a 2^32.

Il modo con il quale un bit-pattern viene convertito in un colore visibile è detto “visual ” e può essere una scala di grigi o un valore di tipo RGB , per ottenere tale conversione considerato per esempio che in un display a 8 bit questi stessi non sono sufficienti a descrivere un colore, i bit vengono trattati come interi e usati come indici di uno o più array di valori RGB[ bit ] costituendo così una tabella di colori detta “Colormap “.

A questa tabella faremo riferimento ogni volta che useremo un colore.

Brevemente i valori nel formato Red, Green, Blue, sono indicati utilizzando tre numeri ciascuno dei quali può essere compreso fra “0 ” e ” 255 “, ogni numero è rappresentato da 8 bit ( questo è il motivo per il quale un display a 8 bit non potrebbe visualizzare un colore senza un metodo visual ) per un totale di 24 bit.

0.0.0 == Nero

255.255.255 == Bianco.

Attraverso questo metodo si può visualizzare l’ intera gamma di colori che X accetta con diverse specifiche, una fra quelle possibili è la esadecimale.

La descrizione completa delle svariate maniere che consentono di utilizzare i colori attraverso GDK/GTK va oltre le finalità di questo documento, in generale mi limiterò a dire che i colori possono essere utilizzati anche per disegnare su un widget che in questo caso viene chiamato drawable.

La maniera più semplice per utilizzare i colori in GTK oltre all’ uso del file rc esterno, per la descrizione del quale si rimanda alle corrispondenti pagine di manuale, è quella di usare un apposito layer di astrazione fra GTK e GDK, cioè GtkStyle.

I temi correntemente utilizzati da GTK attraverso gli opportuni files di rc, vengono memorizzati in una struttura del tipo GtkRcStyle , ciascun widget ha uno style memorizzato in ” widget->style ” e può condividerlo con altri, questo inoltre può essere cambiato mentre il programma è attivo.

Come vediamo di seguito, la struttura GtkRcStyle contiene un set di informazioni che riguardano l’ aspetto di un widget :

struct GtkRcStyle
{
GObject parent_instance;

/*< public >*/

gchar *name;
gchar *bg_pixmap_name[5];
PangoFontDescription *font_desc;

GtkRcFlags color_flags[5];
GdkColor fg[5];
GdkColor bg[5];
GdkColor text[5];
GdkColor base[5];

gint xthickness;
gint ythickness;

/*< private >*/
GArray *rc_properties;

/* list of RC style lists including this RC style */
GSList *rc_style_lists;

GSList *icon_factories;
};

Il campo “private” può essere ignorato, mentre quello “public” contiene risorse per il rendering dei widgets.

I campi ” GdkColor “, sono array di colori che vengono indicizzati dall’ enumerazione di stato dei widgets.

Un widget attivo usa : widget->style->fg[GTK_STATE_NORMAL] per disegnare il testo, Ogni Widget ha uno stile associato, memorizzato nel campo ” Style ” di GtkWidget.

Riassumiamo i diversi stati in cui può trovarsi un widget:

NORMAL – Lo stato normale di un widget, quando il mouse non si trova su di esso, quando non è premuto, ecc.

PRELIGHT (evidenziato)- Quando il mouse si trova sopra al widget verranno usati i colori assegnati per questo stato.

ACTIVE (attivo) – Quando il widget è premuto o cliccato esso sarà attivo, e verranno usati gli attributi assegnati da questa etichetta.

INSENSITIVE (insensibile)- Quando un widget viene reso insensibile, e non può essere attivato, prenderà questi attributi.

SELECTED (selezionato) – Quando un oggetto viene selezionato, prende questi attributi.

Quando si usa un tema, una lista di GtkRcStyle, viene utilizzata per settare una struttura di tipo GtkStyle tuttavia possiamo usare direttamente GtkRcStyle per settare a nostro piacimento i colori di un programma GTK.

Typedef struct _GdkColor GdkColor ;
struct _GdkColor {
gulong pixel;
gushort red;
gushort green;
gushort blue;
};

I campi di una struttura GdkColor sono valori a 16 bit quindi accettano fino a 65.535 combinazioni, ma come detto il colore può essere passato anche in esadecimale, inoltre si ricordi che le etichette e le pixmaps sono widgets “trasparenti” e come tali possono essere colorati solo se messi dentro un EventBox.

Prima di utilizzare un colore, dobbiamo settare i campi RGB e allocarli nella colormap, Havoc Pennington suggerisce due modi operativi che riporto di seguito.

In GTK+ 1.2:

GtkRcStyle *rc_style;
GdkColor color;

/* Inizializzioamo i valori RGB */
color.red = 65535;
color.green = 0;
color.blue = 0;

/* Mettiamo il colore nella struttura GdkColor */
gdk_color_parse (“red”, &color);

/* After filling in your GdkColor, create a GtkRcStyle */
rc_style = gtk_rc_style_new ();

/* Set foreground (fg) color in normal state to red */
rc_style->fg[GTK_STATE_NORMAL] = color;

/* Indicate which colors the GtkRcStyle will affect;
* unflagged colors will follow the theme
*/
rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_FG;
gtk_widget_modify_style (widget, rc_style);
gtk_rc_style_unref (rc_style);

In GTK+ 2.0:

GdkColor color;
gdk_color_parse (“red”, &color);
gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color);

La funzione ” gdk_color_parse ” accetta una specifica di colore che può essere una stringa esadecimale preceduta dal prefisso RGB (ES: RGB:FF/FF/FF ) o un colore in lettere fra quelli presenti nel database e riempie i campi red, green e blue della struttura ” GdkColor “.

Se la specifica di colore non inizia con un prefisso di color space (RGB:) X presume che sia il nome di un colore e lo cerca nel database.

” gdk_color_parse ” restituisce TRUE se comprende la stringa passatagli, quindi possiamo scrivere del codice come questo:

if (gdk_color_parse (“red”, &color) );

gtk_widget_modify_fg (widget, GTK_STATE_NORMAL, &color);
else g_print(“Colore non presente nel database\n”);

Da notare anche il flag : ” GTK_RC_FG ”

La enumerazione GtkRcFlags è usata come una bitmask per specificare quale flag di un GtkRcStyle è settato per ciascun stato del widget.

enum GtkRcFlags

typedef enum
{
GTK_RC_FG = 1 << 0,
GTK_RC_BG = 1 << 1,
GTK_RC_TEXT = 1 << 2,
GTK_RC_BASE = 1 << 3 } GtkRcFlags; GTK_RC_FG : Se presente il colore di foreground è settato per questo stato. GTK_RC_BG : Se presente il colore di background è settato per questo stato. GTK_RC_TEXT : Se presente il colore di testo è settato per questo stato. GTK_RC_BASE : Se presente il colore base è settato per questo stato. Base, rappresenta il colore di background quando usiamo il testo ed è bianco nel tema di default. Oltre al codice proposto, è possibile in uno settare i colori in quest’ altra maniera: /* Creazione Dello Style e settaggio del Flag */ rc_style = gtk_rc_style_new(); rc_style->color_flags[GTK_STATE_NORMAL] |= GTK_RC_BG;
/* Definizione del colore */
rc_style->bg[GTK_STATE_NORMAL].red = 0xffff;
rc_style->bg[GTK_STATE_NORMAL].green = 0xffff;
rc_style->bg[GTK_STATE_NORMAL].blue = 0xffff;

Nel caso in cui stiamo usando Glade per sviluppare la nostra applicazione, dopo la creazione di un widget con la funzione ” create_nome_widget() ” sarà necessario prendere il puntatore all’ oggetto creato prima di modificare lo style.

Poniamo il caso che la finestra principale della nostra applicazione si chiami “Base”, avremo:

Base = create_Base();
Base = lookup_widget(GTK_WIDGET(Base), “Base”);

e finalmente:
gtk_widget_modify_style (Base, rc_style);
gtk_widget_show(Base);

…. enjoy 🙂