Mercurial > wow > reaction
diff Bar.lua @ 72:aa88aed52124
Fixed bugs with state keybinds.
Simplified state driver API
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Thu, 05 Jun 2008 18:34:36 +0000 |
parents | 3d2cef5dc459 |
children | dd01feae0d89 |
line wrap: on
line diff
--- a/Bar.lua Wed Jun 04 21:46:51 2008 +0000 +++ b/Bar.lua Thu Jun 05 18:34:36 2008 +0000 @@ -51,6 +51,9 @@ f:SetParent(UIParent) f:ClearAllPoints() ReAction.UnregisterAllCallbacks(self) + if self.statedriver then + UnregisterStateDriver(f, "reaction") + end self.labelString = nil self.controlFrame = nil self.frame = nil @@ -176,6 +179,49 @@ return self.config.nPages or 1 end + -- + -- 'rule' is a rule-string to pass to RegisterStateDriver + -- 'states' is a { ["statename"] = <don't care> } table of all state names + -- 'keybinds' is a { ["statename"] = keybind } table of all keybound states + -- +function Bar:SetStateDriver( rule, states, keybinds ) + local f = self.frame + local kbprefix = "" + do + local tmp = { } + for s, k in pairs(keybinds) do + if k and #k > 0 then -- filter out false table entries + -- if in a keybound state, set the stack to the new state but stay in the keybound state. + -- use $s as a placeholder for the current state, it will be gsub()'d in later + table.insert(tmp,("%s:$s set() %s"):format(s,s)) + end + end + table.insert(tmp,kbprefix) -- to get a trailing ';' if the table is not empty + kbprefix = table.concat(tmp,";") + end + for state in pairs(states) do + -- For all states: if in a keybound state, stay there (with stack manipulation, see above). + -- Otherwise, go to the state + f:SetAttribute(("statemap-reaction-%s"):format(state),("%s%s"):format(kbprefix:gsub("%$s",state),state)) + + local binding = keybinds[state] + self:SetStateKeybind(binding, state) -- set the binding even if nil, to clear it unconditionally + if binding then + -- for key bindings, use the state-stack to toggle between the last state and the keybound state + -- use a different 'virtual state' passed to attribute 'reaction-state' for key bindings, "<state>_binding" + f:SetAttribute(("statemap-reaction-%s_binding"):format(state), ("%s:pop();*:set(%s)"):format(state,state)) + end + end + + if rule and #rule > 0 then + self.stateDriver = true + RegisterStateDriver(f, "reaction", rule) + elseif self.statedriver then + self.statedriver = false + UnregisterStateDriver(f, "reaction") + end +end + function Bar:SetHideStates(s) for f in pairs(self.buttons) do if f:GetParent() == self.frame then @@ -186,36 +232,36 @@ end function Bar:SetStateKeybind(key, state, defaultstate) - -- set a keybind to toggle transitioning unconditionally to a state - -- use a tiny offscreen button to get around making the bar itself a clickable button + -- Lazily create a tiny offscreen button which sends "<state>_binding" values to the + -- bar frame's state-reaction attribute, by using an override binding to generate a + -- click on the button with a virtual mouse button "state". + -- This gets around making the bar itself a clickable button, which is not desirable local f = self.statebuttonframe - local off = ("%s_off"):format(state) if key then if not f then - f = CreateFrame("Button",self:GetName().."_statebutton",UIParent,"SecureActionButtonTemplate") + f = CreateFrame("Button",self:GetName().."_statebutton",self.frame,"SecureActionButtonTemplate") f:SetPoint("BOTTOMRIGHT",UIParent,"TOPLEFT") f:SetWidth(1) f:SetHeight(1) - f:SetAttribute("attribute-name", "state") - f:SetAttribute("attribute-frame",self.frame) - f:SetAttribute("stateheader",self.frame) + f:SetAttribute("type*","attribute") + f:SetAttribute("attribute-name*","state-reaction") + f:SetAttribute("attribute-frame*",self.frame) f:Show() + f.bindings = { } self.statebuttonframe = f end - -- map two virtual buttons to toggle between the state and the default - f:SetAttribute(("statebutton-%s"):format(state),("%s:%s;%s"):format(state,off,state)) - f:SetAttribute(("type-%s"):format(state),"attribute") - f:SetAttribute(("type-%s"):format(off),"attribute") - f:SetAttribute(("attribute-value-%s"):format(state), state) - f:SetAttribute(("attribute-value-%s"):format(off), defaultstate) - SetBindingClick(key, f:GetName(), state) + f:SetAttribute(("attribute-value-%s"):format(state),("%s_binding"):format(state)) + -- clear the old binding, if any, for this state + if f.bindings[state] then + SetOverrideBinding(self.frame, false, f.bindings[state], nil) + end + SetOverrideBindingClick(self.frame, false, key, f:GetName(), state) -- the state name is used as the virtual button + f.bindings[state] = key elseif f then - f:SetAttribute(("type-%s"):format(state),ATTRIBUTE_NOOP) - f:SetAttribute(("type-%s"):format(off),ATTRIBUTE_NOOP) - local action = ("CLICK %s:%s"):format(f:GetName(),state) - key = GetBindingKey(action) + key = f.bindings[state] if key then - SetBinding(key,nil) + SetOverrideBinding(self.frame, false, key, nil) + f.bindings[state] = nil end end end @@ -227,7 +273,10 @@ table.insert(tmp, ("%s:page%d"):format(s,p)) end local spec = table.concat(tmp,";") - f:SetAttribute("statebutton",spec) + local current = f:GetAttribute("statebutton") + if spec ~= f:GetAttribute("statebutton") then + f:SetAttribute("statebutton", spec) + end SecureStateHeader_Refresh(f) end