UNIVERSITÉ DE CAEN Maitrise d’informatique U.F.R. de Sciences Projet annuel

ENLIGHTENSQUEAK

Loeweistein Nicolas Responsable du projet Perigois Nicolas Serge Stinckwich

Table des matières

Remerciements 3

Introduction 4 Présentation du projet . . . . . . . . . . . . . . . . . . . . . . . . . 4 Motivation dans le choix du projet . . . . . . . . . . . . . . . . . . 4 Plan du rapport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1 Squeak 5

2 Un gestionnaire de raccourcis 6 2.1 Qu’est ce qu’un raccourci ? . . . . . . . . . . . . . . . . . . . . 6 2.2 Quel est l’intêret d’un tel gestionnaire ? . . . . . . . . . . . . . 6 2.3 Comment sont implémentés nos raccourcis ? . . . . . . . . . . 6

2.3.1 La classe ChangeShortcuts . . . . . . . . . . . . . . . . 6 2.3.2 La classe OneShortcut . . . . . . . . . . . . . . . . . . 9 2.3.3 La classe Shortcuts . . . . . . . . . . . . . . . . . . . . 10

2.4 La méthode keystrokeInWorld . . . . . . . . . . . . . . . . . . 11 2.5 Comment utiliser notre interface ? . . . . . . . . . . . . . . . . 14 2.6 Comment ajouter une nouvelle source ? . . . . . . . . . . . . . 17

3 Un gestionnaire de bureaux 18 3.1 Les besoins . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 3.2 La premiére idée : utilisation des projets . . . . . . . . . . . . 18 3.3 La classe InternalThreadNavigationMorph . . . . . . . . . . . 18

4 Améliorations possibles 20

Conclusion 21

REMERCIEMENTS

Avant d’aborder ce rapport, nous tenions à remercier :

M. Serge STINCKWICH, responsable du projet, pour la confiance qu’il a bien voulu nous témoigner en nous confiant ce travail et pour ses conseils avisés,

M. Romain ROBBES, étudiant en DEA et M. Samir SAIDANI, doctorant au laboratoire GREYC de Caen en IA, pour l’aide qu’ils nous ont apportée.

Introduction

Présentation du projet

Dans le cadre du projet annuel, nous avons choisi le thème "EnlightenSqueak" sous la direction de Monsieur Serge Stinckwich. L’objectif de ce projet est de rendre l’environnement Squeak plus agréable d’utilisation (placement de fenêtres, bureaux virtuels, gestion des raccourcis). Faute de temps, nous avons seulement développé la gestion des raccourcis et nous nous en sommes servis pour gérer les bureaux virtuels.

Motivation dans le choix du projet

Nous avons choisi ce thème en partie grâce à un ami qui a utilisé Squeak l’an passé pour son projet annuel et qui nous en a dit beaucoup de bien. De plus, cela nous permettait de découvrir un nouvel environnement et un nouveau langage. Enfin, nous étions très attiré par le fait que notre projet serait envoyé aux autres utilisateurs de Squeak et utilisé par ces derniers, plutôt que mis dans un coin et oublié comme c’est souvent le cas.

Plan du rapport

Dans un premier temps, nous présenterons brièvement l’environnement Squeak. Puis, nous décrirons le contenu de notre projet. Enfin, nous verrons les améliorations qui peuvent être faites.

1 Squeak

Construit sur un langage objet homogène et très puissant, Squeak offre un environnement de développement efficace et très bien adapté au développement orienté objet, une très importante bibliothéque de classes, et permet une productivité et une souplesse de développement difficiles à égaler. Totalement gratuit et open source, surporté par une importante communauté de developpeurs dans le monde, facile à maintenir et à faire évoluer, Squeak a des avantages qui en font un concurrent de poids dans la «competition» des langages et des environnements de developpement pour le prototypage rapide, le developpement Internet, et les applications multimédia, ainsi que pour le developpement d’application de gestion, pour lesquelles la modélisation objet est tout indiquée. Produit jeune, puisque son devellopement a commencé en 1996, Squeak bénéficie pourtant de plus de trente ans d’expérience en développement orienté-objet, et tire largement profit des travaux effectués dans les communautés Smalltalk, Self et Java.

2 Un gestionnaire de raccourcis

2.1 Qu’est ce qu’un raccourci ?

Dans un environnement informatique, un raccourci est une combinaison de touches qui, une fois pressées, exécute une action qui a été au préalable définie. Par exemple, sur le World^{1} de Squeak, si vous utilisez la combinaison de touches Alt-b, vous ouvrirez une fenêtre de navigation dans les classes de Squeak.

2.2 Quel est l’intêret d’un tel gestionnaire ?

L’environnement Squeak donne la possibilité à ses utilisateurs d’utiliser des raccourcis prédéfinis pour exécuter certaines actions. Malheureusement, l’utilisateur ne peut pas les modifier, les supprimer ou même en ajouter de nouveaux. Le seul moyen pour lui est de trouver la méthode où les raccourcis sont définis et de modifier directement le code de cette dernière. Un gestionnaire de raccourcis était donc nécéssaire afin de donner la possibilité aux utilisateurs de Squeak de modifier les raccourcis au moyen d’une petite interface, sans avoir à modifier directement le code de Squeak.

2.3 Comment sont implémentés nos raccourcis ?

Nous avons créé trois classes :

1. ChangeShortcuts

2. OneShortcut

3. Shortcuts

2.3.1 La classe ChangeShortcuts

La classe ChangeShortcuts hérite de la classe Morph qui gère tout ce qui est graphique sous Squeak. Elle contient toutes les méthodes qui ont servies à créer notre interface. Nous n’allons pas détailler ces méthodes car ce serait long et inutile. Cependant, cette classe ne contient pas que des méthodes graphiques. En effet, lorsqu’un utilisateur ajoute ou modifie un raccourci, plutôt que de saisir directement au clavier la combinaison de touches propre au raccourci, il peut directemnt le capturer. Par exemple, au lieu d’écrire en toute lettre “Alt-b”, il appuiera sur les touches “Alt” et “b” ce qui écriera “Alt-b” dans la zone de saisie. Pour pouvoir capturer ces évenements, nous avons dû redéfinir deux méthodes de la classe Morph :

1Le World correspond au bureau.

1. handlesKeyboard

2. keystroke

La méthode handlesKeyboard est définie comme suit :

handlesKeyboard: evt
^true

Elle donne le “droit” de capturer les événements. Si elle renvoyait le booléen false au lieu de true, nous ne pourrions récupérer les événements claviers. Remarque : la méthode handlesKeyboard permet de capter les événements mais une autre commande est nécéssaire :

World currentHand addKeyboardListener: self

Cela autorise notre interface (ou plutôt notre méthode keystroke) à gérer les événements clavier lancés sur le World. Pour reperdre la main, on utilise la commande suivante :

World currentHand removeKeyboardListener: self

Cette dernière est très importante car, si on l’oublie, notre méthode keystroke sera exécutée à chaque utilisation du clavier que l’on est lancé notre interface ou non et que l’on soit sur le World ou non.

La méthode keystroke :

keystroke: evt
| car ctrl alt asc |
car := evt keyCharacter.
asc := car asciiValue.
ctrl := controlKeyPressed.
alt := commandKeyPressed.
ctrl ifTrue: [
      val := 'Ctrl-', (self controlKey: asc).

      rac setText: 'Ctrl', (self controlKey: asc)].
alt ifTrue: [
      val := 'Alt-', car asText.
      rac setText: 'Alt-', car asText].
(ctrl and: alt) ifTrue: [rac setText: 'Ctrl-Alt-']. ``Dont't serve''

Cette méthode définit ce qui se passe lorsque l’on capte un événement clavier . Le paramètre evt est l’événement en question. A partir de cette variable, on peut récupérer le caractère grâce à la méthode keyCharacter ainsi que sa valeur ascii à l’aide de la méthode asciiValue que l’on applique au caractère que l’on vient de récupérer. ControlKeyPressed et commandKeyPressed renvoient chacune un booléen qui indique si, en plus du caractère, les touches Ctrl ou Alt ont été utilisées. Suivant que les variables ctrl ou alt aient la valeur true, on écrit Ctrl-le_caractère ou Alt-le_caractère dans notre fenêtre de saisie représentée ici par la variable rac. La variable val sert à stocker la combinaison de touches et sera donc utilisée lors de la modification (ou l’ajout) du raccourci. On peut voir que pour la cas d’une touche Ctrl de pressée, on utilise une méthode controlKey. Nous avons créé cette dernière car, sous Squeak, la touche Ctrl n’est pas très bien gérée. En effet, comme nous l’avons dit précédemment, nous pouvons récupérer le code ascii de chaque caractère. Mais, si cette valeur reste la même lorsqu’on utilise la touche Alt, elle diffère avec la touche Ctrl. Un événement Ctrl-un_caractère_de_l_alphabet renverra une valeur comprise entre 1 et 26. A l’affichage, nous ne pouvons donc pas utiliser la méthode keyCharacter qui se base sur la code ascii. Lorsque l’on utilise la touche Ctrl, notre variable car reste donc vide car, entre 1 et 26, il n’y a pas de caractères ascii de définis. D’où la méthode controlKey :

controlKey: asciiValue
|tabChar char|
tabChar := #(a b c d e f g h i j k l m n o p q r s t u v w x y z).
char := tabChar atWrap: asciiValue.
char := char asString.
^char

Cette méthode renvoie donc le caractère correspondant à la valeur ascii et est appelée lorsqu’une touche Ctrl est pressée. Pour ce faire, nous utilisons simplement un tableau contenant les différentes lettres de l’aphabet et nous renvoyons la asciiValueième valeur du tableau. La tâche nous est simplifiée du fait que la valeur est comprise entre 1 et 26. Comme on peut le voir, nous ne pouvons utiliser avec Ctrl que les lettres de l’alphabet et, qui plus est, en minuscule. En effet, Squeak ne capte pas la touche shift lorsqu’elle est utilisée avec Ctrl. Quant aux caractères spéciaux ( ! é () etc...) certains ne sont pas captés et les autres ont des valeurs ascii nettement supérieures à 26 et qui ne se suivent pas ce qui les rend difficiles à entrer dans notre tableau. Plutôt que de faire du cas par cas, nous avons donc décidé de nous en tenir aux 26 lettres de l’alphabet en minuscule. Alt pouvant être utilisée avec n’importe quelle touche, quelle soit en minuscule ou en majuscule, et avec les caractères spéciaux, limiter Ctrl n’est donc pas très embêtant, on reste avec un nombre de combinaisons satisfaisables. Un autre problème avec la touche Ctrl est qu’elle empèche également l’utilisation de la touche Alt, la combianaison Ctrl-Alt-un_caractère se révèle donc inutilisable.

2.3.2 La classe OneShortcut

La classe OneShortcut permet de créer un raccourci. Elle comprend quatre variables :

1. key

2. action

3. description

4. source

5. preference La variable key contient la combinaison de touches du raccourci sous

forme de chaine de caractères (’Alt-X’, ’Ctrl-a’, ’r’ etc ...).

Action représente le code exécuté par le raccourci sous forme de chaine de caractères délimitée par les caractères [ et ].

Descr est utilisée lors de l’affichage des raccourcis dans notre interface. Nous préférons afficher une petite description plutôt que le code qui peut être long et pas très parlant.

Source correspond à l’environnement sur lequel le raccourci doit être exécuté. Par exemple, en ce qui nous concerne, nous n’avons tenu compte que des raccourcis du World, c’est pourquoi tous nos raccourcis ont le mot ’World’ comme source.

Sous Squeak, on peut définir des préférences et certains programmes nécéssite une préférence particulière pour être exécutée. Preference contient donc les preferences nécéssaires à l’exécution du raccourci.

Les méthodes de cette classe permettent de créer un raccourci, d’affecter une valeur à une variable ou d’en renvoyer une.

2.3.3 La classe Shortcuts

La classe Shortcuts contient quatre variables :

1. TabShortcuts

2. Evt

3. NbShortcuts

4. Pref

La variable TabShortcuts est une OrderedCollection et contient des objets de type OneShortcut c’est à dire nos raccourcis. Une OrderedCollection est une structure permettant de stocker des objets. L’avantage d’utiliser une telle structure et que l’on n’a pas besoin d’allouer de mémoire lors de sa création, ce qui est très utile dans la mesure où on ne connait pas le nombre de raccourcis qu’il faudra entrer.

Evt contient l’événement clavier. Nous le stockons car les actions des raccourcis peuvent en avoir besoin.

NbShortcuts contient le nombre de raccourcis présents dans la variable TabShortcuts.

Nous expliquerons l’utilité de la variable Pref ultérieurement lorsque nous parlerons de la méthode keystrokeInWorld.

La classe Shortcuts contient des méthode permettant de renvoyer les valeurs de ses variables, de leur en affecter d’autres, de supprimer un raccourci, d’en ajouter un, d’en rechercher un en fonction de sa combinaison de touches et de sa source. Nous disposons également de la méthode refresh dont le but est de supprimer les cases vides dans TabShortcuts. Un vide apparait lorsque l’on supprime un raccourci et peut, par la suite, géner le bon déroulement du programme. Enfin, initialize permet d’initialiser notre système en créant tous les raccourcis qu’il y avait de base(ceux du World) et que nous avons redéfinis. Désormais, Squeak utilise les raccourcis présents dans TabShortcuts.

2.4 La méthode keystrokeInWorld

KeystrokeInWorld est une méthode de la classe PasteUpMorph. C’est elle qui capte les événements du clavier quand on est sur le World. C’est une méthode propre à Squeak et que nous avons été contraints de modifier. Voici à quoi ressemblait cette méthode avant que nous nous en servions :

keystrokeInWorld: evt
| isCmd val isCtrl shortcut index action char aChar |
aChar := evt keyCharacter.
aChar asciiValue = 27 ifTrue:
   [^ActiveWorld putUpWorldMenuFromEscapeKey].
isCmd := evt commandKeyPressed and: [Preferences cmdKeysInText].
(evt commandKeyPressed and: [Preferences eToyFriendly])
       ifTrue:
          [(aChar == $W) ifTrue: [^self putUpWorldMenu: evt]].
(isCmd and: [Preferences honorDesktopCmdKeys])
       ifTrue:
          [(aChar == $o) ifTrue: [^ActiveWorld activateObjectsTool].
           (aChar == $F) ifTrue:
                [^CurrentProjectRefactoring currentToggleFlapsSuppressed].
           (aChar == $N) ifTrue:
              [Preferences classicNavigatorEnabled
                  ifTrue: [^Preference togglePreference: #showProjectNavigator]].
           (aChar == $r) ifTrue: [^ActiveWorld restoreMorphicDisplay].
       Preferences eToyFriendly
            ifFalse:
               [(aChar == $/) ifTrue: [^SystemWindow sendTopWindowToBack].
                (aChar == $b) ifTrue: [^RefactoringBrowser openBrowser].
                (aChar == $k) ifTrue: [^Workspace open].
                (aChar == $m) ifTrue:
                     [^TheWorldMenu new adaptToWorld: World; new Morph].

              (aChar == $t) ifTrue: [^self findATranscript: evt].
              (aChar == $w) ifTrue: [^SystemWindow closeTopWindow].
              (aChar == $z) ifTrue:
                   [^self commandHistory undoOrRedCommand: evt].
              (aChar == $C) ifTrue: [^self findAChangeSorter: evt].
              (aChar == $L) ifTrue: [^findAFileList: evt].
              (aChar == $R) ifTrue: [^openRecentSubmissionsBrowser: evt].
              (aChar == $P) ifTrue: [^findAPreferencesPanel: evt].
              (aChar == $W) ifTrue: [^findAMessageNamesWindow: evt].]]

Comme on peut le voir, cette méthode n’est composée que d’une succession de conditions, une par raccourci. En ajouter, supprimer ou modifier un obligeait donc à modifier directement cette méthode.

Nouvelle version de keystrokeInWorld :

keystrokeInWorld: evt
| isCmd val isCtrl shortcut index action char aChar |
Shortcuts Pref ifTrue: [
isCmd := evt commandKeyPressed and: [Preferences cmdKeysInText].
isCtrl := controlKeyPressed.
val := evt keyCharacter asciiValue.
Shortcuts event: evt.
isCmd ifTrue: [shortcut := 'Alt-', (Character value: val) asString].
isCtrl ifTrue: [
  char := ChangeShortcuts someInstance controlKey: val.
  shortcut := 'Ctrl-', char.]
(isCmd or: isCtrl) ifFalse: [shortcut := (Character value: val)
asString].
index := Shortcuts searchShortcut: shortcut source: 'World'.
index > 0 ifTrue: [
  action := (Shortcuts tabShortcuts at: index) action.
  (Compiler evaluate: action) value]].
Shortcuts Pref ifFalse: [
CODE DE L'ANCIENNE VERSION DE KEYSTROKEINWORLD
]

Nous récupérons l’événement, le mettons sous la forme ’Alt-X’, ’Ctrl-X’ ou X. Puis, nous vérifions que cette combinaison est utilisée par l’un de nos raccourcis. Si c’est le cas, nous exécutons l’action correspondante.

Nous pouvons voir également l’utilisation de la variable Pref de la classe Shortcuts dont nous avons parlé précédemment. Elle a pour but de laisser aux utilisateurs la possibilité de garder et utiliser l’ancienne version de keystrokeInWorld en lui affectant le booléen false. En effet, si nous nous étions contenté de remplacer l’ancien code par le nouveau, les personnes qui auraient installer notre projet aurait perdu l’ancienne version de la méthode keystrokeInWorld. Ceci aurait rendu l’utilisation des raccourcis du World inutilisable à moins de se servir de notre projet.

2.5 Comment utiliser notre interface ?

Pour lancer notre interface, l’utilisateur doit lancer la commande suivante :

ChangeShortcuts new window.

Il peut également utiliser le raccourci ’Alt-c’ qui n’était bien sûr pas présent dans la liste des raccourcis de base du World, mais que nous nous somme permis d’ajouter. Au préalable, l’utilisateur doit bien sûr avoir initialisé nos raccourcis :

Shortcuts initialize.

et autorisé leur utilisation :

Shortcuts pref: true.

L’utilisateur verra donc apparaître la fenêtre suivante :

Fig. 1 – Fenêtre principale

Comme on peut le voir sur la figure ci-avant, lorsque l’on lance l’interface, une fenêtre apparait avec la liste des raccourcis. Pour chacun d’entre eux, on peut voir sa description, la combinaison de touches pour l’exécuter et sa source.

En bas de la fenêtre principale apparait un bouton next et/ou un bouton prev permettant de naviguer parmis les raccourcis dont on affiche que quinze à la fois.

On peut ajouter un raccourci au moyen du bouton add shortcut :

Fig. 2 – Fenêtre d’ajout d’un raccourci

A partir de cette fenêtre, l’utilisateur doit entrer la description du nouveau raccourci, sa source, sa combinaison de touches (key) qui, rappellons-le, peut être capturée et le code qui sera exécuté. Le code devra être écrit entre les crochets. Il devra également rentrer les éventuels préférences que le raccourci nécéssite (true par défaut).

Remarque : Si la personne veut n’utiliser qu’un caractère comme combinaison de touche, il doit le saisir normalement. Nous aurions pu laisser la méthode keystroke s’en charger mais le problème est que, lorsque l’on aurait rempli les autres zones de texte, la même chose serait apparue dans zone prévue pour la combinaison.

Les raccourcis peuvent également être modifiés ou supprimés à l’aide de boutons. Lors d’une suppression à l’aide du bouton delete, l’on demande à l’utilisateur de confirmer son choix ce qui évite de perdre un raccourci parcequ’il s’est trompé de bouton.

Fig. 3 – Fenêtre de confirmation

Le bouton change permet donc de modifier un raccourci :

Fig. 4 – Fenêtre de modification d’un raccourci

Cette fenêtre est identique à celle permettant d’ajouter un raccourci, à la différence que les zones sont déjà remplies par les éléments du raccourci que l’on veut modifier.

2.6 Comment ajouter une nouvelle source ?

Comme nous l’avons déjà dit, nous n’avons modifié que le mode d’utilisation des raccoucis du World. Cependant, un utilisateur de Squeak qui, normalement, connait le SmallTalk, doit pouvoir adapter notre projet et faire en sorte qu’il s’adapte à d’autres sources que le World. Pour ce faire, il lui suffit, de trouver la méthode captant les raccourcis de cette source et de la modifier tel que nous l’avons fait pour la méthode keystrokeInWorld de la classe PasteUpMorph. Si cette source avait déjà des raccourcis qu’il veut garder, il devra les rentrer dans la méthode initialize de notre classe Shortcuts. Il est même préférable qu’il recréé une méthode et l’appelle dans initialize comme nous l’avons fait avec notre initializeWorldShortcuts. Une fois cela fait, il ne reste plus qu’à réinitialiser la classe Shortcuts. Remarque : l’utilisateur qui réinitialise la classe perd tous les raccourcis qu’il a pu ajouter au moyen de notre interface car ces derniers ne sont pas codés en dur dans Squeak.

3 Un gestionnaire de bureaux

3.1 Les besoins

Les bureaux sont des conteneurs de fenêtres. On doit pouvoir passer de l’un à l’autre, en ajouter ...

3.2 La premiére idée : utilisation des projets

En Squeak, il est possible de sauvegarder, dans un projet, l’état courant de l’environnement de développement, afin de pouvoir y revenir par la suite ; la position des fenêtres, l’état des variables, les modifications du code, sont ainsi mémorisés. Un projet est en fait une entité logique qui regroupe tous les développements relatifs à un sujet donné, ainsi que les différentes fenêtres utilisées pour le développement.

Il est raisonnable de penser qu’il est possible de répondre au problème de bureaux virtuels, en utilisant les projets.

De plus, en approfondissant la recherche dans cette direction, nous avons découvert l’existance de la classe ProjectViewMorph, qui est une miniature du projet vers lequel elle pointe. Le simple fait de cliquer dessus avec la souris permet de rentrer dans ce projet.

Une de nos première réalisation fut donc la création d’un Alignment-Morph, contenant la liste des projets. Cette solution, bien que répondant à nos critères fonctionnels et esthétiques, n’était pas très propre. En effet, de par la nature des projets, nous avions une copie de AlignmentMorph dans chaque projet.

3.3 La classe InternalThreadNavigationMorph

Aprés avoir regardé en détail la classe InternalThreadNavigation-Morph. Cette classe permet de naviguer à travers les projets. Le menu que vous obtenez quand vous cliquez sur le point milieu du thread vous permet d’éditer le thread. Il vous donne une trieuse de projet. on peut alors réarranger les représentations des thumbnails des projets.

En alliant cette classe avec une pincée de gestionnaire de raccourci. Nous obtenons un magnifique gestionnaire de bureau.

Cependant pour que l’utilisation des raccourcis soit possible, il faut que dans tous les projets, on dispose d’une référence sur l’instance de Internal-ThreadNavigationMorph. Nous avons donc ajouté une variable globale MultiDesktop.

Smalltalk at: #MultiDesktop put: (InternalThreadNavigationMorph new).

MultiDesktop initialize.

Pour utiliser les fonctionnalités de InternalThreadNavigationMorph, correspondant à nos besoins relatifs à la gestion de bureaux virtuels, nous ajoutons les raccourcis suivants :

Action  code
Aller au i^{me} bureau  MultiDesktop jumpToIndex : i.
Aller dans un bureau  MultiDesktop jumpWithinThread.
Créer un nouveau bureau  MultiDesktop insertNewProject.
Modifier L’ordre des bureaux MultiDesktop editThisThread.

il est possible de regarder les méthodes de la classe, ou le menu qui s’ouvre lorsque l’on clique sur le bouton du milieu du thread. Et ainsi obtenir de nouvelles fonctionnalités au gestionnaire de bureaux.

4 Améliorations possibles

Faute de temps, en partie due à une adaptation difficile à Squeak, nous n’avons pu faire les choses suivantes :

– utiliser les halos et en configuerer un qui attribuerait un raccourci au morph auquel il est lié. Par exemple, sur une fenêtre le raccourci permettrait de l’ouvrir et sur un bouton, d’exécuter l’action du bouton.

– utiliser la classe Preferences au lieu d’ajouter une variable dans notre classe Shortcuts pour dissocier l’ancien code de la méthode keystrokeInWorld du nouveau.

– gérer d’autres raccourcis que ceux du World, en particulier ceux de la classe ParagraphEditor où sont définis les raccourcis propres au zones de texte (copier, coller ...).

– faire des stratégies de placement de fenêtre.

Conclusion

Faire ce projet fut d’en un premier temps plutôt pénible. Autant la programmaton en SmallTalk est facile, autant l’appliquer sous Squeak est difficile. En effet, pour modifier Squeak nous avons besoin d’utiliser les classes et méthodes qui le composent. Cependant, avant d’utiliser l’une d’entre elle il faut la trouver, ce qui est loin d’être une partie de plaisir lorsqu’il y a plusieurs milliers de classes et si peu de documentation de Squeak. Nous avons donc passé la plupart de notre temps sur les browsers à chercher les méthodes dont nous avions besoin ce qui nous a empéché de faire tout ce que nous voulions. Cependant, une fois que l’on s’est bien habitué à Squeak, que l’on ne passe plus des heures à trouver une méthode et à la faire fonctionner, on s’aperçoit vite que Squeak est un outil aux très grandes possibilités et qui devient vite agréable d’utilisation. Et ce à tel point que nous pensons continuer à travailler sur notre projet et concrétiser tout ce que nous n’avons pu faire faute de temps.