P
'
t
i
t
e
C
h
a
t
t
e
 
spacer~ I TOOK AN IQ TEST AND THE RESULTS WERE NEGATIVE Articles | Connexion
 
~Les collections en Squeak (Suite)

Précédent  
  Squeak  
  Suivant
 Présentation

Au cours de notre précédente étape dans le fabuleux monde de Squeak, nous avons appris à manipuler des collections. A l'aide de ces connaissances, nous allons rédiger une petite application en tirant profit.
 Sommaire


 Introduction

Chacun d'entre nous a probablement déjà collé un ou plusieurs petits rectangles jaunes adhésifs sur un coin de son écran afin de se rappeler quelque chose. Notre but sera ce mois-ci de réaliser une petite application graphique de prise de notes appelée Scribble.

L'originalité de notre outil réside dans son interface de communication avec l'utilisateur. Ce n'est pas le clavier, mais la souris qui doit être employée pour rédiger une note. On dessinera donc directement le message "à main levée" sur une zone précise de l'écran. La rédaction de notre programme va nous amener à utiliser les collections pour deux raisons bien distinctes.


 Un post-it

La première étape lors de la conception de notre utilitaire consiste à créer un composant graphique, un morph, possédant l'apparence d'un post-it. Le listing numéro un présente la déclaration de la classe "Scribble" servant à créer un nouveau morph. Ceci fait, il convient d'ajouter quelques lignes de code pour dessiner un rectangle jaune borduré de noir. Dans la liste des catégories de méthodes nous ajoutons donc la catégorie drawing dans laquelle nous créons le message drawOn: tel que décrit par le listing numéro deux. La taille par défaut d'un morph se révèle bien trop petite pour notre application. En surchargeant le message initialize nous pouvons attribuer à notre morph une taille plus importante dès sa création (listing 3). L'exécution de l'instruction "Scribble new openInWorld." dans un Transcript ou un Workspace affiche le post-it nouvellement créé. Malheureusement, l'interaction avec l'utilisateur se trouve plutôt mince pour l'instant.

Morph subclass: #Scribble
  instanceVariableNames: ''
  classVariableNames: ''
  poolDictionaries: ''
  category: 'Login-Squeak'
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
drawOn: aCanvas
  aCanvas fillRectangle: bounds color: Color yellow.
  aCanvas frameRectangle: bounds color: Color black.
       
      
JextCopier dans Jext
initialize
  super initialize.
  self extent: 320@240.
  self center: 320@240.
       
      
JextCopier dans Jext

 Gestion de la souris et collections

Un système simple pour conserver en mémoire un dessin tracé à la souris consiste à relier deux à deux par une ligne tous les points cliqués par l'utilisateur. Lors d'une opération de cliquer/glisser, de nombreux points seront considérés comme "cliqués". Pour garder trace du trajet de la souris, nous ajoutons une nouvelle variable d'instance intitulée path. Cette variable désigne une collection ordonnée que nous créons ainsi dans le message d'initialisation :

path := OrderedCollection new.
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Afin d'ajouter à cette collection les coordonnées des points du dessin, nous devons recevoir les évènements de la souris. Pour ce faire, nous allons activer la réception en surchargeant le message handlesMouseDown: de la sorte :

handlesMouseDown: evt
  ^true
       
      
JextCopier dans Jext
Dorénavant, tout évènement de clic sera transmis à notre morph par l'entremise du message mouseDown:. Les activations de la gestion du cliquer/glisser (mouseMove:) et de l'appui sur une touche (keyStroke:) se voient effectuées de la même manière. Les messages mouseDown: et mouseMove: peuvent à présent enregistrer toutes les positions de la souris :

mouseMove: evt
  path add: evt position - self position.
  self invalidRect: bounds.
       
      
JextCopier dans Jext
La soustraction de la position du morph à la position du clic se révèle extrêmement importante. En fait, tant que l'utilisateur ne déplace pas le post-it, aucun problème n'apparaît. Toutefois, si nous nous contentions d'enregistrer les positions telles quelles, le dessin du message serait relatif à l'écran et non au post-it. Déplacer le post-it ne déplacerait alors pas le dessin. La seconde ligne de ce message impose le rafraîchissement du morph et implique un nouvel appel à notre méthode drawOn:. Outre l'enregistrement des points, le message mouseDown: autorise l'effacement du post-it grâce à la gestion du bouton droit de la souris (appelé "yellow" en squeak) :

evt yellowButtonPressed ifTrue: [ path := OrderedCollection new. ]
ifFalse: [ path add: evt position - self position. ].
       
      
JextCopier dans Jext
Il convient enfin d'apporter quelques modifications à la méthode d'affichage pour faire apparaître le message. Aux quelques lignes présentées dans le listing 2, nous adjoignons donc le code source proposé par le listing 4. Le principe consiste à énumérer la collection path en commençant au second point. Chaque point énuméré se voit relié au point précédent par une ligne de couleur rouge. Bien évidemment, nous devons réaliser un test préalable pour s'assurer que la collection présent un minimum de deux éléments. Vous pourrez constater qu'aux coordonnées des points sont ajoutées les coordonnées du coin supérieur gauche du morph, ceci pour garantir que l'affichage s'opère relativement à ce dernier.

path size > 1 ifTrue: [
  2 to: path size do: [:i |
    aCanvas line: (path at: (i - 1)) + 
    self position to: (path at: i) + 
    self position color: Color red
  ]
].
       
      
JextCopier dans Jext

 Archivage des post-it

La méthode la plus intéressante se nomme keyStroke:. Celle-ci réagit aux appuis sur les touches de la part de l'utilisateur et nous offre l'opportunité d'implémenter quelques fonctionnalités supplémentaires. La première est bien sûr l'annulation du dernier point tracé, lié à la touche 'Z', en supprimant le dernier élément du chemin :

evt keyCharacter = $z ifTrue: [
  path removeLast.
  self invalidRect: bounds.
].
       
      
JextCopier dans Jext | Jext | Plugin Codegeek
Nous voyons ici l'intérêt d'une collection ordonnée : l'accès au dernier élément se fait directement. Les deux autres touches accessibles sont 'S' pour sauvegarder la note et 'L' pour en charger une. La sauvegarde comme le chargement ne demandent que quelques lignes de code et font appel aux collections de la catégorie "stream" servant aux entrées/sorties. Ainsi, le listing 5 démontre comment sauvegarder notre collection. Le nom du fichier doit être entré par l'utilisateur, reportez-vous donc au code source pour en savoir plus à ce sujet. Contrairement au processus de sauvegarde, celui de chargement possède sa propre méthode, intitulée loadFile:. Ceci nous permet de rédiger une méthode de classe, load décrite par le listing 6, dont le rôle sera de charger et d'afficher tous les post-it sauvegardés sur le disque dur de l'utilisateur.

Nous commençons par énumérer tous les fichiers portant l'extension, imposée par notre programme, '.scribble' se trouvant dans le répertoire racine de Squeak. Pour chacun de ces fichiers, une nouvelle instance de l'application s'exécute et charge le fichier considéré. En outre, chaque nouveau post-it créé se trouve décalé par rapport au précédent. Enfin, un post-it vierge apparaît. Ainsi, en exécutant la simple commande "Scribble load", l'utilisateur de l'application aura à sa disposition toutes ses anciennes notes ainsi qu'un espace de travail vierge.

fileStream := FileStream newFileNamed: aFileName.
fileStream store: path.
fileStream close.
       
      
JextCopier dans Jext
load
  | dir files scribbler i |
  i := 0.
  dir := FileDirectory on: (FileDirectory dirPathFor: Smalltalk imageName).
  files := dir fileNamesMatching: '*.scribble'.
  files do: [:file |
    i := i + 1.
    scribbler := Scribble new.
    scribbler loadFile: file.
    scribbler center: 320@240 + ((10@10) * i).
    scribbler openInWorld.
  ].
  Scribble new openInWorld.(((rubrique: Pratique Squeak)))
       
      
JextCopier dans Jext
Le code source complet du programme "Scribble" se trouve sur le CD-Rom accompagnant ce magazine.



par Romain Guy
romain.guy@jext.org
http://www.jext.org
Dernière mise à jour : 14/10/2006


Précédent  
  Squeak  
  Suivant

 
#ProgX©2005 Mathieu GINOD - Romain GUY - Erik LOUISE