PBToolboxAI v5 ← Site

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 #

Userobjectu_pbt_radialmenu
Classe de itensn_pbt_radialmenu_item (of_item(keys))
Serve paraOferecer um punhado de comandos frequentes onde a mão já está
PrincípioDescreve 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 #

PropriedadeTipoPredefiniçãoPapel
ii_max_sectorsinteger8Quantos 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_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)

Métodos #

MétodoPapel
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 #

EventoDisparado 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 #

PropriedadeTipoPredefiniçãoPapel
is_textstring""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_enabledbooleantrueA 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_visiblebooleantrueA 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_checkedbooleanfalseA verdadeiro, um arco fino sob a faixa marca o ramo como ativo
is_imagestring""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_tonestring""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_groupstring""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_accentlong-1Acento deste ramo: a sua faixa quando apontado, e a sua marca (-1 = o do componente)
il_back_colorlong-1Faixa deste ramo em repouso (-1 = a do tema)
il_text_colorlong-1Cor do rótulo deste ramo (-1 = a do tema)
il_back_color_hoverlong-1Fatia deste ramo enquanto é apontado (-1 = a do tema). Dada sem il_text_color_hover, recebe um texto legível por cima
il_text_color_hoverlong-1Cor 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 #

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_count · of_keys_at · of_hasPercorrer o que o componente contém3.2 Os items
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
is_accessible_name · is_accessible_descriptionO nome e a descrição que um leitor de ecrã diz3.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.


← Referência dos componentes · Índice do guia