# codeeditor — `u_pbt_codeeditor` #

← Referencia de componentes · Índice de la guía

> Editor de código con resaltado de sintaxis: diez lenguajes, números de línea, plegado de regiones, búsqueda integrada y arrastre de archivos.

> ▶ Verlo en vivo — Aplicación de demostración, mosaico Code editor: la vista previa, el código que lo genera y esta página, uno al lado del otro.

## De un vistazo #

Userobject | `u_pbt_codeeditor`
Clase de items | — (componente sin items)
Sirve para | Escribir o mostrar código, una consulta SQL, un archivo de configuración: allí donde un `multilineedit` resulta poco legible
Opciones opt-in | `ib_track_caret`, `ib_allow_drop`, `ib_folding`

## Inicio rápido #

    // event open de la ventana
    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'"

    // Releer lo que el usuario ha escrito realmente
    string ls_sql

    ls_sql = uo_editeur.of_get_text()

> `is_text` devuelve lo mismo: lo que escribe el usuario llega ahí en cuanto la escritura se asienta (event `ue_changed`).

## Lenguajes reconocidos #

`is_syntax` acepta una de estas constantes, o `SYNTAX_NONE` (cadena vacía) para texto sin formato, sin resaltado.

Lenguaje | Constante | Otras grafías aceptadas
--- | --- | ---
PowerScript | `SYNTAX_POWERSCRIPT` | `pb`, `powerbuilder`
SQL | `SYNTAX_SQL` | `tsql`, `plsql`
JavaScript | `SYNTAX_JAVASCRIPT` | `js`, `jsx`
JSON | `SYNTAX_JSON` | `jsonc`
Familia 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`

Los lenguajes de una misma familia comparten el resaltado (`SYNTAX_JAVA` colorea como `SYNTAX_C`, `SYNTAX_XML` como `SYNTAX_HTML`): la constante que elija documenta su intención, el resultado en pantalla es el mismo. El valor no distingue mayúsculas de minúsculas y un nombre desconocido recurre al texto sin formato, sin error.

## Propiedades #

### Contenido y lenguaje #

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`is_text` | string | `""` | El código mostrado en el editor. En lectura, devuelve el contenido vivo, incluido lo que ha escrito el usuario
`is_syntax` | string | `""` | Lenguaje de resaltado: constantes `SYNTAX_*` (véase la tabla anterior). `SYNTAX_NONE` = texto sin formato
`ib_readonly` | boolean | `false` | Editor de solo lectura: el usuario consulta sin poder modificar

### Visualización #

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`ib_line_numbers` | boolean | `true` | Muestra u oculta el margen de números de línea, a la izquierda
`ib_current_line` | boolean | `true` | Resalta la línea en la que se encuentra el cursor. Sin resaltado mientras `ib_wrap` está activo.
`ib_folding` | boolean | `false` | Opt-in: permite plegar las regiones (`#region`, bloques entre llaves) desde el margen
`ib_wrap` | boolean | `false` | Ajusta las líneas largas al ancho en lugar de desplazarse lateralmente
`ii_tab_size` | integer | `4` | Número de columnas que ocupa una tabulación
`is_font_family` | string | `""` | Fuente del editor (vacío = fuente monoespaciada del tema)
`ii_font_size` | integer | `0` | Tamaño de la fuente en puntos (`0` = tamaño del tema)

### Navegación e interacciones #

Propiedad | Tipo | Predeterminado | Función
--- | --- | --- | ---
`ib_search_enabled` | boolean | `true` | Activa la barra de búsqueda integrada (Ctrl+F)
`ii_doc_line` | integer | `-1` | Desplaza hasta la línea indicada y la selecciona (numeración a partir de 1). Sin resaltado mientras `ib_wrap` está activo; el desplazamiento sí funciona.
`ib_track_caret` | boolean | `false` | Opt-in: dispara `ue_caret_changed` en cada desplazamiento del cursor
`ib_allow_drop` | boolean | `false` | Opt-in: acepta soltar archivos desde el Explorador de Windows; las rutas completas llegan por `ue_drop_files`
`is_theme_style` | string | `fluent` | Estilo visual del componente (constantes `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante clara u oscura (constantes `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Color de acento de este componente (`-1` = acento del tema)
`is_tooltip` | string | `""` | Tooltip simple mostrado al pasar el ratón por el componente
`is_super_tooltip_title` | string | `""` | Título del tooltip enriquecido (prevalece sobre `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Texto del tooltip enriquecido (se acepta el marcado enriquecido)
`is_super_tooltip_image` | string | `""` | Imagen del tooltip enriquecido

## Métodos #

Método | Función
--- | ---
`of_get_text ( )` → string | Devuelve el contenido vivo: el mismo valor que `is_text`, para el código que prefiere una llamada a método
`of_find (string as_text)` | Abre la barra de búsqueda y resalta todas las apariciones del texto
`of_insert_text (string as_text)` | Inserta texto en el cursor, exactamente como si el usuario lo hubiera escrito: la selección actual se sustituye y el cursor queda después de la inserción. Es el método de un botón insertar fragmento, allí donde `is_text` tiraría el trabajo en curso. Cuando el editor tiene el foco, la inserción pasa por la vía de edición del navegador, de modo que Ctrl+Z sigue deshaciéndola
`of_reset ( )` | Restablece todas las propiedades a su valor predeterminado y vacía el editor
`of_set_redraw (boolean)` | Agrupa una ráfaga de modificaciones en una sola representación
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exporta la representación como imagen

## Eventos #

Evento | Se activa cuando
--- | ---
`ue_changed (string as_text)` | El usuario ha modificado el contenido y su escritura se ha estabilizado; `as_text` lleva el nuevo código completo
`ue_caret_changed (long al_line, long al_col)` | El cursor se ha desplazado; línea y columna contadas a partir de 1 — requiere `ib_track_caret = true`
`ue_find_result (long al_count, long al_index)` | Una búsqueda ha dado resultado: `al_count` apariciones encontradas, `al_index` = posición de la que está destacada
`ue_drop_files (string as_files[])` | Se han soltado archivos desde Windows: rutas completas, una entrada por archivo. Requiere `ib_allow_drop = true`
`ue_drag_enter ( )` | Un arrastre de archivos entra en el editor (`ib_allow_drop`)
`ue_drag_leave ( )` | El arrastre de archivos abandona el editor
`ue_ready ( )` | El componente ha terminado de cargarse; todo lo enviado antes se ha reproducido
`ue_runtime_missing ( )` | El runtime WebView2 está ausente: el componente permanece vacío
`ue_bg_color (long al_color)` | El componente ha calculado el color de fondo de su tema; el userobject ya lo ha adoptado (`backcolor`)

## Ejemplos #

### Un editor de consultas SQL #

    uo_requete.of_set_redraw(false)

    uo_requete.is_syntax = uo_requete.SYNTAX_SQL
    uo_requete.is_text   = "-- Mejores clientes por facturacion cobrada~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()     // lo que el usuario ha escrito realmente
    of_executer(ls_sql)

### Un visor de solo lectura #

Ideal para presentar código generado, un registro o un extracto que el usuario debe leer sin modificarlo.

    uo_apercu.is_syntax = uo_apercu.SYNTAX_POWERSCRIPT

    uo_apercu.ib_readonly     = true      // solo consulta, sin cursor de escritura
    uo_apercu.ib_line_numbers = false     // oculta el margen de numeros
    uo_apercu.ib_current_line = false     // sin resaltado de la linea actual
    uo_apercu.ib_wrap         = true      // ajusta al ancho en vez de desplazarse
    uo_apercu.ii_tab_size     = 2         // tabulaciones mostradas en 2 columnas

    uo_apercu.is_text = of_generer_code()

### Seguir la posición del cursor en una barra de estado #

    uo_editeur.ib_track_caret = true       // suscripcion explicita: si no, ningun evento

    // event ue_caret_changed de uo_editeur : (long al_line, long al_col)
    uo_statut.of_item("pos").is_text = "Línea " + String(al_line) + ", col. " + String(al_col)

Sin `ib_track_caret`, el cursor no informa de nada: este disparador es de frecuencia elevada y permanece desactivado mientras no lo solicite.

### Buscar e ir a una línea #

    // Abre la barra de busqueda y resalta todas las apariciones
    uo_editeur.of_find(/*texto*/ "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 = "Ninguna aparición"
    else
        uo_statut.of_item("main").is_text = String(al_index) + " / " + String(al_count)
    end if

    // Ir directamente a la linea erronea indicada por un compilador
    uo_editeur.ii_doc_line = ll_ligne_erreur     // desplaza y selecciona la linea

### Abrir un archivo soltado desde el Explorador #

    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] lleva la ruta COMPLETA del primer archivo soltado
    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

### Reaccionar a las modificaciones #

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

El evento solo se dispara una vez que la escritura se ha estabilizado: escribir de forma continua no genera un evento por tecla.

## Buenas prácticas #

- Asigne siempre `is_syntax` antes que `is_text`: el código aparece coloreado desde la primera visualización, sin recoloración visible.
- Para una presentación en modo consulta, la combinación `ib_readonly` + `ib_line_numbers = false` + `ib_wrap` da un visor sobrio que ya no parece un editor.
- Para recuperar lo escrito, lea `is_text` (o `of_get_text()`) una vez asentada la escritura, o tome el parámetro `as_text` de `ue_changed`.
- `ib_folding` solo resulta interesante en archivos largos y estructurados; déjelo desactivado para extractos breves.
- Enmarque la carga de un archivo grande con `of_set_redraw(false)` / `of_set_redraw(true)`.
- Llame a `of_reset()` antes de cargar un documento de otra naturaleza: sin ello, el lenguaje, el tamaño de tabulación o el modo de solo lectura anteriores siguen vigentes.

← Referencia de componentes · Índice de la guía