vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[---------------------------------------------------------------------------------
2 General Library providing an alternate StartMoving() that allows you to
3 specify a number of frames to snap-to when moving the frame around
4  
5 Example Usage:
6  
7 <OnLoad>
8 this:RegisterForDrag("LeftButton")
9 </OnLoad>
10 <OnDragStart>
11 StickyFrames:StartMoving(this, {WatchDogFrame_player, WatchDogFrame_target, WatchDogFrame_party1, WatchDogFrame_party2, WatchDogFrame_party3, WatchDogFrame_party4},3,3,3,3)
12 </OnDragStart>
13 <OnDragStop>
14 StickyFrames:StopMoving(this)
15 StickyFrames:AnchorFrame(this)
16 </OnDragStop>
17 ------------------------------------------------------------------------------------]]
18  
19 --[[---------------------------------------------------------------------------------
20 Class declaration, along with a temporary table to hold any existing OnUpdate
21 scripts.
22 ------------------------------------------------------------------------------------]]
23  
24 StickyFrames = {}
25 StickyFrames.scripts = {}
26  
27 --[[---------------------------------------------------------------------------------
28 StickyFrames:StartMoving() - Sets a custom OnUpdate for the frame so it follows
29 the mouse and snaps to the frames you specify
30  
31 frame: The frame we want to move. Is typically "this"
32  
33 frameList: A integer indexed list of frames that the given frame should try to
34 stick to. These don't have to have anything special done to them,
35 and they don't really even need to exist. You can inclue the
36 moving frame in this list, it will be ignored. This helps you
37 if you have a number of frames, just make ONE list to pass.
38  
39 {WatchDogFrame_player, WatchDogFrame_party1, .. WatchDogFrame_party4}
40  
41 left: If your frame has a tranparent border around the entire frame
42 (think backdrops with borders). This can be used to fine tune the
43 edges when you're stickying groups. Refers to any offset on the
44 LEFT edge of the frame being moved.
45  
46 top: same
47 right: same
48 bottom: same
49 ------------------------------------------------------------------------------------]]
50  
51 function StickyFrames:StartMoving(frame, frameList, left, top, right, bottom)
52 local x,y = GetCursorPosition()
53 local aX,aY = frame:GetCenter()
54 local aS = frame:GetEffectiveScale()
55  
56 aX,aY = aX*aS,aY*aS
57 local xoffset,yoffset = (aX - x),(aY - y)
58 self.scripts[frame] = frame:GetScript("OnUpdate")
59 frame:SetScript("OnUpdate", self:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom))
60 end
61  
62 --[[---------------------------------------------------------------------------------
63 This stops the OnUpdate, leaving the frame at its last position. This will
64 leave it anchored to UIParent. You can call StickyFrames:AnchorFrame() to
65 anchor it back "TOPLEFT" , "TOPLEFT" to the parent.
66 ------------------------------------------------------------------------------------]]
67  
68 function StickyFrames:StopMoving(frame)
69 frame:SetScript("OnUpdate", self.scripts[frame])
70 self.scripts[frame] = nil
71 end
72  
73 --[[---------------------------------------------------------------------------------
74 This can be called in conjunction with StickyFrames:StopMoving() to anchor the
75 frame right back to the parent, so you can manipulate its children as a group
76 (This is useful in WatchDog)
77 ------------------------------------------------------------------------------------]]
78  
79 function StickyFrames:AnchorFrame(frame)
80 local xA,yA = frame:GetCenter()
81 local parent = frame:GetParent() or UIParent
82 local xP,yP = parent:GetCenter()
83 local sA,sP = frame:GetEffectiveScale(), parent:GetEffectiveScale()
84  
85 xP,yP = (xP*sP) / sA, (yP*sP) / sA
86  
87 local xo,yo = (xP - xA)*-1, (yP - yA)*-1
88  
89 frame:ClearAllPoints()
90 frame:SetPoint("CENTER", parent, "CENTER", xo, yo)
91 end
92  
93  
94 --[[---------------------------------------------------------------------------------
95 Internal Functions -- Do not call these.
96 ------------------------------------------------------------------------------------]]
97  
98  
99  
100 --[[---------------------------------------------------------------------------------
101 Returns an anonymous OnUpdate function for the frame in question. Need
102 to provide the frame, frameList along with the x and y offset (difference between
103 where the mouse picked up the frame, and the insets (left,top,right,bottom) in the
104 case of borders, etc.w
105 ------------------------------------------------------------------------------------]]
106  
107 function StickyFrames:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom)
108 return function()
109 local x,y = GetCursorPosition()
110 local s = frame:GetEffectiveScale()
111 local sticky = nil
112  
113 x,y = x/s,y/s
114  
115 frame:ClearAllPoints()
116 frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x+xoffset, y+yoffset)
117  
118 for k,v in ipairs(frameList) do
119 if frame ~= v then
120 if self:Overlap(frame, v) then
121 if self:SnapFrame(frame, v, left, top, right, bottom) then break end
122 end
123 end
124 end
125 end
126 end
127  
128  
129 --[[---------------------------------------------------------------------------------
130 Internal debug function.
131 ------------------------------------------------------------------------------------]]
132  
133 function StickyFrames:debug(msg)
134 DEFAULT_CHAT_FRAME:AddMessage("|cffffff00StickyFrames: |r"..tostring(msg))
135 end
136  
137 --[[---------------------------------------------------------------------------------
138 Determines the overlap between two frames. Returns true if the frames
139 overlap anywhere, or false if they don't. Does not consider alpha on the edges of
140 textures.
141 ------------------------------------------------------------------------------------]]
142 function StickyFrames:Overlap(frameA, frameB)
143 local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
144 return ((frameA:GetLeft()*sA) < (frameB:GetRight()*sB))
145 and ((frameB:GetLeft()*sB) < (frameA:GetRight()*sA))
146 and ((frameA:GetBottom()*sA) < (frameB:GetTop()*sB))
147 and ((frameB:GetBottom()*sB) < (frameA:GetTop()*sA))
148 end
149  
150 --[[---------------------------------------------------------------------------------
151 This is called when finding an overlap between two sticky frame. If frameA is near
152 a sticky edge of frameB, then it will snap to that edge and return true. If there
153 is no sticky edge collision, will return false so we can test other frames for
154 stickyness.
155 ------------------------------------------------------------------------------------]]
156 function StickyFrames:SnapFrame(frameA, frameB, left, top, right, bottom)
157 local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
158 local xA, yA = frameA:GetCenter()
159 local xB, yB = frameB:GetCenter()
160 local hA, hB = frameA:GetHeight() / 2, ((frameB:GetHeight() * sB) / sA) / 2
161 local wA, wB = frameA:GetWidth() / 2, ((frameB:GetWidth() * sB) / sA) / 2
162  
163 if not left then left = 0 end
164 if not top then top = 0 end
165 if not right then right = 0 end
166 if not bottom then bottom = 0 end
167  
168 -- Lets translate B's coords into A's scale
169 xB, yB = (xB*sB) / sA, (yB*sB) / sA
170  
171 local stickyAx, stickyAy = wA * 0.75, hA * 0.75
172 local stickyBx, stickyBy = wB * 0.75, hB * 0.75
173  
174 -- Grab the edges of each frame, for easier comparison
175  
176 local lA, tA, rA, bA = frameA:GetLeft(), frameA:GetTop(), frameA:GetRight(), frameA:GetBottom()
177 local lB, tB, rB, bB = frameB:GetLeft(), frameB:GetTop(), frameB:GetRight(), frameB:GetBottom()
178 local snap = nil
179  
180 -- Translate into A's scale
181 lB, tB, rB, bB = (lB * sB) / sA, (tB * sB) / sA, (rB * sB) / sA, (bB * sB) / sA
182  
183 -- Lets check for Left stickyness
184 if lA > (rB - stickyAx) then
185 -- If we are 5 pixels above or below the top of the sticky frame
186 -- Snap to the top edge of it.
187 if tA <= (tB + 5) and tA >= (tB - 5) then
188 yA = (tB - hA)
189 elseif bA <= (bB + 5) and bA >= (bB - 5) then
190 yA = (bB + hA)
191 end
192  
193 -- Set the x sticky position
194 xA = rB + (wA - left)
195  
196 -- Delay the snap until later
197 snap = true
198  
199 -- Check for Right stickyness
200 elseif rA < (lB + stickyAx) then
201 -- If we are 5 pixels above or below the top of the sticky frame
202 -- Snap to the top edge of it.
203 if tA <= (tB + 5) and tA >= (tB - 5) then
204 yA = (tB - hA)
205 elseif bA <= (bB + 5) and bA >= (bB - 5) then
206 yA = (bB + hA)
207 end
208  
209 -- Set the x sticky position
210 xA = lB - (wA - right)
211  
212 -- Delay the snap until later
213 snap = true
214  
215 -- Bottom stickyness
216 elseif bA > (tB - stickyAy) then
217  
218 -- If we are 5 pixels to the left or right of the sticky frame
219 -- Snap to the edge of it.
220  
221 if lA <= (lB + 5) and lA >= (lB - 5) then
222 xA = (lB + wA)
223 elseif rA >= (rB - 5) and rA <= (rB + 5) then
224 xA = (rB - wA)
225 end
226  
227 -- Set the y sticky position
228 yA = tB + (hA - bottom)
229  
230 -- Delay the snap
231 snap = true
232  
233 elseif tA < (bB + stickyAy) then
234 -- If we are 5 pixels to the left or right of the sticky frame
235 -- Snap to the edge of it.
236 if lA <= (lB + 5) and lA >= (lB - 5) then
237 xA = (lB + wA)
238 elseif rA >= (rB - 5) and rA <= (rB + 5) then
239 xA = (rB - wA)
240 end
241  
242 -- Set the y sticky position
243 yA = bB - (hA - bottom)
244  
245 -- Delay the snap
246 snap = true
247 end
248  
249 if snap then
250 frameA:ClearAllPoints()
251 frameA:SetPoint("CENTER", UIParent, "BOTTOMLEFT", xA, yA)
252 return true
253 end
254 end