NewStartCenterBehavior/fr

Documentation en cours

À propos du code proposé dans cette page : tous les changements par rapport au code original d'OpenOffice.org ayant servi de base, et fournis dans cette page, sont :


 * '''sous Licence LGPL V3 ( et vous pouvez-le redistribuer et / ou le modifier selon les termes de la licence GNU Lesser General Public License telle que publiée par la Free Software Foundation)
 * Copyright Eric Bachard 20 Décembre 2010

Version 1.1 ou précédentes
Jusqu'à la version 1.1, le Centre de Démarrage (aussi connu sous le nom de startcenter) se comportait comme suit (voir image ci-dessous) :




 * lorsque le curseur survole une des icônes, une bulle d'aidé apparaît et décrit ce qu'on peut faire en cliquant sur cette icône.


 * un message par icône. Pour la version Française, cela donnait :
 * Créer un texte avec Writer
 * Dessiner avec Draw
 * Créer une présentation avec Impress
 * Créer un tableau avec Calc
 * Ouvrir un document...


 * dès que le curseur de la souris sortait de l'icône, la bulle disparaissait

Le problème, c'est que la bulle d'aide pouvait apparaître n'importe où dans le voisinage immédiat de l'icône, quelquefois allant jusqu'à masquer cette icône, ce qui n'est pas compatible avec une bonne expérience utilisateur.

Future version 1.2
L'amélioration proposée permet maintenant d'afficher :


 * la même chaine que celle affichée par la bulle ;
 * '''toujours au même endroit, quelle que soit l'application présentée;
 * pas besoin de traduire de nouvelles chaînes, celles existant seront simplement réutilisées.

Quelques copies d'écrans mettant en oeuvre le comportement exposé en bas de page.

Amélioration possibles :


 * ne plus afficher "Créer un nouveau document", et ne faire apparaître que ce qui est utile;
 * modifier le Design en déplaçant vers le haut le cadre + les icônes;
 * (merci de compléter la liste).

Copies d'écran
Nouveau comportement du centre de démarrage, lorsque le curseur de la souris survole les icônes

Introduction
Ci-dessous, vous trouverez une description technique de l'implémentation de la fonctionnalité : Nouveau comportement du centre de démarrage. Il est ainsi question de code source (C++), mais aussi de la structure et de l'organisation interne d'OpenOffice.org (framework), et nous supposons que le lecteur possède les bases nécessaires pour lire et comprendre le contenu de ce qui est exposé.

Les pré-requis pour lire cet article sont encore à définir, mais si certaines notions ne vous sont pas familières, nous vous invitons à consulter le wiki d'OpenOffice.org pour compléter vos connaissances, afin de pouvoir lire cet article dans les meilleures conditions possibles.

Tout à commencé quand j'ai activé les infobulles pour donner de l'information à l'utilisateur. Cette infobulle apparaissait lorsque le curseur de la souris survolait une des icônes proposées.

En fait, cette infobulle n'était tout simplement pas adaptée, et pouvait même, dans certains cas se positionner de façon inutile et inefficace.

Le but de cette étude, est de présenter une amélioration. Plutôt qu'utiliser les infobulles,on va faire apparaître, pour chaque application (lorsque le curseur survole l'icône correspondante) la même explication que celle qui était donnée dans l'infobulle, mais toujours à la même position dans le cadre, ceci pour toutes les chaines à afficher.

Au début, ne sachant pas par quel bout commencer, j'ai imaginé une solution, mais elle ne convenait pas. Je dois remercier chaleureusement Philipp Lohmann, qui m'a - encore une fois - gentiment expliqué la marche à suivre ( voir ce mail). J'ai complété les instructions, et détaillé au mieux la méthode que j'ai employée ci-dessous.

Toute remarque constructive permettant d'améliorer cette présentation est la bienvenue.

Spécifications

 * Faire taire les infobulles
 * Démarrer un écouteur d'événements, de type VclWindowEvent
 * Terminer cet écouteur d'événements (dans le destructeur de l'objet BackingWindow, quand la fenêtre se ferme)
 * Initialiser les chaines à afficher, en particulier les fontes
 * Implémenter un callback, déclenché par un événement correct (VclWindowEvent)
 * Proposer un algorithme permettant de n'afficher que la bonne chaîne
 * Mettre en oeuvre l'ensemble
 * Supprimer ce qui ne sert plus
 * Valider le fonctionnement

Modules concernés
Un seul module est concerné dans cette fonctionnalité : framework. Tout se passe dans framework/source/services.

fichiers modifiés :


 * framework/source/services/backingwindow.hxx // interface
 * framework/source/services/backingwindow-OOo4Kids.hxx // implémentation concernant OOo4Kids seulement
 * framework/source/services/backingwindow-OOoLight.cxx // implémentation concernant OOoLight seulement

Faire taire les infobulles
Comme l'a expliqué Philipp Lohmann dans le mail initial, il suffit de créer une méthode de même nom, afin d'avoir la priorité sur celle implémentée dans la toolbox (en fait,je connaissais bien la méthode, qui est très utile en objective-C).

Dans le code, cela se traduit simplement par :

Index: framework/source/services/backingwindow.hxx

=
====================================================== --- framework/source/services/backingwindow.hxx	(revision 1034) +++ framework/source/services/backingwindow.hxx	(working copy) @@ -78,6 +78,9 @@                DecoToolBox( Window* pParent, const ResId& rResId ); void   DataChanged( const DataChangedEvent& rDCEvt ); + +       // The goal is to overload the Toolbox method, thus make the QuickHelp shut up +        void    RequestHelp( const HelpEvent& rHEvt );

Implémentation (dans framework/source/services/backingwindow-OOo4Kids.cxx par exemple) :

Ajouter la méthode qui ne fait rien : +       void DecotoolBox::RequestHelp( const HelpEvent& rHEvt ) + { +    (void)rHEvt; // makes the compiler happy + };

Et ça fonctionne tout droit :-)

Ajout du nouvel écouteur d'événements "EventListener"
La méthode BackingWindow::initControls est appelée une seule fois (Design Pattern "singleton"), et il a semblé opportun d'ajouter l'écouteur dévénements à cet endroit. @@ -383,15 +413,7 @@        }     }			 (removed code) +   maToolbox.AddEventListener( LINK( this, BackingWindow, DecoToolboxHdl ) ); maToolbox.SetSelectHdl( LINK( this, BackingWindow, ToolboxHdl ) ); maToolbox.Show;

L'appel se fait sous la forme d'un callback, qui aura pour but d'exécuter une action lorsqu'un événement du type celui implémenté sera détecté.

Ajout du nouveau Callback
Le callback écoute des événements du type VclWindowEvent* (pointeurs sur objets de type VclWindowEvent), en particulier deux événements, qui apparaissent dans le code ci-dessous :


 * VCLEVENT_TOOLBOX_HIGHLIGHT : Déclenche la mise en surbrillance. Il est émis lorsque le curseur survole une des icônes d'applications du StartCenter
 * VCLEVENT_TOOLBOX_HIGHLIGHTOFF : Fin de subrillance. Il est émis lorsque le curseur sort de la zone correspondant à une icône d'application

L'algorithme choisi sera le suivant : Si événement de type VclWindoEvent et si l'événement est du type VCLEVENT_TOOLBOX_HIGHLIGHT

Choisir l'icone survolée parmi les cas possibles :

Dans le cas où    application Calc survolée : afficher le message pour Calc Fin

Dans le cas où    application Draw survolée : afficher le message pour Draw Fin

Dans le cas où    application Impress survolée : afficher le message pour Impress Fin

Dans le cas où    application Ouvrir survolée : afficher le message pour "Ouvrir un document" Fin

Dans tous les autres cas Fin Sinon Si événement de type VclWindoEvent et si l'événement est du type VCLEVENT_TOOLBOX_HIGHLIGHTOFF Cacher tous les messages Fin si

Initialisation des chaînes
Cette initialisation se passe en 3 étapes :

Étape 1 déclaration dans l'interface. Pour cela, on utilisera des objets de type

 * Contrôle: FixedText
 * Dimensions conteneurs 2D : Size (largeur, hauteur)
 * Fontes
 * Chaînes constantes, de type String (déjà définies, simplement réutilisées)

Étape 2: Initialisation des fontes pour chaque chaîne à afficher
Cela se passera dans Backingwindow::initControls :

maTextFont : déjà initialisée, et obtenue grâce à : maTextFont = GetSettings.GetStyleSettings.GetLabelFont;

Nous aurons à initialiser :


 * la fonte pour chaque chaine,
 * la taille des caractères (y compris l'espace intercaractères
 * l'attribut de style (WEIGHT_NORMAL pour nous)

Exemple, d'initialisation pour le message qui apparaîtra lorsque le curseur survolera l'icône "Calc"

+   // Set the messages to be displayed +   maTextFont.SetSize( Size( 0, 13 ) ); +   maTextFont.SetWeight( WEIGHT_NORMAL ); +   maCalcMessageText.SetText( maCalcString ); +   maCalcMessageText.SetFont( maTextFont ); +   maCalcMessageText.SetControlFont( maTextFont ); +   maCalcMessageSize = Size( maCalcMessageText.GetTextWidth( maCalcString ), maCalcMessageText.GetTextHeight * 1.18 );

Inutile de réinitialiser la taille (méthode SetSize) pour les suivantes, puisque rien ne change :

+ +   maDrawMessageText.SetText( maDrawString ); +   maDrawMessageText.SetFont( maTextFont ); +   maDrawMessageText.SetControlFont( maTextFont ); +   maDrawMessageSize = Size( maDrawMessageText.GetTextWidth( maDrawString ), maDrawMessageText.GetTextHeight * 1.18 ); +

-> voir le code pour toutes les autres chaînes

Étape 3 : positionnement des chaînes dans la fenêtre
Cela se passe dans la méthode BackingWindow::Resize, appelée à chaque fois que quelque chose change

@@ -501,8 +519,70 @@    maCreateText.SetPosSizePixel( Point( (aWindowSize.Width - maCreateSize.Width + STRING_OFFSET_X) / 2, nYPos ),                                   Size( maControlRect.GetWidth, maCreateSize.Height ) ); + +   // defines the location of the Create text +   nYPos += 170;// FIXME: better method ... + +   maCalcMessageText.SetPosSizePixel( Point( (aWindowSize.Width - maCalcMessageSize.Width + STRING_OFFSET_X) / 2, nYPos ), +                                  Size( maControlRect.GetWidth, maCalcMessageSize.Height ) );

Il est important de noter le mode de calcul pour le centrage (le précédent était faux). Il reste toutefois une amélioration à appporter, car il semble que ce calcul ne soit correct qu'à partir du second affichage du StartCenter. [FIXME]

Même chose pour les autres contrôles du même type ci-dessous :

+ +   maDrawMessageText.SetPosSizePixel( Point( (aWindowSize.Width - maDrawMessageSize.Width + STRING_OFFSET_X) / 2, nYPos ), +                                  Size( maControlRect.GetWidth, maDrawMessageSize.Height ) ); + +   maImpressMessageText.SetPosSizePixel( Point( (aWindowSize.Width - maImpressMessageSize.Width + STRING_OFFSET_X) / 2, nYPos ), +                                  Size( maControlRect.GetWidth, maImpressMessageSize.Height ) ); + +   maOpenMessageText.SetPosSizePixel( Point( (aWindowSize.Width - maOpenMessageSize.Width + STRING_OFFSET_X) / 2, nYPos ), +                                  Size( maControlRect.GetWidth, maOpenMessageSize.Height ) ); + +   maWriterMessageText.SetPosSizePixel( Point( (aWindowSize.Width - maWriterMessageSize.Width + STRING_OFFSET_X) / 2, nYPos ), +                                  Size( maControlRect.GetWidth, maWriterMessageSize.Height ) ); }

Implémentation du Callback
L'implémentation retenue est la suivante : +IMPL_LINK( BackingWindow, DecoToolboxHdl, VclWindowEvent*, pEvent ) + { +   if( pEvent && pEvent->GetId == VCLEVENT_TOOLBOX_HIGHLIGHT ) +   { +#ifdef DEBUG +       fprintf(stderr, "Toolbox nItemId = %d \n", maToolbox.GetHighlightItemId ); +#endif +       switch ( maToolbox.GetHighlightItemId ) +       { +            case nItemId_Calc: +           { +                maMessageText.SetText( maCalcString ); +               maMessageSize = Size( maMessageText.GetTextWidth( maCalcString ), +                                       maMessageText.GetTextHeight * DEFAULT_ZOOM_FACTOR ); +           } +                break; +           case nItemId_Draw: +           { +                maMessageText.SetText( maDrawString ); +               maMessageSize = Size( maMessageText.GetTextWidth( maDrawString ), +                                      maMessageText.GetTextHeight * DEFAULT_ZOOM_FACTOR ); +           } +                break; +           case nItemId_Impress: +           { +                maMessageText.SetText( maImpressString ); +               maMessageSize = Size( maMessageText.GetTextWidth( maImpressString ), +                                      maMessageText.GetTextHeight * DEFAULT_ZOOM_FACTOR ); +           } +                break; +           case nItemId_Info: +           { +                maMessageText.SetText( maOpenString ); +               maMessageSize = Size( maMessageText.GetTextWidth( maOpenString ), +                                      maMessageText.GetTextHeight * DEFAULT_ZOOM_FACTOR ); +           } +                break; +           case nItemId_Writer: +           { +                maMessageText.SetText( maWriterString ); +               maMessageSize = Size( maMessageText.GetTextWidth( maWriterString ), +                                      maMessageText.GetTextHeight * DEFAULT_ZOOM_FACTOR ); +           } +                break; +           case nItemId_Extensions: +           case nItemId_Reg: +           case nItemId_TplRep: +           default: +               break; +       } +	 setMessageTextSize; +       maMessageText.Show; +   } +    else if( pEvent && pEvent->GetId == VCLEVENT_TOOLBOX_HIGHLIGHTOFF ) +       maMessageText.Hide; +   return 0; +}

Suppression du code obsolète

 * le positionnement dans initControls ne sert à rien -> supprimé
 * on n'utilise plus les infobulles: la méthode SetItemText devient inutile.
 * même chose pour ShowItem
 * suppression des contrôles dédiés aux chaines de caractères affichées par les infobulles

Exemple : maToolbox.SetItemText( nItemId_Info, aInfoHelpText );

-> toutes les occurences de SetItemText ont aussi été supprimées (pour la même raison).

Validation du fonctionnement
Testé ok sur Mac OS X, mais le code n'est pas OS dépendant, donc devrait fonctionner partout.


 * suppression des infobulles : OK
 * passage d'un item à l'autre au clavier (flèches gauche-droite) : OK
 * passage sur chaque icône, dans un ordre quelquconque, et répété : on affiche toujours la bonne chaîne de caractères : OK
 * suppression de "Créer un nouveau document": OK
 * affichage des chaînes applications l'endroit et en remplacement de "Créer un nouveau document : OK

Résumé : ce qui a été important et ce qui a été ... pénible

 * Temps de travail nécessaire : entre 20h et 24h pleines (déboguage compris) pour la réalisation de la modification
 * Retrouver le bon id : utiliser maToolbox.GetHighlightItemId au lieu de maToolbox.GetCurItemId (qui donne toujours "0") peut sauver un temps précieux.
 * Choix du Callback : lié à la compréhension de ce qu'est une Toolbox pour la BackingWindow (il faut absolument faire l'effort)
 * Initialisation correcte des fonts : utiliser SetControl sauve ... (j'ai perdu beaucoup de temps là-dessus !!)
 * Connaissance des méthodes accessibles : opengrok aide énormément (quel super outil !)