Mercurial > wow > reaction
comparison libs/ReBound-1.0/ReBound-1.0.lua @ 12:2735edcf9ab7
Version 0.34
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Wed, 21 Mar 2007 00:13:27 +0000 |
parents | f3a7bfebc283 |
children | 639282f3a0e0 |
comparison
equal
deleted
inserted
replaced
11:88df7235ad8b | 12:2735edcf9ab7 |
---|---|
1 --[[ | 1 --[[ |
2 Name: ReBound-1.0 | 2 Name: ReBound-1.0 |
3 Revision: $Rev: 1 $ | 3 Revision: $Rev: 2 $ |
4 Author: Flick | 4 Author: Flick |
5 Website: | 5 Website: |
6 Documentation: | 6 Documentation: |
7 SVN: | 7 SVN: |
8 Description: Library for point-and-click key binding interfaces | 8 Description: A library to assist with click-binding |
9 License: MIT | 9 License: MIT |
10 Dependencies: AceLibrary, AceEvent-2.0, AceLocale-2.2 | 10 Dependencies: AceLibrary, AceEvent-2.0, AceLocale-2.2, AceOO-2.0 |
11 ]] | 11 ]] |
12 | 12 |
13 | 13 |
14 local version_major, version_minor = "ReBound-1.0", "$Rev: 1 $" | 14 local version_major, version_minor = "ReBound-1.0", "$Rev: 2 $" |
15 | 15 |
16 if not AceLibrary then error(version_major .. " requires AceLibrary.") end | 16 if not AceLibrary then error(version_major .. " requires AceLibrary.") end |
17 if not AceLibrary:IsNewVersion(version_major, version_minor) then return end | 17 if not AceLibrary:IsNewVersion(version_major, version_minor) then return end |
18 if not AceLibrary:HasInstance("AceEvent-2.0") then error(version_major .. " requires AceEvent-2.0.") end | 18 if not AceLibrary:HasInstance("AceEvent-2.0") then error(version_major .. " requires AceEvent-2.0.") end |
19 if not AceLibrary:HasInstance("AceLocale-2.2") then error(version_major .. " requires AceLocale-2.2.") end | 19 if not AceLibrary:HasInstance("AceLocale-2.2") then error(version_major .. " requires AceLocale-2.2.") end |
20 if not AceLibrary:HasInstance("AceOO-2.0") then error(version_major .. " requires AceOO-2.0.") end | |
20 | 21 |
21 local L = AceLibrary("AceLocale-2.2"):new("ReBound") | 22 local L = AceLibrary("AceLocale-2.2"):new("ReBound") |
22 | 23 |
23 local colorGreen = "|cff00ff00" | 24 local colorGreen = "|cff00ff00" |
24 local colorOff = "|r" | 25 local colorOff = "|r" |
25 | 26 |
26 local mouseButtonConvert = { | 27 local mouseButtonConvert = { |
28 LeftButton = "BUTTON1", | |
29 RightButton = "BUTTON2", | |
27 MiddleButton = "BUTTON3", | 30 MiddleButton = "BUTTON3", |
28 Button4 = "BUTTON4", | 31 Button4 = "BUTTON4", |
29 Button5 = "BUTTON5" | 32 Button5 = "BUTTON5" |
30 } | 33 } |
34 | |
35 --local BINDING_PENDING = { } -- a constant | |
31 | 36 |
32 -- localization | 37 -- localization |
33 L:RegisterTranslations( "enUS", function() | 38 L:RegisterTranslations( "enUS", function() |
34 return { | 39 return { |
35 ["none"] = true, | 40 ["none"] = true, |
36 ["Right-click"] = true, | 41 ["Right-click"] = true, |
42 ["Right Click"] = true, | |
37 ["Click to select for binding"] = true, | 43 ["Click to select for binding"] = true, |
38 ["Shift-click to clear binding"] = true, | 44 ["Shift-click to clear binding"] = true, |
39 ["Press a key to assign binding"] = true, | 45 ["Press a key to assign binding"] = true, |
40 ["is now unbound"] = true, | 46 ["is now unbound"] = true, |
41 } | 47 } |
42 end ) | 48 end ) |
43 | 49 |
44 | 50 |
45 | 51 local ReBound = AceLibrary("AceOO-2.0").Class("AceEvent-2.0") |
46 | 52 |
47 local ReBound = { } | 53 --[[ |
54 ReBound publishes the following events: | |
55 | |
56 -- temporary bindings (prior to SaveBindings() being called) | |
57 REBOUND_BIND_TEMP (id, key, targetFrameName, mouseButton) | |
58 REBOUND_UNBIND_TEMP (id, key) | |
59 | |
60 -- permanent bindings (fired all at once when SaveBindings() is called) | |
61 REBOUND_BIND (id, key, targetFrameName, mouseButton) | |
62 REBOUND_UNBIND (id, key) | |
63 | |
64 These events are published in response to click actions ONLY. This means | |
65 that if a key is unbound from a click-binding frame, and bound to some | |
66 other action, then REBOUND_UNBIND(id,key) will be fired. | |
67 ]] | |
68 | |
69 | |
70 --[[ | |
71 Calls to new() which share ids will return an existing object with that id, similar | |
72 to AceLocale-2.2. | |
73 ]] | |
74 local super_new = ReBound.new | |
75 function ReBound:new( id ) | |
76 self.instances = self.instances or { } | |
77 if self.instances[id] then | |
78 return self.instances[id] | |
79 else | |
80 local i = super_new(self,id) | |
81 self.instances[id] = i | |
82 return i | |
83 end | |
84 end | |
85 | |
86 | |
87 --[[ | |
88 Class object constructor | |
89 | |
90 arguments: | |
91 id : the ID that will be provided in events. This can be absolutely | |
92 anything, but a string is recommended. | |
93 ]] | |
94 local super_init = ReBound.prototype.init | |
95 function ReBound.prototype:init( id ) | |
96 super_init(self) | |
97 | |
98 self.id = id | |
99 self.frames = { } | |
100 self.pending = { } | |
101 self.bindings = { } | |
102 end | |
103 | |
104 | |
48 | 105 |
49 | 106 |
50 --[[ | 107 --[[ |
51 Arguments: | 108 Arguments: |
52 key: A string representation of a key, suitable for passing to SetBinding. | 109 key: A string representation of a key, suitable for passing to SetBinding. |
53 target: The frame with an OnClick handler to attach a click-binding to | 110 target: The frame with an OnClick handler to which the click-binding should be attached |
54 [button]: The mouse button to emulate. Default is "LeftButton". | 111 [button]: The mouse button to emulate. Default is "LeftButton". |
55 | 112 |
56 Returns: | 113 Returns: |
57 nothing. | 114 nothing. |
58 | 115 |
59 Notes: | 116 Notes: |
60 This does not save the bindings. | 117 This does not save the bindings. |
61 ]] | 118 ]] |
62 function ReBound:SetBinding( key, target, button ) | 119 function ReBound.prototype:SetBinding( key, target, button ) |
63 if not key then self:error("ReBound:SetBinding() requires a key argument.") end | 120 if not key then error("ReBound:SetBinding() requires a key argument.") end |
64 if not target then self:error("ReBound:SetBinding() requires a binding target argument") end | 121 if not target then error("ReBound:SetBinding() requires a binding target argument") end |
65 button = button or "LeftButton" | 122 button = button or "LeftButton" |
66 | 123 |
67 -- prevent setting a binding that's already set | 124 -- prevent setting a binding that's already set |
68 local current = { self:GetBinding(target,button) } | 125 local current = { self:GetBinding(target,button) } |
69 for _, b in pairs(current) do | 126 for _, b in pairs(current) do |
80 self:ClearBinding( nil, target, button, true ) | 137 self:ClearBinding( nil, target, button, true ) |
81 | 138 |
82 -- set the new binding | 139 -- set the new binding |
83 SetBindingClick(key, target:GetName(), button) | 140 SetBindingClick(key, target:GetName(), button) |
84 | 141 |
85 -- notify listeners, e.g. for storing the setting | 142 -- store the temporary binding as "pending" for later notification |
86 self.event:TriggerEvent("REBOUND_BIND", key, target:GetName(), button) | 143 table.insert(self.pending, key) |
144 | |
145 -- notify listeners, e.g. for displaying the setting | |
146 self:TriggerEvent("REBOUND_BIND_TEMP", self.id, key, target:GetName(), button) | |
87 end | 147 end |
88 | 148 |
89 | 149 |
90 --[[ | 150 --[[ |
91 Arguments: | 151 Arguments: |
101 If key is provided, then the binding for that key is cleared. If key is not provided and target is provided, then | 161 If key is provided, then the binding for that key is cleared. If key is not provided and target is provided, then |
102 all the bindings attached to the click-binding for that target are cleared. | 162 all the bindings attached to the click-binding for that target are cleared. |
103 | 163 |
104 This does NOT save the bindings. Call SaveBindings() to commit the bindings to disk. | 164 This does NOT save the bindings. Call SaveBindings() to commit the bindings to disk. |
105 ]] | 165 ]] |
106 function ReBound:ClearBinding( key, target, button, silent ) | 166 function ReBound.prototype:ClearBinding( key, target, button, silent ) |
107 if not target and not key then self:error("ReBound:ClearBinding() requires a key or click-binding target argument") end | 167 if not target and not key then error("ReBound:ClearBinding() requires a key or click-binding target argument") end |
108 button = button or "LeftButton" | 168 button = button or "LeftButton" |
109 | 169 |
110 local keys = key and { key } or { self:GetBinding(target,button) } | 170 local keys = key and { key } or { self:GetBinding(target,button) } |
111 for _, k in ipairs(keys) do | 171 for _, k in ipairs(keys) do |
112 -- Print a notification message | 172 -- Print a notification message |
118 -- make click-bindings look prettier | 178 -- make click-bindings look prettier |
119 local f, b = name:match("CLICK (.+)\:(.+)") | 179 local f, b = name:match("CLICK (.+)\:(.+)") |
120 if f then | 180 if f then |
121 name = f | 181 name = f |
122 if b ~= "LeftButton" then | 182 if b ~= "LeftButton" then |
123 if b == "RightButton" then b = "Right Click" end | 183 if b == "RightButton" then b = L["Right Click"] end |
124 name = f .."-"..b | 184 name = f .."-"..b |
125 end | 185 end |
126 end | 186 end |
127 if name and #name > 0 then | 187 if name and #name > 0 then |
128 UIErrorsFrame:AddMessage(name.." ("..colorGreen..keyTxt..colorOff..") "..L["is now unbound"].."!") | 188 UIErrorsFrame:AddMessage(name.." ("..colorGreen..keyTxt..colorOff..") "..L["is now unbound"].."!") |
129 end | 189 end |
130 end | 190 end |
131 end | 191 end |
132 SetBinding(k,nil) | 192 SetBinding(k,nil) |
133 self.event:TriggerEvent("REBOUND_UNBIND", k) | 193 table.insert(self.pending,k) |
134 end | 194 self:TriggerEvent("REBOUND_UNBIND_TEMP", self.id, k) |
135 end | 195 end |
136 | 196 end |
137 | 197 |
138 --[[ | 198 |
139 Gets the keys bound to clicking a frame. | 199 --[[ |
200 Gets the keys currently click-bound to a frame. | |
140 | 201 |
141 Arguments: | 202 Arguments: |
142 target: target frame to query | 203 target: target frame to query |
143 [button]: mouse button to emulate ("LeftButton", "RightButton") | 204 [button]: mouse button to emulate ("LeftButton", "RightButton") |
144 | 205 |
145 Returns: | 206 Returns: |
146 key1, key2, key3, etc, as strings. | 207 key1, key2, key3, etc, as strings. |
147 ]] | 208 ]] |
148 function ReBound:GetBinding( target, button ) | 209 function ReBound.prototype:GetBinding( target, button ) |
149 if not target then self:error("ReBound:GetBinding() requires a target frame argument") end | 210 if not target then error("ReBound:GetBinding() requires a target frame argument") end |
150 button = button or "LeftButton" | 211 button = button or "LeftButton" |
151 return GetBindingKey("CLICK "..target:GetName()..":"..button) | 212 return GetBindingKey("CLICK "..target:GetName()..":"..button) |
152 end | 213 end |
153 | 214 |
154 | 215 |
155 --[[ | 216 --[[ |
217 Publishes permanent binding notification events. | |
218 ]] | |
219 local function PublishBindings(self) | |
220 for _, key in ipairs(self.pending) do | |
221 local action = GetBindingAction(key) | |
222 local frame, button | |
223 if action then | |
224 frame, button = action:match("CLICK (.+)\:(.+)") | |
225 end | |
226 if frame == nil then | |
227 self:TriggerEvent("REBOUND_UNBIND", self.id, key) | |
228 else | |
229 self:TriggerEvent("REBOUND_BIND", self.id, key, frame, button) | |
230 end | |
231 end | |
232 self.pending = { } | |
233 end | |
234 | |
235 | |
236 --[[ | |
237 Saves the bindings using the current scheme. Also publishes events indicating that the | |
238 bindings have been saved/cleared permanently. | |
239 ]] | |
240 function ReBound.prototype:SaveBindings() | |
241 SaveBindings(GetCurrentBindingSet()) -- will trigger an UPDATE_BINDINGS event. | |
242 PublishBindings(self) | |
243 end | |
244 | |
245 | |
246 --[[ | |
247 Reverts the bindings to the ones previously saved. Also publishes events indicating that the | |
248 bindings have been reverted. | |
249 ]] | |
250 function ReBound.prototype:RevertBindings() | |
251 LoadBindings(GetCurrentBindingSet()) -- should trigger an UPDATE_BINDINGS event. | |
252 PublishBindings(self) | |
253 end | |
254 | |
255 | |
256 --[[ | |
257 Clears all bindings associated with registered frames. This is useful, for example, when switching profiles | |
258 and the keybinding data is stored in the profile. | |
259 ]] | |
260 function ReBound.prototype:ClearRegisteredBindings() | |
261 for f, _ in pairs(self.frames) do | |
262 self:ClearBinding(nil,f,"LeftButton",true) | |
263 self:ClearBinding(nil,f,"RightButton",true) | |
264 end | |
265 end | |
266 | |
267 | |
268 --[[ | |
156 Registers a target frame by creating a click-binding frame and putting that frame in the list of | 269 Registers a target frame by creating a click-binding frame and putting that frame in the list of |
157 registered frames, which can then be all shown/hidden as one unit. | 270 registered frames, which can then be all shown/hidden as one unit. |
158 | 271 |
159 Arguments: | 272 Arguments: |
160 target = the frame whose OnClick handler should be the target of keybinding | 273 target = the frame whose OnClick handler should be the target of keybinding |
161 | 274 |
162 Returns: | 275 Returns: |
163 A clickbinder frame. | 276 A clickbinder frame. |
164 ]] | 277 ]] |
165 function ReBound:Register( target ) | 278 function ReBound.prototype:Register( target ) |
166 local f = self:CreateClickBindingFrame(target) | 279 local f = self:CreateClickBindingFrame(target) |
167 self.frames[target] = f | 280 self.frames[target] = f |
168 return f | 281 return f |
169 end | 282 end |
170 | 283 |
171 | 284 |
172 --[[ | 285 --[[ |
173 Unregisters a target frame by removing it from the internal list. Does nothing to the clickbinding frame. | 286 Unregisters a target frame by removing it from the internal list. Does nothing to the clickbinding frame. |
174 | 287 |
175 Arguments: | 288 Arguments: |
176 target = the frame whose OnClick handler should no longer be the target of keybinding | 289 target = the frame whose OnClick handler should no longer be managed. do NOT pass the clickbinding frame. |
177 | 290 |
178 Returns: | 291 Returns: |
179 nothing. | 292 nothing. |
180 ]] | 293 ]] |
181 function ReBound:Unregister( target ) | 294 function ReBound.prototype:Unregister( target ) |
182 self.frames[target] = nil | 295 self.frames[target] = nil |
183 end | 296 end |
184 | 297 |
185 | 298 |
186 --[[ | 299 --[[ |
300 Unregisters all registered frames. | |
301 ]] | |
302 function ReBound.prototype:UnregisterAll() | |
303 self.frames = { } | |
304 end | |
305 | |
306 | |
307 | |
308 --[[ | |
187 Shows all the registered click binding frames. | 309 Shows all the registered click binding frames. |
188 ]] | 310 ]] |
189 function ReBound:ShowAll() | 311 function ReBound.prototype:ShowFrames() |
190 if InCombatLockdown() then | 312 if InCombatLockdown() then |
191 -- can't set bindings while in combat, so don't bother showing them | 313 -- can't set bindings while in combat, so don't bother showing them |
192 UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT) | 314 UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT) |
193 else | 315 else |
194 for _, f in pairs(self.frames) do | 316 for _, f in pairs(self.frames) do |
199 | 321 |
200 | 322 |
201 --[[ | 323 --[[ |
202 Hides all the registered click binding frames. | 324 Hides all the registered click binding frames. |
203 ]] | 325 ]] |
204 function ReBound:HideAll() | 326 function ReBound.prototype:HideFrames() |
327 -- because these frames aren't protected, there's no restriction | |
328 -- on hiding them while in combat. | |
205 for _, f in pairs(self.frames) do | 329 for _, f in pairs(self.frames) do |
206 f:Hide() | 330 f:Hide() |
207 end | 331 end |
208 end | 332 end |
209 | 333 |
301 target - the frame whose OnClick handler should be the target of keybinding | 425 target - the frame whose OnClick handler should be the target of keybinding |
302 | 426 |
303 Returns: | 427 Returns: |
304 A clickbinder frame. | 428 A clickbinder frame. |
305 ]] | 429 ]] |
306 function ReBound:CreateClickBindingFrame( target ) | 430 function ReBound.prototype:CreateClickBindingFrame( target ) |
307 local f = CreateFrame("Button", nil, target) | 431 local f = CreateFrame("Button", nil, target) |
308 f.ReBound = self | 432 f.ReBound = self |
309 f:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square") | 433 f:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square") |
310 f:SetToplevel(1) | 434 f:SetToplevel(1) |
311 f:SetFrameStrata("DIALOG") | 435 f:SetFrameStrata("DIALOG") |
322 | 446 |
323 | 447 |
324 -- library setup | 448 -- library setup |
325 | 449 |
326 local function activate( self, oldLib, oldDeactivate ) | 450 local function activate( self, oldLib, oldDeactivate ) |
327 -- set initial values | 451 -- copy the list of active instances |
328 self.mode = oldLib and oldLib.mode or "char" | 452 self.instances = { } |
329 self.frames = { } | 453 if oldLib and oldLib.instances then |
330 | 454 for k,v in pairs(oldLib.instances) do |
331 self.event = AceLibrary("AceOO-2.0").Class("AceEvent-2.0"):new() | 455 self.instances[k] = v |
332 self.event:RegisterEvent("PLAYER_REGEN_DISABLED", function() self:HideAll() end) | 456 end |
333 | 457 end |
458 | |
334 if oldDeactivate then | 459 if oldDeactivate then |
335 oldDeactivate(oldLib) | 460 oldDeactivate(oldLib) |
336 end | 461 end |
337 end | 462 end |
338 | 463 |
339 local function deactivate( self ) | 464 AceLibrary:Register(ReBound, version_major, version_minor, activate) |
340 self.event:UnregisterEvent("PLAYER_REGEN_DISABLED") | |
341 end | |
342 | |
343 AceLibrary:Register(ReBound, version_major, version_minor, activate, deactivate) | |
344 ReBound = nil | 465 ReBound = nil |