WoW:SecureActionButtonTemplate
The SecureActionButtonTemplate was introduced in Patch 2.0 to allow addons to perform protected actions -- casting spells, executing macros, etc -- by specifying button behavior via its attributes.
Creating a SecureActionButton
To create a SecureActionButton, simply create a button that inherits from the SecureActionButtonTemplate; to make the button instance useful, specify interesting attributes. This can be done in both XML, Lua and a mix of the two:
Using XML:
<Button name="myButton" inherits="SecureActionButtonTemplate" parent="UIParent"> <Attributes> <Attribute name="type" value="action" /> <Attribute name="action" value="1" type="number" /> </Attributes> </Button>
Using Lua: (Warning: the following code does nothing)
local btn = CreateFrame("Button", "myButton", UIParent, "SecureActionButtonTemplate"); btn:SetAttribute("type", "action"); btn:SetAttribute("action", 1);
Modified attributes
Attribute | Used on... |
---|---|
"type" | Any clicks. |
"*type1" | Any left click. |
"type1" | Unmodified left click. |
"shift-type2" | Shift+right click. (But not Alt+Shift+right click) |
"shift-type*" | Shift+any button click. |
"alt-ctrl-shift-type*" | Alt+Control+Shift+any button click. |
"ctrl-alt-shift-type*" | Invalid, as modifiers are in the wrong order. |
Some attribute may change value based on whether a particular combination of modifier keys is held down and/or a particular button is being clicked. Those attributes are typically called modified attributes, and are resolved by the SecureButton_GetModifiedAttribute function.
The "modified attribute" name takes the form of: modifier-name-button. The modifier is one of "alt-", "ctrl-", "shift-", or a combination of them in that order, and the button is a normally number from 1 through 5 or hyphen followed by an arbitrary string. Both the prefix and the suffix can be "*" to signify no regard to the modifier/button; "*attribute*" is thus equivalent to "attribute". Some examples are shown in the table to the right; both the modifier and the button must match the click details in order for the attribute value to be used.
A limited precedence order is defined by the Frame:GetAttribute method.
Button remapping
SecureActionButtons are also able to change the button being clicked in response to whether your target can be assisted ([help]) or attacked ([harm]) by you; the two relevant attributes are "helpbutton" and "harmbutton". The value of those attributes, should they match, will be used as the button to resolve the "type" and other required arguments.
For example, suppose we wanted to create a button that would alter behavior based on whether you can attack your target. Setting the following attributes has the desired effect:
Attribute | Value | Purpose |
---|---|---|
"unit" | "target" | Make all actions target the player's target. |
"*harmbutton1" | "nuke1" | Remap any left clicks to "nuke1" clicks when target is hostile. |
"*harmbutton2" | "nuke2" | Remap any right clicks to "nuke2" clicks when target is hostile. |
"helpbutton1" | "heal1" | Remap unmodified left clicks to "heal1" clicks when target is friendly. |
"type" | "spell" | Make all clicks cast a spell. |
"spell-nuke1" | "Mind Flay" | Cast Mind Flay on "hostile" left click. |
"spell-nuke2" | "Shadow Word: Death" | Cast Shadow Word: Death on "hostile" right click. |
"alt-spell-nuke2" | "Mind Blast" | Cast Mind Blast on "hostile" alt-right click. |
"spell-heal1" | "Flash Heal" | Cast Flash Heal on "friendly" left click. |
If the button is remapped by the "harmbutton" or "helpbutton" attributes, the value of the "unit" attribute is reevaluated with the new button suffix: it is therefore to make a button that would check the hostility of one unit, and perform a reactive action on an entirely different unit.
Action Types
The action the SecureActionButtonTemplate-inheriting frame actually performs is dependent on the value of its modified type attribute, and possibly additional attributes specific to a type.
The table below lists all valid type values and the attributes they use to perform their actions. All relevant attributes can be modified as previously described; and, to the extent possible, all types respect the "unit" attribute for targeting. Generally, variable names are used to refer to the value of the modified attribute sharing their name.
Type | Used attributes | Behavior |
---|---|---|
"actionbar" | "action" | Switches the current action bar depending on the value of the "action" attribute:
|
"action" | "unit", "action" ["actionpage"] |
Performs an action specified by the "action" attribute (a number). If the button:GetID() > 0, paging behavior is supported; see the ActionButton_CalculateAction FrameXML function. |
"pet" | "unit", "action" | Calls CastPetAction(action, unit); |
"spell" | "unit", "spell" | Calls CastSpellByName(spell, unit); |
"item" | "unit" "item" OR ["bag", "slot"] |
Equips or uses the specified item, as resolved by SecureCmdItemParse.
|
"macro" | "macro" OR "macrotext" |
If "macro" attribute is specified, calls RunMacro(macro, button); otherwise, RunMacroText(macrotext, button); |
"cancelaura" | "unit" "index" OR "spell"[, "rank"] |
Calls either CancelUnitBuff(unit, index) or CancelUnitBuff(unit, spell, rank). The first version
Note: the value of the "index" attribute must resolve to nil/false for the "spell", "rank" attributes to be considered. |
"stop" | Calls SpellStopTargeting(). | |
"target" | "unit" | Changes target, targets a unit for a spell, or trades unit an item on the cursor. If "unit" attribute value is "none", your target is cleared. |
"focus" | "unit" | Calls FocusUnit(unit). |
"assist" | "unit" | Calls AssistUnit(unit). |
"mainassist" | "action", "unit" | Performs a main assist status on the unit based on the value of the "action" attribute:
|
"maintank" | "action", "unit" | As "mainassist", but for main tank status. |
"click" | "clickbutton" | Calls clickbutton:Click(button) |
"attribute" | ["attribute-frame",] "attribute-name" "attribute-value" |
Calls frame:SetAttribute(attributeName, attributeValue). If "attribute-frame" is not specified, the button itself is assumed. |
Any other value | "_type" | Action depends on the value of the modified ("_" .. type) attribute, or rawget(button, type), in that order.
|
Additionally, the "target-item" or "target-bag", "target-slot" attributes allow you to create a button that would target a specific item in your inventory for a spell being cast. This targeting is performed after the main type processing, and only if a spell is currently being targetted. It is therefore possible to create a button that would cast a specific spell on a specific item by setting the relevant attributes. For instance, to disenchant an item in bag 1, slot 1:
btn:SetAttribute("type", "spell"); btn:SetAttribute("spell", "Disenchant"); btn:SetAttribute("target-item", "1 1"); -- ("bag slot")
Other attributes
A few more attributes can affect how the button functions:
Attribute | Values | Function |
---|---|---|
"downbutton" | Any string | Remaps the mouse button if this is a "down" click. This transformation is applied before all others. |
"unitsuffix" | "pet", "target", etc. | Appends the attribute's value to the "unit" attribute value when resolving units. |
"toggleForVehicle" | true, false | When the unit's owner is in a vehicle, remap the pet to its owner, and its owner to its pet (the vehicle). Based on the original unit:
|
"allowVehicleTarget" | true, false | If true, allows "toggleForVehicle" to remap units like "party1target" to "partypet1target". |
"checkselfcast" | true, false | If true, and the SELFCAST modifier is held down, resolves the unit to "player". |
"checkfocuscast" | true, false | If true, and the FOCUSCAST modifier is held down, resolves the unit to "focus". |