Repetera (ett antal) alternativ

Ibland vill man upprepa ett antal alternativ för att godtyckligt antal objekt. Antag t.ex. att du vill implementera ett insticksprogram för att sortera en data.frame. Du vill tillåta sortering enligt ett godtyckligt antal kolumner (i händelse av liket i den första kolumnen eller de första kolumnerna). Det skulle helt enkelt kunna realiseras genom att tillåta att användare väljer flera variabler i en <varslot> med multi="true". Men om du vill utöka det, t.ex. tillåta att användaren anger om varje variabel ska konverteras till tecken eller ett nummer, eller om sorteringen ska vara stigande eller fallande, behövs större flexibilitet. Andra exempel skulle kunna vara uppritning av flera linjer i ett diagram (med möjlighet att välja objekt, linjestil, linjefärg, etc. för varje linje), eller ange en avbildning för att koda om från en mängd gamla värden till nya.

Här kommer <optionset> in. Låt oss föst ta en titt på ett enkelt exempel:

<dialog [...]>
        [...]
        <optionset id="set" min_rows="1">
                <content>
                        <row>
                                <input id="firstname" label="Given name(s)" size="small">
                                <input id="lastname" label="Family name" size="small">
                                <radio id="gender" label="Gender">
                                        <optioncolumn label="Male" value="m"/>
                                        <optioncolumn label="Female" value="f"/>
                                </radio>
                        </row>
                </content>

                <optioncolumn id="firstnames" label="Given name(s)" connect="firstname.text">
                <optioncolumn id="lastnames" label="Family name" connect="lastname.text">
                <optioncolumn id="gender" connect="gender.string">
        </optionset>
        [...]
</dialog>
                

Här skapade vi ett användargränssnitt för att ange ett antal personer (t.ex. upphovsmän). Användargränssnittet gräver minst en post (min_rows="1"). Inne i elementet <optionset> börjar vi med att ange innehållet med <content>, dvs, de element som hör till alternativmängden. Du bör redan vara bekant med de flesta elementen inne i <content>.

Därefter anger vi de intressanta variabler som vi vill läsa från alternativmängden i vår JS-fil. Eftersom vi hanterar ett godtyckligt antal objekt, kan vi inte bara läsa getString ("firstname") i JS. Istället anger vi en <optioncolumn> för varje intressant värde. För den första optioncolumn i exemplet, betyder <connect="firstname.text"> att innehållet i elementet <input>, "firstname", läses för varje objekt. Alla <optioncolumn> där en label anges visas på skärmen i en kolumn med den beteckningen. Nu kan vi hämta förnamnen på alla upphovsmän genom att använda getList("set.firstname"), getList("set.lastnames") för efternamnen, och getList("set.gender") för ett strängfält med "m" eller "f".

Observera att det inte finns några begränsningar för vad som kan placeras inne i <optionset>. Det går till och med att använda inbäddade komponenter. Precis som med alla andra element, är det enda man måste göra att samla utmatningsvariablerna av intresse i en specifikation med <optioncolumn>. I fallet med inbäddade insticksprogram, är det ofta en sektion med egenskapen "code". Till exempel:

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

Man kan förstås också använda gränssnittslogik inne i ett optionset. Det finns två sätt att göra det: Man kan skapa en anslutning (eller ett skript) i huvudsektionen <logic> av insticksprogrammet, som vanligt. Dock måste användargränssnittets element i innehållsregionen kommas åt som (t.ex.) "set.contents.firstname.XYZ". Observera prefixet "set" (det id som har tilldelats till mängden och "contents"). Som alternativ kan en separat sektion läggas till som ett underliggande objekt till <optionset> med <logic>. I detta fall, adresseras alla id relativt till innehållsregionen, t.ex. "firstname.XYZ". Endast elementet <script> tillåts inte i logiksektionen för ett optionset. Om skript ska användas, måste insticksprogrammets huvudsektion <logic> utnyttjas.

Notera

När skriptlogik används i optionset, är allt man kan göra att komma åt aktuell innehållsregionen. Sålunda är den typiskt bara användbar för att ansluta element inne i innehållsregionen till varandra. Att ansluta en egenskap utanför <optionset> till en egenskap inne i innehållsregionen kan vara användbart för initiering. Dock gäller inte ändring av innehållsregionen efter initieringen objekten som användaren redan har definierat, bara objektet i mängden som för närvarande är markerat.

"Drivna" optionsets

Hittills har vi betraktat ett <optionset> som tillhandahåller knappar för att lägga till eller ta bort objekt. Dock är det i vissa fall mycket naturligare att välja objekt utanför <optionset>, och bara tillhandahålla alternativ för att anpassa vissa aspekter av varje objekt i ett <optionset>. Antag t.ex. att du vill låta användaren rita upp flera objekt inne i ett diagram. Användaren ska kunna ange linjefärg för varje objekt. Du skulle kunna lösa det genom att lägga till en <varselector> och <varslot> inne i området <content>, vilket låter användaren välja ett objekt i taget. Dock blir det mycket färre klick för användaren, om <varslut multi="true"> används utanför <optionset> istället. Därefter ansluts de utvalda objekten till ett så kallat "drivet" optionset. Så här gör man:

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

Vi börjar med att titta på exemplet längst ner. Observera att två specifikationer av <optioncolumn> har external="true". Det talar om för RKWard att de kontrolleras från utsidan av <optionset>. Här är det enda syftet med alternativkolumnen "varnames" att tillhandahålla lättlästa beteckningar vid visning av optionset (den är ansluten till värdet "shortname" i egenskapen som innehåller de valda objekten). Syftet med alternativkolumnen "vars" är att fungera som "nyckelkolumn", enligt specifikationen <optionset keycolumn="vars"...>. Det betyder att för varje post i listan, erbjuder mängden en uppsättning alternativ, och alternativen är logiskt kopplade till posterna. Kolumnen är ansluten till egenskapen som innehåller de valda objekten i <varslot>. Det vill säga för varje objekt som är valt där, tillåter <optionset> att ange linjefärg.

Notera

Externa kolumner kan också anslutas med connect till egenskaper inne i regionen <content>. Dock är det viktigt att observera att optioncolumns deklarerade med external="true" aldrig ska ändras inne i <optionset>, och optioncolumns deklarerade med external="false" (förval) aldrig ska ändras utanför <optionset>.

Alternativ: När optionsets inte ska användas

Att använda optionset är ett kraftfullt verktyg, men de kan ibland göra mer skada än nytta, eftersom de adderar betydande komplexitet, både från insticksprogramutvecklarens och användarens perspektiv. Tänk dig alltså för en extra gång innan du använder dem. Här är några råd:

  • I några enkla fall kan elementet <matrix> vara ett användbart lättviktigt alternativ.

  • Låt inte insticksprogrammet göra för mycket. Vi gav exemplet att använda optionset för ett insticksprogram för att rita flera linjer i ett diagram. Men i allmänhet är det inte en god idé att skapa ett insticksprogram som producerar enskilda diagram för varje objekt i ett optionset. Låt istället insticksprogrammet skapa ett diagram, som användaren kan anropa flera gånger.

  • Om du inte förväntar dig mer än två eller tre objekt i en mängd, överväg att upprepa alternativen manuellt istället.