Skip to content
TomCrypto edited this page Dec 16, 2014 · 5 revisions

The StructVariable is, strictly speaking, not a true variable. It does not use the native AntTweakBar struct functions, as those do not map well to C#. Instead, it simply holds a list of variables under the same group, which achieves essentially the same result.

The variable itself does little more than maintain a user-provided list of variables and manage their lifetimes. It is meant to be overridden to provide concrete functionality relevant to your application. For instance, the following class implements a complex number variable using two double variables and the standard C# complex type:

sealed class ComplexVariable : StructVariable<Complex>
{
    private DoubleVariable Re { get { return (variables[0] as DoubleVariable); } }
    private DoubleVariable Im { get { return (variables[1] as DoubleVariable); } }

    public ComplexVariable(Bar bar, Complex initialValue)
        : base(bar, new DoubleVariable(bar, initialValue.Real),
                    new DoubleVariable(bar, initialValue.Imaginary))
    {
        Re.Label = "Real";
        Im.Label = "Imaginary";
    }

    public override Complex Value
    {
        get
        {
            return new Complex(Re.Value, Im.Value);
        }

        set
        {
            Re.Value = value.Real;
            Im.Value = value.Imaginary;
        }
    }

    public Double Step
    {
        get { return Re.Step; }
        set
        {
            Re.Step = value;
            Im.Step = value;
        }
    }

    public Double Precision
    {
        get { return Re.Precision; }
        set
        {
            Re.Precision = value;
            Im.Precision = value;
        }
    }
}

There are several important points to note in this implementation. The ComplexVariable type implements the StructVariable<Complex> type, which automatically makes it a value variable that can be added to bars just like any other variable. In the constructor the two double variables for the real and imaginary parts respectively are created and configured.

The Re and Im properties are particularly noteworthy. Notice they map directly to the variables passed in the base constructor. It is recommended to implement these as read-only properties rather than fields, giving them a meaningful name and casting each variable to the proper type as done above.

Note the StructVariable provides a Changed event, which is raised whenever any of the variables change, and a Group property, which controls the group all the variables are under. There is no Validating event, but you can always use the individual variable's Validating events to this effect.

Finally, the remaining code simply uses the Re and Im variables to provide the desired functionality. In this case, the ComplexVariable has configurable Step and Precision properties. The new ComplexVariable can then be instantiated and put into a group e.g. as follows:

var myGroup = new Group(myBar);
var myComplexVar = new ComplexVariable(myBar, Complex.Zero);
myComplexVar.Changed += delegate { /* do something with myComplexVar.Value */ };
myComplexVar.Group = myGroup;
myComplexVar.Step = 0.0002;
myComplexVar.Precision = 4;

myGroup.Label = "A Complex Variable";

Using the StructVariable abstract class in this way is the easiest way to define your own composite variables. Note that the StructVariable holds only value variables, it cannot hold buttons or separators. And since the StructVariable is a value variable, it can also contain other StructVariable instances.

Note: Any variable contained in the StructVariable will be disposed when the StructVariable is disposed, for this reason it is recommended not to expose the variables it holds (e.g. in the example above, Re and Im are private and hidden).

Note: It is recommended not to modify the list of variables outside the base constructor as it can lead to inconsistencies. If your list of variables is dynamic, perhaps it does not really map to a struct.


  • High-level wrapper
  • Integration
    • [Event handling](Event handling)
    • [Organizing variables](Organizing variables)
    • [Error handling](Error handling)
    • Scripting
    • [Exception safety](Exception safety)
    • [Thread safety](Thread safety)
  • Technical manual
    • Context
    • Bar
    • Group
    • IntVariable
    • FloatVariable
    • DoubleVariable
    • BoolVariable
    • EnumVariable
    • StringVariable
    • ColorVariable
    • Color4Variable
    • VectorVariable
    • QuaternionVariable
    • StructVariable
    • Button
    • Separator
    • ...
  • [Low-level wrapper](Low-level wrapper)
Clone this wiki locally