Do I have to assign my widget a unique ID (what if I'm in a loop that creates many instances?) so that I can call SetProperty?
In such cases you probably want to style all those widgets in the same way. That's what classes are for:
for widget in all_my_widgets {
widget.SetClass( "fancy" );
}
...
SetProperty( ".fancy", "Color", sf::Color::Red );
(the "." is the syntax for specifying a class)
Note that the widget's name is also not required! That should answer your second question.
If you leave anything out, it's like placing a "*" wildcard:
- .fancy -> applies to ALL widget types with ANY ID in ALL states, but with class "fancy"
- Button:Prelight -> applies to buttons with ANY ID, ANY class, but state "Prelight"
- #inventory -> applies to ALL widget types with ANY class in ANY state, but with ID "inventory".
There's no version of giving a pointer to SetProperty(). It's possible and there's already a method to build a widget's complete path with all attributes in a widget tree. But I think it's just not needed. It's probably easier to give IDs and select by IDs. This will also get more important when loading GUI descriptions from markup files (like XML).
And why do you need to explicitely write the type of the template parameter? Can't it be deduced from the third argument?
It can, however it's not possible for types that'd be converted implicitly, like int -> short. Properties are stored as boost::any, and types of new properties are always checked against the needed type. I haven't found a way yet to allow shorts for an int property. :)
That's why you should always specify the template parameter, to make sure.