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 |