CiviKey évolue encore un peu

Comme je vous le disais il y a pile un mois (ou un peu plus), une version 2.6.0 de CiviKey est dans les cartons pour la nouvelle année.

Et bien une nouvelle release de la distribution Alpha est disponible (la 2.6.1). Cette release apporte des corrections de bugs dans différents plugins, et surtout de nouvelles fonctionnalités !

Une aide intégrée, facile à utiliser, et bientôt facile à éditer.

 

Un éditeur de clavier beaucoup plus puissant.

Il permet maintenant de créer, modifier, supprimer des touches, des zones, ainsi que leurs layouts etc etc etc. Bref vous pouvez (presque) tout faire avec !

 

 

Niveau stabilité, il reste un peu de chemin à faire afin de corriger les derniers bugs qui peuvent survenir lors de l'utilisation des nouveaux plugins. Cependant le plus dur est fait, il reste maintenant à passer les derniers coups de polish et nous serons près d'ici 2013 pour vous livrer une nouvelle version !

On vous tient au courant :)

Comme la dernière fois, n'hésitez pas à lire le code sur GitHub ou à nous suivre sur Twitter ou Facebook

Une version 2.6.0 de CiviKey pour 2013

Et oui, outre la sortie du nouveau site officiel en aout dernier et un léger problème de mise à jour automatique, CiviKey continu d'évoluer !

Grâce au soutien de la Fondation Garches et d'Alcatel Lucent, CiviKey passera pour la nouvelle de la version 2.5.2 à la version 2.6 !

Une 2.6, pas une 3.0 ?

Et non, pas une 3.0 car aucun changement majeur n'a été fait au sein du noyau depuis la grande bataille de la 2.5. L'objectif de la 2.6 est d'ajouter à CiviKey différents plugins indispensables aux ergothérapeutes et personnes en situations de handicap qui l'utilisent au jour le jour.

Au menu de cette 2.6 les fonctionnalités que tout bon clavier visuel se doit d'avoir : une prédiction de mot, et une solution de défilement des touches du clavier. S'ajoute à cela quatre nouveautés :

  • un clavier permettant grâce au défilement de déplacer et d'effectuer opérations de base de la souris
  • un assistant au premier démarrage
  • un assistant création 
  • et édition de clavier, et enfin une aide contextuelle intégrée

D'ici 2013 ... et avant ?

La sortie finale de la version 2.6 est prévu pour 2013. Vous souhaitez d’ores et déjà essayer nos builds fraichement sortis du four ?

Contactez-nous et nous vous fournirons un installeur spécifique pour la pre-release. Cette alpha version:

  • est déployée parallèlement à tout autre installation existante;
  • se mettra à jour sur notre "canal alpha", un canal de mise à jour différent de celui de la version stable actuelle.

En attendant voici quelques captures des derniers plugins !

La prédiction et défilement fonctionnant sur la skin WPF

Le clavier souris avec le défilement

La première étape de l'assistant création et édition de clavier

 

Evidemment pour ne pas perdre la tradition des posts technique sur l'architecture et l'implémentation de CiviKey de ce blog, deux posts suivront dans les prochaines semaines.

Le premier fera le point sur l'implémentation actuelle du défilement, les concepts sous-jacents ainsi que les évolutions prévues. Et enfin le second plongera dans les tréfonds de la prédiction de mot et explicitera comment cette fonctionnalité majeure est intégrée au sein de notre architecture de plugins. Vaste programme !

En attendant, n'hésitez pas à lire le code sur GitHub ou à nous suivre sur Twitter ou Facebook

Quelle disposition utiliser pour un clavier visuel ?

Le développement de CiviKey avançant il est temps de se poser la question de la disposition des touches. Historiquement l’interface a toujours suivi les dispositions des claviers physiques : un clavier Azerty et un clavier Qwerty comportant toutes les touches d’un clavier normal, avec pavé numérique et touches de fonctions.

Pourtant ce n’est pas forcément la solution la plus ergonomique, aussi bien pour un utilisateur valide que pour un utilisateur handicapé. Heureusement de nombreuses personnes se sont posés la question avant nous, comme Maxime Baas, Yohan Guerrier et Christophe Kolski qui ont publié deux articles traitant de la question, intitulés « Etude comparative entre clavier virtuel de type AZERTY et K-Hermès, destinés à des utilisateurs souffrant d’une Infirmité Motrice Cérébrale » et « Système de saisie de texte visant à réduire l’effort des utilisateurs à handicap moteur ». Le premier étant une comparaison entre deux claviers, un AZERTY (Clavicom NG) et le clavier K-Hermès dont les touches possèdent trois lettres et sont disposées en fonction des probabilités avec les lettres suivantes (par exemple dans la langue française le ‘q’ est souvent suivi du ‘u’, donc la touche contenant ‘u’ sera proche de la touche contenant ‘q’). Le second étant une recherche de disposition idéale visant à réduire l’effort aussi bien physique que psychique des utilisateurs du clavier.

Nous avons donc essayé de tirer de ces articles une définition du « clavier idéal », voici les points qu’il doit respecter :

  • Le nombre de touches du clavier doit être minimum.
  • Les touches retour et espaces étant les touches les plus utilisées sur un clavier, elles doivent être très facilement et rapidement accessibles, voire même multiples.
  • La prédiction de mot / de lettre, doit être intégré au clavier nativement et ne doit pas être une surcouche complexe à utiliser. Elle doit faire partie du comportement normal du clavier.
  • La disposition des touches ne doit pas forcement être calculée en fonction des touches les plus probables mais doit plutôt pouvoir être mémorisée très facilement. (Limiter le nombre de touches participe à ce point.)
  • Toujours dans l’optique de réduire le nombre de touches, il faut utiliser toutes les possibilités des périphériques d’entrée afin de supprimer les touches de changement de mode : le clic gauche peut envoyer une lettre en minuscule tandis que le clic droit envoi une majuscule, d’autre modes peuvent être activés par un clic long gauche et droit par exemple.
  • La grille n’est pas la meilleure solution : dans une grille, chaque touche est entourée au maximum de quatre autre touches… un placement en quinconce permet d’entourer chaque touche de six touches au maximum.

Voici donc la nouvelle disposition, disposée en tenant compte des points cités ci-dessus :

Cette disposition est évidemment amenée à évoluer mais elle représente le standard de ce que doit être un clavier visuel qui doit être plus facile à utiliser qu’une reproduction directe d’un clavier physique.

Composition des solutions

Les solutions de CiviKey sont des solutions dites « composées » : chaque solution tire parti d’une ou plusieurs solutions pour ne faire qu’ajouter des fonctionnalités, sans devoir recopier des projets essentiels. La solution Core est la solution de base, elle regroupe les projets du noyau permettant par exemple de lire et sauvegarder les données de CiviKey. Ensuite la solution Certified apporte un host d’exécution du Core, ainsi que des plugins essentiels, elle est donc composée du résultat de la solution Core. Enfin Contrib est une solution « bac à sable » où tout le monde peut venir tester son plugin. Elle est composée par la solution Certified et contient donc tous ses plugins, et en y ajoutant les plugins développés par les développeurs de la communauté Open Source ou par les étudiants d’In’Tech INFO.

Création d’un « Runtime »

Pour que ces solutions puissent être composées par d’autres il a fallu réfléchir à un système assez souple pour ne lier trop fortement deux solutions entre elles. Il faut par exemple que le développement de Core puisse continuer en parallèle sans impacter Certified.

Pour cela nous avons ajouté un dossier « Runtime » à chaque solution (sauf Core car c’est la solution élémentaire) contenant les résultats de la (ou des) Solutions qui la compose : Certified/Runtime contient donc les binaires de Core. Les projets de la Solution composée n’ont qu’à faire référence aux binaires du dossier Runtime pour les utiliser et les développeurs de la Solution composée gèrent leur répertoire Runtime : ce sont eux qui choisissent de prendre en compte on non les nouvelles versions des composants sur lesquels ils s’appuient.

Ce dossier Runtime peut être mis sous contrôle de SubVersion (ou autre gestionnaire de code source), c’est d’ailleurs ce que nous faisons à Invenietis. De cette façon, les Solutions sont autonomes et il est aisé de « remonter dans le temps » du projet : les sources sont en phase avec les versions exactes des composants sur lesquels la Solution est fondée.

Les « Saveurs »

Lorsqu’on compile une solution dans Visual Studio il est possible de choisir dans quel mode se déroulera la compilation. En mode Debug, pour que les « #If Debug », « Debug.* », etc. soient pris en compte, cela permet de résoudre les bugs plus facilement (via des outils de diagnostic). En mode Release, pour que les performances soient optimales.

Mais il n’y a pas que Debug et Release : si ces « modes de compilation » sont les plus courants, il peut s’avérer nécessaire de gérer d’autres « saveurs » : processeur, optimisations plus ou moins agressive, versions gratuites vs. payantes, signé ou non, etc. La notion de « Saveur » généralise le « mode de compilation » : un même composant logiciel est disponible pour le développeur en plusieurs « saveurs » et celui-ci doit pouvoir les choisir.

Le Runtime de chaque Solution contient un sous dossier par « saveur », typiquement Debug et Release, qui contiennent les résultats des compilations correspondantes. Il est donc possible de choisir quelle « saveur » utiliser simplement en changeant les chemins des références.

Notons qu’il est même possible d’intégrer la version dans la « saveur » : rien n’empêche de travailler en même temps sur des composants « ReleaseOld » et « ReleaseNew » (afin de vérifier que le plugin que l’on écrit marche aussi bien avec deux versions différentes du même composant.

Malheureusement, changer toutes les références à chaque changement de configuration est très fastidieux (une solution comme Certified possède, à date, 14 projets, chaque projet possède au moins 3 références au Core, il faut donc changer 42 chemins à chaque fois que l’on veut passer en Debug/Release).

Pour éviter cette opération, le dossier Runtime contient un répertoire Current. Ce dossier est une copie exacte d’une des saveurs disponible dans Runtime. La solution n’a plus qu’à faire référence systématiquement aux binaires de Current : pour changer de configuration, il suffit de remplacer ces binaires par les binaires de la saveur que vous voulez utiliser. Il est ainsi très facile par exemple d’utiliser le Core en Release dans la solution Certified en mode Debug (ou le contraire).

Pour le moment ce dossier Current est à gérer manuellement, il faut le créer, le mettre en « ignore list » dans SubVersion, et faire un export des binaires de Debug / Release dedans afin de pouvoir les utiliser. Nous spécifions actuellement un petit utilitaire pour automatiser et sécuriser cette opération, il devrait permettre aussi de faire un update automatique des « saveurs » disponibles.

Finissons sur une remarque générale : nous proposons ici un moyen simple de gérer un très classique problème du développement logiciel. Dans le bon vieux temps des compilateurs C, des fichiers make permettaient de se lier à des librairies différentes en fonction de valeur de macro (la « saveur » à produire). Visual Studio n’intègre pas cette possibilité (subordonner ses références au « mode de compilation ») car elle a souvent été mal utilisée et source de problème.

Pour notre part, nous estimons avoir besoin de ce petit jeu : compiler facilement ma Solution avec tous les checks intégrés dans la saveur « Debug » du Core pour faciliter la traque des bugs… alors que ma Solution, elle-même, est compilée en « Release ».

Ou le contraire : j’ai confiance dans le Core, je travaille en Debug et utilise le Core en Release. Bref, les différentes combinaisons sont possibles… Mais nous imposons néanmoins UNE contrainte forte : les « saveurs » doivent être interchangeables au sens où elles doivent toutes contenir les mêmes composants.

Exemple pratique : Faire fonctionner Contrib après un checkout

Voici toutes les étapes pour mettre en œuvre la solution Contrib directement après un checkout. Pour information le dépôt de Contrib est à l’adresse suivante : https://civikey.svn.codeplex.com/svn/trunk/Contrib Voici la marche à suivre :

  1. 1 - Aller dans Runtime/, créer le dossier Current/ et l’ajouter en « ignore list » dans votre client SubVersion.
  2. 2 - Exporter les dll d’un des deux dossiers de Runtime/ vers Current/.
  3. 3 - Lancer la solution Contrib.VS2008.sln.
  4. 4 - Compiler une première fois la solution.
  5. 5 - Dans les propriétés du projet Artefact aller dans la section « Déboguer » puis choisir « Output/Debug (ou Release selon votre mode de compilation)/CiviKey.exe » comme programme de démarrage. Attention cette configuration s’enregistre dans un fichier .user, qui ne doit pas être commit car cette configuration est liée à chaque poste.

Une fois cette configuration faite vous n’aurez plus qu’à changer le mode de compilation de Contrib ou de changer les dll de Runtime/Current/ pour compiler avec les saveurs qu’il vous faut.

Liens entre structure et layout

Les travaux sur la version 2.5.0 du Core, et plus précisément le développement de la nouvelle interface graphique de CiviKey nous ont permis de soulever une nouvelle problématique qui a entrainé l’évolution de la structure même de ce que sont un clavier et son affichage (ou layout).

Un petit rappel ne fait pas de mal

Les classes qui définissent la structure des objets d’un contexte CiviKey sont organisées en deux sections parallèles :

  • la structure de « ce qu’est un clavier », au sens des données liées au comportement et à la nature des objets (propriété Enabled et commandes associées à l’appui d’une touche par exemple)
  • et la façon dont ces claviers doivent être affichés : les Layouts (propriété Visible et positionnement à l’écran par exemple).

 

D’abord, de nouveaux noms

Lors de l’évolution décrite ci-après, on s’est rapidement rendu compte que les noms des classes n’étaient pas suffisamment explicites : ils avaient déjà évolué une première fois pour perdre le préfixe CVK (ICVKContext est devenu IContext), et l’ajout des interfaces « Current » (voir ci-dessous) a fait déborder le vase (avec un horrible ICurrentActualKeyLayoutCurrent…). Olivier a donc décidé de renommer certaines interfaces pour plus de clarté : IKeyboardZone devient IZone (parce qu’après tout, lorsqu’on travaille dans CiviKey on sait bien qu’une zone est une zone de clavier) ; IActualKey devient IKeyMode (car « actual » étant un faux-ami en anglais, certains ne comprenait pas le sens « Réel » de ce nom, IKeyMode est plus clair car cet objet représente simplement une touche - ou Key - dans un Mode donné). Du côté des layouts certains noms ont changé aussi en respectant une parfaite cohérence avec la section structurelle. L’intérêt de ce re-nommage est double :

  • les noms des objets sont « alignés » sur leur « structure » et il est beaucoup plus facile de s’y retrouver.
  • cela permet aussi de séparer les objets Layout des objets Structure dans la liste des classes dans Visual Studio : les Layouts, commençant tous par « ILayout » sont regroupés et non plus éparpillés parmi les autre classes/interfaces.

 

Voici donc la nouvelle organisation des interfaces du modèle :

Avant Maintenant
  • IContext
    • IKeyboard
      • IKeyboardZone
        • IKey
          • IActualKey
      • IKeyboardLayout
        • IKeyboardZoneLayout
          • IKeyLayout
            • IActualKeyLayout
  • IContext
    • IKeyboard
      • IZone
        • IKey
          • IKeyMode
      • ILayout
        • ILayoutZone
          • ILayoutKey
            • ILayoutKeyMode

Mais où est le problème ?

Avant tout, si cela n’est pas déjà fait, il vous faut commencer par lire l’article d’Olivier sur les modes et les fallbacks calculés lorsqu’un IActualKey n’existe pas dans le mode courant.

Désormais armés pour comprendre les modes ainsi que les fallbacks, voici le souci lié à l’ancienne conception de ces classes:

Les relations qui lient les IXXX aux ILayoutXXX sont de type 1:1, et cela est très bien … sauf pour les IKeyMode vs. IKeyModeLayout. En effet cela oblige chaque IKeyMode à « posséder » son ILayoutKeyMode, donc pour deux IKeyMode il faut deux ILayoutKeyMode distincts, ce qui impose donc redéfinir les valeurs des propriétés de ces ILayoutKeyMode, or dans la plupart des cas (99% je pense) les propriétés de layout (largeur, hauteur, position) ne changent pas entre deux IKeyMode différents (ce qui change, ce sont le comportement ou le label). Cela entraine une copie des données, et du coup une surcharge, aussi bien pour le système que pour l’utilisateur lors de la modification de l’affichage d’un clavier (pour déplacer une touche, il faudrait modifier la position de chacun de ses IKeyMode via chaque ILayoutKeyMode).

La solution trouvée à ce problème est assez simple, il suffit d’appliquer le même principe de fallback (la façon dont on retrouve le « meilleur » IKeyMode pour un mode donné) aux ILayoutKeyMode que celui applicable aux IKeyMode. L’impact est qu’il n’y a plus de lien direct entre un IKeyMode et un ILayoutKeyMode. Par contre il est toujours possible via tout IKey de retrouver le ILayoutKey courant, et sur cet ILayoutKey de trouver le « meilleur » ILayoutKeyMode calculé en fonction du mode courant (et non en fonction de l’IKeyMode courant).

Afin de faciliter la programmation, deux nouvelles interfaces ont étés introduites dans le modèle : un IKeyModeCurrent étend IKeyMode, et un ILayoutKeyModeCurrent étend ILayoutKeyMode. Ces deux interfaces ne peuvent être obtenues que via les différentes propriétés « Current » et ne font qu’ajouter une propriété « IsFallBack » qui est vrai si l’objet ne correspond pas exactement au mode courant (mais est juste le « meilleur » objet calculé pour le mode courant).

Pour plus de détails vous trouverez ici le diagramme de classes des objets du Contexte (aussi disponible dans le dossier Context/Model du projet CK.Context de la solution CK.Core).

Le fallback est plus simple à comprendre car il s’applique de façon indépendante aux touches et à leurs layouts. L’implémentation bénéficie également de cette simplification : les objets (internes au CK.Context) qui implémentent IKeyMode et ILayoutKeyMode utilisent exactement le même mécanisme de gestion des fallbacks (qui, à l’occasion, a été optimisé).