# gSetAttributes

Definition: | include xpGUI.e gSetAttributes(gdx id, string attributes, dword_seq args={})
Description: | Sets several attributes of an interface element or elements. id: Identifier(s) of the interface element(s). attributes: Four cases exist: "==": args is a pair-list, eg {{“name1”, attr1}, {“name2”, attr2},...} Elements of args may also be triplets, which trigger a `sprintf(attri, arg3i)`. leading '=' followed by comma-separated names, eg “=name1, name2,...” then args is {attr1, attr2,...} of the correct/exact/matching length. Note that any desired sprintf() would have to be explicitly coded. "=!=": (planned) run-time warning => compiler pause for next, see comments. string with the attributes in the format “name1=attr1, name2=attr2,...” when args!={} this case invokes a `sprintf(attributes,args)`.
pwa/p2js: | Supported.
Comments: | Fairly obviously the (new in 1.0.4) pair-list/names-only attributes is a trivial loop with individual values of any type. The rest of this section is about the older all-string/sprintf handling (/me wonders how/why I ever coped!): Parses the (post-sprintf) attributes string and invokes gSetAttribute(id,namei,attri) for each pair in turn. This routine itself does not care or check whether id is a single or a sequence of ids [ditto names/pairs], and instead leaves all such handling to the "without-s" routine. Most interface elements can be created with an optional implicit inline invocation of gSetAttributes(), which can make code much cleaner than invoking this function directly, as examples 2 and 3 below show. Fairly obviously, attribute values must be expressed(/ible) in textual form, but a bool, for instance, can be set using "1"/"0", "true"/"false", "YES"/"NO", "ON"/"OFF" and similar, as documented for the specific attribute, with (say) "SOMEFLAG=%t, ...", {flag, ...} or a separate gSetAttribute(id,"SOMEFLAG",flag) or gSetInt(id,"SOMEFLAG",flag) being some of the more obvious and straightforward choices. Multiple values can be set using eg "240x80" or "{240,80}" syntax, note however that '{' and '}' are treated the same as double quotes and (currently) cannot be nested (specifically, that is, when gSetAttributes is breaking up the attributes string into fragments to relay on to the gSetAttribute() routine). It may however be possible to contain nested {} in double quotes, eg `NAME="{1,{2,3}}"`, not that any such cases are currently needed, or have been extensively tested. There may be cases such as a title of `thing="X", [SIZE=%d]` which might prove difficult if not impossible to achieve via gSetAttributes(), because of the probable mis-parsing of commas, spaces, [mixed] quotes, and equal signs. Bear this in mind, especially when the data originates from file or user input, and may in fact require careful sanitisation, or even rejection. While quotation marks are parsed, so for example gSetAttributes(id,`TITLE="Address Book", SIZE=500x300`) works fine, there is however quite simply no way to include literal quotation marks in a value when using gSetAttributes(). At a push it might be possible to make it support doubly-escaped strings such as "\\\"" or `\"` (both identical and no \ in either after parsing), but I’m not keen and would probably struggle to justify the potential additional confusion that would probably introduce. Any such potentially confusing fields must be set individually using gSetAttribute() directly. If there is any doubt, especially with settings that are not fixed constants, just do them one at a time. [DEV: I should just do this...] It is not inconceivable this string-only stuff will one day be consigned to the dustbin, where it rightly belongs, bar legacy code. To that end, it is planned for the fourth case to start showing a run-time warning (first time only), with "=!=" being a quick temporary trick, that generates a compile-time message stall rather than annoy real end-users, before finally removing all this stuff, over the course of several releases of phix/xpGUI. That won’t happen until pGUI is no longer part of the standard distro, but will continue to be available as a separate download, which is all some way off yet and assumes that xpGUI will manage to outshine it in every way, which is not yet a given either. C code that uses nested IupSetAtt[ributes[f]]() calls should normally be converted into a single paranormalised function call when possible, otherwise be broken down into consecutive statements that all get passed the same id, and/or explicit variables created (suitably/sensibly/nicely named) for any (previously anonymous) inner elements. Sometimes that can be a bit of a drag, but more often than not the code ends up both easier to read and easier to modify at some later date.
Example 1: |
    -- Select the appropriate file dialog type and title.
    gSetAttributes(filedlg, iff(bOpen?`DIALOGTYPE=OPEN, TITLE=Open`
                                     :`DIALOGTYPE=SAVE, TITLE=Save`))
Example 2: |
    gButton(dlg, "=ACTIVE,IMAGE",{true,xpm}) -- or:
    gButton(dlg, "==",{{"ACTIVE",true},{"IMAGE",xpm}})
Admittedly that is more of an example of when not to use gSetAttributes(), or more accurately implicitly inline it, but of course there would be no difficulty whatsoever extracting attr/arg into [a] separate following gSetAttribute[s]().
Example 3: | Translate C code such as `list = IupList(); IupSetAtt(NULL, list, "VALUE", "3", "1", "Brazil", "2", "USA", "3", "Japan", "4", "France", NULL);` to
    gdx list = gDropDown(changed,"=OPTIONS,VALINT",{{"Brazil","USA","Japan","France"},3})
    -- or
    gdx list = gDropDown({"Brazil","USA","Japan","France"},changed,"VALINT=3")
Which creates a list dropdown with country names and defines Japan as the selected/default option.
See Also: | gSetAttribute, gGetAttribute, gButton, gDropDown, gList