# 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 intégrée 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_editeur.is_syntax = uo_editeur.SYNTAX_SQL
    uo_editeur.is_text   = "SELECT c.name, SUM(o.amount) AS total~r~n" &
                           + "FROM customer c~r~n" &
                           + "WHERE o.status = 'paid'"

    // Relire ce que l'utilisateur a reellement saisi
    string ls_sql

    ls_sql = uo_editeur.of_get_text()

> `is_text` donne la même chose : la frappe de l'utilisateur y est reportée dès que la saisie se pose (event `ue_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
`is_syntax` | string | `""` | Langage de coloration : constantes `SYNTAX_*` (voir le tableau ci-dessus). `SYNTAX_NONE` = texte brut
`ib_readonly` | boolean | `false` | Éditeur en lecture seule : l'utilisateur consulte sans pouvoir modifier

### 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
`ib_current_line` | boolean | `true` | Surligne la ligne où se trouve le curseur. Pas de surlignage en mode `ib_wrap`.
`ib_folding` | boolean | `false` | Opt-in : autorise le repli des régions (`#region`, blocs entre accolades) depuis la gouttière
`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
`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 points (`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)
`ii_doc_line` | integer | `-1` | Fait défiler jusqu'à la ligne indiquée et la sélectionne (numérotation à partir de 1). Pas de surlignage en mode `ib_wrap` : le défilement, lui, fonctionne.
`ib_track_caret` | boolean | `false` | Opt-in : déclenche `ue_caret_changed` à chaque déplacement 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 | `fluent` | Style visuel du composant (constantes `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante claire ou sombre (constantes `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Couleur d'accent de ce composant (`-1` = accent 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 et met en évidence toutes les occurrences du texte
`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 et le curseur se pose après l'insertion. C'est la méthode d'un bouton insérer un extrait, là où `is_text` jetterait le travail en cours. Quand l'éditeur a le focus, l'insertion passe par le chemin d'édition du navigateur : Ctrl+Z l'annule encore
`of_reset ( )` | Remet toutes les propriétés à leur défaut et vide l'éditeur
`of_set_redraw (boolean)` | Regroupe une rafale de modifications en un seul rendu
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exporte le rendu en image

## Événements #

Événement | Déclenché quand
--- | ---
`ue_changed (string as_text)` | L'utilisateur a modifié le contenu et sa frappe s'est stabilisée ; `as_text` porte le nouveau code complet
`ue_caret_changed (long al_line, long al_col)` | Le curseur s'est déplacé ; ligne et colonne comptées à partir de 1 — nécessite `ib_track_caret = true`
`ue_find_result (long al_count, long al_index)` | Une recherche a abouti : `al_count` occurrences trouvées, `al_index` = rang de celle qui est mise en avant
`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`)

## Exemples #

### Un éditeur de requête SQL #

    uo_requete.of_set_redraw(false)

    uo_requete.is_syntax = uo_requete.SYNTAX_SQL
    uo_requete.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"

    uo_requete.of_set_redraw(true)

    // event clicked de cb_executer
    string ls_sql

    ls_sql = uo_requete.of_get_text()     // la saisie reelle de l'utilisateur
    of_executer(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.

    uo_apercu.is_syntax = uo_apercu.SYNTAX_POWERSCRIPT

    uo_apercu.ib_readonly     = true      // consultation seule, pas de curseur de saisie
    uo_apercu.ib_line_numbers = false     // masque la gouttiere de numeros
    uo_apercu.ib_current_line = false     // pas de surlignage de la ligne courante
    uo_apercu.ib_wrap         = true      // renvoie a la ligne plutot que defiler
    uo_apercu.ii_tab_size     = 2         // tabulations affichees sur 2 colonnes

    uo_apercu.is_text = of_generer_code()

### Suivre la position du curseur dans une barre d'état #

    uo_editeur.ib_track_caret = true       // abonnement explicite : sinon aucun evenement

    // event ue_caret_changed de uo_editeur : (long al_line, long al_col)
    uo_statut.of_item("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_editeur.of_find(/*texte*/ "ll_total")

    // event ue_find_result de uo_editeur : (long al_count, long al_index)
    if al_count = 0 then
        uo_statut.of_item("main").is_text = "Aucune occurrence"
    else
        uo_statut.of_item("main").is_text = String(al_index) + " / " + String(al_count)
    end if

    // Aller directement a la ligne fautive d'un compilateur
    uo_editeur.ii_doc_line = ll_ligne_erreur     // defile et selectionne la ligne

### Ouvrir un fichier déposé depuis l'Explorateur #

    uo_editeur.ib_allow_drop = true

    // event ue_drop_files de uo_editeur : (string as_files[])
    string ls_contenu, ls_ligne
    integer li_fichier

    // as_files[1] porte le chemin COMPLET du premier fichier depose
    li_fichier = FileOpen(as_files[1], StreamMode!, Read!)
    if li_fichier > 0 then
        FileReadEx(li_fichier, ls_contenu)
        FileClose(li_fichier)

        uo_editeur.is_syntax = of_langage_selon_extension(as_files[1])
        uo_editeur.is_text   = ls_contenu
    end if

### Réagir aux modifications #

    // event ue_changed de uo_editeur : (string as_text)
    ib_modifie = true
    uo_statut.of_item("main").is_text = String(Len(as_text)) + " caracteres"

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.

## Bonnes pratiques #

- Posez toujours `is_syntax` avant `is_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_wrap` donne une visionneuse sobre qui ne ressemble plus à un éditeur.
- Pour récupérer une saisie, lisez `is_text` (ou `of_get_text()`) une fois la frappe posée, ou prenez le paramètre `as_text` de `ue_changed`.
- `ib_folding` n'a d'intérêt que sur des fichiers longs et structurés ; laissez-le coupé pour de courts extraits.
- 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.

← Référence des composants · Sommaire du guide