PBToolboxAI v4 ← Site

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 y reemplazo, marcadores de diagnóstico en el margen 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 #

Userobjectu_pbt_codeeditor
Clase de items— (componente sin items)
Sirve paraEscribir o mostrar código, una consulta SQL, un archivo de configuración: allí donde un multilineedit resulta poco legible
Opciones opt-inib_track_caret, ib_allow_drop, ib_folding

Inicio rápido #

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

// Releer lo que el usuario ha escrito realmente
ls_sql = uo_editor.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.

LenguajeConstanteOtras grafías aceptadas
PowerScriptSYNTAX_POWERSCRIPTpb, powerbuilder
SQLSYNTAX_SQLtsql, plsql
JavaScriptSYNTAX_JAVASCRIPTjs, jsx
JSONSYNTAX_JSONjsonc
Familia CSYNTAX_C · SYNTAX_CPP · SYNTAX_CSHARP · SYNTAX_JAVAc++, cxx, cs
HTML / XMLSYNTAX_HTML · SYNTAX_XMLhtm, xhtml, svg
CSSSYNTAX_CSSscss, less
PythonSYNTAX_PYTHONpy
YAMLSYNTAX_YAMLyml
MarkdownSYNTAX_MARKDOWNmd, 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 #

PropiedadTipoPredeterminadoFunción
is_textstring""El código mostrado en el editor. En lectura, devuelve el contenido vivo, incluido lo que ha escrito el usuario, con los finales de línea recibidos: un texto en CRLF se relee en CRLF, un texto solo con CR en CR, plegado o no; un texto que los mezcla se relee en CRLF. Un texto nuevo se muestra desde su primera línea, borra los marcadores de of_add_marker y no está modificado (ib_modified)
is_syntaxstring""Lenguaje de resaltado: constantes SYNTAX_* (véase la tabla anterior). SYNTAX_NONE = texto sin formato. Se relee tal como se escribió: SYNTAX_CSHARP sigue siendo SYNTAX_CSHARP, aunque C# comparta la gramática de C
ib_readonlybooleanfalseEditor de solo lectura: el usuario consulta sin poder modificar
ib_modifiedbooleanfalsetrue en cuanto el texto difiere del declarado guardado: un is_text nuevo no está modificado, la escritura, of_insert_text o un reemplazo lo marcan como modificado, deshacer hasta el texto guardado lo devuelve a false. Vuelva a ponerlo en false tras guardar; true lo fuerza

Visualización #

PropiedadTipoPredeterminadoFunción
ib_line_numbersbooleantrueMuestra u oculta el margen de números de línea, a la izquierda; ocultos, un margen estrecho conserva los marcadores de plegado y los diagnósticos de of_add_marker
ib_current_linebooleantrueResalta la línea en la que se encuentra el cursor; en modo ib_wrap la banda cubre todas las filas de la línea
ib_foldingbooleanfalseOpt-in: permite plegar las regiones #region … #endregion (//#region en PowerScript, JavaScript o C) desde el margen: #region empieza plegada, #regionopen abierta; los marcadores siguen ahí incluso con ib_line_numbers = false. Es un modo de lectura: mientras está activo el editor no acepta escritura, porque el área de entrada contiene entonces el texto plegado y no el código fuente; activarlo sobre regiones cerradas también olvida el historial de Ctrl+Z. Un marcador se alcanza con el teclado (Tab); Intro o Espacio lo pliega o despliega
ib_wrapbooleanfalseAjusta las líneas largas al ancho en lugar de desplazarse lateralmente
ii_tab_sizeinteger4Número de columnas que ocupa una tabulación, de 1 a 12 (cualquier otro valor vuelve a 4); Intro tras una llave de apertura sangra con este ancho
is_font_familystring""Fuente del editor (vacío = fuente monoespaciada del tema)
ii_font_sizeinteger0Tamaño de la fuente en píxeles (0 = tamaño del tema)
PropiedadTipoPredeterminadoFunción
ib_search_enabledbooleantrueActiva la barra de búsqueda integrada (Ctrl+F, Ctrl+H para reemplazar — véase «Teclado»); en false, of_find devuelve -4
ib_find_match_casebooleanfalseOpción de búsqueda: solo encuentra el texto con las mismas mayúsculas y minúsculas. El botón Aa de la barra es el mismo interruptor; vale para of_find, of_replace y of_replace_all
ib_find_whole_wordbooleanfalseOpción de búsqueda: solo encuentra el texto como palabra completa (el _ forma parte de la palabra: ls_a no se encuentra dentro de ls_ab). Botón ab de la barra
ib_find_regexbooleanfalseOpción de búsqueda: el texto es una expresión regular (sintaxis JavaScript); el reemplazo de of_replace puede usar entonces $1, $& y $<name>. Una expresión no válida no encuentra nada, enmarca el campo en rojo y hace que of_replace devuelva -5. Botón .* de la barra
il_doc_linelong0Lleva la línea indicada al centro de la vista y la marca con una banda de acento (numeración a partir de 1, como el margen) — la línea que señala una documentación o un resultado de búsqueda. El cursor y la selección del usuario no se mueven (il_caret_line mueve el cursor). Una línea oculta en una región plegada abre esa región; la banda también se pinta en modo ib_wrap. 0 borra la banda; una línea más allá del final no marca nada y se relee tal como se escribió; cualquier is_text nuevo borra la banda
il_caret_linelong1La línea del cursor, a partir de 1, leída en vivo (plegado: la del margen). Escribirla pone el cursor al inicio de esa línea y la lleva a la pantalla — el «ir a la línea» de un error de compilación; una línea oculta en una región plegada abre esa región, una línea más allá del final se detiene en la última. Con ib_track_caret, ue_caret_changed sigue, como con un clic — nada cuando el cursor no se mueve
il_caret_columnlong1La columna del cursor, a partir de 1, leída en vivo: la posición del carácter en su línea (una tabulación cuenta como uno). Escribirla mueve el cursor a lo largo de su línea; más allá del final de la línea se detiene en ese final. Con ib_track_caret, ue_caret_changed sigue, como con un clic
ib_track_caretbooleanfalseOpt-in: dispara ue_caret_changed en cada desplazamiento del cursor — gesto del usuario u orden de su código; un documento nuevo (is_text, una carga) no dice nada del cursor
ib_allow_dropbooleanfalseOpt-in: acepta soltar archivos desde el Explorador de Windows; las rutas completas llegan por ue_drop_files
is_theme_stylestring""Estilo visual del componente (constantes THEME_STYLE_*); vacío = el de la aplicación, seguido en cada cambio
is_theme_modestring""Variante clara u oscura (constantes THEME_MODE_*); vacío = la de la aplicación, seguida en cada cambio
il_theme_accentlong-1Color de acento de este componente (-1 = acento de la aplicación, o el del tema)
is_tooltipstring""Tooltip simple mostrado al pasar el ratón por el componente
is_super_tooltip_titlestring""Título del tooltip enriquecido (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto del tooltip enriquecido (se acepta el marcado enriquecido)
is_super_tooltip_imagestring""Imagen del tooltip enriquecido

Métodos #

MétodoFunción
of_get_text ( ) → stringDevuelve 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, escribe en ella el texto y resalta todas sus apariciones, según las opciones ib_find_* (plegado, solo en las líneas visibles). La primera aparición a partir del cursor se lleva a la pantalla; el cursor solo se mueve cuando el usuario cierra la barra. Un texto vacío vacía el campo y borra los resaltados. Devuelve 0 una vez aplicado, -4 cuando ib_search_enabled vale false, -2 si el componente no está creado
of_insert_text (string as_text)Inserta texto en el cursor, exactamente como si el usuario lo hubiera escrito: la selección actual se reemplaza, el cursor queda tras la inserción y esta se lleva a la pantalla. Es el método de un botón insertar un fragmento, allí donde is_text tiraría el trabajo en curso. Durante una búsqueda, la inserción va al cursor del usuario, nunca sobre la coincidencia. Cuando el foco está en el editor o en su barra de búsqueda, la inserción pasa por el camino de edición del navegador: Ctrl+Z todavía la deshace. Dispara ue_changed, y con ib_track_caret ue_caret_changed sigue, como con una escritura. No se inserta nada mientras el editor está en solo lectura (ib_readonly) o plegado (ib_folding). Devuelve 0 una vez aplicado, -4 en solo lectura o plegado, -5 con un texto vacío, -2 si el componente no está creado
of_replace (string as_find, string as_replace)Reemplaza la primera aparición de as_find a partir del cursor (volviendo al principio) y la lleva a la pantalla; se aplican las opciones ib_find_*, y con ib_find_regex el reemplazo puede usar $1, $& y $<name>. Un Ctrl+Z lo deshace. Con ib_track_caret, ue_caret_changed sigue cuando el cursor se mueve. Devuelve el número de apariciones reemplazadas (1, o 0 si no hay ninguna), -4 en solo lectura o plegado, -5 con una búsqueda vacía o una expresión no válida, -2 si el componente no está creado
of_replace_all (string as_find, string as_replace)Reemplaza todas las apariciones de as_find, en un solo paso de deshacer. Mismas opciones y mismos códigos que of_replace; devuelve el número de apariciones reemplazadas
of_selected_text ( ) → stringDevuelve el texto que el usuario ha seleccionado, leído en vivo ("" sin selección), con los finales de línea de is_text
of_select_range (long al_from_line, long al_from_col, long al_to_line, long al_to_col)Selecciona de (línea, columna) a (línea, columna), todo a partir de 1, y lleva la selección a la pantalla; el cursor se sitúa en el extremo indicado en último lugar, y una columna más allá del final de su línea se detiene en ese final. Con ib_track_caret, ue_caret_changed sigue, como con un arrastre. Devuelve 0 una vez aplicado, -5 con una línea fuera del documento o una columna inferior a 1, -4 cuando el editor está plegado, -2 si el componente no está creado
of_line_count ( )Devuelve el número de líneas del documento, plegado o no, leído en vivo — el límite de un cuadro «ir a la línea»
of_add_marker (long al_line, string as_kind, string as_tooltip)Marca una línea del margen con un diagnóstico — MARKER_ERROR, MARKER_WARNING o MARKER_INFO — y un tooltip (se acepta el marcado): lo que dice un compilador, allí donde lo dice. Varios marcadores pueden compartir una línea: el más grave da el icono, el tooltip los lista todos. Pertenecen al documento: un is_text nuevo los borra. Devuelve 0 una vez aplicado, -5 con una línea fuera del documento o un tipo desconocido, -2 si el componente no está creado
of_remove_marker (long al_line)Retira todos los marcadores de una línea. Devuelve 0 una vez retirados, -5 si la línea no tiene ninguno, -2 si el componente no está creado
of_clear_markers ( )Retira todos los marcadores del margen. Devuelve 0 una vez aplicado, -2 si el componente no está creado
of_marker_count ( )Devuelve el número de marcadores del margen, leído en vivo (dos en una línea cuentan como dos)
of_reset ( )Restablece todas las propiedades a su valor predeterminado y vacía el editor. Devuelve 0 una vez aplicado, -2 si el componente no está creado
of_set_redraw (boolean)Agrupa una ráfaga de modificaciones en una sola representación. Devuelve 0 una vez aplicado, -2 si el componente no está creado
of_save_as_png (string) · of_save_as_jpg (string)Exporta la representación como imagen. Devuelve 0 una vez escrita la imagen, -4 si la escritura falla, -2 si el componente no está creado

Eventos #

EventoSe activa cuando
ue_changed ( )El usuario ha modificado el contenido y su escritura se ha asentado — también se dispara tras of_insert_text o un reemplazo. El evento no lleva nada: rellenarlo obligaba a releer todo el documento en cada pulsación asentada, para una aplicación que casi siempre solo quiere saber que ha cambiado. Quien quiera el código lo pide — is_text o of_get_text(); ib_modified dice si difiere del texto guardado
ue_caret_changed (long al_line, long al_col)El cursor se ha movido (tecla, clic, arrastre, escritura, o su código); línea y columna contadas a partir de 1, la línea es la del margen cuando el editor está plegado, la columna la posición del carácter en su línea (una tabulación cuenta como uno). Su código lo dispara como el gesto (il_caret_line, il_caret_column, of_select_range, of_insert_text, of_replace); nada cuando el cursor no se mueve, y un documento nuevo (is_text, una carga) no dice nada del cursor — requiere ib_track_caret = true
ue_find_result (long al_count, long al_index)Una búsqueda ha terminado, o pasa a otra aparición: al_count apariciones encontradas, al_index = posición de la que está destacada (a partir de 1). Durante la escritura solo se lanza si cambia el recuento; cerrar la barra no lo lanza; tampoco una búsqueda vacía
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)

Teclado #

TeclaEfecto
TabSangra hasta la siguiente tabulación (ii_tab_size); varias líneas seleccionadas: sangra todo el bloque
Mayús+TabReduce la sangría de la línea o del bloque
IntroNueva línea con la misma sangría, un nivel más tras {, ( o [
Ctrl+FAbre la barra de búsqueda, rellenada con la selección (ib_search_enabled)
Ctrl+HAbre la barra con su fila de reemplazo (solo editor modificable)
F3 · Mayús+F3Coincidencia siguiente · anterior, desde el código o la barra
Intro · Mayús+Intro (barra)Coincidencia siguiente · anterior; en el campo de reemplazo, Intro reemplaza la coincidencia actual y Ctrl+Intro las reemplaza todas
EscCierra la barra y pone el cursor en la coincidencia actual
Tab, luego Intro o Espacio (margen)Alcanza un marcador de plegado y lo pliega o despliega (ib_folding)

La columna que indican ue_caret_changed e il_caret_column es la posición del carácter en su línea: una tabulación cuenta como uno, sea cual sea su anchura en pantalla.


Ejemplos #

Un editor de consultas SQL #

// Congelar el dibujo durante la configuracion
uo_query.of_set_redraw(/*on*/ false)

// Coloreado SQL y luego la consulta que mostrar
uo_query.is_syntax = uo_query.SYNTAX_SQL
uo_query.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"

// Un solo redibujado, todo a la vez
uo_query.of_set_redraw(/*on*/ true)
// event clicked de cb_execute
string ls_sql

// Ejecutar la consulta tal como se escribio
ls_sql = uo_query.of_get_text()     // lo que el usuario ha escrito realmente
of_execute(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.

// Coloreado PowerScript
uo_preview.is_syntax = uo_preview.SYNTAX_POWERSCRIPT

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

// El codigo que mostrar
uo_preview.is_text = of_generate_code()

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

// Notificar cada movimiento del cursor (ue_caret_changed)
uo_editor.ib_track_caret = true       // suscripcion explicita: si no, ningun evento
// event ue_caret_changed de uo_editor : (long al_line, long al_col)
uo_status.of_panel(/*key*/ "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_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 = "Ninguna aparición"
else
    uo_status.of_panel(/*key*/ "main").is_text = String(al_index) + " / " + String(al_count)
end if
// Ir a la linea que ha senalado un compilador y marcarla en el margen
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     // el cursor va alli, la linea llega a la pantalla
uo_editor.of_focus_webview()                // el usuario corrige enseguida

Abrir un archivo soltado desde el Explorador #

// 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] lleva la ruta COMPLETA del primer archivo soltado
li_file = FileOpen(as_files[1], StreamMode!, Read!)
if li_file > 0 then
    FileReadEx(li_file, ls_content)
    FileClose(li_file)

    // Colorear segun la extension del archivo y mostrar su contenido
    uo_editor.is_syntax = of_syntax_for_extension(as_files[1])
    uo_editor.is_text   = ls_content
end if

Reaccionar a las modificaciones #

// event ue_changed de uo_editor : ( )
cb_save.enabled = uo_editor.ib_modified     // deshacer hasta el texto guardado lo devuelve a false
// event clicked de cb_save
if of_save_script(uo_editor.is_text) = 1 then
    uo_editor.ib_modified = false     // el texto guardado pasa a ser la referencia
    cb_save.enabled = false
end if

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

Renombrar una variable en todo el script #

// Local variables
long ll_count

// Solo palabras completas: ll_total2 es otra variable
uo_editor.ib_find_whole_word = true
ll_count = uo_editor.of_replace_all(/*find*/ "ll_total", /*replace*/ "ldc_amount")   // un solo Ctrl+Z lo deshace todo

Buenas prácticas #

Heredado de la base común #

Estos miembros existen en todos los componentes visuales — no son propios de este. Se detallan una sola vez, en los capítulos transversales; esta tabla solo dice dónde leerlos.

MiembrosFunciónDetallado en
of_resetPoner el componente a cero3.6 Poner un componente a cero: of_reset()
of_register_shortcut · of_clear_shortcutsAtajos de teclado del componente3.5 Los atajos de teclado
of_is_created · of_is_ready · of_get_last_errorSi ha nacido, si está listo, qué ha fallado3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar el render como imagen3.8 Exportar la representación como imagen
of_set_redrawAgrupar los cambios en un solo repintado3.10 Buenas prácticas
of_preload_iconsIconos mostrados sin retardoVisualización instantánea: of_icon
of_set_translationTraducir una etiqueta del componente5.2 Adaptar una etiqueta: of_set_translation
of_focus_webviewDar el foco al componente6.4 Teclado y foco
of_print · of_print_to_pdfImprimir, o escribir un PDF6.9 Imprimir
of_set_property · of_get_property · of_component_nameControlar una propiedad por su nombre3.1 El motor de propiedades

Dos ayudas no se heredan: of_icon y of_escape_markup viven en n_pbt_utils. Declare uno — n_pbt_utils lnv_utils, nada que crear — y llámelas sobre él.


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