codeeditor — u_pbt_codeeditor #
← Référence des composants · Sommaire du guide
Éditeur de code à coloration syntaxique : dix langages, numéros de ligne, repli de régions, recherche et remplacement, marqueurs de diagnostic dans la gouttière et dépôt de fichiers.
▶ Le voir en vrai — Application de démonstration, tuile Code editor : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Userobject | u_pbt_codeeditor |
| Classe d'items | — (composant sans items) |
| Sert à | Saisir ou afficher du code, une requête SQL, un fichier de configuration : partout où un multilineedit manque de lisibilité |
| Options opt-in | ib_track_caret, ib_allow_drop, ib_folding |
Démarrage rapide #
// event open de la fenetre
uo_editor.is_syntax = uo_editor.SYNTAX_SQL
uo_editor.is_text = "SELECT c.name, SUM(o.amount) AS total~r~n" &
+ "FROM customer c~r~n" &
+ "WHERE o.status = 'paid'"
// Local variables
string ls_sql
// Relire ce que l'utilisateur a reellement saisi
ls_sql = uo_editor.of_get_text()
is_textdonne la même chose : la frappe de l'utilisateur y est reportée dès que la saisie se pose (eventue_changed).
Langages reconnus #
is_syntax accepte l'une de ces constantes, ou SYNTAX_NONE (chaîne vide) pour du texte brut sans coloration.
| Langage | Constante | Autres écritures acceptées |
|---|---|---|
| PowerScript | SYNTAX_POWERSCRIPT | pb, powerbuilder |
| SQL | SYNTAX_SQL | tsql, plsql |
| JavaScript | SYNTAX_JAVASCRIPT | js, jsx |
| JSON | SYNTAX_JSON | jsonc |
| Famille C | SYNTAX_C · SYNTAX_CPP · SYNTAX_CSHARP · SYNTAX_JAVA | c++, cxx, cs |
| HTML / XML | SYNTAX_HTML · SYNTAX_XML | htm, xhtml, svg |
| CSS | SYNTAX_CSS | scss, less |
| Python | SYNTAX_PYTHON | py |
| YAML | SYNTAX_YAML | yml |
| Markdown | SYNTAX_MARKDOWN | md, mkd |
Les langages d'une même famille partagent la coloration (SYNTAX_JAVA colore comme SYNTAX_C, SYNTAX_XML comme SYNTAX_HTML) : la constante que vous choisissez documente votre intention, le résultat à l'écran est le même. La valeur est insensible à la casse et un nom inconnu revient au texte brut, sans erreur.
Propriétés #
Contenu et langage #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_text | string | "" | Le code affiché dans l'éditeur. En lecture, renvoie le contenu vivant, frappe de l'utilisateur comprise, avec les fins de ligne reçues : un texte en CRLF se relit en CRLF, un texte en CR seul en CR, replié ou non ; un texte qui les mélange se relit en CRLF. Un nouveau texte s'affiche depuis sa première ligne, efface les marqueurs d'of_add_marker et n'est pas modifié (ib_modified) |
is_syntax | string | "" | Langage de coloration : constantes SYNTAX_* (voir le tableau ci-dessus). SYNTAX_NONE = texte brut. Se relit tel qu'écrit : SYNTAX_CSHARP reste SYNTAX_CSHARP, même si C# partage la grammaire du C |
ib_readonly | boolean | false | Éditeur en lecture seule : l'utilisateur consulte sans pouvoir modifier |
ib_modified | boolean | false | true dès que le texte diffère de celui déclaré enregistré : un nouveau is_text n'est pas modifié, la frappe, of_insert_text ou un remplacement le rendent modifié, annuler jusqu'au texte enregistré le remet à false. Remettez-le à false après l'enregistrement ; true le force |
Affichage #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
ib_line_numbers | boolean | true | Affiche ou masque la gouttière de numéros de ligne, à gauche ; masqués, une gouttière étroite garde les marqueurs de repli et les diagnostics d'of_add_marker |
ib_current_line | boolean | true | Surligne la ligne où se trouve le curseur ; en mode ib_wrap, la bande couvre toutes les rangées de la ligne |
ib_folding | boolean | false | Opt-in : autorise le repli des régions #region … #endregion (//#region en PowerScript, JavaScript ou C) depuis la gouttière : #region s'ouvre replié, #regionopen déplié ; les marqueurs restent même avec ib_line_numbers = false. C'est un mode de lecture : tant qu'il est actif l'éditeur ne se laisse pas taper, parce que la zone de saisie porte alors le texte replié et non la source; l'activer sur des régions fermées oublie aussi l'historique de Ctrl+Z. Un marqueur s'atteint au clavier (Tab) ; Entrée ou Espace le plie ou le déplie |
ib_wrap | boolean | false | Renvoie les lignes longues à la ligne au lieu de défiler latéralement |
ii_tab_size | integer | 4 | Nombre de colonnes occupées par une tabulation, de 1 à 12 (toute autre valeur revient à 4) ; Entrée après une accolade ouvrante indente de cette largeur |
is_font_family | string | "" | Police de l'éditeur (vide = police à chasse fixe du thème) |
ii_font_size | integer | 0 | Taille de la police en pixels (0 = taille du thème) |
Navigation et interactions #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
ib_search_enabled | boolean | true | Active la barre de recherche intégrée (Ctrl+F, Ctrl+H pour remplacer — voir « Clavier ») ; à false, of_find renvoie -4 |
ib_find_match_case | boolean | false | Option de recherche : ne trouve que le texte de même casse. Le bouton Aa de la barre est le même interrupteur ; vaut pour of_find, of_replace et of_replace_all |
ib_find_whole_word | boolean | false | Option de recherche : ne trouve le texte que comme mot entier (le _ fait partie du mot : ls_a n'est pas trouvé dans ls_ab). Bouton ab de la barre |
ib_find_regex | boolean | false | Option de recherche : le texte est une expression régulière (syntaxe JavaScript) ; le remplacement d'of_replace peut alors employer $1, $& et $<name>. Une expression invalide ne trouve rien, encadre le champ en rouge et fait renvoyer -5 à of_replace. Bouton .* de la barre |
il_doc_line | long | 0 | Amène la ligne indiquée au milieu de la vue et la marque d'une bande d'accent (numérotation à partir de 1, comme la gouttière) — la ligne qu'une documentation ou un résultat de recherche désigne. Le curseur et la sélection de l'utilisateur ne bougent pas (il_caret_line déplace le curseur). Une ligne cachée dans une région repliée ouvre cette région ; la bande se peint aussi en mode ib_wrap. 0 efface la bande ; une ligne au-delà du texte ne marque rien et se relit telle qu'écrite ; tout nouveau is_text efface la bande |
il_caret_line | long | 1 | La ligne du curseur, à partir de 1, lue en direct (replié : celle de la gouttière). L'écrire pose le curseur au début de cette ligne et l'amène à l'écran — le « aller à la ligne » d'une erreur de compilation ; une ligne cachée dans une région repliée ouvre cette région, une ligne au-delà du texte s'arrête à la dernière. Avec ib_track_caret, ue_caret_changed suit, comme pour un clic — rien quand le curseur ne bouge pas |
il_caret_column | long | 1 | La colonne du curseur, à partir de 1, lue en direct : le rang du caractère dans sa ligne (une tabulation compte pour un). L'écrire déplace le curseur le long de sa ligne ; au-delà de la fin de ligne, il s'arrête à cette fin. Avec ib_track_caret, ue_caret_changed suit, comme pour un clic |
ib_track_caret | boolean | false | Opt-in : déclenche ue_caret_changed à chaque déplacement du curseur — geste de l'utilisateur ou ordre de votre code ; un nouveau document (is_text, un chargement) ne dit rien du curseur |
ib_allow_drop | boolean | false | Opt-in : accepte le dépôt de fichiers depuis l'Explorateur Windows ; les chemins complets arrivent par ue_drop_files |
is_theme_style | string | "" | Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement |
is_theme_mode | string | "" | Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement |
il_theme_accent | long | -1 | Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème) |
is_tooltip | string | "" | Info-bulle simple affichée au survol du composant |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie |
Méthodes #
| Méthode | Rôle |
|---|---|
of_get_text ( ) → string | Renvoie le contenu vivant — la même valeur que is_text, pour le code qui préfère un appel de méthode |
of_find (string as_text) | Ouvre la barre de recherche, y inscrit le texte et met en évidence toutes ses occurrences, selon les options ib_find_* (replié, dans les lignes visibles seulement). La première occurrence à partir du curseur est amenée à l'écran ; le curseur lui-même ne bouge qu'à la fermeture de la barre par l'utilisateur. Un texte vide vide le champ et efface les surlignages. Renvoie 0 une fois appliqué, -4 quand ib_search_enabled vaut false, -2 si le composant n'est pas créé |
of_insert_text (string as_text) | Insère du texte au curseur, exactement comme si l'utilisateur l'avait tapé : la sélection en cours est remplacée, le curseur se pose après l'insertion et celle-ci est amenée à l'écran. C'est la méthode d'un bouton insérer un extrait, là où is_text jetterait le travail en cours. Pendant une recherche, l'insertion se fait au curseur de l'utilisateur, jamais sur l'occurrence. Quand le focus est dans l'éditeur ou dans sa barre de recherche, l'insertion passe par le chemin d'édition du navigateur : Ctrl+Z l'annule encore. Lève ue_changed, et avec ib_track_caret ue_caret_changed suit, comme pour une frappe. Rien n'est inséré tant que l'éditeur est en lecture seule (ib_readonly) ou replié (ib_folding). Renvoie 0 une fois appliqué, -4 en lecture seule ou replié, -5 sur un texte vide, -2 si le composant n'est pas créé |
of_replace (string as_find, string as_replace) | Remplace la première occurrence de as_find à partir du curseur (en repartant du début) et l'amène à l'écran ; les options ib_find_* s'appliquent, et avec ib_find_regex le remplacement peut employer $1, $& et $<name>. Un Ctrl+Z l'annule. Avec ib_track_caret, ue_caret_changed suit quand le curseur bouge. Renvoie le nombre d'occurrences remplacées (1, ou 0 s'il n'y en a aucune), -4 en lecture seule ou replié, -5 sur une recherche vide ou une expression invalide, -2 si le composant n'est pas créé |
of_replace_all (string as_find, string as_replace) | Remplace toutes les occurrences de as_find, en un seul pas d'annulation. Mêmes options et mêmes codes qu'of_replace ; renvoie le nombre d'occurrences remplacées |
of_selected_text ( ) → string | Renvoie le texte que l'utilisateur a sélectionné, lu en direct ("" sans sélection), avec les fins de ligne de is_text |
of_select_range (long al_from_line, long al_from_col, long al_to_line, long al_to_col) | Sélectionne de (ligne, colonne) à (ligne, colonne), le tout à partir de 1, et amène la sélection à l'écran ; le curseur se place au bout donné en dernier, et une colonne au-delà de la fin de sa ligne s'arrête à cette fin. Avec ib_track_caret, ue_caret_changed suit, comme pour un glisser. Renvoie 0 une fois appliqué, -5 sur une ligne hors du document ou une colonne inférieure à 1, -4 quand l'éditeur est replié, -2 si le composant n'est pas créé |
of_line_count ( ) | Renvoie le nombre de lignes du document, replié ou non, lu en direct — la borne d'une boîte « aller à la ligne » |
of_add_marker (long al_line, string as_kind, string as_tooltip) | Marque une ligne de la gouttière d'un diagnostic — MARKER_ERROR, MARKER_WARNING ou MARKER_INFO — avec une info-bulle (balisage accepté) : ce que dit un compilateur, là où il le dit. Plusieurs marqueurs peuvent partager une ligne : le plus grave donne l'icône, l'info-bulle les liste tous. Ils appartiennent au document : un nouveau is_text les efface. Renvoie 0 une fois appliqué, -5 sur une ligne hors du document ou un genre inconnu, -2 si le composant n'est pas créé |
of_remove_marker (long al_line) | Retire tous les marqueurs d'une ligne. Renvoie 0 une fois retirés, -5 si la ligne n'en porte aucun, -2 si le composant n'est pas créé |
of_clear_markers ( ) | Retire tous les marqueurs de la gouttière. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_marker_count ( ) | Renvoie le nombre de marqueurs de la gouttière, lu en direct (deux sur une ligne comptent pour deux) |
of_reset ( ) | Remet toutes les propriétés à leur défaut et vide l'éditeur. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_set_redraw (boolean) | Regroupe une rafale de modifications en un seul rendu. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_save_as_png (string) · of_save_as_jpg (string) | Exporte le rendu en image. Renvoie 0 une fois l'image écrite, -4 si l'écriture échoue, -2 si le composant n'est pas créé |
Événements #
| Événement | Déclenché quand |
|---|---|
ue_changed ( ) | L'utilisateur a modifié le contenu et sa frappe s'est stabilisée — levé aussi après of_insert_text ou un remplacement. L'événement ne porte rien : le remplir imposait de relire tout le document à chaque frappe posée, pour une application qui le plus souvent veut seulement savoir que ça a changé. Celle qui veut le code le demande — is_text ou of_get_text() ; ib_modified dit s'il diffère du texte enregistré |
ue_caret_changed (long al_line, long al_col) | Le curseur a bougé (touche, clic, glisser, frappe, ou votre code) ; ligne et colonne comptées à partir de 1, la ligne étant celle de la gouttière quand l'éditeur est replié, la colonne le rang du caractère dans sa ligne (une tabulation compte pour un). Votre code le lève comme le geste (il_caret_line, il_caret_column, of_select_range, of_insert_text, of_replace) ; rien quand le curseur ne bouge pas, et un nouveau document (is_text, un chargement) ne dit rien du curseur — nécessite ib_track_caret = true |
ue_find_result (long al_count, long al_index) | Une recherche a abouti, ou passe à une autre occurrence : al_count occurrences trouvées, al_index = rang de celle qui est mise en avant (à partir de 1). Pendant la frappe, il n'est levé que si le compte change ; fermer la barre ne le lève pas ; une recherche vide non plus |
ue_drop_files (string as_files[]) | Des fichiers ont été déposés depuis Windows : chemins complets, une entrée par fichier. Nécessite ib_allow_drop = true |
ue_drag_enter ( ) | Un glissement de fichiers entre sur l'éditeur (ib_allow_drop) |
ue_drag_leave ( ) | Le glissement de fichiers quitte l'éditeur |
ue_ready ( ) | Le composant a fini de charger ; tout ce qui a été envoyé avant a été rejoué |
ue_runtime_missing ( ) | Le runtime WebView2 est absent : le composant reste vide |
ue_bg_color (long al_color) | Le composant a calculé sa couleur de fond de thème ; l'userobject l'a déjà adoptée (backcolor) |
Clavier #
| Touche | Effet |
|---|---|
| Tab | Indente jusqu'au taquet suivant (ii_tab_size) ; plusieurs lignes sélectionnées : indente tout le bloc |
| Maj+Tab | Désindente la ligne ou le bloc |
| Entrée | Nouvelle ligne à la même indentation, un niveau de plus après {, ( ou [ |
| Ctrl+F | Ouvre la barre de recherche, remplie avec la sélection (ib_search_enabled) |
| Ctrl+H | Ouvre la barre avec sa ligne de remplacement (éditeur modifiable seulement) |
| F3 · Maj+F3 | Occurrence suivante · précédente, depuis le code ou la barre |
| Entrée · Maj+Entrée (barre) | Occurrence suivante · précédente ; dans le champ de remplacement, Entrée remplace l'occurrence courante et Ctrl+Entrée les remplace toutes |
| Échap | Ferme la barre et pose le curseur sur l'occurrence courante |
| Tab, puis Entrée ou Espace (gouttière) | Atteint un marqueur de repli, le plie ou le déplie (ib_folding) |
La colonne que rapportent ue_caret_changed et il_caret_column est le rang du caractère dans sa ligne : une tabulation compte pour un, quelle que soit sa largeur à l'écran.
Exemples #
Un éditeur de requête SQL #
// Geler l'affichage pendant la mise en place
uo_query.of_set_redraw(/*on*/ false)
// Coloration SQL, puis la requete a afficher
uo_query.is_syntax = uo_query.SYNTAX_SQL
uo_query.is_text = "-- Meilleurs clients par chiffre d'affaires encaisse~r~n" &
+ "SELECT c.name, SUM(o.amount) AS total~r~n" &
+ "FROM customer c~r~n" &
+ " INNER JOIN orders o ON o.cust_id = c.id~r~n" &
+ "WHERE o.status = 'paid'~r~n" &
+ "GROUP BY c.name~r~n" &
+ "ORDER BY total DESC"
// Un seul dessin, tout d'un coup
uo_query.of_set_redraw(/*on*/ true)
// event clicked de cb_execute
string ls_sql
// Executer la requete telle que saisie
ls_sql = uo_query.of_get_text() // la saisie reelle de l'utilisateur
of_execute(ls_sql)
Une visionneuse en lecture seule #
Idéale pour présenter du code généré, un journal ou un extrait que l'utilisateur doit lire sans le modifier.
// Coloration PowerScript
uo_preview.is_syntax = uo_preview.SYNTAX_POWERSCRIPT
// Une visionneuse en lecture seule : ni curseur, ni gouttiere, ni surlignage
uo_preview.ib_readonly = true // consultation seule, pas de curseur de saisie
uo_preview.ib_line_numbers = false // masque la gouttiere de numeros
uo_preview.ib_current_line = false // pas de surlignage de la ligne courante
uo_preview.ib_wrap = true // renvoie a la ligne plutot que defiler
uo_preview.ii_tab_size = 2 // tabulations affichees sur 2 colonnes
// Le code a afficher
uo_preview.is_text = of_generate_code()
Suivre la position du curseur dans une barre d'état #
// Signaler chaque deplacement du curseur (ue_caret_changed)
uo_editor.ib_track_caret = true // abonnement explicite : sinon aucun evenement
// event ue_caret_changed de uo_editor : (long al_line, long al_col)
uo_status.of_panel(/*key*/ "pos").is_text = "Ligne " + String(al_line) + ", col. " + String(al_col)
Sans ib_track_caret, le curseur ne remonte rien : ce déclencheur est de fréquence élevée et reste coupé tant que vous ne le demandez pas.
Rechercher et aller à une ligne #
// Ouvre la barre de recherche et met en evidence toutes les occurrences
uo_editor.of_find(/*text*/ "ll_total")
// event ue_find_result de uo_editor : (long al_count, long al_index)
if al_count = 0 then
uo_status.of_panel(/*key*/ "main").is_text = "Aucune occurrence"
else
uo_status.of_panel(/*key*/ "main").is_text = String(al_index) + " / " + String(al_count)
end if
// Aller a la ligne qu'un compilateur a signalee et la marquer dans la gouttiere
uo_editor.of_add_marker(/*line*/ ll_error_line, /*kind*/ uo_editor.MARKER_ERROR, /*tooltip*/ ls_error_text)
uo_editor.il_caret_line = ll_error_line // le curseur y va, la ligne vient a l'ecran
uo_editor.of_focus_webview() // l'utilisateur corrige aussitot
Ouvrir un fichier déposé depuis l'Explorateur #
// Accept files dropped from the Explorer
uo_editor.ib_allow_drop = true
// event ue_drop_files de uo_editor : (string as_files[])
string ls_content
integer li_file
// as_files[1] porte le chemin COMPLET du premier fichier depose
li_file = FileOpen(as_files[1], StreamMode!, Read!)
if li_file > 0 then
FileReadEx(li_file, ls_content)
FileClose(li_file)
// Colorer selon l'extension du fichier, puis afficher son contenu
uo_editor.is_syntax = of_syntax_for_extension(as_files[1])
uo_editor.is_text = ls_content
end if
Réagir aux modifications #
// event ue_changed de uo_editor : ( )
cb_save.enabled = uo_editor.ib_modified // annuler jusqu'au texte enregistre le remet a false
// event clicked de cb_save
if of_save_script(uo_editor.is_text) = 1 then
uo_editor.ib_modified = false // le texte enregistre devient la reference
cb_save.enabled = false
end if
L'événement n'est levé qu'une fois la frappe stabilisée : une saisie continue ne génère pas un événement par touche.
Renommer une variable dans tout le script #
// Local variables
long ll_count
// Mots entiers seulement : ll_total2 est une autre variable
uo_editor.ib_find_whole_word = true
ll_count = uo_editor.of_replace_all(/*find*/ "ll_total", /*replace*/ "ldc_amount") // un seul Ctrl+Z annule tout
Bonnes pratiques #
- Posez toujours
is_syntaxavantis_text: le code est coloré dès le premier affichage, sans recoloration visible. - Pour un affichage en consultation, la combinaison
ib_readonly+ib_line_numbers = false+ib_wrapdonne une visionneuse sobre qui ne ressemble plus à un éditeur. - Pour récupérer une saisie, lisez
is_text(ouof_get_text()) une fois la frappe posée — c'est-à-dire dans votreue_changed, qui vous dit quand. ib_foldingn'a d'intérêt que sur des fichiers longs et structurés ; laissez-le coupé pour de courts extraits. Coupez-le avant de laisser modifier : un plan replié se lit, il ne s'édite pas, etof_get_text()rend toujours la source entière, régions fermées comprises.- Encadrez le chargement d'un gros fichier par
of_set_redraw(false)/of_set_redraw(true). - Appelez
of_reset()avant de charger un document d'une autre nature : sans cela, le langage, la taille de tabulation ou le mode lecture seule précédents restent en place. - Après un enregistrement, remettez
ib_modifiedàfalse: il redevienttrueà la première frappe, etfalsesi l'utilisateur annule jusqu'au texte enregistré. - Pour montrer les erreurs d'une compilation,
of_clear_markers()puis unof_add_markerpar diagnostic, etil_caret_linesur le premier.
Hérité du socle commun #
Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.
| Membres | Rôle | Détaillé dans |
|---|---|---|
of_reset | Remettre le composant à zéro | 3.6 Remettre un composant à zéro : of_reset() |
of_register_shortcut · of_clear_shortcuts | Raccourcis clavier du composant | 3.5 Les raccourcis clavier |
of_is_created · of_is_ready · of_get_last_error | S'il est né, s'il est prêt, ce qui a échoué | 3.7 Diagnostic |
of_save_as_png · of_save_as_jpg | Exporter le rendu en image | 3.8 Exporter le rendu en image |
of_set_redraw | Grouper les modifications en un seul repaint | 3.10 Bonnes pratiques |
of_preload_icons | Icônes affichées sans délai | Affichage instantané : of_icon |
of_set_translation | Traduire un libellé du composant | 5.2 Adapter un libellé : of_set_translation |
of_focus_webview | Donner le focus au composant | 6.4 Clavier et focus |
of_print · of_print_to_pdf | Imprimer, ou écrire un PDF | 6.9 Imprimer |
of_set_property · of_get_property · of_component_name | Piloter une propriété par son nom | 3.1 Le moteur de propriétés |
Deux aides ne sont pas héritées : of_icon et of_escape_markup vivent sur n_pbt_utils. Déclarez-en une — n_pbt_utils lnv_utils, rien à créer — et appelez-les dessus.