Gambas France BETA


Pas de compte ? Incription

Et si on faisait des Plugins

1
AuteurMessages
O.Coquet#1 Posté le 11/11/2024 à 13:29:05
Ce qui n'est pas devra-t-être inventé Re-bonjour à tous !

Dans ma constante quête de nouveautés pour mon logiciel de Domotique, étant arrivé à une version stable et satisfaisante(pour moi :lol: ), je ne suis plus trop enclin à triturer mon code qui marche. De plus, l'interface visuelle étant assez chargée et mon vieil Assus portable un peu fainéant, modifier le code devient une plaie dès lors que la fenêtre principale est affichée dans Gambas. Les temps d'attente sont favorable à une consommation déraisonnable de café :x

J'ai donc décidé d'ajouter des fonctions intéressantes dans un code à part, un Plugin, je vais donc dans ce post, vous montrer que réaliser un plugin dans gambas est assez simple et, avec un peu de rigueur, qu'il est assez agréable de rajouter des fonctions à votre logiciel de calcul de temps de cuisson de la tarte aux cerises..... :P :P :P

Allez, prochain message: les Bases
Amitié
Olivier (Alias Olinux)

Raspberry pi 3 et 4, pc Xubuntu, Arduino.....
Quelques autres "vieux" ordinateurs !
Et un bon fer à souder
O.Coquet#2 Posté le 12/11/2024 à 10:40:34
Ce qui n'est pas devra-t-être inventéAllez Zou !
Les bases et le pourquoi du comment des choses:

Pourquoi des Plugins ?

On a des fois une appli développée et stable, on souhaite ajouter un certain nombre de fonctions sans retoucher le code de l'apli.
à cela plusieurs solutions:
1) On rajoute une classe dans l'appli qui va ajouter ces fonctions, mais ça sous-entend de mettre à jour toute l'apli après avoir re-généré l'exécutable. Si c'est chez vous pas de souci, si elle est distribuée, ça implique une réinstallation de la part de ceux qui la possèdent.

2) On crée un composant qu'on modifie. Idem qu'au dessus, il faut réinstaller le composant à chaque modif, avec probablement une désinstallation de l'ancien composant. De plus, il y a un gros risque que sur certaines installations, le composant soit absent, du coup, l'appli plante. Et en dernier, cela sous entend que l'utilisation de ce composant soit prévue dès le départ dans votre appli.

3) On crée dans l'appli, dès le début, un code qui sera capable de charger un ou des "Plugins" si il en trouve dans un répertoire spécial (Chez moi c'est <Plugins>), et qui, si il en trouve, lance une fonction spéciale pour chacun d'entre eux. Bien sûr, afin de simplifier les choses, tous vos plugins disposeront de cette même fonction pour démarrer (Chez moi: init()).

Dans ce dernier cas, celui qui nous intéresse, la seule obligation au développement de votre appli, c'est de créer cette fonction de recherche et chargement de plugins et de lancement de la fonction init() sur chacun d'entre eux. A partir de cet instant, vous pourrez faire autant de plugins que vous voudrez, et votre appli va s'enrichir de nouvelles fonctions sans que vous ayez à toucher une ligne de code de l'appli d'origine, et en plus, chacun pourra choisir les plugins qu'il veut utiliser sans se soucier des autres.

Petite contrainte, il semble qu'un tel plugin ne soit pas capable de charger les components qui lui sont nécessaires (si ils ne sont pas présents dans l'appli) après qu'il ait été intégré dans l'appli principale, il sera donc nécessaire dans la fonction init() de faire un: Component.Load("le nom du composant") afin que celui ci soit disponible à l'exécution.

A noter un autre avantage, pour distribuer votre plugin, seul l'exécutable sert à quelque-chose, donc un seul fichier à distribuer.

Voila pour les explication
Prochain message: un exemple simple (dans la journée)
Amitié
Olivier (Alias Olinux)

Raspberry pi 3 et 4, pc Xubuntu, Arduino.....
Quelques autres "vieux" ordinateurs !
Et un bon fer à souder
O.Coquet#3 Posté le 12/11/2024 à 12:25:35
Ce qui n'est pas devra-t-être inventéBon allez on se lance, d'abord on crée une première appli, la plus simple possible,ça sera l'appli de départ que l'on ne touchera plus ensuite.

Créons une fenêtre qui ressemble à ça:


On ne peut plus simple:
un bouton <Je suis vide> destiné à être modifié par le plugin si il existe
un bouton <Appel le plugin> destiné à lancer la fonction init() du plugin si il existe

maintenant le code pour gérer cette fenêtre:
' Gambas class file

'on déclare un object qui hébergera la classe principale du plugin

Public Fct1 As Object

'on déclare une variable true ou false qui nous permet d'indiquer
'si le plugin est chargé ou non

Public Plugin_Charg As Boolean = False

'au lancement de l'appli, c'est la première chose qui se lance
Public Sub Form_Open()

'on essaye de charger le plugin si il existe
'pour l'exemple nous donnons son nom
'Nous verrons plus tard comment charger les plugins
'Sans connaître leur nom

Try Component.Load(Application.path & "/TestComp.plg")

'si le plugin est chargé, on l'indique en mettant
'l'indicateur "Plugin_Charg" à true

If Not Error Then
Plugin_Charg = True

'On référence la classe principale du plugin
Fct1 = Object.New("Fct1")
Endif

End

'ici la fonction appelée si on clique sur le bouton
'"Appel le plugin"

Public Sub Button2_Click()

'si le plugin est chargé
If Plugin_Charg = True Then

'Lance la fonction init() du plugin
Fct1.init(Me)'<==le Me permet de signaler au plugin ou se trouve la fenêtre de l'appli
Else

'sinon, on signale que le plugin n'est pas là
Message.Info("Plugin non présent, je ne fais rien !")
Endif


End

'Fonction de base appelée par le click sur le bouton
'"Je suis vide!"

Public Sub Button1_Click()

'affichage du fait que ce bouton ne fait
'rien de base si le plugin n'est pas chargé

Message.Info("Plugin non présent, je ne fais rien !")

End

Voilà, notre superbe appli est créée, on compile et basta, on y touche plus.
Essayez la pour voir son comportement sans plugin.

Prochain message: le plugin
Amitié
Olivier (Alias Olinux)

Raspberry pi 3 et 4, pc Xubuntu, Arduino.....
Quelques autres "vieux" ordinateurs !
Et un bon fer à souder
O.Coquet#4 Posté le 12/11/2024 à 13:02:01
Ce qui n'est pas devra-t-être inventéAtaquons nous à notre superbe plugin:

on crée une appli (on peut choisir en ligne de commande si le plugin ne contient pas de fenêtre)
on choisi son nom (pour l'exemple, le même que celui donné dans l'appli, on verra ensuite comment lui donner le nom que l'on veut)
on coche l'option static et exporté.
ensuite on va dans les propriétés du projet, on le déclare du type "bibliothèque" dans la description, puis on descend dans les propriétés et on coche: gestion des formulaires, gestion des boucles d’événement et chargement et sauvegarde d'images

Voilà, maintenant, le code:

'ici, c'est inscrit automatiquement, cela veut dire que les fonctions
'sont disponibles à l'extérieur de cette classe.
'et que cette classe est static (en gros une seule instance qui ne bouge pas)

Export
Create Static

'un observateur, on verra plus bas à quoi il sert
Public myobserver As Observer

'fonction obligatoirement présente dans une appli en ligne de commande
'ici on ne s'en sert pas.

Public Sub Main()


End

'La fameuse fonction init()
'c'est elle qui fait la base du travail pour taper
'l'incruste dans votre appli

Public Sub init(Mform As Object) <===== c'est ici qu’atterrit le Me de l'appli

'on change le texte du boutton de l'appli
Mform.Button1.text = "plugin !"

'On attache le bouton à ce plugin (kidnapping ! )
Object.Attach(Mform.Button1, Me, "Plugin")

'On redirige les évènements de ce bouton vers une fonction du plugin
'C'est à ça que sert l'observeur, il zyeute les évènements de ce bouton
'et les ré-oriente vers une fonction du plugin

myobserver = New Observer(Mform.Button1) As "Plugin"

End

'La fonction ou atterrisent les évènements click
'du bouton kidnapé

Public Sub Plugin_click()

'Un joli message qui prouve que le plugin a fait
'son boulot !

Message.info("c'est moi!\r\nDepuis le plugin")

End

et c'est tout
à partir de là, vous pouvez faire ce que vous voulez dans votre plugin
L'utilisateur de votre appli aura l'impression que tout vient de l'appli.

Reste a créer l'exécutable, on le renomme avec une extension ".plg", choix personnel, et on le copie vers le dossier ou se trouve l'exécutable de l'appli principale, et c'est tout, vous voyez on peut pas plus simple !


Prochain message demain: charger les plugins sans connaître leur nom.

Amitié
Olivier (Alias Olinux)

Raspberry pi 3 et 4, pc Xubuntu, Arduino.....
Quelques autres "vieux" ordinateurs !
Et un bon fer à souder
O.Coquet#5 Posté hier à 09:15:32
Ce qui n'est pas devra-t-être inventéAvant de passer à la version Multi-Plugins, il me paraît nécessaire d'apporter quelques précisions concernant le développement de l'appli principale, à savoir celle qui accueillera des Plugins :

- l'appli doit être développée avec des contrôles publiques (du moins pour ceux dont vous souhaitez qu'ils soient directement modifiables via un Plugin).

- Toutes les références de l'appli principale doivent se baser sur des variables globales et publiques. Par exemple, si vous avez à utiliser un chemin d'accès à un fichier, celui-ci doit être stocké dans une variable Globale et publique et pas codée en dur.

exemple:
Si votre appli principale doit aller lire un fichier, on ne code pas:

1
2
3
4
5
6
PUBLIC SUB lire_fichier()
DIM fichier AS STRING

fichier = File.Load(Application.Path & "/monfichier.txt")

END SUB

Ici, on voit bien que le chemin d'accès ainsi que le nom du fichier ne sont pas modifiables depuis l'extérieur.
Mais:

1
2
3
4
5
6
7
8
PUBLIC mon_fichier AS STRING = "monfichier.txt"
PUBLIC fichier_path AS STRING = Applicaton.Path

PUBLIC SUB lire_fichier()

fichier = File.Load(fichier_path & "/" & mon_fichier)

END SUB

Ici, un Plugin extérieur pourra facilement modifier le chemin d'accès et le nom de fichier en modifiant le contenu des variables globales et publiques! mon_fichier et fichier_path.

D'une manière générale, évitez à tous prix d'utiliser des choses écrites en dur dans le code, cela vous évitera quelques galères au moment du développement d'un Plugin.

Olivier
Amitié
Olivier (Alias Olinux)

Raspberry pi 3 et 4, pc Xubuntu, Arduino.....
Quelques autres "vieux" ordinateurs !
Et un bon fer à souder
1