PBToolboxAI v4 ← Site

codeeditor — u_pbt_codeeditor #

← Referência dos componentes · Índice do guia

Editor de código com realce de sintaxe: dez linguagens, números de linha, dobragem de regiões, pesquisa e substituição, marcadores de diagnóstico na calha e largada de ficheiros.

▶ Ver ao vivo — Aplicação de demonstração, mosaico Code editor: a pré-visualização, o código que o produz e esta página, lado a lado.


Em resumo #

Userobjectu_pbt_codeeditor
Classe de items— (componente sem items)
Serve paraIntroduzir ou apresentar código, uma consulta SQL, um ficheiro de configuração: em todos os casos em que um multilineedit carece de legibilidade
Opções opt-inib_track_caret, ib_allow_drop, ib_folding

Início rápido #

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

// Reler o que o utilizador introduziu realmente
ls_sql = uo_editor.of_get_text()

is_text devolve o mesmo: aquilo que o utilizador escreve chega lá assim que a escrita assenta (event ue_changed).


Linguagens reconhecidas #

is_syntax aceita uma destas constantes, ou SYNTAX_NONE (cadeia vazia) para texto simples sem realce.

LinguagemConstanteOutras grafias aceites
PowerScriptSYNTAX_POWERSCRIPTpb, powerbuilder
SQLSYNTAX_SQLtsql, plsql
JavaScriptSYNTAX_JAVASCRIPTjs, jsx
JSONSYNTAX_JSONjsonc
Família 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

As linguagens de uma mesma família partilham o realce (SYNTAX_JAVA colore como SYNTAX_C, SYNTAX_XML como SYNTAX_HTML): a constante escolhida documenta a intenção do programador, mas o resultado no ecrã é o mesmo. O valor não distingue maiúsculas de minúsculas e um nome desconhecido recai no texto simples, sem erro.


Propriedades #

Conteúdo e linguagem #

PropriedadeTipoPredefiniçãoFunção
is_textstring""O código apresentado no editor. Em leitura, devolve o conteúdo vivo, incluindo aquilo que o utilizador escreveu, com os finais de linha recebidos: um texto em CRLF relê-se em CRLF, um texto só com CR em CR, dobrado ou não; um texto que os mistura relê-se em CRLF. Um texto novo apresenta-se a partir da primeira linha, apaga os marcadores de of_add_marker e não está modificado (ib_modified)
is_syntaxstring""Linguagem de realce: constantes SYNTAX_* (ver a tabela acima). SYNTAX_NONE = texto simples. Relê-se tal como foi escrita: SYNTAX_CSHARP continua SYNTAX_CSHARP, mesmo que C# partilhe a gramática do C
ib_readonlybooleanfalseEditor só de leitura: o utilizador consulta sem poder modificar
ib_modifiedbooleanfalsetrue assim que o texto difere do declarado como guardado: um novo is_text não está modificado, a escrita, of_insert_text ou uma substituição tornam-no modificado, anular até ao texto guardado repõe-no a false. Reponha-o a false depois de guardar; true força-o

Apresentação #

PropriedadeTipoPredefiniçãoFunção
ib_line_numbersbooleantrueMostra ou oculta a calha de números de linha, à esquerda; ocultos, uma calha estreita mantém os marcadores de dobragem e os diagnósticos de of_add_marker
ib_current_linebooleantrueRealça a linha onde se encontra o cursor; no modo ib_wrap a faixa cobre todas as filas da linha
ib_foldingbooleanfalseOpt-in: permite a dobragem das regiões #region … #endregion (//#region em PowerScript, JavaScript ou C) a partir da calha: #region começa dobrada, #regionopen aberta; os marcadores ficam mesmo com ib_line_numbers = false. É um modo de leitura: enquanto está activo o editor não aceita escrita, porque a área de entrada contém então o texto dobrado e não o código-fonte; ativá-lo sobre regiões fechadas também esquece o histórico de Ctrl+Z. Um marcador alcança-se pelo teclado (Tab); Enter ou Espaço dobra-o ou expande-o
ib_wrapbooleanfalseMuda as linhas longas de linha em vez de deslocar lateralmente
ii_tab_sizeinteger4Número de colunas ocupadas por uma tabulação, de 1 a 12 (qualquer outro valor volta a 4); Enter depois de uma chaveta de abertura indenta com esta largura
is_font_familystring""Tipo de letra do editor (vazio = tipo de letra monoespaçado do tema)
ii_font_sizeinteger0Tamanho do tipo de letra em píxeis (0 = tamanho do tema)
PropriedadeTipoPredefiniçãoFunção
ib_search_enabledbooleantrueAtiva a barra de pesquisa integrada (Ctrl+F, Ctrl+H para substituir — ver «Teclado»); a false, of_find devolve -4
ib_find_match_casebooleanfalseOpção de pesquisa: só encontra o texto com as mesmas maiúsculas e minúsculas. O botão Aa da barra é o mesmo interruptor; vale para of_find, of_replace e of_replace_all
ib_find_whole_wordbooleanfalseOpção de pesquisa: só encontra o texto como palavra inteira (o _ faz parte da palavra: ls_a não é encontrado em ls_ab). Botão ab da barra
ib_find_regexbooleanfalseOpção de pesquisa: o texto é uma expressão regular (sintaxe JavaScript); a substituição de of_replace pode então usar $1, $& e $<name>. Uma expressão inválida não encontra nada, enquadra o campo a vermelho e faz of_replace devolver -5. Botão .* da barra
il_doc_linelong0Traz a linha indicada para o meio da vista e marca-a com uma faixa de destaque (numeração a partir de 1, como a calha) — a linha que uma documentação ou um resultado de pesquisa designa. O cursor e a seleção do utilizador não se mexem (il_caret_line desloca o cursor). Uma linha escondida numa região dobrada abre essa região; a faixa também é pintada no modo ib_wrap. 0 apaga a faixa; uma linha para lá do fim não marca nada e relê-se tal como foi escrita; qualquer novo is_text apaga a faixa
il_caret_linelong1A linha do cursor, a partir de 1, lida ao vivo (dobrado: a da calha). Escrevê-la põe o cursor no início dessa linha e trá-la para o ecrã — o «ir para a linha» de um erro de compilação; uma linha escondida numa região dobrada abre essa região, uma linha para lá do fim fica na última. Com ib_track_caret, ue_caret_changed segue-se, como com um clique — nada quando o cursor não se mexe
il_caret_columnlong1A coluna do cursor, a partir de 1, lida ao vivo: a posição do carácter na sua linha (uma tabulação conta como um). Escrevê-la desloca o cursor ao longo da linha; para lá do fim da linha fica nesse fim. Com ib_track_caret, ue_caret_changed segue-se, como com um clique
ib_track_caretbooleanfalseOpt-in: aciona ue_caret_changed em cada deslocação do cursor — gesto do utilizador ou ordem do seu código; um documento novo (is_text, um carregamento) não diz nada do cursor
ib_allow_dropbooleanfalseOpt-in: aceita a largada de ficheiros a partir do Explorador do Windows; os caminhos completos chegam através de ue_drop_files
is_theme_stylestring""Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança
is_theme_modestring""Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança
il_theme_accentlong-1Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema)
is_tooltipstring""Tooltip simples apresentado ao passar sobre o componente
is_super_tooltip_titlestring""Título do tooltip enriquecido (prevalece sobre is_tooltip)
is_super_tooltip_textstring""Texto do tooltip enriquecido (aceita marcação enriquecida)
is_super_tooltip_imagestring""Imagem do tooltip enriquecido

Métodos #

MétodoFunção
of_get_text ( ) → stringDevolve o conteúdo vivo: o mesmo valor que is_text, para código que prefira uma chamada de método
of_find (string as_text)Abre a barra de pesquisa, escreve nela o texto e realça todas as suas ocorrências, segundo as opções ib_find_* (dobrado, só nas linhas visíveis). A primeira ocorrência a partir do cursor é trazida para o ecrã; o cursor só se move quando o utilizador fecha a barra. Um texto vazio esvazia o campo e apaga os realces. Devolve 0 uma vez aplicado, -4 quando ib_search_enabled vale false, -2 se o componente não estiver criado
of_insert_text (string as_text)Insere texto no cursor, exatamente como se o utilizador o tivesse escrito: a seleção atual é substituída, o cursor fica depois da inserção e esta é trazida para o ecrã. É o método de um botão inserir um excerto, onde is_text deitaria fora o trabalho em curso. Durante uma pesquisa, a inserção vai para o cursor do utilizador, nunca sobre a ocorrência. Quando o foco está no editor ou na sua barra de pesquisa, a inserção passa pelo caminho de edição do navegador: Ctrl+Z ainda a anula. Aciona ue_changed, e com ib_track_caret ue_caret_changed segue-se, como com uma escrita. Nada é inserido enquanto o editor estiver só de leitura (ib_readonly) ou dobrado (ib_folding). Devolve 0 uma vez aplicado, -4 só de leitura ou dobrado, -5 com um texto vazio, -2 se o componente não estiver criado
of_replace (string as_find, string as_replace)Substitui a primeira ocorrência de as_find a partir do cursor (recomeçando do início) e trá-la para o ecrã; aplicam-se as opções ib_find_*, e com ib_find_regex a substituição pode usar $1, $& e $<name>. Um Ctrl+Z anula-a. Com ib_track_caret, ue_caret_changed segue-se quando o cursor se mexe. Devolve o número de ocorrências substituídas (1, ou 0 se não houver nenhuma), -4 só de leitura ou dobrado, -5 com uma pesquisa vazia ou uma expressão inválida, -2 se o componente não estiver criado
of_replace_all (string as_find, string as_replace)Substitui todas as ocorrências de as_find, num único passo de anulação. Mesmas opções e mesmos códigos que of_replace; devolve o número de ocorrências substituídas
of_selected_text ( ) → stringDevolve o texto que o utilizador selecionou, lido ao vivo ("" sem seleção), com os finais de linha de is_text
of_select_range (long al_from_line, long al_from_col, long al_to_line, long al_to_col)Seleciona de (linha, coluna) a (linha, coluna), tudo a partir de 1, e traz a seleção para o ecrã; o cursor fica na extremidade indicada em último lugar, e uma coluna para lá do fim da sua linha fica nesse fim. Com ib_track_caret, ue_caret_changed segue-se, como com um arrastamento. Devolve 0 uma vez aplicado, -5 com uma linha fora do documento ou uma coluna inferior a 1, -4 quando o editor está dobrado, -2 se o componente não estiver criado
of_line_count ( )Devolve o número de linhas do documento, dobrado ou não, lido ao vivo — o limite de uma caixa «ir para a linha»
of_add_marker (long al_line, string as_kind, string as_tooltip)Marca uma linha da calha com um diagnóstico — MARKER_ERROR, MARKER_WARNING ou MARKER_INFO — e um tooltip (aceita marcação): o que um compilador diz, onde o diz. Vários marcadores podem partilhar uma linha: o mais grave dá o ícone, o tooltip lista-os todos. Pertencem ao documento: um novo is_text apaga-os. Devolve 0 uma vez aplicado, -5 com uma linha fora do documento ou um tipo desconhecido, -2 se o componente não estiver criado
of_remove_marker (long al_line)Retira todos os marcadores de uma linha. Devolve 0 uma vez retirados, -5 se a linha não tiver nenhum, -2 se o componente não estiver criado
of_clear_markers ( )Retira todos os marcadores da calha. Devolve 0 uma vez aplicado, -2 se o componente não estiver criado
of_marker_count ( )Devolve o número de marcadores da calha, lido ao vivo (dois numa linha contam como dois)
of_reset ( )Repõe todas as propriedades nos respetivos valores predefinidos e esvazia o editor. Devolve 0 depois de aplicado, -2 se o componente não estiver criado
of_set_redraw (boolean)Agrupa uma rajada de modificações numa única representação. Devolve 0 depois de aplicado, -2 se o componente não estiver criado
of_save_as_png (string) · of_save_as_jpg (string)Exporta a representação como imagem. Devolve 0 depois de a imagem ser escrita, -4 se a escrita falhar, -2 se o componente não estiver criado

Eventos #

EventoAcionado quando
ue_changed ( )O utilizador modificou o conteúdo e a escrita assentou — acionado também depois de of_insert_text ou de uma substituição. O evento não transporta nada: preenchê-lo obrigava a reler todo o documento a cada escrita assente, para uma aplicação que na maioria das vezes só quer saber que mudou. Quem quiser o código pede-o — is_text ou of_get_text(); ib_modified diz se difere do texto guardado
ue_caret_changed (long al_line, long al_col)O cursor deslocou-se (tecla, clique, arrastamento, escrita, ou o seu código); linha e coluna contadas a partir de 1, sendo a linha a da calha quando o editor está dobrado e a coluna a posição do carácter na sua linha (uma tabulação conta como um). O seu código aciona-o como o gesto (il_caret_line, il_caret_column, of_select_range, of_insert_text, of_replace); nada quando o cursor não se mexe, e um documento novo (is_text, um carregamento) não diz nada do cursor — requer ib_track_caret = true
ue_find_result (long al_count, long al_index)Uma pesquisa foi concluída, ou passa para outra ocorrência: al_count ocorrências encontradas, al_index = posição daquela que está destacada (a partir de 1). Durante a escrita só é lançado se a contagem mudar; fechar a barra não o lança; nem uma pesquisa vazia
ue_drop_files (string as_files[])Foram largados ficheiros a partir do Windows: caminhos completos, uma entrada por ficheiro. Requer ib_allow_drop = true
ue_drag_enter ( )Um arrastamento de ficheiros entra no editor (ib_allow_drop)
ue_drag_leave ( )O arrastamento de ficheiros sai do editor
ue_ready ( )O componente terminou o carregamento; tudo o que foi enviado antes foi reproduzido
ue_runtime_missing ( )O runtime WebView2 está ausente: o componente permanece vazio
ue_bg_color (long al_color)O componente calculou a cor de fundo do respetivo tema; o userobject já a adotou (backcolor)

Teclado #

TeclaEfeito
TabIndenta até à tabulação seguinte (ii_tab_size); várias linhas selecionadas: indenta todo o bloco
Shift+TabReduz a indentação da linha ou do bloco
EnterNova linha com a mesma indentação, um nível a mais depois de {, ( ou [
Ctrl+FAbre a barra de pesquisa, preenchida com a seleção (ib_search_enabled)
Ctrl+HAbre a barra com a sua linha de substituição (só editor modificável)
F3 · Shift+F3Ocorrência seguinte · anterior, a partir do código ou da barra
Enter · Shift+Enter (barra)Ocorrência seguinte · anterior; no campo de substituição, Enter substitui a ocorrência atual e Ctrl+Enter substitui todas
EscFecha a barra e põe o cursor na ocorrência atual
Tab, depois Enter ou Espaço (calha)Alcança um marcador de dobragem e dobra-o ou expande-o (ib_folding)

A coluna indicada por ue_caret_changed e il_caret_column é a posição do carácter na sua linha: uma tabulação conta como um, seja qual for a sua largura no ecrã.


Exemplos #

Um editor de consultas SQL #

// Congelar o desenho durante a configuracao
uo_query.of_set_redraw(/*on*/ false)

// Coloracao SQL, depois a consulta a mostrar
uo_query.is_syntax = uo_query.SYNTAX_SQL
uo_query.is_text   = "-- Melhores clientes por volume de negocios recebido~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"

// Um so redesenho, tudo de uma vez
uo_query.of_set_redraw(/*on*/ true)
// event clicked de cb_execute
string ls_sql

// Executar a consulta tal como foi introduzida
ls_sql = uo_query.of_get_text()     // o que o utilizador introduziu realmente
of_execute(ls_sql)

Um visualizador só de leitura #

Ideal para apresentar código gerado, um registo ou um excerto que o utilizador deve ler sem o modificar.

// Coloracao PowerScript
uo_preview.is_syntax = uo_preview.SYNTAX_POWERSCRIPT

// Um visualizador so de leitura: sem cursor, sem margem, sem realce
uo_preview.ib_readonly     = true      // apenas consulta, sem cursor de escrita
uo_preview.ib_line_numbers = false     // oculta a calha de numeros
uo_preview.ib_current_line = false     // sem realce da linha atual
uo_preview.ib_wrap         = true      // muda de linha em vez de deslocar
uo_preview.ii_tab_size     = 2         // tabulacoes apresentadas em 2 colunas

// O codigo a mostrar
uo_preview.is_text = of_generate_code()

Acompanhar a posição do cursor numa barra de estado #

// Notificar cada movimento do cursor (ue_caret_changed)
uo_editor.ib_track_caret = true       // subscricao explicita: caso contrario nenhum evento
// event ue_caret_changed de uo_editor : (long al_line, long al_col)
uo_status.of_panel(/*key*/ "pos").is_text = "Linha " + String(al_line) + ", col. " + String(al_col)

Sem ib_track_caret, o cursor não comunica nada: este acionador é de frequência elevada e permanece desligado enquanto não for pedido.

Pesquisar e ir para uma linha #

// Abre a barra de pesquisa e realca todas as ocorrencias
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 = "Nenhuma ocorrência"
else
    uo_status.of_panel(/*key*/ "main").is_text = String(al_index) + " / " + String(al_count)
end if
// Ir para a linha que um compilador assinalou e marca-la na calha
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     // o cursor vai para la, a linha vem para o ecra
uo_editor.of_focus_webview()                // o utilizador corrige de imediato

Abrir um ficheiro largado a partir do 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] transporta o caminho COMPLETO do primeiro ficheiro largado
li_file = FileOpen(as_files[1], StreamMode!, Read!)
if li_file > 0 then
    FileReadEx(li_file, ls_content)
    FileClose(li_file)

    // Colorir pela extensao do ficheiro e mostrar o seu conteudo
    uo_editor.is_syntax = of_syntax_for_extension(as_files[1])
    uo_editor.is_text   = ls_content
end if

Reagir às modificações #

// event ue_changed de uo_editor : ( )
cb_save.enabled = uo_editor.ib_modified     // anular ate ao texto guardado repoe-no a false
// event clicked de cb_save
if of_save_script(uo_editor.is_text) = 1 then
    uo_editor.ib_modified = false     // o texto guardado passa a ser a referencia
    cb_save.enabled = false
end if

O evento só é despoletado depois de a escrita estabilizar: uma introdução contínua não gera um evento por cada tecla.

Mudar o nome de uma variável em todo o script #

// Local variables
long ll_count

// So palavras inteiras: ll_total2 e outra variavel
uo_editor.ib_find_whole_word = true
ll_count = uo_editor.of_replace_all(/*find*/ "ll_total", /*replace*/ "ldc_amount")   // um unico Ctrl+Z anula tudo

Boas práticas #

Herdado da base comum #

Estes membros existem em todos os componentes visuais — não são próprios deste. São detalhados uma só vez, nos capítulos transversais; esta tabela apenas diz onde os ler.

MembrosFunçãoDetalhado em
of_resetRepor o componente a zero3.6 Repor um componente a zero: of_reset()
of_register_shortcut · of_clear_shortcutsAtalhos de teclado do componente3.5 Os atalhos de teclado
of_is_created · of_is_ready · of_get_last_errorSe nasceu, se está pronto, o que falhou3.7 Diagnóstico
of_save_as_png · of_save_as_jpgExportar a renderização como imagem3.8 Exportar a representação como imagem
of_set_redrawAgrupar as alterações num único repinte3.10 Boas práticas
of_preload_iconsÍcones mostrados sem atrasoApresentação instantânea: of_icon
of_set_translationTraduzir uma legenda do componente5.2 Adaptar uma etiqueta: of_set_translation
of_focus_webviewDar o foco ao componente6.4 Teclado e focus
of_print · of_print_to_pdfImprimir, ou escrever um PDF6.9 Imprimir
of_set_property · of_get_property · of_component_nameControlar uma propriedade pelo nome3.1 O motor de propriedades

Duas ajudas não são herdadas: of_icon e of_escape_markup vivem em n_pbt_utils. Declare um — n_pbt_utils lnv_utils, nada a criar — e chame-as nele.


← Referência dos componentes · Índice do guia