# codeeditor — `u_pbt_codeeditor` #

← Component reference · Guide contents

> Code editor with syntax highlighting: ten languages, line numbers, region folding, built-in search, and file drop.

> ▶ See it live — Demo application, Code editor tile: the preview, the code behind it and this page, side by side.

## At a glance #

Userobject | `u_pbt_codeeditor`
Item class | — (component without items)
Used for | Entering or displaying code, a SQL query, a configuration file: anywhere a `multilineedit` is not readable enough
Opt-in options | `ib_track_caret`, `ib_allow_drop`, `ib_folding`

## Quick start #

    // window open event
    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'"

    // Read back what the user has actually typed
    string ls_sql

    ls_sql = uo_editeur.of_get_text()

> `is_text` gives the same thing: the user's typing lands there as soon as the input settles (`ue_changed` event).

## Supported languages #

`is_syntax` accepts one of these constants, or `SYNTAX_NONE` (empty string) for plain text with no highlighting.

Language | Constant | Other accepted spellings
--- | --- | ---
PowerScript | `SYNTAX_POWERSCRIPT` | `pb`, `powerbuilder`
SQL | `SYNTAX_SQL` | `tsql`, `plsql`
JavaScript | `SYNTAX_JAVASCRIPT` | `js`, `jsx`
JSON | `SYNTAX_JSON` | `jsonc`
C family | `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`

Languages of the same family share their highlighting (`SYNTAX_JAVA` colors like `SYNTAX_C`, `SYNTAX_XML` like `SYNTAX_HTML`): the constant you pick documents your intent, the result on screen is the same. The value is case-insensitive, and an unknown name falls back to plain text without raising an error.

## Properties #

### Content and language #

Property | Type | Default | Purpose
--- | --- | --- | ---
`is_text` | string | `""` | The code displayed in the editor. When read back, returns the live content, the user's typing included
`is_syntax` | string | `""` | Highlighting language: `SYNTAX_*` constants (see the table above). `SYNTAX_NONE` = plain text
`ib_readonly` | boolean | `false` | Read-only editor: the user can consult without being able to modify

### Display #

Property | Type | Default | Purpose
--- | --- | --- | ---
`ib_line_numbers` | boolean | `true` | Shows or hides the line number gutter, on the left
`ib_current_line` | boolean | `true` | Highlights the line where the caret sits. No highlight while `ib_wrap` is on.
`ib_folding` | boolean | `false` | Opt-in: allows regions (`#region`, blocks between braces) to be folded from the gutter
`ib_wrap` | boolean | `false` | Wraps long lines instead of scrolling sideways
`ii_tab_size` | integer | `4` | Number of columns a tab character takes up
`is_font_family` | string | `""` | Editor font (empty = the theme's monospaced font)
`ii_font_size` | integer | `0` | Font size in points (`0` = the theme's size)

### Navigation and interaction #

Property | Type | Default | Purpose
--- | --- | --- | ---
`ib_search_enabled` | boolean | `true` | Enables the built-in search bar (Ctrl+F)
`ii_doc_line` | integer | `-1` | Scrolls to the given line and selects it (numbering starts at 1). No highlight while `ib_wrap` is on; the scrolling still works.
`ib_track_caret` | boolean | `false` | Opt-in: raises `ue_caret_changed` every time the caret moves
`ib_allow_drop` | boolean | `false` | Opt-in: accepts files dropped from Windows Explorer; the full paths arrive through `ue_drop_files`
`is_theme_style` | string | `fluent` | Visual style of the component (`THEME_STYLE_*` constants)
`is_theme_mode` | string | `light` | Light or dark variant (`THEME_MODE_*` constants)
`il_theme_accent` | long | `-1` | Accent color of this component (`-1` = the theme accent)
`is_tooltip` | string | `""` | Simple tooltip shown when hovering the component
`is_super_tooltip_title` | string | `""` | Title of the rich tooltip (takes precedence over `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Text of the rich tooltip (rich markup accepted)
`is_super_tooltip_image` | string | `""` | Image of the rich tooltip

## Methods #

Method | Purpose
--- | ---
`of_get_text ( )` → string | Returns the live content — the same value as `is_text`, for code that prefers a method call
`of_find (string as_text)` | Opens the search bar and highlights every occurrence of the text
`of_insert_text (string as_text)` | Inserts text at the caret, exactly as if the user had typed it: the current selection is replaced and the caret lands after the insertion. This is the method behind an insert snippet button, where `is_text` would throw the work in progress away. When the editor has the focus, the insertion goes through the browser's own edit path, so Ctrl+Z still undoes it
`of_reset ( )` | Returns every property to its default and empties the editor
`of_set_redraw (boolean)` | Batches a burst of changes into a single render
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exports the rendering as an image

## Events #

Event | Raised when
--- | ---
`ue_changed (string as_text)` | The user has modified the content and their typing has settled; `as_text` carries the complete new code
`ue_caret_changed (long al_line, long al_col)` | The caret has moved; line and column counted from 1 — requires `ib_track_caret = true`
`ue_find_result (long al_count, long al_index)` | A search has succeeded: `al_count` occurrences found, `al_index` = rank of the one currently highlighted
`ue_drop_files (string as_files[])` | Files have been dropped from Windows: full paths, one entry per file. Requires `ib_allow_drop = true`
`ue_drag_enter ( )` | A file drag enters the editor (`ib_allow_drop`)
`ue_drag_leave ( )` | The file drag leaves the editor
`ue_ready ( )` | The component has finished loading; everything sent beforehand has been replayed
`ue_runtime_missing ( )` | The WebView2 runtime is missing: the component stays empty
`ue_bg_color (long al_color)` | The component has computed its theme background color; the userobject has already adopted it (`backcolor`)

## Examples #

### A SQL query editor #

    uo_requete.of_set_redraw(false)

    uo_requete.is_syntax = uo_requete.SYNTAX_SQL
    uo_requete.is_text   = "-- Top customers by revenue collected~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)

    // clicked event of cb_executer
    string ls_sql

    ls_sql = uo_requete.of_get_text()     // what the user really typed
    of_executer(ls_sql)

### A read-only viewer #

Ideal for presenting generated code, a log, or an excerpt the user has to read without modifying it.

    uo_apercu.is_syntax = uo_apercu.SYNTAX_POWERSCRIPT

    uo_apercu.ib_readonly     = true      // consultation only, no editing caret
    uo_apercu.ib_line_numbers = false     // hides the number gutter
    uo_apercu.ib_current_line = false     // no current line highlight
    uo_apercu.ib_wrap         = true      // wraps rather than scrolls
    uo_apercu.ii_tab_size     = 2         // tabs displayed over 2 columns

    uo_apercu.is_text = of_generer_code()

### Tracking the caret position in a status bar #

    uo_editeur.ib_track_caret = true       // explicit opt-in: otherwise no event at all

    // ue_caret_changed event of uo_editeur: (long al_line, long al_col)
    uo_statut.of_item("pos").is_text = "Line " + String(al_line) + ", col. " + String(al_col)

Without `ib_track_caret`, the caret reports nothing: this trigger fires very often and stays off until you ask for it.

### Searching and jumping to a line #

    // Opens the search bar and highlights every occurrence
    uo_editeur.of_find(/*text*/ "ll_total")

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

    // Jump straight to the line a compiler flagged
    uo_editeur.ii_doc_line = ll_ligne_erreur     // scrolls to and selects the line

### Opening a file dropped from Explorer #

    uo_editeur.ib_allow_drop = true

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

    // as_files[1] carries the FULL path of the first dropped file
    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

### Reacting to changes #

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

The event is only raised once the typing has settled: continuous input does not generate one event per keystroke.

## Best practices #

- Always set `is_syntax` before `is_text`: the code is colored from the very first paint, with no visible recoloring.
- For a read-only display, combining `ib_readonly` + `ib_line_numbers = false` + `ib_wrap` gives you a plain viewer that no longer looks like an editor.
- To retrieve user input, read `is_text` (or `of_get_text()`) once the typing has settled, or take the `as_text` argument of `ue_changed`.
- `ib_folding` is only worth it on long, structured files; leave it off for short excerpts.
- Wrap the loading of a large file in `of_set_redraw(false)` / `of_set_redraw(true)`.
- Call `of_reset()` before loading a document of a different nature: otherwise the previous language, tab size or read-only mode stay in place.

← Component reference · Guide contents