User Interface

How do use and read selection choice from a custom popup?

If you want to create a popup selection choice an argument for a command, the easiest option is to use a LXtTextValueHintcreate and set that hint for an integer argument using dyna_SetHint.

C++

static LXtTextValueHint argChoices[] =
{
        0, "choiceA",
        1, "choiceB",
        2, "choiceC",
        -1, NULL
}
MyCommand::MyCommand ()
{
        dyna_Add ("choices", LXsTYPE_INTEGER);
        dyna_SetHint (argChoices);
}

If you’re list is dynamic, Text Value Hints might not be an option. Instead you can use CLxUIValue or CLxDynamicUIValue inside of a overridden atrui_UIValue function to create your list of choices.

C++

CLxDynamicUIValue MyCommand::atrui_UIValue (unsigned int argIdx)
{
        CLxUIValue              *pop = NULL;
        CLxUser_Scene            scene;
        CLxUser_Item             item;
        const char              *name;
        CLxSceneSelection        scnSel;
        unsigned                 i, n;

        if (argIdx == 0) {
                scnSel.Get(scene);
                pop = new CLxUIValue();
                pop->popup_add ("choiceA");
                pop->popup_add ("choiceB");
                scene.ItemCount(cit_mesh, &n);
                for (i=0; i<n; i++) {
                        scene.ItemByIndex(cit_mesh, i, item);
                        item.UniqueName(&name);
                        pop->popup_add(item.IdentPtr(), name);
                }
                return pop;
        }
}

It can be tricky to work out how to read these values later on, however.

C++

// Read which choice was selected
int choiceIdx;
choiceIdx = dyna_Int(0);

// Create a hint and set it using the UIValueHints method
CLxLoc_UIValueHints hnts;
LXtObjectID obj;
atrui_UIValueHints(0, &obj);
hnts.take(obj);

// Read the user name at the chosen index (or any other property)
stMeshIdent = hnts.PopUserName(mIdx);

How do I make my command button update when the enable state changes?

You need a notifier. Command notifiers send change flags on specific events to indicate that some aspect of the command’s state may have changed. Flags can indicate the enable/disable state, the label, the value, or the datatype.

*Notifiers can be added to a basic command by implementing basic_Notifier() which returns the name and arguments for each notifier by index. *Common notifiers for selection changes, mesh edits, etc, can be found in the notifier docs. *Changes to plug-in state can trigger notifications by declaring a notifier server. These are created by inheriting from CLxCommandNotifier.

How do I make my command’s boolean argument appear as a toggle button?

You can set the default style of a command’s boolean argument using UIHints, done by implementing arg_UIHints() in Python. By default, boolean type arguments will appear as a checkbox when exposed in the UI, but you can specify the hint for the boolean argument’s index to default to a toggle button like this.

C++

...

Python

def arg_UIHints (self, index, hints):
        if index == 0:
                hints.BooleanStyle (lx.symbol.iBOOLEANSTYLE_BUTTON)

How do I open a file dialog from my command?

Normally this is done in your Interact() method, something like this:

C++

class CCommmandUtility {
   public:
   void        fire (const char *cmd)
   {
           check ( srv_cmd.ExecuteArgString (-1, LXiCTAG_NULL, cmd) );
   }

   CLxUser_CommandService         srv_cmd;
};

        void
CMyLoadCommand::cmd_Interact ()
{
        /*
         * Open the dialog using the "dialog.*" sub-commands. Works here
         * because they are non-model, non-undoable commands.
         */
        fire ("dialog.setup fileOpen");
        fire ("dialog.title {Load Animation}");
        fire ("dialog.fileTypeCustom {Quicktime Movie} {*.mov;*.mp4} mov");
        fire ("dialog.open");

        /*
         * Query the result, getting a list of filenames.
         */
        CLxUser_Command          resCmd;
        CLxUser_ValueArray       va;
        LXtObjectID              obj;
        unsigned int             n;

        check ( srv_cmd.NewCommand (resCmd, "dialog.result") );
        check ( srv_cmd.QueryIndex (resCmd, 0, va), LXe_FAILED );

        /*
         * Although it's a list, there's only one filename (since this was
         * a single-file dialog).  We'll set our filename argument to the
         * first one in the list.
         */
        n = va.Count ();
        if (!n)
                return;

        std::string              filename;

        check ( va.String (0, filename) );
        check ( attr_SetString (0, filename.c_str ()) );
}

The check() functions are defined in the lx_err namespace.