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_textgives the same thing: the user's typing lands there as soon as the input settles (ue_changedevent).
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_syntaxbeforeis_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_wrapgives you a plain viewer that no longer looks like an editor. - To retrieve user input, read
is_text(orof_get_text()) once the typing has settled, or take theas_textargument ofue_changed. ib_foldingis 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.