Mercurial > wow > reaction
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 71:3d2cef5dc459 | 72:aa88aed52124 |
|---|---|
| 49 f:UnregisterAllEvents() | 49 f:UnregisterAllEvents() |
| 50 f:Hide() | 50 f:Hide() |
| 51 f:SetParent(UIParent) | 51 f:SetParent(UIParent) |
| 52 f:ClearAllPoints() | 52 f:ClearAllPoints() |
| 53 ReAction.UnregisterAllCallbacks(self) | 53 ReAction.UnregisterAllCallbacks(self) |
| 54 if self.statedriver then | |
| 55 UnregisterStateDriver(f, "reaction") | |
| 56 end | |
| 54 self.labelString = nil | 57 self.labelString = nil |
| 55 self.controlFrame = nil | 58 self.controlFrame = nil |
| 56 self.frame = nil | 59 self.frame = nil |
| 57 self.config = nil | 60 self.config = nil |
| 58 end | 61 end |
| 174 -- multi-state functions -- | 177 -- multi-state functions -- |
| 175 function Bar:GetNumPages() | 178 function Bar:GetNumPages() |
| 176 return self.config.nPages or 1 | 179 return self.config.nPages or 1 |
| 177 end | 180 end |
| 178 | 181 |
| 182 -- | |
| 183 -- 'rule' is a rule-string to pass to RegisterStateDriver | |
| 184 -- 'states' is a { ["statename"] = <don't care> } table of all state names | |
| 185 -- 'keybinds' is a { ["statename"] = keybind } table of all keybound states | |
| 186 -- | |
| 187 function Bar:SetStateDriver( rule, states, keybinds ) | |
| 188 local f = self.frame | |
| 189 local kbprefix = "" | |
| 190 do | |
| 191 local tmp = { } | |
| 192 for s, k in pairs(keybinds) do | |
| 193 if k and #k > 0 then -- filter out false table entries | |
| 194 -- if in a keybound state, set the stack to the new state but stay in the keybound state. | |
| 195 -- use $s as a placeholder for the current state, it will be gsub()'d in later | |
| 196 table.insert(tmp,("%s:$s set() %s"):format(s,s)) | |
| 197 end | |
| 198 end | |
| 199 table.insert(tmp,kbprefix) -- to get a trailing ';' if the table is not empty | |
| 200 kbprefix = table.concat(tmp,";") | |
| 201 end | |
| 202 for state in pairs(states) do | |
| 203 -- For all states: if in a keybound state, stay there (with stack manipulation, see above). | |
| 204 -- Otherwise, go to the state | |
| 205 f:SetAttribute(("statemap-reaction-%s"):format(state),("%s%s"):format(kbprefix:gsub("%$s",state),state)) | |
| 206 | |
| 207 local binding = keybinds[state] | |
| 208 self:SetStateKeybind(binding, state) -- set the binding even if nil, to clear it unconditionally | |
| 209 if binding then | |
| 210 -- for key bindings, use the state-stack to toggle between the last state and the keybound state | |
| 211 -- use a different 'virtual state' passed to attribute 'reaction-state' for key bindings, "<state>_binding" | |
| 212 f:SetAttribute(("statemap-reaction-%s_binding"):format(state), ("%s:pop();*:set(%s)"):format(state,state)) | |
| 213 end | |
| 214 end | |
| 215 | |
| 216 if rule and #rule > 0 then | |
| 217 self.stateDriver = true | |
| 218 RegisterStateDriver(f, "reaction", rule) | |
| 219 elseif self.statedriver then | |
| 220 self.statedriver = false | |
| 221 UnregisterStateDriver(f, "reaction") | |
| 222 end | |
| 223 end | |
| 224 | |
| 179 function Bar:SetHideStates(s) | 225 function Bar:SetHideStates(s) |
| 180 for f in pairs(self.buttons) do | 226 for f in pairs(self.buttons) do |
| 181 if f:GetParent() == self.frame then | 227 if f:GetParent() == self.frame then |
| 182 f:SetAttribute("hidestates",s) | 228 f:SetAttribute("hidestates",s) |
| 183 end | 229 end |
| 184 end | 230 end |
| 185 SecureStateHeader_Refresh(self.frame) | 231 SecureStateHeader_Refresh(self.frame) |
| 186 end | 232 end |
| 187 | 233 |
| 188 function Bar:SetStateKeybind(key, state, defaultstate) | 234 function Bar:SetStateKeybind(key, state, defaultstate) |
| 189 -- set a keybind to toggle transitioning unconditionally to a state | 235 -- Lazily create a tiny offscreen button which sends "<state>_binding" values to the |
| 190 -- use a tiny offscreen button to get around making the bar itself a clickable button | 236 -- bar frame's state-reaction attribute, by using an override binding to generate a |
| 237 -- click on the button with a virtual mouse button "state". | |
| 238 -- This gets around making the bar itself a clickable button, which is not desirable | |
| 191 local f = self.statebuttonframe | 239 local f = self.statebuttonframe |
| 192 local off = ("%s_off"):format(state) | |
| 193 if key then | 240 if key then |
| 194 if not f then | 241 if not f then |
| 195 f = CreateFrame("Button",self:GetName().."_statebutton",UIParent,"SecureActionButtonTemplate") | 242 f = CreateFrame("Button",self:GetName().."_statebutton",self.frame,"SecureActionButtonTemplate") |
| 196 f:SetPoint("BOTTOMRIGHT",UIParent,"TOPLEFT") | 243 f:SetPoint("BOTTOMRIGHT",UIParent,"TOPLEFT") |
| 197 f:SetWidth(1) | 244 f:SetWidth(1) |
| 198 f:SetHeight(1) | 245 f:SetHeight(1) |
| 199 f:SetAttribute("attribute-name", "state") | 246 f:SetAttribute("type*","attribute") |
| 200 f:SetAttribute("attribute-frame",self.frame) | 247 f:SetAttribute("attribute-name*","state-reaction") |
| 201 f:SetAttribute("stateheader",self.frame) | 248 f:SetAttribute("attribute-frame*",self.frame) |
| 202 f:Show() | 249 f:Show() |
| 250 f.bindings = { } | |
| 203 self.statebuttonframe = f | 251 self.statebuttonframe = f |
| 204 end | 252 end |
| 205 -- map two virtual buttons to toggle between the state and the default | 253 f:SetAttribute(("attribute-value-%s"):format(state),("%s_binding"):format(state)) |
| 206 f:SetAttribute(("statebutton-%s"):format(state),("%s:%s;%s"):format(state,off,state)) | 254 -- clear the old binding, if any, for this state |
| 207 f:SetAttribute(("type-%s"):format(state),"attribute") | 255 if f.bindings[state] then |
| 208 f:SetAttribute(("type-%s"):format(off),"attribute") | 256 SetOverrideBinding(self.frame, false, f.bindings[state], nil) |
| 209 f:SetAttribute(("attribute-value-%s"):format(state), state) | 257 end |
| 210 f:SetAttribute(("attribute-value-%s"):format(off), defaultstate) | 258 SetOverrideBindingClick(self.frame, false, key, f:GetName(), state) -- the state name is used as the virtual button |
| 211 SetBindingClick(key, f:GetName(), state) | 259 f.bindings[state] = key |
| 212 elseif f then | 260 elseif f then |
| 213 f:SetAttribute(("type-%s"):format(state),ATTRIBUTE_NOOP) | 261 key = f.bindings[state] |
| 214 f:SetAttribute(("type-%s"):format(off),ATTRIBUTE_NOOP) | |
| 215 local action = ("CLICK %s:%s"):format(f:GetName(),state) | |
| 216 key = GetBindingKey(action) | |
| 217 if key then | 262 if key then |
| 218 SetBinding(key,nil) | 263 SetOverrideBinding(self.frame, false, key, nil) |
| 264 f.bindings[state] = nil | |
| 219 end | 265 end |
| 220 end | 266 end |
| 221 end | 267 end |
| 222 | 268 |
| 223 function Bar:SetStatePageMap(state, map) -- map is a { ["statename"] = pagenumber } table | 269 function Bar:SetStatePageMap(state, map) -- map is a { ["statename"] = pagenumber } table |
| 225 local tmp = { } | 271 local tmp = { } |
| 226 for s, p in pairs(map) do | 272 for s, p in pairs(map) do |
| 227 table.insert(tmp, ("%s:page%d"):format(s,p)) | 273 table.insert(tmp, ("%s:page%d"):format(s,p)) |
| 228 end | 274 end |
| 229 local spec = table.concat(tmp,";") | 275 local spec = table.concat(tmp,";") |
| 230 f:SetAttribute("statebutton",spec) | 276 local current = f:GetAttribute("statebutton") |
| 277 if spec ~= f:GetAttribute("statebutton") then | |
| 278 f:SetAttribute("statebutton", spec) | |
| 279 end | |
| 231 SecureStateHeader_Refresh(f) | 280 SecureStateHeader_Refresh(f) |
| 232 end | 281 end |
| 233 | 282 |
| 234 function Bar:SetStateKeybindOverrideMap(states) -- 'states' is an array of state-names that should have keybind overrides enabled | 283 function Bar:SetStateKeybindOverrideMap(states) -- 'states' is an array of state-names that should have keybind overrides enabled |
| 235 local f = self.frame | 284 local f = self.frame |
