Archives pour la catégorie Tutorials

Crée tes propres menus sans limite !

Aujourd’hui nous allons apprendre quelque chose qui vous sera extrêmement utile dans vos programmes Lua.
Vous connaissez surement ces fameux menus sur la plupart des applications de votre TI-nspire, que l’on ouvre avec la touche menu, et ou l’on peut soit choisir l’option avec le touchpad, soit sélectionner une lettre ou un chiffre pour exécuter la commande.
Vous devriez penser que reproduire cela sur vos applications Lua est très peu envisageable, vue qu’il faudrait beaucoup de code pour reproduire ces menus de manière exacte.
Pourtant, c’est bien plus simple que vous ne le pensez.

En effet, depuis l’os 3.0, le Lua intègre une fonction très intéressante, la fonction toolpalette.register.
Mais comment elle fonctionne ?
Ce que nous allons faire maintenant, c’est créer une table (si vous ne connaissez pas ce genre de variable en Lua, allez vous renseigner).
Une table qui va contenir toutes les informations nécessaires à notre menu. Voici donc un exemple qui vous fera comprendre plus vite que des mots :

votreTable = {
    {"Couleur",  --Menu parent
        {"Rouge"},  -- Sous options
        {"Vert"},
        {"Bleue"}
    }
}

Notez que vous pouvez très bien construire votre table de la manière suivante :

 votreTable = {{"Couleur",{"Rouge"},{"Vert"},{"Bleue"}}}

Mais la manière montrée au dessus est bien plus claire et lisible, grâce à l’indentation.

Si vous l’avez bien compris, ce menu va nous servir d’abord à choisir l’option Couleur, puis choisir notre couleur entre Rouge, Vert et Bleue.
Super, vous avez crée votre table, qu’est ce qui vous reste à faire ?
Nous allons simplement utiliser le toolpalette.register cité plus haut :

toolpalette.register(votreTable)

Et voila, vous pouvez essayer et voire votre magnifique menu ! …Mais que ce passe-t-il, Erreur ?
Oui, comme l’indique votre erreur, vous devez associer une fonction à votre table. Sinon votre menu ne servirait qu’à décorer.
Notre superbe menu sert à changer la couleur du fond, nous allons donc devoir faire quelques réglages avant de pouvoir admirer le travail.

D’abord, nous allons créer la fonction qui changera notre couleur. Nous allons l’appeler changerCouleur(menuparent,option).
Les deux arguments de cet fonction sont prédéfinis par toolpalette, le premier renvoie le menu parent (ici, l’option « Couleur ») tandis que l’autre renvoie l’option qu’on a sélectionné (Rouge, Vert ou Bleue)
Nous allons également créer une table couleurdufond qui contiendra l’information de quelle est la couleur du fond (par défaut, le blanc : {255,255,255}).
Il nous suffit juste de rajouter un misérable test « If » pour changer la variable couleurdufond en fonction de notre choix d’option.
Voila ce que ca donne :

couleurdufond = {255,255,255}
 
function changerCouleur(menuparent,option)
    if option=="Rouge" then
        couleurdufond = {255,0,0}
    elseif option=="Vert" then
        couleurdufond = {0,255,0}
    elseif option=="Bleue" then
        couleurdufond = {0,0,255}
    end
    platform.window:invalidate()
end

Notez le platform.window:invalidate() à la fin de la fonction changerCouleur, qui sert à appeler on.paint(gc) pour repeindre l’écran avec la nouvelle couleur.
Voila, c’est presque terminé. Plus qu’à coder notre fonction on.paint(gc) :

w = platform.window:width()
h = platform.window:height()
 
function on.paint(gc)
    gc:setColorRGB(unpack(couleurdufond))
    gc:fillRect(0,0,w,h)
end

Le unpack comme son nom l’indique, sert simplement à « casser » la table pour revoyer les valeures qu’elle contient une par une.

Et voila le tant attenu résultat :

Et le beau code source qui va avec :

w = platform.window:width()
h = platform.window:height()
 
couleurdufond = {255,255,255}
 
function changerCouleur(menuparent,option)
    if option=="Rouge" then
        couleurdufond = {255,0,0}
    elseif option=="Vert" then
        couleurdufond = {0,255,0}
    elseif option=="Bleue" then
        couleurdufond = {0,0,255}
    end
    platform.window:invalidate()
end
 
votreTable = {
    {"Couleur",
        {"Rouge",changerCouleur},
        {"Vert",changerCouleur},
        {"Bleue",changerCouleur}
    }
}
 
toolpalette.register(votreTable)
 
function on.paint(gc)
    gc:setColorRGB(unpack(couleurdufond))
    gc:fillRect(0,0,w,h)
end

Nous allons maintenant apprendre à activer/désactiver une option, grâce à la fonction toolpalette.enable(menuparent,option,booléen)
Comme pour notre fonction changerCouleur, l’argument menuparent renvoie « Couleur » alors que l’option renvoie Rouge, Vert ou Bleue.
Si on veut activer l’option, on indique true en dernier argument, sinon, on indique false.
Pour l’exemple, nous allons désactiver l’option Vert :

toolpalette.enable("Couleur","Vert",false)

Voila ce que ça donne :

Pour finir, une bonne petite astuce : la création de raccourcis, très utiles pour éviter d’avoir à chaque fois de réouvrir le menu.
Il vous suffira juste d’indiquer quel est le raccourci dans le menu, et de créer votre fonction on.charIn(touche) :

Ici, notre raccourci seront les touches « r », « v » ou « b » :

function on.charIn(touche)
    if touche=="r" then
        couleurdufond = {255,0,0}
    elseif touche=="v" then
        couleurdufond = {0,255,0}
    elseif touche=="b" then
        couleurdufond = {0,0,255}
    end
    platform.window:invalidate()
end

Et voila, c’est finit, vous maîtrisez les menus maintenant. C’est à vous de libérer votre créativité et coder des programmes epoustouflants en Lua, amusez vous bien 😉

Téléchargement du fichier : Classeur1

Un nouveau Screen Manager plus intelligent

Ca ne fait pas si longtemps que Jim Bauwens nous a agréablement surpris avec une façon élégante de personnaliser l’objet « gc » avec vos propres fonctions. Mais il frappe encore !

En effet, il a trouvé/créé un nouveau moyen, plus intelligent qu’avant, de créer un Screen Manager. Si vous n’êtes pas familier avec ce superbe concept, allez-donc vous renseigner 😉
Pour ceux qui le sont, par contre, vous devez savoir qu’une partie du code nécessaire est le listing/lien complet des fonctions à utiliser, des événements vers les screens.

Par exemple :

function on.arrowKey(key) activeScreen:arrowKey(key) end
function on.timer() activeScreen:timer() end
 
-- long list of all handled events...       Then, somewhere else :
 
function myScreen:arrowKey(key)
    -- Your awesome code goes here
end
function myScreen:timer()
    print("I'm the myScreen timer, ticking....")
end
 
-- etc.

Ca marche, certes, mais … c’est un peu barbant.

Allons voir ce que Jim a créé.
Je définis cette nouvelle façon comme « plus intelligente » parce qu’avec ce code, vous n’aurez même plus besoin explicitement de vous tracasser sur la gestion des événements comme vous en avez l’habitude (avec des on.arrowKey, on.enterKey… ou le bon vieux on.paint ). Oui, vous avez bien lu : plus besoin de « function on.paint(gc) … » etc. !

« Qu’est-ce que c’est que cette magie noire », me direz-vous ?
Hé bien, encore une fois, tout repose sur l’utilisation futée des métatables Lua.
En gros, les métatables sont un ensemble de propriétés définissant le comportement d’un objet (généralement une table).
Il existe une propriété « __index » que vous pouvez définir, qui va décrire comment la table réagira quand le script appelle un élément non-défini de celle-ci. Assez utile, croyez-moi 😉
Bref, le truc c’est que quand vous écrivez « function on.paint(gc) », tout ce que vous faites, c’est implémenter la méthode « paint » de la table « on » (d’où le point).
Ce que l’on souhaite pouvoir faire, c’est de se débarasser de cette décalration explicite, et de rediriger l’événement « paint » vers tel ou tel Screen (et les autres événements aussi…)
Bref, nous allons donc utiliser une méthode « eventDistributer » qui prend comme arguments tout ce qui lui est passé, grâce à l’utilisation de « … » (l’événement suivi de ses paramètres, si c’est le cas), et qui les « passe » au Screen que l’on veut (tout en vérifiant que cela est bien possible pour le screen en question):

local triggeredEvent = "paint"  -- first declaration, it will be overwritten anyway
local eventDistributer = function (...)
     local currentScreen = GetScreen()
     if currentScreen[triggeredEvent] then
         currentScreen[triggeredEvent](currentScreen, ...)
     end
end

Ce code devrait vous paraître assez clair.

Ce qu’il nous reste désormais à faire, c’est de lier cette fonction à l’__index de la métatable de « on » (vous remarquerez l’intelligente utilisation des closures) :

local eventCatcher = {}
 
eventCatcher.__index = function (tbl, event)
    triggeredEvent = event
    return eventDistributer
end
 
setmetatable(on, eventCatcher)

Ce code permet au script de comprendre que quand un événement, sans handler explicite, est déclenché, il devra exécuter cette fonction (qui retourne (closure) une fonction qui prendra les arguments de l’événement et qui redirigera le tout via l’eventDistributer, donc vers l’event handler approprié du bon Screen). Je conçois que ceci peut vous paraître un peu confus/complexe, mais vous finirez par comprendre 🙂

Bref, voila le code complet du Screen Manager et de l’eventDistributer.
(Comme d’habitude, vous aurez à créer (et push) vos Screens, par la suite)

local screens = {}
local screenLocation = {}
local currentScreen = 0
 
function RemoveScreen(screen)
    screen:removed()
    table.remove(screens, screenLocation[screen])
    screenLocation[screen] = nil
    currentScreen = #screens -- sets the current screen as the top one on the stack.
    if #screens<=0 then print("Uh oh. This shouldn't have happened ! You must have removed too many screens.") end
end
 
function PushScreen(screen)
    -- if already activated, remove it first (so that it will be on front later)
    if screenLocation[screen] then
        RemoveScreen(screen)
    end
 
    table.insert(screens, screen)
    screenLocation[screen] = #screens
 
    currentScreen = #screens
    screen:pushed()
end
 
function GetScreen()
    return screens[currentScreen] or RootScreen
end
 
Screen = class()
 
function Screen:init() end
 
function Screen:pushed() end
function Screen:removed() end
 
RootScreen = Screen() -- "fake", empty placeholder screen.
 
local eventCatcher = {}
local triggeredEvent = "paint"
 
local eventDistributer = function (...)
     local currentScreen = GetScreen()
     if currentScreen[triggeredEvent] then
         currentScreen[triggeredEvent](currentScreen, ...)
     end
end
 
eventCatcher.__index = function (tbl, event)
    triggeredEvent = event
    return eventDistributer
end
 
-- finally linking everything
setmetatable(on, eventCatcher)

Je suis sur que parmi vous lecteurs, nombreux sont ceux intéressés par un .tns d’exemple directement, « tout prêt » 😉 Je vous ai préparé ceci : cliquez ici pour télécharger le fichier. C’est un exemple de base avec quelques événements, mais sans une seule fonction on.xxx définie explicitement, et dans 2 screens. J’ai plutôt assez bien commenté le code pour que vous puissiez comprendre rapidement 🙂

Pour un exemple plus terre-à-terre, montrant en même temps cette technique et celle de la personnalisation du gc, je vous suggère de télécharger le jeu Memory de Jim, ici.

Comment ajouter vos propres fonctions à « gc »

Salut à tous,

Comme vous le savez, afin de réaliser des opérations graphiquesen Lua sur la plateforme Nspire, vous devez utiliser gc et ses méthodes que TI a créé, comme drawString, drawRect, fillArc, etc.

Et bien, comment feriez-vous pour avoir votre propre fonction « gc », comme drawRoundRect ?

Vous pourriez très bien faire quelque chose comme :

function drawRoundRect(gc, x, y, wd, ht, rd)
        if rd > ht/2 then rd = ht/2 end
        gc:drawLine(x + rd, y, x + wd - (rd), y)
        gc:drawArc(x + wd - (rd*2), y + ht - (rd*2), rd*2, rd*2, 270, 90)
        gc:drawLine(x + wd, y + rd, x + wd, y + ht - (rd))
        gc:drawArc(x + wd - (rd*2), y, rd*2, rd*2,0,90)
        gc:drawLine(x + wd - (rd), y + ht, x + rd, y + ht)
        gc:drawArc(x, y, rd*2, rd*2, 90, 90)
        gc:drawLine(x, y + ht - (rd), x, y + rd)
        gc:drawArc(x, y + ht - (rd*2), rd*2, rd*2, 180, 90)
end
 
function on.paint(gc)
        drawRoundRect(gc, 100, 50, 20, 15, 5)
        ...
end

Certes, ceci fonctionne.

Mais ne serait-ce pas plus sympa de pouvoir écrire quelque chose du genre : « gc:drawRoundRect(100,50,20,15,5) », qui fait bien plus naturel et qui ne requiert pas le passage explicite de gc en premier argument ? 😉
Well, here is the definitive solution to this, by Jim Bauwens 😉

function AddToGC(key, func)
        local gcMetatable = platform.withGC(getmetatable)
        gcMetatable[key] = func
end
 
local function drawRoundRect(gc, x, y, wd, ht, rd)
        -- the code above
end
 
AddToGC("drawRoundRect", drawRoundRect)
 
function on.paint(gc)
        gc:drawRoundRect(100, 50, 20, 15, 5)
        ...
end

 

A noter :

Vous avez pu remarqué l’utilisation de platform.withGC, qui est une fonction de l’API « 2.0 »+ (OS 3.2+). VOici comment la « recréer » pour les versions plus anciennes :

if not platform.withGC then
        platform.withGC = function(func, ...)
            local gc = platform.gc()
            gc:begin()
            func(..., gc)
            gc:finish()
        end
    end

 
[Update] : John Powers from TI commented that this definition of platform.withGC has some limitations, and proposed this better version (thanks !) :

if not platform.withGC then
    function platform.withGC(f)
        local gc = platform.gc()
        gc:begin()
        local result = {f(gc)}
        gc:finish()
        return unpack(result)
    end
end

Des tutoriaux Nspire Lua de A-à-Z

Cette page lie les excellents tutoriaux de Steve Arnold, sur CompassTech.

Ils sont tous en anglais, cependant.
Vous pouvez trouvez quelque de nos tutoriaux en français ici.

 





The lessons in this next section require OS 3.2 functionality.




Comment convertir un fichier .lua en .tns ?

Retour à la partie 1

Vous avez deux possibilités :

1) Utiliser le logiciel Nspire pour ordinateur

Depuis la version 3.2 (mi-2012), le logiciel Nspire (« TINCS ») inclut un éditeur de script, pour directement créer, éditer, tester, et débugger vos codes Lua à l’intérieur des documents Nspire 🙂

Il est disponible depuis le menu Insérer > Editeur de script.

2) Utiliser « Luna »

Luna est un outil communautaire et open-source, créé par Olivier « ExtendeD » Armand, permettant de créer des fichiers .tns (TI-Nspire) à partir notamment d’un code source Lua.

Vous pouvez télécharger un exécutable Windows ici sur TI-Planet.

Pour les autres plateformes, vous pouvez compiler son code source, disponible au même lien.

Pour l’utiliser, il suffit d’écrire, dans un terminal / invite de commandes, le chemin vers le fichier Lua puis vers celui du .tns que vous voulez créer :

1
luna.exe myscript.lua mydocument.tns

Partie 3 !

Tester le type d’un objet avec l’opérateur is()

Le Lua sur TI-Nspire permet de créer facilement des classes avec la fonction class() qui permet également de créer des classes héritées, basées sur le modèle de la classe mère avec quelques différences. Malheureusement, étant donné que le concept de classes n’est que superficiel, il n’existe ni fonction ni syntaxe spécifique pour travailler avec certains types de classes. Dans ce tutoriel nous allons voir comment reproduire le fonctionnement de l’opérateur is() présent dans d’autres langages de programmation orienté objet, tel que le C#.

L’opérateur is() permet de distinguer un objet qui a été créée à partir d’une classe spécifique, mais aussi des classes mères (Etant donné que l’héritage en Lua est une pure copie de la classe mère, il n’est pas possible de gérer l’héritage avec l’opérateur is que nous allons créer).

Voici un petit exemple de ce qu’on désire faire :

function is(obj, class)
  -- we are going to create it
end
 
A = class()
function A:init(x)
  self.x = x
end
 
B = class(A)
function B:init(x)
  self.x = x * 2
end
 
t = { A(1),  B(1) }
for k, v in pairs(t) do
  if is(v, A) then
    print("A class, value = "..v.x)
  elseif is(v, B) then
    print("B class, value = "..(v.x / 2))
  end
end

Nous voyons ici très bien l’intérêt : si nous stockons dans un tableau des objets issus de classes héritées donc portant certaines propriétés en commun, nous voulons dans certains cas distinguer si l’objet est issu de telle ou telle classe.

Mais alors comment écrire la fonction is() dans ce cas ? Rajouter un champ ? Non ! En effet, le fonction class() affecte déjà certains champs sans que vous ne le sachiez. class() affecte le champ __index de la table (ou objet), et il contient un pointeur vers la classe mère. Lorsque vous faites a = A() , a.__index est égal à A.__index (en terme de références).

Ainsi, voici la fonction is()

function is(obj, class)
  return obj.__index == class.__index
end

NB : Comme la limite entre classes et objet est assez floue en Lua (contrairement à d’autres langages où un objet est instancié par une classe), il est possible de tester si deux objets appartiennent à la même classe mère de la même manière :

A = class()
function A:init() end
a = A()
b = A()
is(a, b) -- returns true

Appel au constructeur de la classe mère

Vous êtes très certainement nombreux à avoir remarqué que l’utilisation des classes en Lua sur TI-Nspire était pratique, mais trop simple pour optimiser le code dans certains cas de figure.

Ce cas particulier est la possibilité d’appeler le constructeur de la classe mère dans le constructeur de la classe fille pour éviter de répéter les instructions. En effet, au moindre changement de champs dans la classe mère impliquait qu’il faille changer toutes les classes filles pour les modifier en conséquence.

Voici un exemple :

A = class()
function A:init(x)
  self.t = 0
  self.x = x
end
 
B = class(A)
function B:init(x, y)
  self.t = 0
  self.x = x
  self.y = y
end

Ici, si on veut changer t = 0 du constructeur de la class mère, il faudrait alors changer également le constructeur de la classe B pour rester cohérent. Une première approche consiste à procéder comme suit :

A = class()
function A:init(x)
  self.t = 0
  self.x = x
end
 
B = class(A(0, 0)) -- construction of the object before inheriting
function B:init(x, y)
  self.x = x
  self.y = y
end

Mais là encore, le champ x est répété.

Une chose que nous avons oublié de considérer ici est que B est une classe héritée de A, donc les champs de A sont forcément répétés dans B. Pourtant le constructeur de B, on est justement en train de le redéfinir en écrasant celui venant de A. N’y a-t-il pas moyen d’appeler le constructeur de A tout en passant l’objet B en paramètre ?

Et bien oui !

Une picure de rappel pour bien comprendre est cependant nécessaire. En effet, faire ceci :

dummy = class()
function dummy:doSomething()
  self.mark = 0
end
dummy:doSomething()

revient exactement au même que faire cela :

dummy = class()
function dummy.doSomething(self)
  self.mark = 0
end
dummy.doSomething(dummy)

ou encore :

dummy = class()
function dummy:doSomething()
  self.mark = 0
end
dummy.doSomething(dummy)

La présence des doubles points permet de passer automatiquement en 1er paramètre l’objet portant la méthode. Donc rien de nous empêche de ne pas utiliser ce sucre syntaxique pour faire passer un autre objet à la place de l’objet portant la propriété !

Ce qui revient à faire comme suit :

A = class()
function A:init(x)
  self.t = 0
  self.x = x
end
 
B = class(A)
function B:init(x, y)
  A.init(self, x) -- call the A class constructor in order to avoir repetitions
  self.y = y
end

Leçon 1 : Premiers pas avec le Lua sur TI-Nspire

Aujourd’hui, Inspired-Lua vous propose une traduction et adaptation du guide de Steve Arnold que vous pouvez retrouver en cliquant ici. Depuis l’OS 3.0, les Ti-Nspire possèdent une nouvelle fonctionnalité en matière de programmation : le Lua. Ce dernier est un langage de programmation à la fois moderne et rapide. Les scripts écrits en Lua avec un simple éditeur de texte peuvent être convertis en .tns (format des documents TI-Nspire) à l’aide de TI-Nspire Scripting Tool . De tels scripts donnent de nouvelles possibilités étonnantes et puissantes pour la création de documents TI-Nspire afin d’apprendre ou d’enseigner.

Avec un peu d’expérience, les programmeurs de Lua peuvent créer d’incroyables programmes, auxquels l’imagination est la seule limite. A titre d’exemple, voici un tableau périodique des éléments réalisé par l’équipe de TI-Planet. Comme vous pouvez le voir, les possibilités sont énormes. Toutefois, même les débutants peuvent profiter des particularités offertes par le Lua dans des conditions plus limitées mais qui restent quand même puissantes. Ce tutoriel pour débutants offre de bonnes bases grâce auxquelles les élèves comme les enseignants pourront commencer à créer leurs propres documents !

L’objectif ici sera de commencer le Lua en affichant du texte. Des graphiques et des images dynamiques suivront plus tard.

Leçon 1.1: Premiers pas avec le Lua sur TI-Nspire

Pour cette première leçon, nous utiliserons le programme Oclua (On Calc lua) développé par Olivier Armand. Commencez par télécharger l’archive Oclua d’après ce lien . Ensuite, décompressez l’archive et transférez le fichier .tns sur votre calculatrice.

Gif Oclua
Oclua fonctionne à la fois sur la calculatrice et sur le logiciel TI-Nspire. Pour commencer à utiliser Oclua, ouvrez tout d’abord le fichier, puis créer une nouvelle application dans le classeur. (CTRL+I) Choisissez l’éditeur mathématique. Vous pourrez écrire le code en Lua ici. Ensuite, pour l’exécuter, vous n’aurez qu’à copier ce code et à le coller dans le premier onglet. (CTRL+A pour tout sélectionner, CTRL+C pour le copier, et enfin CTRL+V pour le coller) Rapide et facile à prendre en main, Oclua est idéal pour commencer à utiliser le Lua. Cette procédure est expliqué à travers l’image en gif ci-contre (Ignorez les deux lignes horizontales, elles sont dues au logiciel utilisé pour enregistrer l’animation – elles n’apparaîtront pas sur votre version du document). Toutefois, nous verrons par la suite que de meilleures solutions existent.

Les choses sérieuses commencent : nous allons créer votre première fonction en Lua ! Mais ne vous inquiétez pas, rien de bien compliqué. Tout d’abord, nous allons apprendre comment afficher du texte en Lua. Insérez une page éditeur mathématique comme nous l’avons vue. Recopiez-y le code ci-dessous

function on.paint(gc)
  gc:drawString("hello world", 0, 20)
end

Notez que l’indentation (ajout d’espace/tabulation dans des scripts) n’est pas du tout obligatoire elle permet juste de mieux se retrouver dans de longues lignes de codes. (Ici elle n’a que peu d’intérêt mais il faut mieux prendre ces habitudes dès le départ)
Le Lua est un langage sensible à la casse c’est-à-dire que vous devez écrire exactement les fonctions comme montrées ici. Dans cet exemple, tout est en minuscules, excepté le « S » de String.
Vous devriez voir le texte « hello world » écrit en haut à gauche de la page. Voyons ce que l’on peut apprendre de cet exemple :

  • La structure pour définir une fonction est la même que dans beaucoup de langages.
function nom(argument)
  quelques instructions
end
  • Dans notre exemple, nous avons utilisé une fonction standard du Lua appelée « on.paint ». Vous la rencontrerez dans la plupart (si ce n’est tous) les scripts en Lua. Lorsque vous utilisez cette fonction, elle affiche le texte sur l’écran.
  • « gc » signifie « graphics context ». (Contexte graphique :P) Il est utilisé quand des éléments graphiques de n’importe quel type sont employés. Vous pouvez voir dans cette fonction, l’unique ligne de code est définie par ce terme gc. Ne vous inquiétez pas, vous vous y habituerez vite !
  • La ligne d’instruction de cette fonction est assez explicative : gc:drawString (“hello world”,0,20). Dans le contexte graphique (gc) on va afficher (draw, dessiner) la chaîne de caractère (String) qui est “hello world” à la position (0,20) sur la fenêtre
  • Il faut savoir que le système de coordonnées à pour origine le coin en haut à gauche de l’écran. Ainsi, les coordonnées ne doivent pas être négative pour afficher correctement du contenu graphique. Dans notre exemple, le point choisi est (0,20). Si l’ordonnée était inférieure, le texte serait coupé.
Vous devriez prendre quelques minutes pour découvrir cette première fonction et appliquer ce que vous venez d’apprendre. Essayez de déplacer le texte afin de comprendre le système de coordonnées. Essayez de centrer votre texte. Vous en apprendrez ainsi plus sur les dimensions de l’écran.
Cependant, vous verrez plus tard qu’un texte centré sur une plateforme (calculatrice, ordinateur) n’est pas forcément adapté à une autre. Mais alors, comment faire ? Nous allons voir cela dans la suite de notre cours ! En attendant, amusez-vous bien ! 🙂

Mais pourquoi ?

Il est peut-être temps de s’arrêter un instant et de se demander – Pourquoi s’ennuyer à faire cela ? Il y a d’autres façons beaucoup simples pour afficher du texte à l’écran.
Deux propriétés très importantes d’une fenêtre en Lua sur TI-Nspire, par opposition à une fenêtre classique dans l’éditeur mathématique :
  • Cliquez sur n’importe quelle fenêtre en Lua. Déplacez-la, essayez de l’éditer. C’est impossible. Le texte que vous affichez ne peut pas être édité par l’utilisateur du document. Dans l’éditeur mathématique, l’utilisateur peut bien sur changer – et en effet détruire – tout ce que l’auteur a pris le temps de faire. En plus, comme on peut le faire dans l’éditeur, le texte affiché peut être à la fois dynamique et statique. Donc on peut facilement créer de puissants outils d’apprentissage tout comme on peut le faire avec l’éditeur, mais dans un environnement plus sécurisé.
  • Dans la seconde partie de cette leçon, vous apprendrez à contrôler la taille de la police, la couleur et le style, et comment facilement centrer le texte sur une ligne, et même au centre de la fenêtre. En Lua, on a un contrôle significatif de la façon dont le texte est affiché – bien plus qu’en utilisant l’éditeur. En terme de couleurs, vous avez accés à des millions de couleurs !

Leçon 1.2: Un peu plus intéressant ?

Bon, retour au travail. Prêt pour la suite ?
Si vous n’êtes pas sur la page 1.2 d’Oclua, retournez-y. Nous allons ajouter quelques lignes à notre script on.paint.
function on.paint(gc)
  gc:setFont("sansserif", "b", 12)
  gc:setColorRGB(158, 5, 8)
  gc:drawString("Ceci est mon texte", 20, 20)
end
A nouveau, étudiez ces quelques lignes – essayez de modifier les différentes valeurs. Vous allez vite vous rendre compte que setFont possède trois entrées :
  • la famille : « serif » ou « sansserif »
  • le style : « b » pour bold (gras) ; « r » pour regular (normal) ; « i » pour italic (italique) ; « bi » pour bold italic (gras et italique)
  • la taille

setColorRGBpermet d’accéder simplement à une multitude de couleurs : RGB signifie Red (rouge ; 255,0,0) Green (vert ; 0,255,0) Blue (bleu ; 0,0,255). Il y a de nombreuses couleurs entre ces valeurs, ou vous pouvez accéder à la liste en ligne ou juste télécharger le PDF que j’utilise. Mes couleurs fétiches sont burgundy (158, 5, 8 )> et navy (20, 20, 138), et qui vont très bien ensemble ! C’est vraiment mieux qu’une simple palette de 9 à 15 couleurs actuellement disponible sur TI-Npire !Si vous n’êtes pas perdu en lisant ce cours, c’est que vous êtes sur la bonne voie ! Nous allons finir cette leçon par une notion importante en Lua : centrer le texte. Nous en profiterons pour introduire les variables locales et globales.

Le Lua dispose de toutes sortes de commandes très utiles, comme platform.window:heigth() et platform.window:width().

Comme vous pouvez le deviner, ces commandes permettent de récupérer les valeurs actuelles de la fenêtre. Ainsi, platform.window:heigth() permet de connaître la hauteur de l’écran tandis que platform.window:width(). permet d’en connaître la largeur. Une nouvelle fois, faites bien attention aux majuscules et aux espaces ! Ici, tout est en minuscules.
Si on stock ces valeurs dans des variables, que nous appellerons w et h (pour width et height respectivement), nous pourrons les réutiliser hors de la fonction et dans un script plus grand. Mais nous aurons l’occasion d’y revenir un peu plus tard.

Voici deux nouvelles fonctions tout aussi importantes : getStringHeight et getStringWidth. Comme leurs noms l’indiquent, elle permettent de déterminer la largeur et la hauteur d’une chaîne de caractères.

function on.paint(gc)
  local h=platform.window:height()
  local w=platform.window:width()
  gc:setFont("sansserif", "b", 12)
  gc:setColorRGB(158, 5, 8)
  local sw = gc:getStringWidth("Ceci est mon texte")
  local sh = gc:getStringHeight("Ceci est mon texte")
  gc:drawString("Ceci est mon texte", w/2 - sw/2, h/2 + sh/2)
end
On commence par définir les dimensions de la fenêtre avec w et h. On peut aussi obtenir les dimensions de la chaîne de caractères
Maintenant, pour centrer la chaîne :
  • Horizontalement : on prend le centre de la fenêtre (w/2) puis on recule de la moitié de la largeur de la chaîne de caractères (w/2 – sw/2).
  • Veritcalement : on suit la même procédure, à une différence près : verticalement, on compte à l’envers en Lua : plus on va bas, plus le nombre est grand ; plus on va haut, plus il est faible ! (h/2 + sh/2)

Et maintenant ?

C’est tout pour cette leçon – à vous de jouer !
Pourquoi ne pas essayer d’aligner votre texte à droite ? Jetez un œil au centrage que nous venons de réaliser et inspirez-vous-en pour aligner le texte à droite et à gauche.
Et pour le placer en haut ou en bas ? Comment feriez vous ? Essayez différentes couleurs !Dans la prochaine leçon, nous apprendrons à donner vie à notre texte et à utiliser une table pour organiser plusieurs lignes de texte de façon structurée sur votre page !

Leçon 2 : Créer une table dynamique

Dans cette leçon, nous allons introduire deux notions très importantes, et surtout pratiques du Lua : créer une table, et récupérer une variable d’une application TI-Nspire vers un script en Lua. Nous allons aussi rencontrer les boucles « For ». Si vous débutez en programmation, je vous recommande fortement de vous familiariser avec cette boucle dans d’autres langages, par exemple en TI Basic, avant de tenter ce genre de choses en Lua.A nouveau nous utiliserons Oclua pour créer et tester les scripts vus lors de ce cours, seulement pour notre confort. Les scripts en Lua peuvent être écrits dans n’importe quel éditeur de texte (De NotePad à Word, en passant par le bloc-notes). Pour les utilisateurs de windows, la gratuité de NotePad++ en fait un excellent choix pour ce genre de travail car il colore le texte et participe à la structure de votre script. Pour les utilisateurs de Mac, Xcode est sur votre CD d’installation sous les Outils Développeurs, et fera parfaitement l’affaire. Si vous êtes prêts à dépenser quelques euros, TextMate est excellent (et « connaît » même le Lua ce qui peut aider pour la syntaxe et les bugs).

Mais alors, pour quoi ne pas garder Oclua ? Eh bien, le document peut seulement être lu. Lorsque vous créez une page en Lua en collant votre script, tout semble normal. Cependant, fermez et ré ouvrez votre document (même après avoir enregistré) et vous revoilà devant la page vide « Paste your script here ». Ainsi, ce programme est génial pour apprendre et tester les scripts, mais si vous avez besoin d’utiliser un script à n’importe quel moment, vous aurez besoin de TI-Nsipre Scripting Tools, dont nous reparlerons dans la prochaine leçon. En attendant, nous continuerons avec Oclua. Dans la dernière leçon, nous avons découvert les variables locales, et la création de w et h qui représentent la largeur et la hauteur de la fenêtre. Ces variables s’ajustent dynamiquement. Ainsi, si vous passez de la vue en mode ordinateur à la vue calculatrice, ou si vous redimensionnez ou partagez la fenêtre, alors les variables s’adapteront. Utiliser ces variables plutôt que des valeurs statiques signifie que votre page aura le même affichage, quelle que soit la fenêtre.

Dans cet exemple, nous commencerons par définir deux nouvelles variables locales : La table, grâce à des accolades vides (comme sur TI-Nspire), et le nombre de lignes.

Leçon 2.1 : La boucle For en Lua

Comme je l’ai dit précédemment, je suppose que vous avez déjà eu l’occasion de rencontrer la structure « For…End » (Elle s’appelle « For…EndFor » sur TI-Nspire. En Lua, les fonctions de contrôle se terminent toutes par End)

Boucle sur TI-Nspire

For k, 1, 10
   var := k* (k+1)
EndFor

Boucle en Lua

for k = 1, 10 do
   var = k* (k+1)
end

Le résultat de ces deux boucles est identique : à la fin, la variable var vaudra 110. La syntaxe en Lua est similaire à celle de la TI-Nspire. Au lieu d’utiliser For k, de, à, [pas] sur TI-Nspire, le Lua remplace la première virgule par un égal, le mot « do » apparaît à la fin de la ligne de définition, et enfin, veillez à ce que tout soit en minuscules. Le pas est [optionnel] dans les deux cas.

Nous allons maintenant nous appuyer sur un script qui nous servira d’exemple dans la suite de ce cours.

function on.paint(gc)
  local h = platform.window:height()
  local w = platform.window:width()
  local table = {}
  local nbligne = 3
  gc:setFont("sansserif","r",10)
  gc:setColorRGB(158,8,5)
 
  for k = 1, nbligne do
    table[k] = "Ligne #"..k
    strheight = gc:getStringHeight(table[k])
    strwidth = gc:getStringWidth(table[k])
    gc:drawString(table[k], w/2-strwidth/2, h*k/(nbligne + 1) + strheight/2)
  end
end

Dans cet exemple, nous irons de k = 1 à k = 3, en affichant chaque ligne au fur et à mesure. Les possibilités de cette structure sont assez évidentes – ici, on peut facilement afficher 10 lignes, ou n’importe quel nombre …

Vous avez peut-être reconnu les quelques ligne de l’exemple précédent : lignes qui définissent la police, la couleur, la largeur / hauteur de la chaîne de caractères, et enfin qui affiche le string. Ici, on ajoute une ligne qui crée chaque ligne de notre table. Histoire de bien mettre les choses au clair, la syntaxe table[k] fait référence au k-ème élément de la table. Donc table[1] est la première « ligne » ou « rangée » ou quoi que ce soit qui vous permette de visualiser. Cela fonctionne exactement de la même façon que sur TI-Nspire.

Leçon 2.3 : Créons des lignes pour notre Table !

Pensons un instant à l’organisation d’une table sur TI-Nspire. On la définirait ainsi :

 table := { "un", "deux", 7 }

Maintenant, si on utilisait table[1], on obtiendrait « un », et pour table[3], on obtiendrait la valeur 7. En Lua, la même chose se produirait. En fait, le Lua est même un peu plus flexible dans la maniabilité des variables. Sur TI-Nspire, il faut bien faire attention à distinguer le string « 7 » du chiffre 7. Ces deux variables ont une structure de données différente. En Lua, cela n’a pas d’importance, tant qu’elles sont utilisées de manière adéquate. Donc même si vous utilisez une variable num qui contient le string « 7 », le Lua peut parfaitement l’utiliser en tant que chiffre, avec par exemple 2*num qui va donner 14. En revanche, si num contenait « sept », le calcul serait impossible, car on ne peut évidemment pas multiplier un string par un nombre.

Revenons en à notre exemple : on crée en fait chaque ligne de notre table au fur et à mesure que le programme progresse. Quand k = 1, alors table[1] est défini comme la concaténation (Mot barbare, la mise bout à bout de deux chaînes) grâce aux deux points « .. » du string « ligne # » et de la valeur de k (1). Donc, table[1] = « ligne#1 ». Facile !

Leçon 2.4 : Plaçons ces nouvelles lignes !

Créer toutes ces lignes est plutôt facile. Mais nous devons un peu réfléchir et calculer avant de les afficher correctement. On les centrera horizontalement, comme on l’a déjà fait. Cependant, nous devons les espacer de la même façon verticalement. En d’autres termes, nous devons diviser notre hauteur de fenêtre (h) par un plus le nombre de ligne (1 – nbligne) – car on place en fait les espaces entre les lignes ! Une fois que l’on a compris ceci, le calcul devient plus simple : h*k / (nbligne + 1).
Un petit exemple pour bien comprendre : On veut afficher 3 lignes.
– On aura la première à 1*h / 4
– La deuxième à 2*h / 4 (qui donne h/2)
– La dernière à 3*h / 4
On peut encore faire mieux ! Comment me direz-vous ? En ajoutant la moitié de la hauteur du string ! (h*k / (nbligne + 1) + strheight / 2) Les lignes seront maintenant parfaitement alignées !

________________________

Wow ! On a déjà parcouru un long chemin depuis vos débuts ! Prenez une pause ! Je vous conseille d’essayer de comprendre ce qui se passe plus haut. Modifiez, touchez à tout, comprenez ! On apprend toujours par ses erreurs !

Vous êtes maintenant prêts pour ma dernière partie de ce cours ! On va rendre le tout dynamique !

________________________

Leçon 2.5 : Donnons vie à nos lignes !

Avant de commencer, un petit rappel : un affichage dynamique est par définition le contraire d’un affichage statique. C’est-à-dire qu’un affichage dynamique va s’ajuster grâce à différents paramètres, par exemple un ou plusieurs changements dans une / des variable(s) ; alors qu’un affichage statique ne change pas. (Il porte bien son nom !)

Revenons-en à nos moutons. Nous allons commencer par diviser notre écran (sur le Ti-Nspire Computer Software, en allant dans DOC, et choisir le partage vertical), ensuite dans une des deux parties, nous allons créer un curseur grâce à l’application géométrie.

Après avoir choisi cette application, allez dans Menu > Actions > Insérer un curseur. Ensuite, placez le où vous voulez. Click droit sur le curseur, puis choisissez les paramètres du curseur :
– Variable : lignes
– Valeur : 5 (Cela n’a pas d’importance)
– Minimum : 1
– Maximum : 5
– Incrément : 1
– Style : vertical

Pour une meilleure apparence (optionnel !), click droit sur le curseur, puis choisissez réduire avec le style vertical.

Créer ce curseur est un jeu d’enfant. Mais à quoi ça sert si on ne l’utilise pas dans un script en Lua ? Une solution très simple existe. Elle s’appelle var.recall. Cette commande va nous permettre de remplacer la valeur fixe de nbligne par une valeur dynamique, celle du curseur. On va donc utiliser :

 local nbligne = (var.recall("lignes") or 1)

Ici, var.recall recherche une variable appelée « lignes » et attribue sa valeur à nbligne. (Si la variable lignes existe bien sur) Sinon, elle attribue la valeur 1 – pour ne pas faire planter le programme dans le cas où lignes n’existe pas. Cool.

Et maintenant ?

Bravo ! Ainsi s’achève la deuxième leçon. Prenez un peu de temps pour assimiler toutes ces nouveautés avant de passer à la suite.

Dans la prochaine leçon, on verra comment modifier le contenu de ces lignes, car je suppose qu’obtenir un alignement de « ligne#1 », « ligne#2 », etc ne vous sera que de faible utilité ! 😀