comparison Libs/LibWindow-1.1/LibWindow-1.1.lua @ 9:f2a55f2d45c8

- added LibWindow to handle the window position.
author Tercioo
date Fri, 12 Feb 2016 14:11:13 -0200
parents
children fedcd7c21db9
comparison
equal deleted inserted replaced
8:2f9d1a15506a 9:f2a55f2d45c8
1 --[[
2 Name: LibWindow-1.1
3 Revision: $Rev: 8 $
4 Author(s): Mikk (dpsgnome@mail.com)
5 Website: http://old.wowace.com/wiki/LibWindow-1.1
6 Documentation: http://old.wowace.com/wiki/LibWindow-1.1
7 SVN: http://svn.wowace.com/root/trunk/WindowLib/Window-1.0
8 Description: A library that handles the basics of "window" style frames: scaling, smart position saving, dragging..
9 Dependencies: none
10 License: Public Domain
11 ]]
12
13 local MAJOR = "LibWindow-1.1"
14 local MINOR = tonumber(("$Revision: 8 $"):match("(%d+)"))
15
16 local lib = LibStub:NewLibrary(MAJOR,MINOR)
17 if not lib then return end
18
19 local min,max,abs = min,max,abs
20 local pairs = pairs
21 local tostring = tostring
22 local UIParent,GetScreenWidth,GetScreenHeight,IsAltKeyDown = UIParent,GetScreenWidth,GetScreenHeight,IsAltKeyDown
23 -- GLOBALS: error, ChatFrame1, assert
24
25 local function print(msg) ChatFrame1:AddMessage(MAJOR..": "..tostring(msg)) end
26
27 lib.utilFrame = lib.utilFrame or CreateFrame("Frame")
28 lib.delayedSavePosition = lib.delayedSavePosition or {}
29 lib.windowData = lib.windowData or {}
30 --[frameref]={
31 -- names={optional names data from .RegisterConfig()}
32 -- storage= -- tableref where config data is read/written
33 -- altEnable=true/false
34 --}
35
36
37 lib.embeds = lib.embeds or {}
38
39 local mixins = {} -- "FuncName"=true
40
41
42
43 ---------------------------------------------------------
44 -- UTILITIES
45 ---------------------------------------------------------
46
47
48 local function getStorageName(frame, name)
49 local names = lib.windowData[frame].names
50 if names then
51 if names[name] then
52 return names[name]
53 end
54 if names.prefix then
55 return names.prefix .. name;
56 end
57 end
58 return name;
59 end
60
61 local function setStorage(frame, name, value)
62 lib.windowData[frame].storage[getStorageName(frame, name)] = value
63 end
64
65 local function getStorage(frame, name)
66 return lib.windowData[frame].storage[getStorageName(frame, name)]
67 end
68
69
70 lib.utilFrame:SetScript("OnUpdate", function(this)
71 this:Hide()
72 for frame,_ in pairs(lib.delayedSavePosition) do
73 lib.delayedSavePosition[frame] = nil
74 lib.SavePosition(frame)
75 end
76 end)
77
78 local function queueSavePosition(frame)
79 lib.delayedSavePosition[frame] = true
80 lib.utilFrame:Show()
81 end
82
83
84 ---------------------------------------------------------
85 -- IMPORTANT APIS
86 ---------------------------------------------------------
87
88 mixins["RegisterConfig"]=true
89 function lib.RegisterConfig(frame, storage, names)
90 if not lib.windowData[frame] then
91 lib.windowData[frame] = {}
92 end
93 lib.windowData[frame].names = names
94 lib.windowData[frame].storage = storage
95
96 --[[ debug
97 frame.tx = frame:CreateTexture()
98 frame.tx:SetTexture(0,0,0, 0.4)
99 frame.tx:SetAllPoints(frame)
100 frame.tx:Show()
101 ]]
102 end
103
104
105
106
107 ---------------------------------------------------------
108 -- POSITIONING AND SCALING
109 ---------------------------------------------------------
110
111 local nilParent = {
112 GetWidth = function()
113 return GetScreenWidth() * UIParent:GetScale()
114 end,
115 GetHeight = function()
116 return GetScreenHeight() * UIParent:GetScale()
117 end,
118 GetScale = function()
119 return 1
120 end,
121 }
122
123 mixins["SavePosition"]=true
124 function lib.SavePosition(frame)
125 local parent = frame:GetParent() or nilParent
126 -- No, this won't work very well with frames that aren't parented to nil or UIParent
127 local s = frame:GetScale()
128 local left,top = frame:GetLeft()*s, frame:GetTop()*s
129 local right,bottom = frame:GetRight()*s, frame:GetBottom()*s
130 local pwidth, pheight = parent:GetWidth(), parent:GetHeight()
131
132 local x,y,point;
133 if left < (pwidth-right) and left < abs((left+right)/2 - pwidth/2) then
134 x = left;
135 point="LEFT";
136 elseif (pwidth-right) < abs((left+right)/2 - pwidth/2) then
137 x = right-pwidth;
138 point="RIGHT";
139 else
140 x = (left+right)/2 - pwidth/2;
141 point="";
142 end
143
144 if bottom < (pheight-top) and bottom < abs((bottom+top)/2 - pheight/2) then
145 y = bottom;
146 point="BOTTOM"..point;
147 elseif (pheight-top) < abs((bottom+top)/2 - pheight/2) then
148 y = top-pheight;
149 point="TOP"..point;
150 else
151 y = (bottom+top)/2 - pheight/2;
152 -- point=""..point;
153 end
154
155 if point=="" then
156 point = "CENTER"
157 end
158
159 setStorage(frame, "x", x)
160 setStorage(frame, "y", y)
161 setStorage(frame, "point", point)
162 setStorage(frame, "scale", s)
163
164 frame:ClearAllPoints()
165 frame:SetPoint(point, frame:GetParent(), point, x/s, y/s);
166 end
167
168
169 mixins["RestorePosition"]=true
170 function lib.RestorePosition(frame)
171 local x = getStorage(frame, "x")
172 local y = getStorage(frame, "y")
173 local point = getStorage(frame, "point")
174
175 local s = getStorage(frame, "scale")
176 if s then
177 (frame.lw11origSetScale or frame.SetScale)(frame,s)
178 else
179 s = frame:GetScale()
180 end
181
182 if not x or not y then -- nothing stored in config yet, smack it in the center
183 x=0; y=0; point="CENTER"
184 end
185
186 x = x/s
187 y = y/s
188
189 frame:ClearAllPoints()
190 if not point and y==0 then -- errr why did i do this check again? must have been a reason, but i can't remember it =/
191 point="CENTER"
192 end
193
194 if not point then -- we have position, but no point, which probably means we're going from data stored by the addon itself before LibWindow was added to it. It was PROBABLY topleft->bottomleft anchored. Most do it that way.
195 frame:SetPoint("TOPLEFT", frame:GetParent(), "BOTTOMLEFT", x, y)
196 -- make it compute a better attachpoint (on next update)
197 queueSavePosition(frame)
198 return
199 end
200
201 frame:SetPoint(point, frame:GetParent(), point, x, y)
202 end
203
204
205 mixins["SetScale"]=true
206 function lib.SetScale(frame, scale)
207 setStorage(frame, "scale", scale);
208 (frame.lw11origSetScale or frame.SetScale)(frame,scale)
209 lib.RestorePosition(frame)
210 end
211
212
213
214 ---------------------------------------------------------
215 -- DRAG SUPPORT
216 ---------------------------------------------------------
217
218
219 function lib.OnDragStart(frame)
220 lib.windowData[frame].isDragging = true
221 frame:StartMoving()
222 end
223
224
225 function lib.OnDragStop(frame)
226 frame:StopMovingOrSizing()
227 lib.SavePosition(frame)
228 lib.windowData[frame].isDragging = false
229 if lib.windowData[frame].altEnable and not IsAltKeyDown() then
230 frame:EnableMouse(false)
231 end
232 end
233
234 local function onDragStart(...) return lib.OnDragStart(...) end -- upgradable
235 local function onDragStop(...) return lib.OnDragStop(...) end -- upgradable
236
237 mixins["MakeDraggable"]=true
238 function lib.MakeDraggable(frame)
239 assert(lib.windowData[frame])
240 frame:SetMovable(true)
241 frame:SetScript("OnDragStart", onDragStart)
242 frame:SetScript("OnDragStop", onDragStop)
243 frame:RegisterForDrag("LeftButton")
244 end
245
246
247 ---------------------------------------------------------
248 -- MOUSEWHEEL
249 ---------------------------------------------------------
250
251 function lib.OnMouseWheel(frame, dir)
252 local scale = getStorage(frame, "scale")
253 if dir<0 then
254 scale=max(scale*0.9, 0.1)
255 else
256 scale=min(scale/0.9, 3)
257 end
258 lib.SetScale(frame, scale)
259 end
260
261 local function onMouseWheel(...) return lib.OnMouseWheel(...) end -- upgradable
262
263 mixins["EnableMouseWheelScaling"]=true
264 function lib.EnableMouseWheelScaling(frame)
265 frame:SetScript("OnMouseWheel", onMouseWheel)
266 end
267
268
269 ---------------------------------------------------------
270 -- ENABLEMOUSE-ON-ALT
271 ---------------------------------------------------------
272
273 lib.utilFrame:SetScript("OnEvent", function(this, event, key, state)
274 if event=="MODIFIER_STATE_CHANGED" then
275 if key == "LALT" or key == "RALT" then
276 for frame,_ in pairs(lib.altEnabledFrames) do
277 if not lib.windowData[frame].isDragging then -- if it's already dragging, it'll disable mouse on DragStop instead
278 frame:EnableMouse(state == 1)
279 end
280 end
281 end
282 end
283 end)
284
285 mixins["EnableMouseOnAlt"]=true
286 function lib.EnableMouseOnAlt(frame)
287 assert(lib.windowData[frame])
288 lib.windowData[frame].altEnable = true
289 frame:EnableMouse(not not IsAltKeyDown())
290 if not lib.altEnabledFrames then
291 lib.altEnabledFrames = {}
292 lib.utilFrame:RegisterEvent("MODIFIER_STATE_CHANGED")
293 end
294 lib.altEnabledFrames[frame] = true
295 end
296
297
298
299 ---------------------------------------------------------
300 -- Embed support (into FRAMES, not addons!)
301 ---------------------------------------------------------
302
303 function lib:Embed(target)
304 if not target or not target[0] or not target.GetObjectType then
305 error("Usage: LibWindow:Embed(frame)", 1)
306 end
307 target.lw11origSetScale = target.SetScale
308 for name, _ in pairs(mixins) do
309 target[name] = self[name]
310 end
311 lib.embeds[target] = true
312 return target
313 end
314
315 for target, _ in pairs(lib.embeds) do
316 lib:Embed(target)
317 end