Documentation de Gambas - /dev/gambas

/dev/gambas
Le page anglaise est plus récente.

# Comment Programmer Des Composants En Gambas

- Introduction

- Classes exportées

  - Classes exportées cachées

- Contrôles

- La Constante `_Properties`

  - Syntaxe

  - Types de propriétés

  - Listes de constantes

  - Exemples

- Les Autres Constantes Spéciales

  - La constante _DefaultEvent

  - La constante `_DefaultSize`

  - La constante `_DrawWith`

  - La constante `_Arrangement`

- Icônes des contrôles

- Exigences des Composants

- Débogage, installation et empaquetage du composant

  - Débogage

  - Installation

  - Empaquetage

- Conclusion

## Introduction

Toute les informations suivantes concernent Gambas 3.

Les composants Gambas sont des bibliothèques partagées, écrites en C, C++ ou directement en gambas, qui ajoutent de nouvelles classes à l'interpréteur gambas.

Un composant écrit en gambas est un projet gambas normal ayant les caractéristiques distinctives suivantes :

- Dans l'onglet "Option" du dialogue des propriétés du projet, le combo-box "Ce projet est un composant" est positionné à "Oui".

- Certaines des classes du projet sont exportées.

- Les classes exportées qui sont des contrôles doivent déclarer certaines constantes publiques spéciales fournissant à l'IDE toute l'information nécessaire pour gérer le contrôle.

- L'onglet "Nécessite" du dialogue des propriétés du projet est complété par les dépendances du nouveau composant.

De nombreux composants officiels sont déjà écrits en gambas, et vous pouvez les utiliser comme exemples. Le code source de ces composants se situe dans le répertoire `/comp/src` de l'archive des sources de gambas.

Voici la liste de ces composants:

- gb.chart

- gb.db.form

- gb.form

- gb.form.dialog

- gb.form.mdi

- /wiki/comp/gb.info

- gb.report

- gb.settings

- gb.web

Notez que certains composants écrits en C/C++ possèdent également des parties écrites en gambas :

- gb.qt4

- gb.gtk

- gb.desktop

Le code source de la partie gambas est situé à l'intérieur du répertoire des sources de ces composants. Par exemple, la partie gambas de gb.qt4 est située dans `/gb.qt/src`.

## Classes exportées

Ainsi donc, le but d'un composant est de mettre de nouvelles classes à la disposition de l'interpréteur Gambas.

Les classes que vous voulez mettre à disposition doivent être exportées depuis votre projet, sinon l'utilisateur de votre composant ne les verra pas.

Pour marquer une classe comme exportée, il vous suffit d'ajouter le mot-clé gambas EXPORT au début du code source de la classe.

Si une Méthode ou une propriété d'une classe exportée renvoie un objet d'une autre classe déclarée dans votre composant, alors cette autre classe doit être exportée aussi. Sinon, l'utilisateur ne sera pas capable d'enregistrer une référence sur lui, à moins d'utiliser un type de donnée Object.

Si une classe exportée hérite une autre classe déclarée dans votre composant, alors cette autre classe doit être exportée aussi. Sinon, vous obtiendrez une erreur lorsque l'interpréteur voudra charger le composant.

Pour un bon exemple de composant simple ne comportant que des classes exportées, examinez le code source de gb.settings et sa classe Settings.

### Classes exportées cachées

Si vous devez exporter certaines classes que vous ne voulez pas rendre visibles à l'utilisateur, vous pouvez les cacher en plaçant simplement un caractère de soulignement au début de leur nom.

Par exemple, regardez dans le code source de gb.desktop; vous y verrez de nombreuses classes exportées qui sont explicitement rendues invisibles.

Cette méthode vous permet de remplacer le concept de classes "virtuel" qui existe uniquement dans les composants écrits en C/C++.

## Contrôles

Les contrôles sont des classes exportées spéciales qui vont apparaître dans la boîte à outils des contrôles dans l'IDE.

Les contrôles sont habituellement des contrôles graphiques qui affichent quelque-chose et interagissent avec l'utilisateur. Mais il peut s'agir aussi de classes normales, qui n'affichent rien, comme le contrôle Timer. Dans ce cas, ils sont appelés contrôles virtuel.

Les composants de l'Interface Utilisateur Graphique (gb.qt4 ou gb.gtk) fournissent deux classes que vous devriez utiliser comme classes parentes pour créer vos propres contrôles:

- UserControl, pour les contrôles simples.

- UserContainer, pour créer des conteneurs.

UserControl et UserContainer sont en réalité des classes, dérivées de la classe Container. De cette facon, vous pouvez créer de nouveaux contrôles ou de nouveaux conteneurs en combinant des contrôles ou conteneurs préexistants.

Un bon exemple de l'utilisation de UserControl est fourni par le code source du contrôle FileView. Ce contrôle intègre un TreeView et un IconView au sein d'un UserControl, affichant l'un ou l'autre en fonction du type de vue demandée par l'utilisateur.

Vous trouverez un bon exemple de l'utilisation de UserContainer dans le code source du contrôle ListContainer. Ce contrôle est un conteneur permettant de créer une ListBox dont les éléments sont d'autres contrôles.

Les contrôles doivent déclarer certaines constantes cachées spéciales utilisées par l'IDE pour gérer le contrôle.

Constante | Type | Par défaut | Description
--- | --- | --- | ---
`_IsControl` | Booléen | `FALSE` | Pour qu’une classe exportée devienne un contrôle, cette propriété doit être positionnée à TRUE,
`_IsContainer` | Booléen | `FALSE` | Si un contrôle est un conteneur, c.a.d. si vous placez, dans l’éditeur de formulaire de l’IDE, d’autres contrôles à l’intérieur.
`_IsMultiContainer` | Booléen | `FALSE` | Si un contrôle est un conteneur multiple, comme un TabStrip.
`_IsVirtual` | Booléen | `FALSE` | Si un contrôle est virtuel, c.a.d juste une classe normale que vous pouvez placer dans l’éditeur de formulaire, comme le Timer ou la classe Printer.
`_IsForm` | Booléen | `FALSE` | Si un contrôle est en fait un formulaire, c.a.d. le conteneur de niveau supérieur de tous le contrôles de la même famille.
`_Family` | Chaîne | `"*"` | La famille du contrôle, c.a.d. le type d’objet au premier plan où vous pourrez placer le contrôle. Par exemple : `"Form"` pour un contrôle formulaire, `"Report"` pour un contrôle rapport, et `"*"` pour un contrôle qui peut être mis n’importe où.
`_Group` | Chaîne | `_Family` | Le nom de l’onglet de la boîte à outils de l’IDE où le contrôle sera placé. Par défaut, le nom de famille sera utilisé, ou le groupe `"Spécial"` si le contrôle n’appartient à aucune famille.
`_Similar` | Chaîne | `""` | Une liste de groupes de similarités, séparés par des virgules. L’éditeur de formulaire de l’IDE autorisera le remplacement du contrôle par tout contrôle du même groupe de similarité. Un groupe de similarité est normalement un nom de contrôle.
`_Propriétés` | Chaîne | `""` | La liste des propriétés du contrôle. Voir ci dessous.
`_DefaultEvent` | Chaîne | `""` | L’Evènement par défaut du contrôle. Voir ci dessous.
`_DefaultSize` | Chaîne | `""` | La taille par défaut du contrôlé. Voir ci dessous.
`_DrawWith` | Chaîne | `""` | Le contrôle GUI réel utilisé pour dessiner le contrôle dans l’éditeur de formulaire. Voir ci-dessous.
`_Arrangement` | Entier | `0` | La disposition automatique si le contrôle est un conteneur et s’il dispose ses fils automatiquement. Voir ci-dessous.

Seules les constantes `_IsControl` et `_Properties` sont obligatoires.

Comme toute constante, ces constantes cachées sont héritées. Vous n’avez donc pas réellement besoin de les déclarer dans chaque contrôle, dès lors qu’elles ont une relation d’héritage entre elles.

## La Constante `_Properties`

Cette constante est la plus importante, et elle est obligatoire. Elle décrit toutes les propriétés qui apparaîtront pour le contrôle dans la feuille de propriété de l'IDE, leur type, leur valeur par défaut et d'autres informations dépendantes du type de propriété.

### Syntaxe

Cette constante spéciale est une chaîne de la forme suivante :

PUBLIC CONST _Properties AS String = " [ * , ] Property1 , Property2 , ... "

Chaque propriété obéit à la syntaxe suivante:

[-] Nom [ { Type [ Arguments ] } ] = Défaut

- Nom_est le nom de la propriété. Bien sûr, la propriété doit être déclarée et implémentée dans le code source du contrôle.

- Type est le type de la propriété. Il peut être plus précis que le type de donnée de la propriété. Par exemple, "Color" voudra dire que la propriété est un entier, mais la feuille de propriétés de l'IDE ouvrira un sélecteur de couleur pour définir sa valeur. S'il n'est pas défini, le type de la propriété est son type de donnée.

- Arguments sont des arguments optionnels qui dépendent de la valeur de Type.

- Défaut est la valeur par défaut de la propriété. Ici, la syntaxe dépend du type de la propriété.

La première propriété peut être une étoile, ce qui veut dire que le contrôle reçoit automatiquement toutes les propriétés déclarée dans la constante `_Properties` de sa classe parente. Dans ce cas, un nom de propriété peut débuter par le signe "moins", signifiant ainsi que cette propriété doit être enlevée de la liste héritée de la classe parente.

### Types de propriétés

Voici les différentes valeurs admises actuellement pour Type:

Propriété ; Type | Description | Arguments
--- | --- | ---
Color | Un entier représentant une couleur. L'IDE affichera un sélecteur de couleur pour éditer la valeur de cette propriété. |
Font | Une police de caractères. L'IDE affichera un sélecteur de police pour éditer la valeur de cette propriété. | Font [ :Fixed ] Utilisez `Font:Fixed` pour n'autoriser que les polices à chasse fixe.
Path | Le chemin d'un fichier. L'IDE affichera un sélecteur de fichier pour éditer la valeur de cette propriété. |
Picture | Une image située dans le répertoire du projet, ou une icône prédéfinie. L'IDE affichera un sélecteur d'image pour éditer la valeur de cette propriété. |
Range | Une valeur entière avec un minimum et un maximum. L'IDE utilisera un contrôle SpinBox pour éditer la valeur de cette propriété. | Range: Minimum; Maximum

La valeur par Défaut doit obéir au type de donnée de la propriété. Pour les propriétés booléennes, vous pouvez spécifier "True" ou "False".

Vous devez être prudent lorsque vous définissez (ou non) la valeur par Défaut d'une propriété.

- D'abord, si elle n'est pas spécifiée, la valeur par défaut prise en compte est la valeur par défaut associée au type de donnée de la propriété (FALSE pour une propriété Boolean, 0 pour une propriété numérique...).

- Enfin, la valeur par défaut doit correspondre précisément à l'implémentation de la propriété. En effet, lorsqu'une propriété est mise à sa valeur par défaut dans l'éditeur de formulaire de l'IDE, aucun code n'est produit pour initialiser la propriété au moment de l'exécution.

### Listes de constantes

Pour les propriétés qui prennent leur valeur dans une liste de constantes de la même classe, vous pouvez spécifier une classe au lieu d'un type de propriété, avec une liste facultative de constantes.

Voici la syntaxe:

Propriété ; Type | Description | Arguments
--- | --- | ---
Class name | Une liste de constantes. L'IDE utilisera un contrôle ComboBox pour éditer la valeur de la propriété, et la remplira avec les constantes indiquées. | Classe . ( * | Constante1 ; Constante2 ; ... ) [ = Défaut ] Si une étoile est utilisée au lieu d'une liste de constantes, alors toutes les constantes de la classe spécifiée seront utilisées.

Si elle est spécifiée, la valeur par Défaut doit être le nom d'une des constantes, et non sa valeur réelle!

### Exemples

Par exemple, la valeur de `Control._Properties` est :

    X{Position},Y{Position},Width{Dimension},Height{Dimension},Visible=True,Enabled=True,Font{Font},
    Background{Color}=-1,Foreground{Color}=-1,Tag,
    Mouse{Mouse.Default;Blank;Arrow;Cross;Wait;Text;SizeAll;SizeH;SizeV;SizeN;SizeS;SizeW;SizeE;SizeNWSE;SizeNESW;SplitH;SplitV;Pointing}=Default,
    ToolTip,Drop,Expand,Ignore

Elle est héritée par tous les autres contrôles et conteneurs.

Voici la valeur de `_Properties pour ListBox`:

    *,List,Mode{Select.*}=Single,Sorted

## Les Autres Constantes Spéciales

### La constante _DefaultEvent

Cette constante est une chaîne représentant l'Evènement par défaut du contrôle. Cet événement par défaut est utilisé lorsque vous double-cliquez sur un contrôle dans l'éditeur de formulaire de l'IDE.

Par exemple:

    PUBLIC CONST _DefaultEvent AS String = "Click"

Cette constante est facultative mais vous devriez la déclarer d'office.

### La constante `_DefaultSize`

Cette constante est une chaîne représentant la taille par défaut du contrôle lorsqu'il est déposé depuis la boîte à outils sur l'éditeur de formulaire. Il s'agit de la largeur et de la hauteur exprimées comme multiples de Desktop.Scale, séparées par une virgule.

Par exemple:

    PUBLIC CONST _DefaultSize AS String = "36,36"

Cette constante est facultative. Si elle n'est pas déclarée, l'IDE tâchera de faire de son mieux.

### La constante `_DrawWith`

Cette constante est une chaîne indiquant à l'IDE quel contrôle doit être utilisé pour le dessiner sur l'éditeur de formulaire.

Par défaut, les contrôle qui sont membres de gb.qt4, /wiki/comp/gb.qt.ext, gb.form et gb.form.mdi sont tracés en étant instanciés avec la propriété Design activée.

Si un contrôle n'est pas un membre des composants ci-dessus, alors l'IDE dessinera un cadre contenant l'icône du contrôle ainsi que son nom.

En définissant cette constante, l'IDE n'utilisera pas un DrawingArea, mais bien le contrôle que vous aurez indiqué.

Par exemple:

    PUBLIC CONST _DrawWith AS String = "TextBox"

### La constante `_Arrangement`

Cette constante est une valeur entière représentant le style d'arrangement que l'IDE imposera pour ordonner les contrôles enfants à l'intérieur d'un conteneur avant de les sauvegarder sur disque.

Cette valeur est une des valeurs entières de la classe de constantes Arrange

Par exemple:

    PUBLIC CONST _Arrangement AS Integer = 2 ' Arrange.Vertical

Vous ne pouvez pas utiliser directement les constantes Arrange lorsque vous êtes à l'intérieur d'une déclaration de constante. Il s'agit d'une limitation du langage Gambas.

Cette constante est optionnelle et utilisée uniquement lorsque le contrôle est un conteneur. Si elle n'est pas définie, aucun arrangement n'est imposé.

## Icônes des contrôles

Chaque contrôle doit posséder une icône qui sera affichée dans la boîte à outils des contrôles de l'IDE.

Pour mettre à disposition les icônes de vos composant contrôles, vous devez créer un répertoire `/control` à la racine de votre projet et y placer un fichier PNG pour chaque contrôle.

En Gambas 3, le répertoire du `contrôle` doit être créé dans le répertoire `.hidden` (caché). C’est la section "Project" dans l’arborescence projet de développement d’environnement.

Le nom d'une icône de contrôle doit être le nom de la classe du contrôle en minuscules et avec l'extension `.png`.

Par exemple :

    $ cd gb.db.form
    $ cd control
    $ ls
    databrowser.png  datacombo.png  datacontrol.png  datasource.png  datatree.png  dataview.png

## Exigences des Composants

Vous pouvez spécifier les exigences du composant dans l’onglet " Nécessite " du dialog propriété du projet de l’IDE].

Notez que cet onglet n’est pas visible quand un projet n’est pas un composant.

Dans cet onglet, vous inscrirez toutes les dépendances de votre composant à d'autres composants.

La section "Fonctionnalités" possède quatre cases à cocher, chacune d'elles correspondant à une fonctionnalité fournie par un ou plusieurs composants. Utilisez cette section lorsque votre composant a besoin d'une fonctionnalité spécifique qui ne repose pas sur un composant particulier.

Si vous avez vraiment besoin de certains composants spécifiques, vous pouvez les sélectionner dans la section "Composants" de l'onglet.

Les composants que vous sélectionnez dans l'onglet "Composants" du dialogue propriété n'ont rien à voir avec les composants que vous indiquez dans l'onglet "Nécessite".

Ils sont seulement utilisés lorsque vous exécutez le projet du composant depuis l'IDE à des fins de débogage.

## Débogage, installation et empaquetage du composant

### Débogage

Pour débugger votre composant, vous pouvez l'utiliser directement et exécuter son projet tel quel!

La classe de démarrage du projet, ainsi que les composants cochés dans l'onglet "Composants" du dialogue de propriété du projet ne perturberont en aucune manière le comportement du composant lorsqu'il sera installé et utilisé par d'autres projets.

### Installation

Vous pouvez installer le composant dans votre répertoire utilisateur en cochant l'option correspondante dans le dialogue "Générer Exécutable".

Une fois installé à cet endroit, le composant apparaîtra dans l'onglet "Composants" du dialogue de propriété du projet, comme tous les autres composants installés globalement.

Pour désinstaller le composant de votre répertoire utilisateur, il suffit de décocher l'option dans le dialogue "Générer Exécutable ..." et de refaire l’éxécutable.

### Empaquetage

L'IDE peut fabriquer des paquets binaires de votre composant, tout comme il le fait avec n'importe quel autre projet normal.

Simplement, il y aura moins d'options à définir : un composant n'a pas d'entrée de menu, par exemple.

Le paquet binaire installera le composant de manière globale et celui-ci sera utilisable au même titre que n'importe quel autre composant officiel mis à disposition par Gambas.

Si vous voulez distribuer votre composant, vous devrez le nommer selon un schéma précis pour éviter que les paquets de composants n'entrent en conflit.

Le nom de votre composant devra être : `gambas3-/fournisseur/-/nom/`

- `gambas3` est le préfixe de tous les composants gambas.

- `fournisseur` est le nom du fournisseur. Pour les composants gambas officiels, le nom du fournisseur est simplement `gb`.

- `nom` est le nom du composant.

Même si l'assistant d'empaquetage permet d'insérer la chaîne du nom du fournisseur dans le nom du paquet, évitez de le faire.

Placez plutôt votre nom de fournisseur à l'intérieur du nom de projet du composant, de sorte qu'il apparaisse dans le nom du composant final et que l'utilisateur puisse le voir.

Pour l'instant, une faille de l'empaqueteur empêche de prendre en compte la version de projet du composant pour générer les dépendances du paquet. Par conséquent, vous devrez mettre vous-même la version de projet de votre composant à la version courante de Gambas!

## Conclusion

J'essaie de trouver le moyen le plus facile pour fabriquer des composants avec l'IDE. Ce n'est pas encore parfait mais si vous avez un commentaire ou une question à ce sujet, s'il vous plaît, utilisez la mailing-list!

Notez que les choses changeront sûrement avant la sortie définitive de Gambas 3.

Et, bien sûr, si vous voulez corriger ou améliorer cet article, vous êtes les bienvenus.