Prise en charge de ToolsAPI pour l'éditeur de code
Remonter à Extension de l'EDI par l'utilisation de l'API Tools
A partir de RAD Studio 11.3, les utilisateurs disposent d'un ensemble complet d'outils API (ToolsAPI) pour personnaliser l'éditeur de code (opérations Paint, demande d'informations, obtention d'événements pour l'éditeur de code, etc.).
Sommaire
- 1 Comment les utiliser
- 2 Concepts fondamentaux
- 3 Services de l'éditeur de code
- 4 Optimiser les opérations de lecture et d'écriture de l'éditeur de code
- 5 Evénements de l'éditeur de code
- 6 Etat de l'éditeur
- 7 Etat des lignes
- 8 Menu contextuel de l'éditeur
- 9 Options de l'éditeur de code
- 10 Espace de la gouttière de l'éditeur
- 11 Voir aussi
Comment les utiliser
Des plugins très pratiques et intéressants fonctionnent désormais depuis l'éditeur. Nous souhaitons par conséquent fournir une API complète qui stimulera l'innovation et facilitera l'écriture de plugins qui réaliseront des tâches auxquelles nous n'avons même pas pensé.
Ces API permettent aux utilisateurs d'intercepter toutes les étapes du rendu visuel dans l'éditeur (ligne, gouttière, texte). Des événements sont appelés avant et après chaque étape pour que les éléments créés viennent s'ajouter à ce qui existe déjà dans l'EDI ou viennent remplacer des éléments existants (en empêchant l'EDI d'afficher ce qui s'affiche habituellement par défaut).
Vous pouvez obtenir la liste complète des éditeurs, des vues d'édition et établir des correspondances entre eux. Les utilisateurs peuvent lancer des requêtes sur l'état d'un éditeur ou bien lancer des requêtes sur l'état de chaque ligne. Les événements Paint incluent le contexte entier. Utilisez-les pour les opérations de dessin dans l'éditeur ou pour obtenir des informations sur les éditeurs et les éléments qu'ils contiennent, même en dehors de toute opération de dessin.
Concepts fondamentaux
Le texte/code est stocké dans le tampon de l'éditeur (IOTAEditView.Buffer fournit un IOTAEditBuffer). Une vue (IOTAEditView) représente une fenêtre d'affichage sur ce tampon. Elle est utilisée par un contrôle d'éditeur (le contrôle VCL qui implémente l'éditeur). Il n'y a qu'un seul tampon pour le contenu d'un fichier, mais les utilisateurs peuvent utiliser plusieurs vues pour y accéder et le modifier, ce qui entraîne l'ouverture de nombreuses fenêtres d'éditeur du même fichier. Chaque contrôle d'éditeur correspond à une vue, et vice-versa.
Numéros de ligne de l'éditeur et numéros de ligne logique
Il ne faut pas confondre les numéros de ligne de l'éditeur et les numéros de ligne logique. La différence est importante lorsque des lignes sont élidées (repliées). Dans l'EDI, le terme élidé désigne du code replié. Un éditeur peut contenir de nombreuses lignes visibles à l'écran, mais au point de pliage, les numéros de ligne de l'éditeur et les numéros de ligne logique divergent, de sorte que le point de pliage se retrouve en dehors de l'écran.
Les lignes logiques sont des numéros de ligne "réels".
Les lignes de l'éditeur sont celles qui sont affichées dans l'éditeur ou qui le seraient si vous faisiez défiler l'éditeur.
Par exemple, dans un fichier comportant dix lignes (lignes logiques), les lignes 4-7 étant repliées/élidées, les lignes logiques vont jusqu'à dix, mais les lignes de l'éditeur vont jusqu'à sept (pour les sections élidées, une ligne est toujours présente). Les lignes visibles correspondent à celles effectivement affichées à l'écran dans l'éditeur. En raison du pliage, ces lignes peuvent être un sous-ensemble des lignes dans le tampon. Par conséquent, les lignes visibles de l'éditeur sont toujours continues, mais les numéros de ligne logique peuvent avoir des intervalles et comporter des sauts aux points de pliage.
Il est possible de convertir un numéro de ligne logique en numéro de ligne de l'éditeur en utilisant l'état d'une ligne. Les deux types de numérotation peuvent être utilisés pour interroger l'état. Vous obtenez ainsi l'état de la ligne logique ou de la ligne de l'éditeur, et pouvez lui demander à quelle ligne logique ou ligne de l'éditeur il correspond.
Services de l'éditeur de code
Le point de départ est l'interface INTACodeEditorServices. Cette interface vous permet de :
- Vous inscrire aux événements de l'éditeur, tels que : souris, défilement, redimensionnement et dessin.
- Rechercher la vue d'un contrôle d'éditeur et le contrôle d'éditeur qui lui est associé. Il n'y a qu'un seul tampon, mais plusieurs vues de ce tampon peuvent exister, et chaque contrôle d'éditeur utilise une seule vue.
- Lister tous les contrôles de l'éditeur et toutes les vues d'édition.
- Obtenir le contrôle d'éditeur supérieur (le dernier avec lequel vous avez interagi).
- Obtenir l'état de l'éditeur pour un contrôle. Vous pouvez obtenir l'état de n'importe quelle ligne à partir de l'état de l'éditeur.
- Obtenir diverses informations concernant l'éditeur.
- Réserver une partie de la gouttière de l'éditeur à l'usage de vos plugins.
- Accéder à INTACodeEditorServices à partir de
BorlandIDEServicescomme avec les autres interfaces. - Invalider (c'est-à-dire forcer le rafraîchissement) des parties d'un éditeur : par ligne logique, pour un rectangle ou l'intégralité de l'éditeur.
Optimiser les opérations de lecture et d'écriture de l'éditeur de code
Lecture à partir du tampon de l'éditeur
Utilisez l'interface IOTAEditReader pour lire depuis le tampon de l'éditeur. Cette API de bas niveau est très performante. Elle permet un accès direct au contenu de l'éditeur. Si vous devez analyser le code par l'intermédiaire de chaînes basées sur des pointeurs, vous pouvez le faire sans allocation ni copie de chaînes.
Pour obtenir le contenu du tampon de l'éditeur pour un ensemble de lignes, appelez GetLineData, en transmettant le numéro de la première ligne, le numéro de la dernière ligne, le rappel et un pointeur arbitraire qui peut représenter n'importe quelle donnée de votre choix, qui sera transmise telle quelle au rappel. Cette méthode est utilisée pour pointer sur une instance d'objet afin de la convertir en méthode orientée objet dans le rappel.
Le rappel obtient le numéro de la ligne, le pointeur inchangé transmis et un pointeur vers les informations de la ligne. Cette structure d'informations contient la longueur de la ligne, le type de fin de ligne (une énumération représentant CRLF, seulement CR, seulement LF, etc.) et un pointeur sur la chaîne ligne.
La chaîne ligne est au format UTF8 sans caractère de fin nul et sans octets de fin de ligne. Il s'agit simplement d'un pointeur direct vers le contenu de la ligne dans la mémoire du tampon de l'éditeur.
L'interface IOTAEditReader vous permet de :
- Obtenir le nombre de lignes dans le tampon via la propriété
LinesInBuffer.
- Obtenir les données d'une seule ligne ou d'une série de lignes en utilisant la procédure suivante :
procedure GetLineData(AFirstLine: Integer; ARange; Integer;
ACallBack: TOTALineDataCallback; AUserData: Pointer);
- L'obtention des données d'une ligne requiert un rappel tel que :
TOTALineDataCallback = procedure(ALine: Longint; ALineInfo:
POTALineInfo; AUserData: Pointer)
Vous pouvez également effectuer des tâches comme calculer le nombre de lignes sans transférer ni analyser la totalité du tampon (ce qui était obligatoire avec la précédente API), ainsi que calculer la taille du tampon en octets, là encore sans streaming.
Ecrire à partir du tampon de l'éditeur
Voici différentes méthodes pour écrire dans le tampon de l'éditeur :
IOTAEditWriter: une interface qui fournit une API de type flux avec une position, puis permet de copier, d'insérer, de supprimer, etc. des primitives. Cette méthode requiert la rationalisation du texte de l'éditeur pour les opérations à implémenter.Insert(): surcharges prenant un UTF8String. Cette méthode est davantage orientée numéros de lignes.
Méthodes plus performantes :
InsertBlankLine: insère une ligne vide à un numéro de ligne spécifique.InsertLine: insère une ligne à un numéro de ligne spécifique. Cette méthode amène un pointeur vers un contenu UTF8 ou UTF8String et insère ce contenu dans la nouvelle ligne.DeleteLine: supprime une ligne à un numéro de ligne spécifique.ReplaceLine: remplace une ligne à un numéro de ligne spécifique avec un pointeur sur un contenu UTF8 ou UTF8String.
IOTAEditPosition. Ces primitives sont plus proches de la façon dont un humain interagit avec l'éditeur ; leurs performances sont raisonnablement élevées et elles sont une alternative à IOTAEditWriter.Evénements de l'éditeur de code
Recensez une instance de l'interface de notification INTACodeEditorEvents en utilisant AddEditorEventsNotifier. Cela vous permet d'être notifié lorsqu'une grande variété d'événements se produisent, notamment des événements en lien avec la souris, les fenêtres, les changements d'état de l'éditeur et le dessin.
Considérations à prendre en compte pour les performances
De nombreux événements se produisent pendant que l'utilisateur interagit avec l'éditeur. Pour optimiser les performances, le notificateur ne vous informe que des types d'événements pour lesquels vous avez demandé à recevoir des notifications. Pour ce faire, implémentez AllowedEvents, qui renvoie un ensemble d'événements (souris, fenêtre, etc.) pour lesquels vous souhaitez être averti. Par exemple, pour recevoir des notifications à propos des événements de la souris, AllowedEvents doit renvoyer un ensemble incluant cevMouseEvents. Tous les événements en relation avec la souris (enfoncement du bouton de la souris, déplacement de la souris, relâchement du bouton de la souris) sont ainsi renvoyés. Il n'est pas possible de s'abonner à un événement spécifique, seulement à des types d'événements regroupés.
Si possible, limitez les notifications en ne surveillant que les types d'événements dont vous avez besoin. En effet, une surabondance de notifications peut entraîner des problèmes de performances. De même, assurez-vous que les méthodes qui gèrent les événements sont aussi légères que possible et effectuent un minimum d'opérations. Chaque fois que possible, différez les processus longs (par exemple, en utilisant TThread.ForceQueue pour exécuter une méthode ultérieurement). Un traitement long pendant la gestion des événements engendrera un décalage lors de la saisie, un ralentissement du dessin ou d'autres effets similaires.
Les méthodes d'optimisation suivantes permettent de réduire la sur-notification.
- AllowedEvents : renvoie les événements auxquels le plugin s'intéresse.
- AllowedGutterStages et AllowedLineStages : masques similaires pour les étapes du dessin (gouttière, ligne et texte) durant lesquelles vous souhaitez que votre plugin soit appelé.
Pour éviter un impact sur les performances, utilisez le résultat de ces méthodes pour vous assurer que votre plugin est uniquement appelé pour les événements nécessaires.
Evénements des fenêtres
Les API suivantes vous permettent de vérifier si un élément devrait se trouver sur l'écran de l'éditeur. Vous pouvez demander la nouvelle taille de l'éditeur en utilisant les propriétés TWinControl Width et Height de l'éditeur, comme pour n'importe quel composant visuel normal.
- Redimensionnez l'éditeur avec EditorResized.
- Faites défiler l'éditeur avec EditorScrolled.
Ces événements sont uniquement appelés lorsque cevWindowEvents est renvoyé dans AllowedEvents.
Evénements de la souris
Les événements de la souris permettent aux utilisateurs d'implémenter des éléments interactifs à l'intérieur de l'éditeur. Ils incluent :
Ces événements sont uniquement appelés lorsque cevMouseEvents est renvoyé dans AllowedEvents.
Evénements de changement d'état
Les événements de changement d'état se produisent quand des lignes sont élidées ou réaffichées et indiquent sur quelle ligne cela se produit.
Evénements de dessin
Il existe plusieurs méthodes de dessin : pour dessiner une ligne, le texte de la ligne et la gouttière de l'éditeur. Le dessin est basé sur des lignes. Il suit le modèle interne de l'éditeur, qui ne permet pas de dessiner quelque chose qui n'est pas associé à une ligne, même si c'est possible en dessinant un rectangle dans chaque ligne.
Pour chacun de ces trois éléments (gouttière, ligne, texte), les méthodes :
- Sont appelées plusieurs fois : une par étape du dessin, avant et après cette étape.
- L'étape du dessin inclut le début et la fin (c'est-à-dire avant et après le dessin), l'arrière-plan de la ligne, le balisage général, les paires en surbrillance, la marge droite et les indicateurs de ligne repliée.
- Sont transmises avec le contexte, qui donne accès au rectangle de dessin, au canevas, au numéro de ligne, au numéro de ligne logique, au nom de fichier, au contrôle et à la vue d'édition. Elles permettent également de demander l'état des lignes et de l'éditeur.
- Peuvent empêcher l'EDI de gérer une étape de dessin qu'elle gère normalement par défaut. Si plusieurs plugins sont impliqués dans le dessin, vous ne pouvez pas empêcher les autres plugins d'effectuer le dessin.
Méthodes Paint
L'interface INTACodeEditorEvents inclut les méthodes de dessin suivantes :
- BeginPaint et EndPaint : ces méthodes sont appelées avant et après l'intégralité des opérations Paint dans l'éditeur. BeginPaint force un rafraîchissement complet du dessin de l'éditeur.
- Ces méthodes sont uniquement appelées lorsque
cevBeginEndPaintEventsest renvoyé dansAllowedEvents.
- Ces méthodes sont uniquement appelées lorsque
- PaintGutter : utilisez cette méthode pour dessiner la gouttière de l'éditeur.
- Cette méthode est uniquement appelée lorsque
cevPaintGutterEventsest renvoyé dansAllowedEvents.
- Cette méthode est uniquement appelée lorsque
- PaintLine : il s'agit de la méthode générale pour dessiner une ligne. Une utilisation courante de cette méthode consiste à modifier le dessin de l'arrière-plan ou à ajouter un balisage supplémentaire une fois le texte dessiné.
- Cette méthode est uniquement appelée lorsque
cevPaintLineEventsest renvoyé dansAllowedEvents.
- Cette méthode est uniquement appelée lorsque
- PaintText : cette méthode est appelée lorsque le contenu du code (c'est-à-dire le texte) est dessiné dans une ligne de l'éditeur. Appelez-la pour chaque segment de texte logique, par exemple chaque symbole ou commentaire. Les paramètres fournissent également des informations sur le numéro de la colonne dans laquelle le texte est dessiné, sur le texte lui-même, sur la mise en évidence de la syntaxe et indique si le texte est sélectionné. Etant donné que, comme pour toutes les méthodes, cela peut empêcher le dessin de l'EDI, cette méthode peut être utilisée pour modifier le formatage du code de l'EDI.
- Cette méthode est uniquement appelée lorsque
cevPaintTextEventsest renvoyé dansAllowedEvents.
- Cette méthode est uniquement appelée lorsque
Evénements de recensement et étapes de dessin
Comme ces méthodes peuvent être utilisées de manière très granulaire (dans de nombreuses étapes de dessin, avant et après le traitement de l'EDI, pour les trois différentes zones de dessin), cela peut avoir un impact sur les performances pendant le dessin. Ce problème peut être réglé en s'abonnant à un sous-ensemble granulaire d'événements , qui correspond aux méthodes qui seront appelées. Implémentez AllowedEvents pour renvoyer les événements à appeler.
Ensuite, ces événements peuvent être appelés pour plusieurs étapes du processus de dessin. Là encore, vous devez spécifier à quelles étapes les appeler pour des raisons d'optimisation. Implémentez AllowedGutterStages pour renvoyer les étapes du dessin de la gouttière de l'éditeur pour lesquelles vous voulez être averti et AllowedLineStages pour les étapes du dessin d'une ligne pour lesquelles vous voulez être averti. PaintText n'implique pas plusieurs étapes.
Etat de l'éditeur
L'interface INTACodeEditorState permet à l'utilisateur d'obtenir des informations sur les éléments affichés pour un éditeur spécifique, notamment :
- Le rectangle de l'éditeur.
- La taille de la gouttière.
- Le bord gauche où le code est dessiné.
- Le composant de l'éditeur de code (comme un TWinControl) et la vue d'édition utilisée.
- Les lignes inférieure et supérieure visibles.
- Les colonnes droite et gauche visibles (défilement horizontal).
- La largeur (en caractères) de la plus grande ligne visible.
- Conversion d'un point en pixels en position de caractère (index et ligne).
- Conversion de la position d'un caractère (index et ligne) en rectangle de délimitation du caractère.
- Demander si une ligne spécifique est visible.
- Demander des informations sur les lignes élidées.
- Obtenir l'état d'une ligne spécifique.
Pour obtenir l'état de l'éditeur, lancez une requête avec INTACodeEditorServices ou via le paramètre Context dans les méthodes Paint, qui fournit l'état de l'éditeur et des lignes, ainsi que d'autres informations de contexte de dessin. L'état de l'éditeur est créé lorsqu'il est demandé.
Etat des lignes
L'interface INTACodeEditorLineState permet à l'utilisateur de demander des informations pour une ligne spécifique. Vous pouvez obtenir l'état d'une ligne par l'intermédiaire de l'interface INTACodeEditorState. Pour n'importe quelle ligne, vous pouvez demander :
- Le numéro de ligne de l'éditeur et le numéro de ligne logique.
- S'il s'agit d'une ligne élidée : la ligne visible représentant une section élidée de lignes, ainsi que le début et la fin de cette section élidée.
- Divers rectangles : la totalité du rectangle de la ligne sur toute la largeur de l'éditeur, le rectangle de la gouttière, le rectangle de balisage de la gouttière (par exemple, l'endroit où les numéros de ligne et les symboles +/- de pliage sont dessinés), le rectangle de la zone du code, un rectangle qui limite le texte.
- Le texte d'une ligne et le sous-ensemble de texte qui est visible pour la ligne.
INTACodeEditorLineState possède désormais une propriété State, qui vous indique si :
eleLineHighlight: la ligne est en surbrillance.eleErrorLine: la ligne contient une erreur.eleExecution: la ligne est en cours d'exécution.eleBreakpoint: la ligne contient un point d'arrêt.eleInvalidBreakpoint: la ligne contient un point d'arrêt non valide.eleDisabledBreakpoint: la ligne contient un point d'arrêt désactivé.eleCompiled: la ligne a été compilée et peut contenir un point d'arrêt.
Pour obtenir l'état de la ligne, lancez une requête avec INTACodeEditorState pour un éditeur spécifique ou via le paramètre Context dans les méthodes Paint, qui fournit l'état de l'éditeur et des lignes, ainsi que d'autres informations de contexte du dessin. L'état de la ligne est créé lorsqu'il est demandé.
INTACodeEditorLineState possède maintenant une propriété CellState, indexée par colonne, qui vous indique si la cellule spécifique a l'un des états suivants :
eceSelected: la cellule est actuellement sélectionnée.eceHotLink: la cellule contient un lien hypertexte actif.eceHotLinkable: la cellule prend en charge les liens hypertexte.eceSyncEditBackground: la cellule se trouve dans l'arrière-plan d'un groupe d'édition synchronisé.eceSyncEditSearch: la cellule fait partie d'un groupe d'édition synchronisé actuellement recherché.eceSyncEditMatch: la cellule fait partie d'un groupe d'édition synchronisé qui contient un élément correspondant.eceSearchMatch: la cellule est une correspondance pour une requête de recherche.eceExtraMatch: la cellule est une correspondance secondaire pour une requête de recherche.eceBraceMatch: la cellule est une accolade correspondante ou un crochet correspondant.eceHint: la cellule contient un conseil.eceWarning: la cellule contient un message d'avertissement.eceError: la cellule contient un message d'erreur.eceDisabledCode: la cellule contient du code désactivé.eceFoldBox: la cellule correspond à une zone qui permet de replier ou déplier une section de code.
Menu contextuel de l'éditeur
Les constantes cEdMenuCat répertoriées ci-dessous définissent les différentes catégories de listes d'actions utilisées pour construire le menu local de l'éditeur. INTAEditorLocalMenu permet d'ajouter le menu local de l'éditeur, et ces constantes peuvent être utilisées pour contrôler l'emplacement où une nouvelle liste d'actions est ajoutée.
Voici la liste des actions dans chaque catégorie de menu :
cEdMenuCatIdentifier: Chercher la déclaration.cEdMenuCatBreakPoint: Activé, Propriétés du point d'arrêt.cEdMenuCatDebugDebug: Exécuter jusqu'au curseur.cEdMenuCatBase: Ouvrir le fichier source/en-tête, Ouvrir le fichier sous le curseur, Rechercher le symbole sous le curseur, Rechercher une rubrique, Vue tampon suivante, Vue tampon précédente, Modification suivante, Modification précédente, Modification non enregistrée suivante, Modification non enregistrée précédentecEdMenuCatModule: Ouvrir le fichier source/en-tête, Voir les messages et Afficher dans l'explorateur.cEdMenuCatClipboard: Couper, Copier et Coller.cEdMenuCatBookMarks: Tous les éléments Aller à et Basculer le signet.cEdMenuCatDebug: Déboguer et Exécuter jusqu'au curseur.cEdMenuCatDebug: Voir, Message, Lecture seule, Voir comme fiche.cEdMenuCatView: Voir comme fiche.cEdMenuCatElide: Plier, Commentaires de documentation, Méthodes, Plus proche, Imbriqué, Régions, Espace de nommage, Types, Déplier, Tous, Plus proche.cEdMenuCatVersionControl: Tous les éléments de menu liés aux plugins de contrôle de version.cEdMenuCatRefactor: Chercher, Chercher les références, Chercher les références locales, Rechercher le symbole de déclaration, Refactoring.cEdMenuCatFormat: Englober, Synchroniser les prototypes.cEdMenuCatRepository: Ajouter au référentiel.cEdMenuCatLast: Voir les messages, Lecture seule, Options de l'éditeur.
Options de l'éditeur de code
L'interface INTACodeEditorOptions permet aux utilisateurs de demander des informations sur les couleurs, la gouttière visible, les fontes, les tailles, etc.
Espace de la gouttière de l'éditeur
La gouttière de l'éditeur est actuellement le meilleur endroit pour dessiner des informations par ligne. RAD Studio l'utilise pour les numéros de ligne, les marqueurs de pliage de ligne, les indications de modification de ligne, les points d'arrêt, les signets, etc. Réservez une partie de la gouttière de l'éditeur, car cela augmentera la largeur de la gouttière pour votre plugin. Pour ce faire, utilisez RequestGutterColumn, en spécifiant une taille en pixels. Cette partie peut se trouver avant ou après (à gauche ou à droite), là où les points d'arrêt ou les numéros de ligne sont dessinés.
La méthode GetGutterColumnRect permet aux utilisateurs d'obtenir le rectangle pour une zone recensée spécifique de la gouttière. Ou utilisez la méthode GetGutterColumnRect pour obtenir le rectangle de la zone recensée dans la gouttière de l'éditeur.
Autres modifications apportées à ToolsAPI
- Depuis 11.3, les ToolsAPI suivantes pour le dessin de l'éditeur sont obsolètes :
INTAEditViewModifier.BeginPaintINTAEditViewModifier.EndPaintINTAEditViewModifier.PaintLine
Nous recommandons d'utiliser le nouvel ensemble d'API.