Opções repetidas (um conjunto de)

Às vezes, você deseja repetir um conjunto de opções para um número arbitrário de itens. Por exemplo, suponha que você queira implementar um plugin para classificar um data.frame. Você pode querer permitir a classificação por um número arbitrário de colunas (em caso de empate entre as primeiras colunas). Isso pode ser facilmente implementado permitindo que o usuário selecione várias variáveis ​​em um <varslot> com multi="true". Mas se você quiser estender isso, por exemplo, permitindo que o usuário especifique para cada variável se ela deve ser convertida para caractere/numérica ou se a classificação deve ser crescente ou decrescente, você precisa de mais flexibilidade. Outros exemplos seriam plotar várias linhas em um único gráfico (permitindo selecionar objeto, estilo de linha, cor da linha etc. para cada linha) ou especificar um mapeamento para recodificar de um conjunto de valores antigos para novos valores.

Digite o <conjunto de opções>. Vamos analisar um exemplo simples primeiro:

<dialog [...]>
        [...]
        <optionset id="set" min_rows="1">
                <content>
                        <row>
                                <input id="firstname" label="Nome(s) fornecido(s)" size="small">
                                <input id="lastname" label="Nome de família" size="small">
                                <radio id="gender" label="Gênero">
                                        <optioncolumn label="Masculino" value="m"/>
                                        <optioncolumn label="Feminino" value="f"/>
                                </radio>
                        </row>
                </content>

                <optioncolumn id="firstnames" label="Nome(s) fornecido(s)" connect="firstname.text">
                <optioncolumn id="lastnames" label="Nome de família" connect="lastname.text">
                <optioncolumn id="gender" connect="gender.string">
        </optionset>
        [...]
</dialog>
                

Aqui, criamos uma interface de usuário para especificar um número de pessoas (por exemplo, autores). A interface requer pelo menos uma entrada (min_rows="1"). Dentro do elemento <optionset>, começamos especificando o <content>, isto é, os elementos que pertencem ao conjunto de opções. Você já deve estar familiarizado com a maioria dos elementos dentro do <content>.

Em seguida, especificamos as variáveis ​​de interesse que queremos ler do conjunto de opções em nosso arquivo JS. Como lidaremos com um número arbitrário de itens, não podemos simplesmente ler getString("firstname") em JS. Em vez disso, para cada valor de interesse, especificamos um <optioncolumn>. Para a primeira optioncolumn no exemplo, `<connect="firstname.text"> significa que o conteúdo do elemento "firstname" é lido para cada item. Os itens <optioncolumn> para os quais um label é fornecido serão exibidos na tela, em uma coluna correspondente a esse rótulo. Em JS, agora podemos buscar os primeiros nomes de todos os autores usando getList("set.firstname"), getList("set.lastnames") para os sobrenomes e getList("set.gender") para um array de strings "m"/"f".

Observe que não há restrições quanto ao que você pode colocar dentro de um <optionset>. Você pode até usar componentes embedded. Assim como com qualquer outro elemento, tudo o que você precisa fazer é coletar as variáveis ​​de saída de interesse em uma <optioncolumn>-specification. No caso de plugins incorporados, isso geralmente é uma seção da propriedade "code". Por exemplo:

<dialog [...]>
        [...]
        <optionset id="set" min_rows="1">
                <content>
                        [...]
                        <embed id="color" component="rkward::color_chooser" label="Color"/>
                </content>

                [...]
                <optioncolumn id="color_params" connect="color.code.printout">
        </optionset>
        [...]
</dialog>
                

Claro que você também pode usar lógica de interface do usuário dentro de um optionset. Existem duas opções para fazer isso: Você pode fazer isso estabelecendo uma conexão (ou script) na seção principal <logic> do seu plugin, como de costume. No entanto, você acessará os elementos da interface do usuário na região de conteúdo como (por exemplo) "set.contents.firstname.XYZ". Observe o prefixo "set" (o id que você atribuiu ao conjunto e "contents"). Alternativamente, você pode adicionar uma seção <logic> separada como um elemento filho do seu <optionset>. Nesse caso, os ids serão endereçados em relação à região de conteúdo, por exemplo, "firstname.XYZ". Somente o elemento <script> não é permitido na seção de <logic> do plugin.Se você quiser usar scripts, terá que utilizar a seção principal <logic> do plugin.

Nota

Ao criar scripts de lógica em um conjunto de opções, tudo o que você pode fazer é acessar a região de conteúdo atual. Portanto, normalmente, só faz sentido conectar elementos dentro da região de conteúdo entre si. Conectar uma propriedade fora do <optionset> a uma propriedade dentro da região de conteúdo pode ser útil para inicialização. No entanto, modificar a região de conteúdo após a inicialização não se aplicará aos itens que o usuário já definiu. Apenas ao item atualmente selecionado no conjunto.

"Driven" optionsets

Até agora, consideramos um <optionset> que fornece botões para adicionar/remover itens. No entanto, em alguns casos, é muito mais natural selecionar itens fora do <optionset> e fornecer opções para personalizar alguns aspectos de cada item apenas em um <optionset>. Por exemplo, suponha que você queira permitir que o usuário plote vários objetos em um único gráfico. Para cada objeto, o usuário deve poder especificar a cor da linha. Você poderia resolver isso colocando um <varselector> e um <varslot> dentro da área <content>, permitindo que o usuário selecione um item por vez. No entanto, isso significará muito menos cliques para o usuário se você usar um <varslot multi="true""> fora do <optionset>. Em seguida, você conectará essa seleção de objetos a um conjunto de opções chamado "controlado". Veja como:

<dialog [...]>
        <logic>
                <connect client="set.vars" governor="vars.available"/>
                <connect client="set.varnames" governor="vars.available.shortname"/>
        </logic>
        [...]
        <varselector id="varsel"/>
        <varslot id="vars" label="Objects to plot"/>
        <optionset id="set" keycolumn="var">
                <content>
                        [...]
                        <embed id="color" component="rkward::color_chooser" label="Line color"/>
                </content>

                [...]
                <optioncolumn id="vars" external="true">
                <optioncolumn id="varnames" external="true" label="Variable">
                <optioncolumn id="color_params" connect="color.code.printout">
        </optionset>
        [...]
</dialog>
                

Começaremos analisando o exemplo abaixo. Você notará que duas especificações de <optioncolumn> têm external="true". Isso indica à RKWard que elas são controladas de fora do <optionset>. Aqui, o único propósito da coluna de opções "varnames" é fornecer rótulos de fácil leitura na exibição do conjunto de opções (ela está conectada ao modificador "shortname" da propriedade que contém os objetos selecionados). O propósito da coluna de opções "vars" é servir como a coluna "chave", conforme especificado por <optionset keycolumn="vars"...>. Isso significa que para cada entrada nesta lista, o conjunto oferecerá um conjunto de opções, e as opções estão logicamente vinculadas a essas entradas. Esta coluna está conectada à propriedade que contém os objetos selecionados no <varslot>. Ou seja, para cada objeto selecionado ali, o <optionset> permitirá especificar a cor da linha.

Nota

A coluna externa também pode ser connect (conectada) a propriedades dentro da região <content>. No entanto, é importante observar que as colunas de opções declaradas como external="true" nunca devem ser modificadas de dentro do <optionset>, e as colunas de opções declaradas como external="false" (o padrão) nunca devem ser modificadas de fora do <optionset>.

Alternativas: Quando não usar conjuntos de opções

Optionsets são uma ferramenta poderosa, mas às vezes podem causar mais danos do que benefícios, pois adicionam uma complexidade considerável, tanto da perspectiva de um desenvolvedor de plugins quanto da perspectiva de um usuário. Portanto, pense duas vezes antes de usá-los. Aqui estão algumas dicas:

  • Para alguns casos simples, o elemento <matrix> pode fornecer uma alternativa leve e útil.

  • Não sobrecarregue seu plugin com muitas funcionalidades. Demos o exemplo de usar um conjunto de opções (optionset) para que um plugin desenhe várias linhas em um único gráfico. Mas, em geral, não é uma boa ideia criar um plugin que gere gráficos individuais para cada item em um conjunto de opções. Em vez disso, faça com que o plugin gere um único gráfico, e o usuário possa chamá-lo várias vezes.

  • Se você não espera mais do que dois ou três itens em um conjunto, considere repetir as opções manualmente.