Comme expliqué ci-dessus (See A propos d'adesklets.), adesklets est principalement une console interactive d'Imlib2, avec quelques fonctionnalités supplémentaires :
Commençons un session interactive typique pour voir ce qui se passe. Sous X, ouvrez un terminal et tapez :
adesklets :
Comme dans la section
précédente (See 'Utilisation d'adesklets comme un
éditeur graphique en ligne de commande'.), vous
obtenez une invite. Maintenant entrez la commande
'images_info
'. Vous devriez voir en réponse
sur la sortie standard :
2 images id 0 width 1 height 1 alpha 1 filename (null) id 1 width 1 height 1 alpha 1 filename (null) command 0 ok: images_info
Cela signifie que vous avez deux images : image 0 et image 1, et quelles ont une taille de 1x1 pixel. Ceux sont les seules images que vous ne pouvez jamais détruire ni modifier comme vous le souhaitez (les redimensionner indépendamment, les retourner diagonalement, etc. Lisez ce qui suit pour savoir pourquoi.)
Mais ou sont ces fenêtres ? Pour
l'instant ce sont seulement des images de 1x1 pixel, et elles ne
sont pas montrées1 à l'écran.
Ainsi, redimensionnons les à 100x100 pixels : tapez
'window_resize 100 100
'. Maintenant, si vous retapez
la commande 'images_info
', vous obtiendrez :
2 images id 0 width 100 height 100 alpha 1 filename (null) id 1 width 100 height 100 alpha 1 filename (null) command 2 ok: images_info
Vous voyez ? Les images d'avant-plan et
d'arrière-plan ont été redimensionées
à 100x100 pixels : de plus, l'arrière-plan a
été mis à jour pour contenir la nouvelle
image de fond. Maintenant, rendons cette fenêtre visible.
Tapez les deux commandes : 'window_reset managed
' et
enfin 'window_show
'.
La première commande demande à adesklets de laisser votre gestionnaire de fenêtre "géré" votre fenêtre (ce qui n'est pas fait par défaut) : cela signifie que la fenêtre va être décorée, et que vous pourrez changer sa visibilité2 de façon interactive. La seconde montre votre fenêtre de 100x100. Rien d'impressionnant : un carré noir de 100x100 avec une barre de titre et des bordures.
Comme dit plus haut, seule l'image 0
(avant-plan) est affichée par défaut. Maintenant,
tapons : 'window_set_transparency 1
'. Wouah! Nous
voyons la fenêtre racine en dessous ! Avec "window
transparency" activé, l'image 1 (arrière-plan) est
d'abord copiée dans la fenêtre, puis l'image 0
(avant-plan) qui est entièrement noire et transparente,
est mise par-dessus3.
Il est temps de parler des couleurs :
souvenez-vous qu'adesklets est une console d'Imlib2 : en
conséquence, comme Imlib24, les couleurs sont
toujours de véritables couleurs 32 bits codées en
RVBA - huit bits par canal (de 0 à 255), incluant un canal
alpha (transparence). La conversion de palette se fait
automatiquement si la profondeur de votre écran est
inférieure, vous n'avez pas à vous en occuper. Si
vous tapez : 'context_get_color
', vous obtiendrez
:
command 0 ok: context color 255 255 255 255
Imlib2 est le roi de l'état de la
machine ; ainsi, il vient avec un "contexte" qui garde en
mémoire une série d'attributs qui seront
utilisés dans des opérations futures. Par exemple,
nous savons maintenant que la couleur qui sera utilisée,
aussi longtemps que nous ne la modifions pas, sera un blanc
opaque (rouge=255, bleue=255, vert=255, alpha=255). Si nous
tapons : 'context_get_image
', il nous retourne :
command 0 ok: context image 0
Cela signifie que toute opération que
nous effectuons sur une fenêtre est directement fait sur
l'image d'avant-plan. Dessinons un rectangle plein
semi-transparent de couleur magenta sur l'avant-plan. La commande
pourra être : 'context_set_color 255 0 0 200
'
et 'image_fill_rectangle 25 25 50 50
'.
Élégant, n'est-ce pas ?
Si vous avez l'habitude de programmer avec
Imlib2, vous devriez avoir remarqué que ces
dernières commandes vous sont familières. C'est
normal : la plupart des fonctions C d'Imlib2 sont
présentées de la même façon dans les
'commandes' d'adesklets. Ainsi, la commande d'adesklets
'image_fill_rectangle
' suit la même
sémantique que la fonction
'imlib_image_fill_rectangle()
' d'Imlib2, la commande
'context_set_color
' que la fonction
'imlib_context_set_color()
', etc. Les deux seules
différences significatives (et systématiques) sont
que partout où vous utiliserez un objet
'Imlib_Quelquechose
' en C, vous utiliserez un entier
ID avec adesklets, et dans la sémantique des fonctions
'imlib_free_Quelquechose()
' on a besoin de donner un
entier ID au lieu d'un objet de ce type permettant de
libérer le contexte sélectionné.
Illustrons cela. Chargeons la police "Vera" inclue dans adesklets à la taille 20pt, mettons la en police par défaut, et écrivons dans un bloc blanc opaque 'Hello' en diagonale sur l'image d'avant-plan du coin haut gauche avant de décharger la police. Cela devrait ressembler à :
6 >>> load_font Vera/20 command 6 ok: new font 0 7 >>> context_set_font 0 command 7 ok: context_set_font 0 8 >>> context_set_direction text_to_angle command 8 ok: context_set_direction text_to_angle 9 >>> context_set_angle 45 command 9 ok: context_set_angle 45 10 >>> context_set_color 255 255 255 255 command 10 ok: context_set_color 255 255 255 255 11 >>> text_draw 0 0 Hello command 11 ok: text_draw 0 0 Hello 12 >>> free_font 0 command 12 ok: free_font 0
Si vous regardez votre documentation
d'Imlib2, vous remarquerez immédiatement les deux
différences que l'on vient de dire : toutes les
références à la police Vera/20 sont faites
par un entier ID (0 ici), et la commande
'free_font
', contrairement à la fonction
correspondante 'imlib_free_font()
', est
appelée avec l'ID de la police comme argument plutôt
que le contexte de la police.
A partir de là, imaginons que vous
voulez sauver l'image résultante ; ce n'est pas un
problème - tapons : 'save_image out.png
', et
l'avant-plan est sauvé dans un fichier "out.png" dans le
répertoire de travail courant5. Maintenant,
juste pour le plaisir, quittons adesklets, et lançons une
autre session interactive pour voir si nous pouvons recharger
cette image. Tapez juste la commande "quit
" ou
pressez ^D (Control D: fin de fichier), votre nouvelle session
devrait ressembler à ceci :
0 >>> window_resize 100 100 command 0 ok: window_resize 100 100 1 >>> window_reset managed command 1 ok: window_reset managed 2 >>> window_set_transparency 1 command 2 ok: window_set_transparency 1 3 >>> load_image out.png command 3 ok: new image 2 4 >>> blend_image_onto_image 2 0 0 0 100 100 0 0 100 100 command 4 ok: blend_image_onto_image 2 0 0 0 100 100 0 0 100 100 5 >>> window_show command 5 ok: window_show 6 >>> free_image 2 command 6 ok: free_image 2
Bien sur, nous voulons visualiser le
résultat - c'est pourquoi nous avons utilisez les
commandes 'window_reset
',
'window_set_transparency
' et
'window_show
' : elles n'ont pas d'autres
utilités. La commande
'blend_image_onto_image
' vient droit de Imlib2 aussi
; elle prend la nouvelle image 2 que l'on vient de crée
lors de la troisième commande, et la met dans un contexte
d'image (image 0 - avant-plan par défaut), à partir
de ces coordonnées (0,0) pour une taille de 100x100
pixels, et la met dans un rectangle allant de (0,0) et de taille
100x100 pixels de l'image 0. Il est finalement bon de noter que,
avec adesklets, il y a toujours une image dans le contexte
d'Imlib2 : dès que vous essayer de libérer l'image
courante, le contexte d'image est remis à l'image
d'avant-plan.
D'accord, c'est presque la fin de cette introduction. A partir de là vous pouvez jouer avec adesklets - il est vraiment facile de l'utiliser si vous vous êtes déjà familiarisé avec Imlib2. Sinon, votre meilleure ressource est certainement d'avoir la documentation d'Imlib2 pas trop loin. :-)
Quelques dernières astuces :
help
'.history
' pour
afficher votre session courante dans un fichier6.pause
' à
la fin du script pour geler l'interpréteur.Voici un exemple :
#!/usr/bin/env adesklets -f # Rendre la fenêtre 'géré' # window_reset managed # Redimmensioner la fenêtre à 100x100 pixels # window_resize 100 100 # Montrer la fenêtre, puis la geler pendant 10 secondes avant de sortir # window_show pause 10
Vous aurez juste besoin de rendre ce script exécutable et de le lancer. Comme d'habitude, les sorties seront affichées sur la sortie standard.
de desklet
Lorsque vous serez prêt pour un véritable travail7, vous pourrez vouloir utilisé un véritable langage de script plutôt que le rudimentaire interpréteur adesklets que nous avons utilisé dans l'introduction ; vous ne savez jamais quand les variables sont accessibles.
Au moment ou j'écris ces lignes (10 juin 2005), seul le
support pour Python est complet8. A partir de python, les
choses ne sont pas très différentes qu'à
partir de l'interpréteur : les commandes ont
été encapsulées dans des fonctions python,
et une classe publique Events_handler
a
été construite pour manipuler les retours
asynchrones de l'interpréteur. Jetez un coup d'oeil sur le
script test/test.py de l'archive source
de la version 0.4.10 :
""" test_fr.py - S.Fourmanoit <syfou@users.sourceforge.net>, Guillaume Boitel <g.boitel@wanadoo.fr> Petit script de test non-exhaustif pour adesklets : - Redimensionne la fenêtre adesklets à 100x100 pixels - La met sous le contrôle du gestionnaire de fenêtre - La rend pseudo-transparente - L'affiche à l'écran - Attends ensuite que l'utilisateur la quitte, génère une alarme toutes les 10 secondes et attrape les événements motion_notify dès qu'ils apparaissent. Pour l'essayer : - Installer adesklets avec le support python activé (par défaut) - Lancer python test.py à partir de ce répertoire. """ import adesklets class My_Events(adesklets.Events_handler): def __init__(self): adesklets.Events_handler.__init__(self) def __del__(self): adesklets.Events_handler.__del__(self) def ready(self): adesklets.window_resize(100,100) adesklets.window_reset(adesklets.WINDOW_MANAGED) adesklets.window_set_transparency(True) adesklets.window_show() def quit(self): print 'Quitting...' def alarm(self): print 'Alarm. Next in 10 seconds.' return 10 def motion_notify(self, delayed, x, y): print 'Motion notify:', x, y, delayed My_Events().pause()Voilà ! 26 ligne de code python, et nous avons un desklet parfaitement fonctionnel. Je pense que cela s'explique tout seul : jetez un coup d'oeil à l'aide intégrée de python pour
adesklets
,
adesklets.functions
et
adesklets.Events_handler
pour une bonne et
complète explication. En deux mots, tout ce que nous avons
fait ici c'est :
adesklets
: cela
instancie automatiquement un processus fils adesklets et configure toutes les
communications : quand l'initialisation du paquetage ne
retourne pas d'exception, cela signifie que
l'interpréteur tourne et est prêt à
accepter des commandes.adesklets.Events_handler
et redéfinir des
méthodes invoquées pour les
événements qui nous intéresse (tous les
autres événements ne sont pas simplement
ignorés, ils ne sont pas
générés).Enfin, mentionnons que vous pouvez regarder dans le code source du desklet weather du site web du projet situé sur sourceforge pour un script python pour adesklets plus conséquent.
[1] "Mappé" dans un patois de X Window
[2] Une fenêtre "non-gérée" est très utile pour les desklets : c'est comme si c'était une partie de la fenêtre racine puisqu'elle peut être construite pour ne jamais être en avant-plan et pour rester affichée lorsque l'on change d'espace de travail.
[3] Bien... Pas tout à fait : il y a un buffer qui est mise en jeu pour la performance, mais l'opération est logiquement équivalente à cette description.
[4] Gardez votre documentation d'Imlib2 à proximité : c'est très utile - http://atmos.org/docs/imlib2/index.html fournit une agréable introduction, bien qu'un peu ancienne.
[5] Pour que ça marche, vous avez besoin d'avoir une installation d'Imlib2 proprement configuré pour utiliser libpng, ou vous risquez de recevoir une erreur "no loader for file format".
[6] Pour que ça marche, vous avez besoin d'avoir GNU history lorsque vous compilez adesklets.
[7] :-)
[8] adesklets a été écrit pour être facile d'usage pour différents langages interprétés ; le futur développement inclue des encapsulations pour Perl et Ruby - n'hésitez pas à proposer votre aide si vous voulez accélérer les choses.
[9] Cette dernière étape n'est
pas obligatoire : le script peut très bien continuer,
mais il a été écrit ainsi pour supporter
les signaux d'interruptions. Regarder
`help(adesklets.Events_handler)
' pour de plus
amples informations.