radialmenu — u_pbt_radialmenu #
← Referência dos componentes · Índice do guia
Menu de contexto radial: os comandos em coroa à volta do cursor, escolhidos pela direção em vez de lidos numa lista.
▶ Ver ao vivo — Aplicação de demonstração, mosaico Radial menu: a pré-visualização, o código que o produz e esta página, lado a lado.
Em resumo #
| Userobject | u_pbt_radialmenu |
| Classe de itens | n_pbt_radialmenu_item (of_item(keys)) |
| Serve para | Oferecer um punhado de comandos frequentes onde a mão já está |
| Princípio | Descreve os ramos; a roda, a forma e a navegação são connosco |
Arranque rápido #
// Uma roda montada para o que esta sob o cursor
uo_wheel.of_add_item(/*keys*/ "cut", /*text*/ "Cut")
uo_wheel.of_add_item(/*keys*/ "copy", /*text*/ "Copy")
uo_wheel.of_add_item(/*keys*/ "paste", /*text*/ "Paste")
uo_wheel.of_add_item(/*keys*/ "delete", /*text*/ "Delete")
// Abre-se ao soltar o botao direito: ver ue_rclicked
Abrir e depois escolher #
A roda abre-se ao largar o botão direito, e é preciso um segundo clique para escolher. Não é um detalhe de implementação: se abrisse ao premir, o largar desse mesmo clique selecionaria de imediato o setor caído sob o cursor, e o utilizador lançaria um comando sem o ter visto.
É por isso que of_show() é chamado a partir do evento de clique direito do controlo sobre o qual o utilizador faz o gesto (um statictext, um button, uma grelha…): nesse instante o botão já está em cima, e o clique seguinte é mesmo o que escolhe. O menu radial, esse, não tem superfície nenhuma — logo, nenhum evento de rato próprio.
O componente em si é invisível: não ocupa lugar na janela. Coloque-o onde quiser, com largura e altura nulas — só existe enquanto a roda está aberta.
O ramo apontado — com o rato ou o teclado — mostra o rótulo inteiro, por cima dos vizinhos: um setor guarda no máximo duas linhas (uma só a partir de nove ramos), e é isso que lhe permite levar um rótulo curto sem mentir sobre o que faz. O cubo central é a saída: clicar nele fecha a roda; dentro de uma sub-roda, sobe um nível. Enquanto a roda está aberta a aplicação continua a correr: um ramo retirado, desativado ou ocultado entretanto já não se escolhe (em vez disso, ue_dismissed); of_clear, of_reset, of_close e um segundo of_show fecham a roda aberta, e também of_remove_item quando a roda mostrava o ramo retirado — ue_dismissed é disparado de imediato, e of_is_open responde falso assim que a chamada regressa.
// Abre-se ao soltar o botao direito: ver ue_rclicked
uo_wheel.of_show()
Pelo teclado, as setas percorrem os ramos saltando os desativados, Enter ou Espaço escolhe, ← e Retrocesso sobem um nível, e Escape sobe um nível numa sub-roda — só fecha a roda na raiz. Nenhuma destas teclas chega à aplicação enquanto a roda está aberta. Em leitura da direita para a esquerda, a coroa gira no outro sentido e ← e → trocam de papel: → sobe um nível.
Para a abrir pelo teclado — a tecla Menu, Shift+F10 —, chame of_show_over a partir do controlo que tem o foco, com ab_keyboard a verdadeiro: a roda centra-se nesse controlo, esteja onde estiver o rato, e o seu primeiro ramo que responde fica aceso — Enter escolhe-o, as setas continuam a partir daí. of_show_over(controlo) sem esse segundo argumento serve também um botão de barra de ferramentas: a roda abre-se sobre ele.
As sub-rodas #
Um endereço pendura ramos sob outro: export/pdf. Escolher o ramo pai não escolhe nada: a roda é substituída pela dos seus filhos, e o cubo passa a ser o caminho de volta.
Porquê substituir em vez de acrescentar uma segunda coroa? Porque um anel exterior dividiria os setores por dois em cada nível. Oito ramos já é o máximo legível; não há espaço para mostrar dois níveis ao mesmo tempo.
O evento ue_item_selected comunica o endereço completo (export/pdf), não a chave da folha sozinha. Duas sub-rodas podem portanto nomear os seus ramos da mesma forma.
// A branch, then two entries at its address
uo_wheel.of_add_item(/*keys*/ "export", /*text*/ "Export")
uo_wheel.of_add_item(/*keys*/ "export/pdf", /*text*/ "PDF")
uo_wheel.of_add_item(/*keys*/ "export/csv", /*text*/ "CSV")
Para retirar um ramo — com a sua sub-roda — sem reconstruir toda a roda: of_remove_item("export/csv"). Os outros ramos ficam no lugar.
Quando há ramos a mais #
Uma roda lê-se pela direção, e para além de oito setores as fatias deixam de se distinguir. ii_max_sectors fixa esse teto (de 3 a 12, 8 por predefinição).
Os ramos a mais não se perdem: o último lugar da coroa passa a ser um ramo que os contém a todos e que abre como sub-roda. Um menu que deixasse cair a cauda seria um menu que mente sobre o que oferece.
Apertar a coroa é muitas vezes um ganho: quatro ramos largos apontam-se mais depressa do que oito estreitos.
Propriedades #
| Propriedade | Tipo | Predefinição | Papel |
|---|---|---|---|
ii_max_sectors | integer | 8 | Quantos ramos uma coroa pode levar (3 a 12). O que exceder passa sob um último ramo que abre como sub-roda. Acima de oito, a roda compacta-se (ícone mais pequeno, rótulo numa linha) para que os rótulos não se sobreponham |
is_theme_style | string | "" | Estilo visual do componente (constantes THEME_STYLE_*); vazio = o da aplicação, seguido a cada mudança |
is_theme_mode | string | "" | Variante clara ou escura (constantes THEME_MODE_*); vazio = a da aplicação, seguida a cada mudança |
il_theme_accent | long | -1 | Cor de destaque deste componente (-1 = destaque da aplicação, ou o do tema) |
Métodos #
| Método | Papel | |
|---|---|---|
of_add_item (string as_keys, string as_text) | Acrescenta um ramo no seu endereço: format/strike pendura-se sob Format, que já tem de existir. É esse mesmo endereço que volta em ue_item_selected quando é escolhido. Devolve 0 depois de acrescentado, -5 se o endereço for recusado (pai não encontrado, endereço já ocupado, nível vazio como export/ ou /pdf, chave que contém ` | ou começa por __), -2` se o componente não estiver criado |
of_add_item (string as_keys, string as_text, string as_image, boolean ab_checked) | O mesmo, com o ícone e a marca — o ícone como terceiro argumento, como em todo o resto da biblioteca. Um ramo desativa-se através do seu manípulo: of_item(keys).ib_enabled = false. Devolve 0 depois de acrescentado, -5 se o endereço for recusado (pai não encontrado, endereço já ocupado, nível vazio como export/ ou /pdf, chave que contém ` | ou começa por __), -2` se o componente não estiver criado |
of_clear ( ) | Esvazia a roda e liberta os manípulos obtidos por of_item (cada um designava um ramo que já não existe). Devolve 0 depois de aplicado, -2 se o componente não estiver criado | |
of_close ( ) | Fecha a roda do componente se estiver no ecrã, sem escolha: ue_dismissed é disparado de imediato, como num clique fora — mesmo para uma roda pedida um instante antes e ainda não desenhada — e of_is_open responde falso assim que regressa. Nada aberto, nada acontece. Devolve 0 depois de feito, -2 se o componente não estiver criado | |
of_is_open ( ) | true enquanto uma roda do componente está no ecrã — aberta, e ainda não respondida por uma escolha ou um fecho. of_show e of_close são aplicados antes de regressarem: responde verdadeiro logo após of_show, falso logo após of_close | |
long of_show ( ) | Abre a roda centrada no cursor. Chame-o a partir do clique direito do controlo que recebe o gesto. Uma roda sem nenhum ramo visível não se abre: é disparado ue_dismissed. Uma roda ainda no ecrã é substituída: dispara primeiro ue_dismissed. Devolve 0 depois de pedido, -2 se o componente não estiver criado | |
long of_show (long al_x, long al_y) | O mesmo, centrada numa posição de ecrã em píxeis. Coordenadas negativas são um ponto real, (-1, -1) incluído: um ecrã colocado à esquerda ou acima do principal. Devolve 0 depois de pedido, -2 se o componente não estiver criado | |
long of_show_over (dragobject ado_control) | Abre a roda centrada num controlo — uma imagem, um campo, um botão de barra de ferramentas —, esteja onde estiver o rato. Devolve 0 depois de pedido, -5 se o controlo não for válido, -2 se o componente não estiver criado | |
long of_show_over (dragobject ado_control, boolean ab_keyboard) | Igual, dizendo como a roda foi pedida: ab_keyboard a verdadeiro quando o utilizador a abriu pelo teclado (tecla Menu, Shift+F10) — o seu primeiro ramo que responde fica aceso, Enter escolhe-o. Devolve 0 depois de pedido, -5 se o controlo não for válido, -2 se o componente não estiver criado | |
of_item (string as_keys) | Devolve o manípulo de um ramo, pelo seu endereço, para o alterar depois (rótulo, estado, cores). Uma chave simples é resolvida no endereço completo do único ramo que a leva: of_item("csv") e of_item("import/csv") devolvem então o mesmo manípulo. Ambígua, ou levada por nenhum ramo, devolve um manípulo que não muda nada em vez do ramo errado. of_key() do manípulo devolve a chave do último nível | |
of_remove_item (string as_keys) | Retira um ramo e a sua sub-roda; os outros ficam. Uma chave simples é resolvida como faz of_item. A roda no ecrã só fecha (ue_dismissed) se mostrava esse ramo: retirar um oculto deixa-a aberta. Devolve 0 depois de retirado, -5 se nenhum ramo vive nesse endereço, -2 se o componente não estiver criado | |
of_reset ( ) | Esvazia a roda e repõe todas as propriedades no valor de origem. Devolve 0 depois de aplicado, -2 se o componente não estiver criado |
Eventos #
| Evento | Disparado quando |
|---|---|
ue_item_selected (string as_keys) | O utilizador escolheu um ramo. as_keys é o seu endereço completo (export/pdf), não a chave da folha sozinha. Um só evento por gesto: um duplo clique escolhe uma única vez |
ue_dismissed ( ) | A roda fechou sem que nenhum ramo fosse escolhido: clique no cubo, clique fora da roda, Escape na raiz — ou pelo código: of_close, of_clear, of_reset, of_remove_item de um ramo que mostrava, um segundo of_show que a substitui, um of_show que não tinha nada para mostrar. Uma vez por abertura, de imediato: of_is_open já responde falso |
Um clique num canto da janela, fora do disco, conta como um clique fora: a roda fecha-se (
ue_dismissed) e o clique passa para a aplicação que está atrás, em vez de ser engolido por um quadrado invisível.
Propriedades de item #
| Propriedade | Tipo | Predefinição | Papel |
|---|---|---|---|
is_text | string | "" | Rótulo do ramo. Mantenha-o curto: um setor é uma fatia, não uma linha, e mostra no máximo duas linhas — o ramo apontado mostra o rótulo inteiro. Vazio, mostra-se a chave |
ib_enabled | boolean | true | A falso, o ramo fica desativado e o seu setor ignora todos os cliques. Relê-se como o definiu: um ramo desativado por não ter nenhuma subentrada visível continua a reler verdadeiro |
ib_visible | boolean | true | A falso, o ramo sai da roda — sub-roda incluída — sem ser eliminado; os setores fecham-se, e volta tal como estava. Um ramo cujas subentradas estão todas ocultas fica na roda, desativado: já não tem nada para abrir e não se escolhe como uma folha |
ib_checked | boolean | false | A verdadeiro, um arco fino sob a faixa marca o ramo como ativo |
is_image | string | "" | O ícone do ramo, mudado no lugar — um Reproduzir que passa a Pausa. "" retira-o. Os mesmos caminhos que of_add_item (mono:, tint:, ficheiro.dll:NOME) |
is_tone | string | "" | O tom do comando: o seu rótulo colorido pelo tema, claro ou escuro, em repouso — u_pbt_radialmenu.TONE_DANGER para o que destrói, TONE_WARN, TONE_SUCCESS, TONE_INFO. "" ou TONE_NEUTRAL = o texto do tema; uma cor sua (il_text_color) prevalece |
is_group | string | "" | Um grupo de opção: os ramos de um mesmo grupo sob o mesmo pai excluem-se — marcar um (ib_checked = true, ou a escolha do utilizador, antes de ue_item_selected) desmarca os outros. "" = um ramo comum |
il_accent | long | -1 | Acento deste ramo: a sua faixa quando apontado, e a sua marca (-1 = o do componente) |
il_back_color | long | -1 | Faixa deste ramo em repouso (-1 = a do tema) |
il_text_color | long | -1 | Cor do rótulo deste ramo (-1 = a do tema) |
il_back_color_hover | long | -1 | Fatia deste ramo enquanto é apontado (-1 = a do tema). Dada sem il_text_color_hover, recebe um texto legível por cima |
il_text_color_hover | long | -1 | Cor do rótulo deste ramo enquanto é apontado (-1 = a do tema) |
Um ramo não mostra nenhuma dica: a janela redonda não tem espaço fora do disco. O is_tooltip herdado pelo manípulo é guardado e relê-se, mas nunca é mostrado — é o ramo apontado que mostra o rótulo inteiro.
Exemplos #
Uma roda por contexto #
// Uma roda montada para o que esta sob o cursor
uo_wheel.of_clear()
uo_wheel.of_add_item(/*keys*/ "bold", /*text*/ "Bold", /*image*/ "mono:img\packimages.dll:svg/samples/bold", /*checked*/ true)
uo_wheel.of_add_item(/*keys*/ "find", /*text*/ "Find", /*image*/ "mono:img\packimages.dll:svg/samples/find", /*checked*/ false)
Reagir ao caminho escolhido #
// Evento ue_item_selected do menu radial
// as_keys traz o caminho completo, p. ex. "export/pdf"
choose case as_keys
case "export/pdf"
of_export_pdf()
case "delete"
of_delete_selection()
end choose
Marcar, desativar, apertar #
// Mark a branch as being on
uo_wheel.of_item(/*keys*/ "bold").ib_checked = true
// Grey out the one that makes no sense here
uo_wheel.of_item(/*keys*/ "paste").ib_enabled = false
// No maximo quatro ramos numa coroa
uo_wheel.ii_max_sectors = 4
Pelo teclado, e fechada pelo código #
// Tecla Menu na grelha: a roda abre-se centrada nela, primeiro ramo aceso
uo_wheel.of_show_over(/*control*/ dw_orders, /*keyboard*/ true)
// Mais tarde, a partir de um temporizador: a roda fecha sem escolha (ue_dismissed)
if uo_wheel.of_is_open() then uo_wheel.of_close()
Um grupo de opção, um comando que destrói #
// Tres ramos exclusivos: escolher um desmarca os outros dois
uo_wheel.of_item(/*keys*/ "align/left").is_group = "align"
uo_wheel.of_item(/*keys*/ "align/center").is_group = "align"
uo_wheel.of_item(/*keys*/ "align/right").is_group = "align"
// Delete assume o tom do perigo, claro ou escuro
uo_wheel.of_item(/*keys*/ "delete").is_tone = u_pbt_radialmenu.TONE_DANGER
Boas práticas #
- Abra ao LARGAR o clique direito do controlo, nunca ao premir. É o que separa abrir de escolher, e o utilizador precisa de ambos.
- Rótulos curtos. Uma ou duas palavras. O setor está lá para a direção; o texto inteiro só se lê ao apontar o ramo.
- Quatro a seis ramos valem mais que oito. Uma roda recorda-se pela posição; quantas menos posições, mais depressa se aprendem.
- Ponha os comandos mais frequentes em cima e em baixo. São as duas direções que a mão alcança sem pensar.
- Mantenha a ordem estável de uma abertura para a outra: todo o interesse de uma roda é que o gesto acabe por preceder a leitura.
- Um menu radial não substitui um menu de lista. Vinte comandos raros leem-se melhor numa lista; guarde a roda para o punhado que se usa a toda a hora.
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.
| Membros | Função | Detalhado em |
|---|---|---|
of_count · of_keys_at · of_has | Percorrer o que o componente contém | 3.2 Os items |
of_reset | Repor o componente a zero | 3.6 Repor um componente a zero: of_reset() |
of_register_shortcut · of_clear_shortcuts | Atalhos de teclado do componente | 3.5 Os atalhos de teclado |
of_is_created · of_is_ready · of_get_last_error | Se nasceu, se está pronto, o que falhou | 3.7 Diagnóstico |
of_save_as_png · of_save_as_jpg | Exportar a renderização como imagem | 3.8 Exportar a representação como imagem |
of_set_redraw | Agrupar as alterações num único repinte | 3.10 Boas práticas |
of_preload_icons | Ícones mostrados sem atraso | Apresentação instantânea: of_icon |
of_set_translation | Traduzir uma legenda do componente | 5.2 Adaptar uma etiqueta: of_set_translation |
of_focus_webview | Dar o foco ao componente | 6.4 Teclado e focus |
of_print · of_print_to_pdf | Imprimir, ou escrever um PDF | 6.9 Imprimir |
of_set_property · of_get_property · of_component_name | Controlar uma propriedade pelo nome | 3.1 O motor de propriedades |
is_accessible_name · is_accessible_description | O nome e a descrição que um leitor de ecrã diz | 3.4 Propriedades e eventos opcionais |
Neste lançador invisível, of_count e of_keys_at percorrem o que adicionou, ramos ocultos incluídos — não o que a roda vai desenhar. A exportação como imagem, a impressão, of_focus_webview e of_set_redraw não têm aqui efeito útil: o componente não desenha nada de próprio, a roda vive na sua própria janela.
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.