flickerstreak@25
|
1 local ReAction = ReAction
|
flickerstreak@25
|
2 local L = ReAction.L
|
flickerstreak@25
|
3 local _G = _G
|
flickerstreak@25
|
4 local CreateFrame = CreateFrame
|
flickerstreak@33
|
5 local floor = math.floor
|
flickerstreak@75
|
6 local fmod = math.fmod
|
flickerstreak@75
|
7 local format = string.format
|
flickerstreak@33
|
8
|
flickerstreak@77
|
9 ReAction:UpdateRevision("$Revision$")
|
flickerstreak@25
|
10
|
flickerstreak@90
|
11 local Bar = { }
|
flickerstreak@90
|
12 local proto = { __index = Bar }
|
flickerstreak@90
|
13 local weak = { __mode = "k" }
|
flickerstreak@75
|
14
|
flickerstreak@77
|
15 ReAction.Bar = Bar -- export to ReAction
|
flickerstreak@25
|
16
|
flickerstreak@77
|
17 function Bar:New( name, config )
|
flickerstreak@25
|
18 if type(config) ~= "table" then
|
flickerstreak@28
|
19 error("ReAction.Bar: config table required")
|
flickerstreak@25
|
20 end
|
flickerstreak@75
|
21
|
flickerstreak@90
|
22 -- create new self
|
flickerstreak@90
|
23 self = setmetatable(
|
flickerstreak@90
|
24 {
|
flickerstreak@90
|
25 config = config,
|
flickerstreak@90
|
26 name = name,
|
flickerstreak@90
|
27 buttons = setmetatable( { }, weak ),
|
flickerstreak@90
|
28 width = config.width or 480,
|
flickerstreak@90
|
29 height = config.height or 40
|
flickerstreak@90
|
30 },
|
flickerstreak@90
|
31 proto )
|
flickerstreak@90
|
32
|
flickerstreak@90
|
33 -- The frame type is 'Button' in order to have an OnClick handler. However, the frame itself is
|
flickerstreak@90
|
34 -- not mouse-clickable by the user.
|
flickerstreak@90
|
35 local parent = config.parent and (ReAction:GetBar(config.parent) or _G[config.parent]) or UIParent
|
flickerstreak@90
|
36 local f = CreateFrame("Button", name and format("ReAction-%s",name), parent,
|
flickerstreak@90
|
37 "SecureHandlerStateTemplate, SecureHandlerClickTemplate")
|
flickerstreak@90
|
38 f:SetFrameStrata("MEDIUM")
|
flickerstreak@90
|
39 f:SetWidth(self.width)
|
flickerstreak@90
|
40 f:SetWidth(self.height)
|
flickerstreak@103
|
41 f:SetAlpha(config.alpha or 1.0)
|
flickerstreak@90
|
42 f:Show()
|
flickerstreak@90
|
43 f:EnableMouse(false)
|
flickerstreak@90
|
44 f:SetClampedToScreen(true)
|
flickerstreak@25
|
45
|
flickerstreak@90
|
46 -- Override the default frame accessor to provide strict read-only access
|
flickerstreak@77
|
47 function self:GetFrame()
|
flickerstreak@77
|
48 return f
|
flickerstreak@77
|
49 end
|
flickerstreak@77
|
50
|
flickerstreak@75
|
51 self:ApplyAnchor()
|
flickerstreak@63
|
52 ReAction.RegisterCallback(self, "OnConfigModeChanged")
|
flickerstreak@77
|
53
|
flickerstreak@77
|
54 return self
|
flickerstreak@25
|
55 end
|
flickerstreak@25
|
56
|
flickerstreak@25
|
57 function Bar:Destroy()
|
flickerstreak@75
|
58 local f = self:GetFrame()
|
flickerstreak@25
|
59 f:UnregisterAllEvents()
|
flickerstreak@90
|
60 ReAction.UnregisterAllCallbacks(self)
|
flickerstreak@25
|
61 f:Hide()
|
flickerstreak@25
|
62 f:SetParent(UIParent)
|
flickerstreak@25
|
63 f:ClearAllPoints()
|
flickerstreak@25
|
64 end
|
flickerstreak@25
|
65
|
flickerstreak@63
|
66 function Bar:OnConfigModeChanged(event, mode)
|
flickerstreak@75
|
67 self:ShowControls(mode) -- Bar:ShowControls() defined in Overlay.lua
|
flickerstreak@25
|
68 end
|
flickerstreak@25
|
69
|
flickerstreak@25
|
70 function Bar:ApplyAnchor()
|
flickerstreak@90
|
71 local f = self:GetFrame()
|
flickerstreak@90
|
72 local c = self.config
|
flickerstreak@90
|
73 local p = c.point
|
flickerstreak@90
|
74
|
flickerstreak@90
|
75 f:SetWidth(c.width)
|
flickerstreak@90
|
76 f:SetHeight(c.height)
|
flickerstreak@51
|
77 f:ClearAllPoints()
|
flickerstreak@90
|
78
|
flickerstreak@90
|
79 if p then
|
flickerstreak@90
|
80 local a = f:GetParent()
|
flickerstreak@90
|
81 if c.anchor then
|
flickerstreak@90
|
82 local bar = ReAction:GetBar(c.anchor)
|
flickerstreak@52
|
83 if bar then
|
flickerstreak@90
|
84 a = bar:GetFrame()
|
flickerstreak@52
|
85 else
|
flickerstreak@90
|
86 a = _G[c.anchor]
|
flickerstreak@52
|
87 end
|
flickerstreak@25
|
88 end
|
flickerstreak@90
|
89 local fr = a or f:GetParent()
|
flickerstreak@90
|
90 f:SetPoint(p, a or f:GetParent(), c.relpoint, c.x or 0, c.y or 0)
|
flickerstreak@25
|
91 else
|
flickerstreak@25
|
92 f:SetPoint("CENTER")
|
flickerstreak@25
|
93 end
|
flickerstreak@25
|
94 end
|
flickerstreak@25
|
95
|
flickerstreak@51
|
96 function Bar:SetAnchor(point, frame, relativePoint, x, y)
|
flickerstreak@51
|
97 local c = self.config
|
flickerstreak@75
|
98 c.point = point or c.point
|
flickerstreak@103
|
99 c.anchor = frame or c.anchor
|
flickerstreak@75
|
100 c.relpoint = relativePoint or c.relpoint
|
flickerstreak@51
|
101 c.x = x or c.x
|
flickerstreak@51
|
102 c.y = y or c.y
|
flickerstreak@51
|
103 self:ApplyAnchor()
|
flickerstreak@103
|
104 ReAction:RefreshBar(self)
|
flickerstreak@51
|
105 end
|
flickerstreak@51
|
106
|
flickerstreak@51
|
107 function Bar:GetAnchor()
|
flickerstreak@51
|
108 local c = self.config
|
flickerstreak@90
|
109 return (c.point or "CENTER"),
|
flickerstreak@90
|
110 (c.anchor or self:GetFrame():GetParent():GetName()),
|
flickerstreak@90
|
111 (c.relpoint or c.point or "CENTER"),
|
flickerstreak@90
|
112 (c.x or 0),
|
flickerstreak@90
|
113 (c.y or 0)
|
flickerstreak@25
|
114 end
|
flickerstreak@25
|
115
|
flickerstreak@25
|
116 function Bar:GetSize()
|
flickerstreak@75
|
117 local f = self:GetFrame()
|
flickerstreak@75
|
118 return f:GetWidth(), f:GetHeight()
|
flickerstreak@25
|
119 end
|
flickerstreak@25
|
120
|
flickerstreak@25
|
121 function Bar:SetSize(w,h)
|
flickerstreak@90
|
122 local f = self:GetFrame()
|
flickerstreak@25
|
123 self.config.width = w
|
flickerstreak@25
|
124 self.config.height = h
|
flickerstreak@75
|
125 f:SetWidth(w)
|
flickerstreak@75
|
126 f:SetHeight(h)
|
flickerstreak@25
|
127 end
|
flickerstreak@25
|
128
|
flickerstreak@25
|
129 function Bar:GetButtonSize()
|
flickerstreak@25
|
130 local w = self.config.btnWidth or 32
|
flickerstreak@25
|
131 local h = self.config.btnHeight or 32
|
flickerstreak@25
|
132 -- TODO: get from modules?
|
flickerstreak@25
|
133 return w,h
|
flickerstreak@25
|
134 end
|
flickerstreak@25
|
135
|
flickerstreak@25
|
136 function Bar:SetButtonSize(w,h)
|
flickerstreak@25
|
137 if w > 0 and h > 0 then
|
flickerstreak@25
|
138 self.config.btnWidth = w
|
flickerstreak@25
|
139 self.config.btnHeight = h
|
flickerstreak@25
|
140 end
|
flickerstreak@75
|
141 ReAction:RefreshBar(self)
|
flickerstreak@25
|
142 end
|
flickerstreak@25
|
143
|
flickerstreak@25
|
144 function Bar:GetButtonGrid()
|
flickerstreak@25
|
145 local cfg = self.config
|
flickerstreak@25
|
146 local r = cfg.btnRows or 1
|
flickerstreak@25
|
147 local c = cfg.btnColumns or 1
|
flickerstreak@25
|
148 local s = cfg.spacing or 4
|
flickerstreak@25
|
149 return r,c,s
|
flickerstreak@25
|
150 end
|
flickerstreak@25
|
151
|
flickerstreak@86
|
152 function Bar:GetNumButtons()
|
flickerstreak@86
|
153 local r,c = self:GetButtonGrid()
|
flickerstreak@86
|
154 return r*c
|
flickerstreak@86
|
155 end
|
flickerstreak@86
|
156
|
flickerstreak@25
|
157 function Bar:SetButtonGrid(r,c,s)
|
flickerstreak@25
|
158 if r > 0 and c > 0 and s > 0 then
|
flickerstreak@25
|
159 local cfg = self.config
|
flickerstreak@25
|
160 cfg.btnRows = r
|
flickerstreak@25
|
161 cfg.btnColumns = c
|
flickerstreak@25
|
162 cfg.spacing = s
|
flickerstreak@25
|
163 end
|
flickerstreak@75
|
164 ReAction:RefreshBar(self)
|
flickerstreak@25
|
165 end
|
flickerstreak@25
|
166
|
flickerstreak@94
|
167 function Bar:ClipNButtons( n )
|
flickerstreak@94
|
168 local cfg = self.config
|
flickerstreak@94
|
169 local r = cfg.btnRows or 1
|
flickerstreak@94
|
170 local c = cfg.btnColumns or 1
|
flickerstreak@94
|
171
|
flickerstreak@94
|
172 cfg.btnRows = ceil(n/c)
|
flickerstreak@94
|
173 cfg.btnColumns = min(n,c)
|
flickerstreak@94
|
174 end
|
flickerstreak@94
|
175
|
flickerstreak@25
|
176 function Bar:GetName()
|
flickerstreak@25
|
177 return self.name
|
flickerstreak@25
|
178 end
|
flickerstreak@25
|
179
|
flickerstreak@77
|
180 function Bar:GetFrame()
|
flickerstreak@77
|
181 -- this method is included for documentation purposes. It is overridden
|
flickerstreak@90
|
182 -- for each object in the :New() method.
|
flickerstreak@77
|
183 error("Invalid Bar object: used without initialization")
|
flickerstreak@77
|
184 end
|
flickerstreak@77
|
185
|
flickerstreak@90
|
186 -- only ReAction:RenameBar() should call this function. Calling from any other
|
flickerstreak@90
|
187 -- context will desync the bar list in the ReAction class.
|
flickerstreak@90
|
188 function Bar:SetName(name)
|
flickerstreak@90
|
189 self.name = name
|
flickerstreak@90
|
190 self:SetLabel(self.name) -- Bar:SetLabel() defined in Overlay.lua
|
flickerstreak@77
|
191 end
|
flickerstreak@77
|
192
|
flickerstreak@103
|
193 function Bar:GetAlpha()
|
flickerstreak@103
|
194 return self.config.alpha or 1.0
|
flickerstreak@103
|
195 end
|
flickerstreak@103
|
196
|
flickerstreak@103
|
197 function Bar:SetAlpha(value)
|
flickerstreak@103
|
198 self.config.alpha = value
|
flickerstreak@103
|
199 self:GetFrame():SetAlpha(value or 1.0)
|
flickerstreak@103
|
200 ReAction:RefreshBar(self)
|
flickerstreak@103
|
201 end
|
flickerstreak@103
|
202
|
flickerstreak@90
|
203 function Bar:AddButton(idx, button)
|
flickerstreak@90
|
204 local f = self:GetFrame()
|
flickerstreak@90
|
205
|
flickerstreak@90
|
206 -- store in a weak reverse-index array
|
flickerstreak@90
|
207 self.buttons[button] = idx
|
flickerstreak@90
|
208
|
flickerstreak@90
|
209 -- Store a properly wrapped reference to the child frame as an attribute
|
flickerstreak@90
|
210 -- (accessible via "frameref-btn#")
|
flickerstreak@90
|
211 f:SetFrameRef(format("btn%d",idx), button:GetFrame())
|
flickerstreak@90
|
212 end
|
flickerstreak@90
|
213
|
flickerstreak@90
|
214 function Bar:RemoveButton(button)
|
flickerstreak@90
|
215 local idx = self.buttons[button]
|
flickerstreak@90
|
216 if idx then
|
flickerstreak@90
|
217 self:GetFrame():SetAttribute(format("frameref-btn%d",idx),nil)
|
flickerstreak@90
|
218 self.buttons[button] = nil
|
flickerstreak@33
|
219 end
|
flickerstreak@33
|
220 end
|
flickerstreak@33
|
221
|
flickerstreak@90
|
222 -- iterator returns button, idx and does NOT iterate in index order
|
flickerstreak@90
|
223 function Bar:IterateButtons()
|
flickerstreak@75
|
224 return pairs(self.buttons)
|
flickerstreak@75
|
225 end
|
flickerstreak@75
|
226
|
flickerstreak@75
|
227 function Bar:PlaceButton(button, baseW, baseH)
|
flickerstreak@75
|
228 local idx = self.buttons[button]
|
flickerstreak@90
|
229 if idx then
|
flickerstreak@90
|
230 local r, c, s = self:GetButtonGrid()
|
flickerstreak@90
|
231 local bh, bw = self:GetButtonSize()
|
flickerstreak@90
|
232 local row, col = floor((idx-1)/c), fmod((idx-1),c) -- zero-based
|
flickerstreak@90
|
233 local x, y = col*bw + (col+0.5)*s, -(row*bh + (row+0.5)*s)
|
flickerstreak@90
|
234 local scale = bw/baseW
|
flickerstreak@90
|
235 local b = button:GetFrame()
|
flickerstreak@25
|
236
|
flickerstreak@90
|
237 b:ClearAllPoints()
|
flickerstreak@90
|
238 b:SetPoint("TOPLEFT",x/scale,y/scale)
|
flickerstreak@90
|
239 b:SetScale(scale)
|
flickerstreak@72
|
240 end
|
flickerstreak@72
|
241 end
|
flickerstreak@72
|
242
|
flickerstreak@108
|
243 function Bar:SkinButton()
|
flickerstreak@108
|
244 -- does nothing by default
|
flickerstreak@108
|
245 end |