flickerstreak@10
|
1 --[[
|
flickerstreak@10
|
2 Name: ReBound-1.0
|
flickerstreak@17
|
3 Revision: $Rev: 3 $
|
flickerstreak@10
|
4 Author: Flick
|
flickerstreak@10
|
5 Website:
|
flickerstreak@10
|
6 Documentation:
|
flickerstreak@10
|
7 SVN:
|
flickerstreak@12
|
8 Description: A library to assist with click-binding
|
flickerstreak@10
|
9 License: MIT
|
flickerstreak@17
|
10 Dependencies: AceLibrary, AceEvent-2.0, AceLocale-2.2, AceOO-2.0, AceConsole-2.0
|
flickerstreak@10
|
11 ]]
|
flickerstreak@10
|
12
|
flickerstreak@10
|
13
|
flickerstreak@17
|
14 local version_major, version_minor = "ReBound-1.0", "$Rev: 3 $"
|
flickerstreak@10
|
15
|
flickerstreak@10
|
16 if not AceLibrary then error(version_major .. " requires AceLibrary.") end
|
flickerstreak@10
|
17 if not AceLibrary:IsNewVersion(version_major, version_minor) then return end
|
flickerstreak@17
|
18 for _, lib in pairs({ "AceEvent-2.0", "AceLocale-2.2", "AceOO-2.0", "AceConsole-2.0" }) do
|
flickerstreak@17
|
19 if not AceLibrary:HasInstance(lib) then error(version_major .. " requires "..lib) end
|
flickerstreak@17
|
20 end
|
flickerstreak@10
|
21
|
flickerstreak@10
|
22 local L = AceLibrary("AceLocale-2.2"):new("ReBound")
|
flickerstreak@10
|
23
|
flickerstreak@17
|
24 -- localization
|
flickerstreak@17
|
25 L:RegisterTranslations( "enUS", function()
|
flickerstreak@17
|
26 return {
|
flickerstreak@17
|
27 ["none"] = true,
|
flickerstreak@17
|
28 ["Click"] = true,
|
flickerstreak@17
|
29 ["Right-click"] = true,
|
flickerstreak@17
|
30 ["Shift-click"] = true,
|
flickerstreak@17
|
31 ["Shift-right-click"] = true,
|
flickerstreak@17
|
32 ["Right Click"] = true,
|
flickerstreak@17
|
33 ["to select for binding"] = true,
|
flickerstreak@17
|
34 ["to select for alternate (right-click) binding"] = true,
|
flickerstreak@17
|
35 ["to clear binding"] = true,
|
flickerstreak@17
|
36 ["to clear alternate (right-click) binding"] = true,
|
flickerstreak@17
|
37 ["Press a key to assign binding"] = true,
|
flickerstreak@17
|
38 ["is now unbound"] = true,
|
flickerstreak@17
|
39 }
|
flickerstreak@17
|
40 end )
|
flickerstreak@17
|
41
|
flickerstreak@17
|
42
|
flickerstreak@17
|
43
|
flickerstreak@17
|
44 local kbValidate = AceLibrary("AceConsole-2.0").keybindingValidateFunc
|
flickerstreak@17
|
45
|
flickerstreak@10
|
46 local colorGreen = "|cff00ff00"
|
flickerstreak@17
|
47 local colorOrange = "|cffffcc00"
|
flickerstreak@10
|
48 local colorOff = "|r"
|
flickerstreak@10
|
49
|
flickerstreak@10
|
50 local mouseButtonConvert = {
|
flickerstreak@12
|
51 LeftButton = "BUTTON1",
|
flickerstreak@12
|
52 RightButton = "BUTTON2",
|
flickerstreak@10
|
53 MiddleButton = "BUTTON3",
|
flickerstreak@10
|
54 Button4 = "BUTTON4",
|
flickerstreak@10
|
55 Button5 = "BUTTON5"
|
flickerstreak@10
|
56 }
|
flickerstreak@10
|
57
|
flickerstreak@17
|
58 -- TODO: localize
|
flickerstreak@17
|
59 local keybindAbbreviations = {
|
flickerstreak@17
|
60 [KEY_BACKSPACE] = "BkSp",
|
flickerstreak@17
|
61 [KEY_BUTTON3] = "M-3",
|
flickerstreak@17
|
62 [KEY_BUTTON4] = "M-4",
|
flickerstreak@17
|
63 [KEY_BUTTON5] = "M-5",
|
flickerstreak@17
|
64 [KEY_DOWN] = "Down",
|
flickerstreak@17
|
65 [KEY_ESCAPE] = "Esc",
|
flickerstreak@17
|
66 [KEY_INSERT] = "Ins",
|
flickerstreak@17
|
67 [KEY_LEFT] = "Left",
|
flickerstreak@17
|
68 [KEY_MOUSEWHEELDOWN] = "M-Down",
|
flickerstreak@17
|
69 [KEY_MOUSEWHEELUP] = "M-Up",
|
flickerstreak@17
|
70 [KEY_NUMLOCK] = "NumLk",
|
flickerstreak@17
|
71 [KEY_NUMPAD0] = "Np0",
|
flickerstreak@17
|
72 [KEY_NUMPAD1] = "Np1",
|
flickerstreak@17
|
73 [KEY_NUMPAD2] = "Np2",
|
flickerstreak@17
|
74 [KEY_NUMPAD3] = "Np3",
|
flickerstreak@17
|
75 [KEY_NUMPAD4] = "Np4",
|
flickerstreak@17
|
76 [KEY_NUMPAD5] = "Np5",
|
flickerstreak@17
|
77 [KEY_NUMPAD6] = "Np6",
|
flickerstreak@17
|
78 [KEY_NUMPAD7] = "Np7",
|
flickerstreak@17
|
79 [KEY_NUMPAD8] = "Np8",
|
flickerstreak@17
|
80 [KEY_NUMPAD9] = "Np9",
|
flickerstreak@17
|
81 [KEY_NUMPADDECIMAL] = "Np.",
|
flickerstreak@17
|
82 [KEY_NUMPADDIVIDE] = "Np/",
|
flickerstreak@17
|
83 [KEY_NUMPADMINUS] = "Np-",
|
flickerstreak@17
|
84 [KEY_NUMPADMULTIPLY] = "Np*",
|
flickerstreak@17
|
85 [KEY_NUMPADPLUS] = "Np+",
|
flickerstreak@17
|
86 [KEY_PAGEDOWN] = "PgDn",
|
flickerstreak@17
|
87 [KEY_PAGEUP] = "PgUp",
|
flickerstreak@17
|
88 [KEY_PRINTSCREEN] = "PrScr",
|
flickerstreak@17
|
89 [KEY_RIGHT] = "Right",
|
flickerstreak@17
|
90 [KEY_SCROLLLOCK] = "ScrLk",
|
flickerstreak@17
|
91 [KEY_SPACE] = "Sp",
|
flickerstreak@17
|
92 [KEY_UP] = "Up",
|
flickerstreak@17
|
93 }
|
flickerstreak@10
|
94
|
flickerstreak@10
|
95
|
flickerstreak@12
|
96 local ReBound = AceLibrary("AceOO-2.0").Class("AceEvent-2.0")
|
flickerstreak@10
|
97
|
flickerstreak@12
|
98 --[[
|
flickerstreak@12
|
99 ReBound publishes the following events:
|
flickerstreak@10
|
100
|
flickerstreak@12
|
101 -- temporary bindings (prior to SaveBindings() being called)
|
flickerstreak@12
|
102 REBOUND_BIND_TEMP (id, key, targetFrameName, mouseButton)
|
flickerstreak@12
|
103 REBOUND_UNBIND_TEMP (id, key)
|
flickerstreak@12
|
104
|
flickerstreak@12
|
105 -- permanent bindings (fired all at once when SaveBindings() is called)
|
flickerstreak@12
|
106 REBOUND_BIND (id, key, targetFrameName, mouseButton)
|
flickerstreak@12
|
107 REBOUND_UNBIND (id, key)
|
flickerstreak@12
|
108
|
flickerstreak@12
|
109 These events are published in response to click actions ONLY. This means
|
flickerstreak@12
|
110 that if a key is unbound from a click-binding frame, and bound to some
|
flickerstreak@12
|
111 other action, then REBOUND_UNBIND(id,key) will be fired.
|
flickerstreak@12
|
112 ]]
|
flickerstreak@12
|
113
|
flickerstreak@12
|
114
|
flickerstreak@12
|
115 --[[
|
flickerstreak@12
|
116 Calls to new() which share ids will return an existing object with that id, similar
|
flickerstreak@12
|
117 to AceLocale-2.2.
|
flickerstreak@12
|
118 ]]
|
flickerstreak@17
|
119 ReBound.instances = { }
|
flickerstreak@12
|
120 local super_new = ReBound.new
|
flickerstreak@12
|
121 function ReBound:new( id )
|
flickerstreak@17
|
122 local instances = self.instances
|
flickerstreak@17
|
123 instances[id] = instances[id] or super_new(self,id)
|
flickerstreak@17
|
124 return instances[id]
|
flickerstreak@12
|
125 end
|
flickerstreak@12
|
126
|
flickerstreak@12
|
127
|
flickerstreak@12
|
128 --[[
|
flickerstreak@12
|
129 Class object constructor
|
flickerstreak@12
|
130
|
flickerstreak@12
|
131 arguments:
|
flickerstreak@12
|
132 id : the ID that will be provided in events. This can be absolutely
|
flickerstreak@12
|
133 anything, but a string is recommended.
|
flickerstreak@12
|
134 ]]
|
flickerstreak@17
|
135 local super_init = ReBound.super.prototype.init
|
flickerstreak@12
|
136 function ReBound.prototype:init( id )
|
flickerstreak@12
|
137 super_init(self)
|
flickerstreak@12
|
138
|
flickerstreak@12
|
139 self.id = id
|
flickerstreak@12
|
140 self.frames = { }
|
flickerstreak@12
|
141 self.pending = { }
|
flickerstreak@12
|
142 self.bindings = { }
|
flickerstreak@12
|
143 end
|
flickerstreak@12
|
144
|
flickerstreak@12
|
145
|
flickerstreak@10
|
146
|
flickerstreak@10
|
147
|
flickerstreak@10
|
148 --[[
|
flickerstreak@10
|
149 Arguments:
|
flickerstreak@10
|
150 key: A string representation of a key, suitable for passing to SetBinding.
|
flickerstreak@12
|
151 target: The frame with an OnClick handler to which the click-binding should be attached
|
flickerstreak@10
|
152 [button]: The mouse button to emulate. Default is "LeftButton".
|
flickerstreak@17
|
153 [silent]: boolean - whether to suppress messages about keys being unbound.
|
flickerstreak@10
|
154
|
flickerstreak@10
|
155 Returns:
|
flickerstreak@10
|
156 nothing.
|
flickerstreak@10
|
157
|
flickerstreak@10
|
158 Notes:
|
flickerstreak@10
|
159 This does not save the bindings.
|
flickerstreak@10
|
160 ]]
|
flickerstreak@12
|
161 function ReBound.prototype:SetBinding( key, target, button )
|
flickerstreak@12
|
162 if not key then error("ReBound:SetBinding() requires a key argument.") end
|
flickerstreak@12
|
163 if not target then error("ReBound:SetBinding() requires a binding target argument") end
|
flickerstreak@17
|
164 if key and not kbValidate(key) then error("ReBound:SetBinding(): invalid key code "..tostring(key)) end
|
flickerstreak@17
|
165
|
flickerstreak@10
|
166 button = button or "LeftButton"
|
flickerstreak@10
|
167
|
flickerstreak@10
|
168 -- prevent setting a binding that's already set
|
flickerstreak@10
|
169 local current = { self:GetBinding(target,button) }
|
flickerstreak@10
|
170 for _, b in pairs(current) do
|
flickerstreak@10
|
171 if b == key then
|
flickerstreak@10
|
172 return
|
flickerstreak@10
|
173 end
|
flickerstreak@10
|
174 end
|
flickerstreak@10
|
175
|
flickerstreak@10
|
176 -- clear the old binding for the key. This isn't strictly necessary, but it allows us to collect
|
flickerstreak@10
|
177 -- notification of the unbinding in one place (ClearBinding).
|
flickerstreak@17
|
178 self:ClearBinding( key, nil, nil, silent )
|
flickerstreak@10
|
179
|
flickerstreak@10
|
180 -- clear the old binding for the target and button (silently)
|
flickerstreak@10
|
181 self:ClearBinding( nil, target, button, true )
|
flickerstreak@10
|
182
|
flickerstreak@10
|
183 -- set the new binding
|
flickerstreak@10
|
184 SetBindingClick(key, target:GetName(), button)
|
flickerstreak@10
|
185
|
flickerstreak@12
|
186 -- store the temporary binding as "pending" for later notification
|
flickerstreak@12
|
187 table.insert(self.pending, key)
|
flickerstreak@12
|
188
|
flickerstreak@12
|
189 -- notify listeners, e.g. for displaying the setting
|
flickerstreak@12
|
190 self:TriggerEvent("REBOUND_BIND_TEMP", self.id, key, target:GetName(), button)
|
flickerstreak@10
|
191 end
|
flickerstreak@10
|
192
|
flickerstreak@10
|
193
|
flickerstreak@10
|
194 --[[
|
flickerstreak@10
|
195 Arguments:
|
flickerstreak@10
|
196 [key]: A string representation of a key, suitable for passing to SetBinding. This can be nil if target is specified.
|
flickerstreak@10
|
197 [target]: The frame with a click keybinding to search for a key.
|
flickerstreak@10
|
198 [button]: The mouse button to emulate. Default is "LeftButton". Only used with [target].
|
flickerstreak@10
|
199 [silent]: if true, omits printout.
|
flickerstreak@10
|
200
|
flickerstreak@10
|
201 Returns:
|
flickerstreak@10
|
202 nothing.
|
flickerstreak@10
|
203
|
flickerstreak@10
|
204 Notes:
|
flickerstreak@10
|
205 If key is provided, then the binding for that key is cleared. If key is not provided and target is provided, then
|
flickerstreak@10
|
206 all the bindings attached to the click-binding for that target are cleared.
|
flickerstreak@10
|
207
|
flickerstreak@10
|
208 This does NOT save the bindings. Call SaveBindings() to commit the bindings to disk.
|
flickerstreak@10
|
209 ]]
|
flickerstreak@12
|
210 function ReBound.prototype:ClearBinding( key, target, button, silent )
|
flickerstreak@12
|
211 if not target and not key then error("ReBound:ClearBinding() requires a key or click-binding target argument") end
|
flickerstreak@10
|
212 button = button or "LeftButton"
|
flickerstreak@10
|
213
|
flickerstreak@10
|
214 local keys = key and { key } or { self:GetBinding(target,button) }
|
flickerstreak@10
|
215 for _, k in ipairs(keys) do
|
flickerstreak@10
|
216 -- Print a notification message
|
flickerstreak@10
|
217 if k and not silent then
|
flickerstreak@10
|
218 local action = GetBindingAction(k)
|
flickerstreak@10
|
219 if action then
|
flickerstreak@10
|
220 local name = GetBindingText(action,"BINDING_NAME_")
|
flickerstreak@10
|
221 local keyTxt = GetBindingText(k,"KEY_")
|
flickerstreak@10
|
222 -- make click-bindings look prettier
|
flickerstreak@10
|
223 local f, b = name:match("CLICK (.+)\:(.+)")
|
flickerstreak@10
|
224 if f then
|
flickerstreak@10
|
225 name = f
|
flickerstreak@10
|
226 if b ~= "LeftButton" then
|
flickerstreak@12
|
227 if b == "RightButton" then b = L["Right Click"] end
|
flickerstreak@10
|
228 name = f .."-"..b
|
flickerstreak@10
|
229 end
|
flickerstreak@10
|
230 end
|
flickerstreak@10
|
231 if name and #name > 0 then
|
flickerstreak@10
|
232 UIErrorsFrame:AddMessage(name.." ("..colorGreen..keyTxt..colorOff..") "..L["is now unbound"].."!")
|
flickerstreak@10
|
233 end
|
flickerstreak@10
|
234 end
|
flickerstreak@10
|
235 end
|
flickerstreak@10
|
236 SetBinding(k,nil)
|
flickerstreak@12
|
237 table.insert(self.pending,k)
|
flickerstreak@12
|
238 self:TriggerEvent("REBOUND_UNBIND_TEMP", self.id, k)
|
flickerstreak@10
|
239 end
|
flickerstreak@10
|
240 end
|
flickerstreak@10
|
241
|
flickerstreak@10
|
242
|
flickerstreak@10
|
243 --[[
|
flickerstreak@12
|
244 Gets the keys currently click-bound to a frame.
|
flickerstreak@10
|
245
|
flickerstreak@10
|
246 Arguments:
|
flickerstreak@10
|
247 target: target frame to query
|
flickerstreak@10
|
248 [button]: mouse button to emulate ("LeftButton", "RightButton")
|
flickerstreak@10
|
249
|
flickerstreak@10
|
250 Returns:
|
flickerstreak@10
|
251 key1, key2, key3, etc, as strings.
|
flickerstreak@10
|
252 ]]
|
flickerstreak@12
|
253 function ReBound.prototype:GetBinding( target, button )
|
flickerstreak@12
|
254 if not target then error("ReBound:GetBinding() requires a target frame argument") end
|
flickerstreak@10
|
255 button = button or "LeftButton"
|
flickerstreak@10
|
256 return GetBindingKey("CLICK "..target:GetName()..":"..button)
|
flickerstreak@10
|
257 end
|
flickerstreak@10
|
258
|
flickerstreak@10
|
259
|
flickerstreak@10
|
260 --[[
|
flickerstreak@17
|
261 Gets the localized, abbreviated key cap text for the primary binding on a target.
|
flickerstreak@17
|
262 Abbreviations are more aggressive than the standard Blizzard abbreviation
|
flickerstreak@17
|
263 (which just shortens modifier keys)
|
flickerstreak@17
|
264
|
flickerstreak@17
|
265 Arguments:
|
flickerstreak@17
|
266 target: target frame to query
|
flickerstreak@17
|
267 [abbrev]: boolean flag to abbreviate the result
|
flickerstreak@17
|
268 [button]: mouse button to emulate ("LeftButton", "RightButton")
|
flickerstreak@17
|
269
|
flickerstreak@17
|
270 Returns:
|
flickerstreak@17
|
271 abbreviated, localized key label
|
flickerstreak@17
|
272 ]]
|
flickerstreak@17
|
273 function ReBound.prototype:GetBindingText( target, abbrev, button )
|
flickerstreak@17
|
274 local key = self:GetBinding(target,button)
|
flickerstreak@17
|
275 local txt = key and GetBindingText(key, "KEY_", abbrev and 1) or ""
|
flickerstreak@17
|
276
|
flickerstreak@17
|
277 if txt and abbrev then
|
flickerstreak@17
|
278 -- further abbreviate some key names
|
flickerstreak@17
|
279 txt = string.gsub(txt, "[^%-]+$", keybindAbbreviations)
|
flickerstreak@17
|
280 -- the above does not handle "num pad -"
|
flickerstreak@17
|
281 txt = string.gsub(txt, KEY_NUMPADMINUS, keybindAbbreviations)
|
flickerstreak@17
|
282 end
|
flickerstreak@17
|
283 return txt
|
flickerstreak@17
|
284 end
|
flickerstreak@17
|
285
|
flickerstreak@17
|
286
|
flickerstreak@17
|
287 --[[
|
flickerstreak@12
|
288 Publishes permanent binding notification events.
|
flickerstreak@12
|
289 ]]
|
flickerstreak@12
|
290 local function PublishBindings(self)
|
flickerstreak@12
|
291 for _, key in ipairs(self.pending) do
|
flickerstreak@12
|
292 local action = GetBindingAction(key)
|
flickerstreak@12
|
293 local frame, button
|
flickerstreak@12
|
294 if action then
|
flickerstreak@12
|
295 frame, button = action:match("CLICK (.+)\:(.+)")
|
flickerstreak@12
|
296 end
|
flickerstreak@12
|
297 if frame == nil then
|
flickerstreak@12
|
298 self:TriggerEvent("REBOUND_UNBIND", self.id, key)
|
flickerstreak@12
|
299 else
|
flickerstreak@12
|
300 self:TriggerEvent("REBOUND_BIND", self.id, key, frame, button)
|
flickerstreak@12
|
301 end
|
flickerstreak@12
|
302 end
|
flickerstreak@12
|
303 self.pending = { }
|
flickerstreak@12
|
304 end
|
flickerstreak@12
|
305
|
flickerstreak@12
|
306
|
flickerstreak@12
|
307 --[[
|
flickerstreak@12
|
308 Saves the bindings using the current scheme. Also publishes events indicating that the
|
flickerstreak@12
|
309 bindings have been saved/cleared permanently.
|
flickerstreak@12
|
310 ]]
|
flickerstreak@12
|
311 function ReBound.prototype:SaveBindings()
|
flickerstreak@12
|
312 SaveBindings(GetCurrentBindingSet()) -- will trigger an UPDATE_BINDINGS event.
|
flickerstreak@12
|
313 PublishBindings(self)
|
flickerstreak@12
|
314 end
|
flickerstreak@12
|
315
|
flickerstreak@12
|
316
|
flickerstreak@12
|
317 --[[
|
flickerstreak@12
|
318 Reverts the bindings to the ones previously saved. Also publishes events indicating that the
|
flickerstreak@12
|
319 bindings have been reverted.
|
flickerstreak@12
|
320 ]]
|
flickerstreak@12
|
321 function ReBound.prototype:RevertBindings()
|
flickerstreak@12
|
322 LoadBindings(GetCurrentBindingSet()) -- should trigger an UPDATE_BINDINGS event.
|
flickerstreak@12
|
323 PublishBindings(self)
|
flickerstreak@12
|
324 end
|
flickerstreak@12
|
325
|
flickerstreak@12
|
326
|
flickerstreak@12
|
327 --[[
|
flickerstreak@12
|
328 Clears all bindings associated with registered frames. This is useful, for example, when switching profiles
|
flickerstreak@12
|
329 and the keybinding data is stored in the profile.
|
flickerstreak@12
|
330 ]]
|
flickerstreak@12
|
331 function ReBound.prototype:ClearRegisteredBindings()
|
flickerstreak@12
|
332 for f, _ in pairs(self.frames) do
|
flickerstreak@12
|
333 self:ClearBinding(nil,f,"LeftButton",true)
|
flickerstreak@12
|
334 self:ClearBinding(nil,f,"RightButton",true)
|
flickerstreak@12
|
335 end
|
flickerstreak@12
|
336 end
|
flickerstreak@12
|
337
|
flickerstreak@12
|
338
|
flickerstreak@12
|
339 --[[
|
flickerstreak@10
|
340 Registers a target frame by creating a click-binding frame and putting that frame in the list of
|
flickerstreak@10
|
341 registered frames, which can then be all shown/hidden as one unit.
|
flickerstreak@10
|
342
|
flickerstreak@10
|
343 Arguments:
|
flickerstreak@10
|
344 target = the frame whose OnClick handler should be the target of keybinding
|
flickerstreak@10
|
345
|
flickerstreak@10
|
346 Returns:
|
flickerstreak@10
|
347 A clickbinder frame.
|
flickerstreak@10
|
348 ]]
|
flickerstreak@12
|
349 function ReBound.prototype:Register( target )
|
flickerstreak@10
|
350 local f = self:CreateClickBindingFrame(target)
|
flickerstreak@10
|
351 self.frames[target] = f
|
flickerstreak@10
|
352 return f
|
flickerstreak@10
|
353 end
|
flickerstreak@10
|
354
|
flickerstreak@10
|
355
|
flickerstreak@10
|
356 --[[
|
flickerstreak@10
|
357 Unregisters a target frame by removing it from the internal list. Does nothing to the clickbinding frame.
|
flickerstreak@10
|
358
|
flickerstreak@10
|
359 Arguments:
|
flickerstreak@12
|
360 target = the frame whose OnClick handler should no longer be managed. do NOT pass the clickbinding frame.
|
flickerstreak@10
|
361
|
flickerstreak@10
|
362 Returns:
|
flickerstreak@10
|
363 nothing.
|
flickerstreak@10
|
364 ]]
|
flickerstreak@12
|
365 function ReBound.prototype:Unregister( target )
|
flickerstreak@10
|
366 self.frames[target] = nil
|
flickerstreak@10
|
367 end
|
flickerstreak@10
|
368
|
flickerstreak@10
|
369
|
flickerstreak@10
|
370 --[[
|
flickerstreak@12
|
371 Unregisters all registered frames.
|
flickerstreak@12
|
372 ]]
|
flickerstreak@12
|
373 function ReBound.prototype:UnregisterAll()
|
flickerstreak@12
|
374 self.frames = { }
|
flickerstreak@12
|
375 end
|
flickerstreak@12
|
376
|
flickerstreak@12
|
377
|
flickerstreak@12
|
378
|
flickerstreak@12
|
379 --[[
|
flickerstreak@10
|
380 Shows all the registered click binding frames.
|
flickerstreak@10
|
381 ]]
|
flickerstreak@17
|
382 function ReBound.prototype:ShowRegisteredFrames()
|
flickerstreak@10
|
383 if InCombatLockdown() then
|
flickerstreak@10
|
384 -- can't set bindings while in combat, so don't bother showing them
|
flickerstreak@10
|
385 UIErrorsFrame:AddMessage(ERR_NOT_IN_COMBAT)
|
flickerstreak@10
|
386 else
|
flickerstreak@10
|
387 for _, f in pairs(self.frames) do
|
flickerstreak@10
|
388 f:Show()
|
flickerstreak@10
|
389 end
|
flickerstreak@10
|
390 end
|
flickerstreak@10
|
391 end
|
flickerstreak@10
|
392
|
flickerstreak@10
|
393
|
flickerstreak@10
|
394 --[[
|
flickerstreak@10
|
395 Hides all the registered click binding frames.
|
flickerstreak@10
|
396 ]]
|
flickerstreak@17
|
397 function ReBound.prototype:HideRegisteredFrames()
|
flickerstreak@12
|
398 -- because these frames aren't protected, there's no restriction
|
flickerstreak@12
|
399 -- on hiding them while in combat.
|
flickerstreak@10
|
400 for _, f in pairs(self.frames) do
|
flickerstreak@10
|
401 f:Hide()
|
flickerstreak@10
|
402 end
|
flickerstreak@10
|
403 end
|
flickerstreak@10
|
404
|
flickerstreak@10
|
405 -- click binding frame implementation functions
|
flickerstreak@10
|
406 local function ShowTooltip1( self )
|
flickerstreak@10
|
407 local target = self:GetParent()
|
flickerstreak@10
|
408
|
flickerstreak@10
|
409 GameTooltip:ClearLines()
|
flickerstreak@10
|
410 GameTooltip:SetOwner(self,"ANCHOR_TOPRIGHT")
|
flickerstreak@10
|
411 -- line 1: button name and current binding
|
flickerstreak@10
|
412 GameTooltip:AddDoubleLine(target:GetName(), colorGreen.."("..(self.ReBound:GetBinding(target,"LeftButton") or L["none"])..")"..colorOff)
|
flickerstreak@10
|
413 -- line 2: current right-click binding (if any)
|
flickerstreak@10
|
414 local binding2 = self.ReBound:GetBinding(target,"RightButton")
|
flickerstreak@10
|
415 if binding2 then
|
flickerstreak@10
|
416 GameTooltip:AddDoubleLine(L["Right-click"]..":", colorGreen.."("..binding2..")"..colorOff)
|
flickerstreak@10
|
417 end
|
flickerstreak@10
|
418 -- line 3: instructions
|
flickerstreak@17
|
419 GameTooltip:AddLine(colorGreen..L["Click"]..colorOff.." "..L["to select for binding"])
|
flickerstreak@17
|
420 GameTooltip:AddLine(colorGreen..L["Shift-click"]..colorOff.." "..L["to clear binding"])
|
flickerstreak@17
|
421 GameTooltip:AddLine("")
|
flickerstreak@17
|
422 GameTooltip:AddLine(colorOrange..L["Right-click"]..colorOff.." "..L["to select for alternate (right-click) binding"])
|
flickerstreak@17
|
423 GameTooltip:AddLine(colorOrange..L["Shift-right-click"]..colorOff.." "..L["to clear alternate (right-click) binding"])
|
flickerstreak@10
|
424 GameTooltip:Show()
|
flickerstreak@10
|
425 end
|
flickerstreak@10
|
426
|
flickerstreak@10
|
427 local function ShowTooltip2( self )
|
flickerstreak@10
|
428 if GameTooltip:IsOwned(self) then
|
flickerstreak@10
|
429 local target = self:GetParent()
|
flickerstreak@10
|
430 GameTooltip:ClearLines()
|
flickerstreak@10
|
431 GameTooltip:SetOwner(self)
|
flickerstreak@10
|
432 local clickSuffix = self.selectedButton == "RightButton" and (" ("..L["Right-click"]..")") or ""
|
flickerstreak@10
|
433 -- line 1: button name and binding to be set
|
flickerstreak@10
|
434 GameTooltip:AddDoubleLine(target:GetName()..clickSuffix, colorGreen.."("..(self.ReBound:GetBinding(target,self.selectedButton) or L["none"])..")"..colorOff)
|
flickerstreak@10
|
435 -- line 2: instructions
|
flickerstreak@10
|
436 GameTooltip:AddLine(colorGreen..L["Press a key to assign binding"]..colorOff)
|
flickerstreak@10
|
437 GameTooltip:Show()
|
flickerstreak@10
|
438 end
|
flickerstreak@10
|
439 end
|
flickerstreak@10
|
440
|
flickerstreak@10
|
441 local function OnClick( self, button )
|
flickerstreak@10
|
442 if button == "LeftButton" or button == "RightButton" then
|
flickerstreak@10
|
443 if IsShiftKeyDown() then
|
flickerstreak@10
|
444 self.ReBound:ClearBinding( nil, self:GetParent(), button )
|
flickerstreak@10
|
445 self.selectedButton = nil
|
flickerstreak@10
|
446 self:EnableKeyboard(false)
|
flickerstreak@10
|
447 ShowTooltip1(self)
|
flickerstreak@10
|
448 else
|
flickerstreak@10
|
449 self.selectedButton = button
|
flickerstreak@10
|
450 self:EnableKeyboard(true)
|
flickerstreak@10
|
451 ShowTooltip2(self)
|
flickerstreak@10
|
452 end
|
flickerstreak@10
|
453 elseif self.selectedButton then
|
flickerstreak@10
|
454 self.ReBound:SetBinding( mouseButtonConvert[button], self:GetParent(), self.selectedButton )
|
flickerstreak@10
|
455 self.selectedButton = nil
|
flickerstreak@10
|
456 self:EnableKeyboard(false)
|
flickerstreak@10
|
457 ShowTooltip1(self)
|
flickerstreak@10
|
458 end
|
flickerstreak@10
|
459 end
|
flickerstreak@10
|
460
|
flickerstreak@10
|
461 local function OnEnter( self )
|
flickerstreak@10
|
462 -- clear current binding button
|
flickerstreak@10
|
463 self.selectedButton = nil
|
flickerstreak@10
|
464 -- show tooltip 1
|
flickerstreak@10
|
465 ShowTooltip1(self)
|
flickerstreak@10
|
466 end
|
flickerstreak@10
|
467
|
flickerstreak@10
|
468 local function OnLeave( self )
|
flickerstreak@10
|
469 -- disable keyboard input, if it was enabled
|
flickerstreak@10
|
470 self:EnableKeyboard(false)
|
flickerstreak@10
|
471 -- hide tooltip
|
flickerstreak@10
|
472 if GameTooltip:IsOwned(self) then
|
flickerstreak@10
|
473 GameTooltip:Hide()
|
flickerstreak@10
|
474 end
|
flickerstreak@10
|
475 end
|
flickerstreak@10
|
476
|
flickerstreak@10
|
477 local function OnKeyDown( self, key )
|
flickerstreak@10
|
478 if key == nil or key == "UNKNOWN" or key == "SHIFT" or key == "CTRL" or key == "ALT" then
|
flickerstreak@10
|
479 return
|
flickerstreak@10
|
480 end
|
flickerstreak@10
|
481 if IsShiftKeyDown() then key = "SHIFT-"..key end
|
flickerstreak@10
|
482 if IsControlKeyDown() then key = "CTRL-"..key end
|
flickerstreak@10
|
483 if IsAltKeyDown() then key = "ALT-"..key end
|
flickerstreak@10
|
484
|
flickerstreak@10
|
485 if key ~= "ESCAPE" then
|
flickerstreak@10
|
486 self.ReBound:SetBinding( key, self:GetParent(), self.selectedButton )
|
flickerstreak@10
|
487 end
|
flickerstreak@10
|
488
|
flickerstreak@10
|
489 self:EnableKeyboard(false)
|
flickerstreak@10
|
490 self.selectedButton = nil
|
flickerstreak@10
|
491 ShowTooltip1(self)
|
flickerstreak@10
|
492 end
|
flickerstreak@10
|
493
|
flickerstreak@10
|
494 --[[
|
flickerstreak@10
|
495 Creates a click-binding frame attached to the target frame, which can be used for point-and-click keybind assignments. The
|
flickerstreak@10
|
496 frame is initially hidden by default. It is not registered with ReBound for automatic show/hide: use Register() for that.
|
flickerstreak@10
|
497
|
flickerstreak@10
|
498 Arguments:
|
flickerstreak@10
|
499 target - the frame whose OnClick handler should be the target of keybinding
|
flickerstreak@10
|
500
|
flickerstreak@10
|
501 Returns:
|
flickerstreak@10
|
502 A clickbinder frame.
|
flickerstreak@10
|
503 ]]
|
flickerstreak@12
|
504 function ReBound.prototype:CreateClickBindingFrame( target )
|
flickerstreak@10
|
505 local f = CreateFrame("Button", nil, target)
|
flickerstreak@10
|
506 f.ReBound = self
|
flickerstreak@10
|
507 f:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square")
|
flickerstreak@10
|
508 f:SetToplevel(1)
|
flickerstreak@10
|
509 f:SetFrameStrata("DIALOG")
|
flickerstreak@10
|
510 f:RegisterForClicks("AnyUp")
|
flickerstreak@10
|
511 f:SetScript("OnClick", OnClick)
|
flickerstreak@10
|
512 f:SetScript("OnEnter", OnEnter)
|
flickerstreak@10
|
513 f:SetScript("OnLeave", OnLeave)
|
flickerstreak@10
|
514 f:SetScript("OnKeyDown", OnKeyDown)
|
flickerstreak@10
|
515 f:SetAllPoints(target)
|
flickerstreak@10
|
516 f:Hide()
|
flickerstreak@10
|
517 return f
|
flickerstreak@10
|
518 end
|
flickerstreak@10
|
519
|
flickerstreak@10
|
520
|
flickerstreak@10
|
521
|
flickerstreak@10
|
522 -- library setup
|
flickerstreak@10
|
523
|
flickerstreak@10
|
524 local function activate( self, oldLib, oldDeactivate )
|
flickerstreak@12
|
525 -- copy the list of active instances
|
flickerstreak@12
|
526 self.instances = { }
|
flickerstreak@12
|
527 if oldLib and oldLib.instances then
|
flickerstreak@12
|
528 for k,v in pairs(oldLib.instances) do
|
flickerstreak@12
|
529 self.instances[k] = v
|
flickerstreak@12
|
530 end
|
flickerstreak@12
|
531 end
|
flickerstreak@12
|
532
|
flickerstreak@10
|
533 if oldDeactivate then
|
flickerstreak@10
|
534 oldDeactivate(oldLib)
|
flickerstreak@10
|
535 end
|
flickerstreak@10
|
536 end
|
flickerstreak@10
|
537
|
flickerstreak@12
|
538 AceLibrary:Register(ReBound, version_major, version_minor, activate)
|
flickerstreak@10
|
539 ReBound = nil
|