annotate AceGUIWidget-lib-st.lua @ 38:bb41be8f13b2

Remove some older commented code. Cosmetic comment changes. Clear stray empty 'count' strings out of rebroadcast loot histories, if restoring previous version's data (and not in combat).
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Fri, 23 Dec 2011 01:08:02 +0000
parents 822b6ca3ef89
children 1070a14cfee4
rev   line source
farmbuyer@1 1 --[[-----------------------------------------------------------------------------
farmbuyer@1 2 lib-st Beta Wrapper Widget
farmbuyer@1 3
farmbuyer@1 4 lib-st does not recycle the objects (called "ST" here) that it creates and
farmbuyer@1 5 returns. We therefore do not try to hold onto an ST when the widget is
farmbuyer@1 6 being recycled. This means that Constructor() does very little work, and
farmbuyer@1 7 does not actually construct an ST.
farmbuyer@1 8
farmbuyer@1 9 OnAcquire cannot construct an ST either, because we don't yet have any
farmbuyer@1 10 creation parameters from the user to feed to CreateST. (Allowing such to
farmbuyer@1 11 be passed along from AceGUI:Create() would require changes to core AceGUI
farmbuyer@1 12 code, and I don't feel like trying to overcome that inertia.)
farmbuyer@1 13
farmbuyer@1 14 The upshot is that the widget returned from Create is broken and useless
farmbuyer@1 15 until its CreateST member has been called. This means that correct behavior
farmbuyer@1 16 depends entirely on the user remembering to do so.
farmbuyer@1 17
farmbuyer@1 18 "The gods do not protect fools. Fools are protected by more capable fools."
farmbuyer@1 19 - Ringworld
farmbuyer@1 20
farmbuyer@1 21
farmbuyer@1 22 Version 1 initial functioning implementation
farmbuyer@1 23 Version 2 reshuffle to follow new AceGUI widget coding style
farmbuyer@1 24 Version 3 add .tail_offset, defaulting to same absolute value as .head_offset
farmbuyer@1 25 -farmbuyer
farmbuyer@1 26 -------------------------------------------------------------------------------]]
farmbuyer@1 27 local Type, Version = "lib-st", 3
farmbuyer@1 28 local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
farmbuyer@1 29 if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
farmbuyer@1 30
farmbuyer@1 31 -- Lua APIs
farmbuyer@1 32 local ipairs, error = ipairs, error
farmbuyer@1 33
farmbuyer@1 34 -- WoW APIs
farmbuyer@1 35 local debugstack = debugstack
farmbuyer@1 36 local CreateFrame = CreateFrame
farmbuyer@1 37
farmbuyer@1 38
farmbuyer@1 39 --[[-----------------------------------------------------------------------------
farmbuyer@1 40 Support functions
farmbuyer@1 41 -------------------------------------------------------------------------------]]
farmbuyer@1 42
farmbuyer@1 43 -- Some AceGUI functions simply Won't Work in this context. Name them
farmbuyer@1 44 -- here, and code calling them will get a somewhat informative error().
farmbuyer@1 45 local oopsfuncs = {
farmbuyer@1 46 'SetRelativeWidth', 'SetRelativeHeight',
farmbuyer@1 47 'SetFullWidth', 'SetFullHeight',
farmbuyer@1 48 }
farmbuyer@1 49 local err = "Oops! The AceGUI function you tried to call (%s) does not "
farmbuyer@1 50 .. "make sense with lib-st and has not been implemented."
farmbuyer@1 51
farmbuyer@1 52 local function Oops(self)
farmbuyer@1 53 -- if you ever wanted an example of "brown paper bag" code, here it is
farmbuyer@1 54 local ds = debugstack(0)
farmbuyer@1 55 local func = ds:match("AceGUIWidget%-lib%-st%.lua:%d+:%s+in function `(%a+)'")
farmbuyer@1 56 error(err:format(func or "?"))
farmbuyer@1 57 end
farmbuyer@1 58
farmbuyer@1 59
farmbuyer@1 60 --[[
farmbuyer@1 61 Users with an ST already constructed can drop it into a widget directly
farmbuyer@1 62 using this routine. It must be safe to call this more than once with
farmbuyer@1 63 new widgets on the same ST.
farmbuyer@1 64
farmbuyer@1 65 This is where most of the intelligence of the wrapper is located. That
farmbuyer@1 66 is, if you can call my code "intelligent" with a straight face. Lemme
farmbuyer@1 67 try again.
farmbuyer@1 68
farmbuyer@1 69 Think of the widget wrapper as a brain. When ALL THREE neurons manage
farmbuyer@1 70 to fire at the same time and produce a thought, this function represents
farmbuyer@1 71 the thought. Sigh.
farmbuyer@1 72 ]]
farmbuyer@1 73 local ShiftingSetPoint, ShiftingSetAllPoints
farmbuyer@1 74 local function WrapST (self, st)
farmbuyer@1 75 if not st.frame then
farmbuyer@1 76 error"lib-st instance has no '.frame' field... wtf did you pass to this function?"
farmbuyer@1 77 end
farmbuyer@1 78 if st.frame.obj and (st.frame.obj ~= self) then
farmbuyer@1 79 error"lib-st instance already has an '.obj' field from a different widget, cannot use with AceGUI!"
farmbuyer@1 80 end
farmbuyer@1 81 self.st = st
farmbuyer@1 82 if not st.head then
farmbuyer@1 83 error"lib-st instance has no '.head' field, must use either ScrollingTable:CreateST or this widget's CreatST first"
farmbuyer@1 84 end
farmbuyer@1 85 self.frame = st.frame -- gutsy, but looks doable
farmbuyer@1 86
farmbuyer@1 87 -- Possibly have already wrapped this ST in a previous widget, careful.
farmbuyer@1 88 if st.frame.obj ~= self then
farmbuyer@1 89 self.frame.realSetPoint = self.frame.SetPoint
farmbuyer@1 90 self.frame.SetPoint = ShiftingSetPoint
farmbuyer@1 91 self.frame.SetAllPoints = ShiftingSetAllPoints
farmbuyer@1 92 end
farmbuyer@1 93
farmbuyer@1 94 -- This needs the .frame field. This also creates .obj inside that
farmbuyer@1 95 -- field and calls a SetScript as well.
farmbuyer@1 96 return AceGUI:RegisterAsWidget(self)
farmbuyer@1 97 end
farmbuyer@1 98
farmbuyer@1 99
farmbuyer@1 100 --[[-----------------------------------------------------------------------------
farmbuyer@1 101 Scripts
farmbuyer@1 102 -------------------------------------------------------------------------------]]
farmbuyer@1 103 --[[
farmbuyer@1 104 All of an ST's subframes are attached to its main frame, which we have in
farmbuyer@1 105 the st.frame link, and that's what AceGUI uses for all positioning. Except
farmbuyer@1 106 that ST:SetDisplayCols creates its "head" row /above/ the main frame, and
farmbuyer@1 107 so the row of labels eats into whatever upper border space AceGUI calculates,
farmbuyer@1 108 often overlapping other elements.
farmbuyer@1 109
farmbuyer@1 110 We get around this by replacing ST's main frame's SetPoint with a custom
farmbuyer@1 111 version that just moves everything down a few pixels to allow room for the
farmbuyer@1 112 head row.
farmbuyer@1 113
farmbuyer@1 114 FIXME this may need to be a secure hook (ugh, would end up calling the real
farmbuyer@1 115 setpoint twice) rather than a replacement.
farmbuyer@1 116 ]]
farmbuyer@1 117 local DEFAULT_OFFSET = 7
farmbuyer@1 118 function ShiftingSetPoint(frame,anchor,other,otheranchor,xoff,yoff)
farmbuyer@1 119 local ho,to = frame.obj.head_offset, frame.obj.tail_offset
farmbuyer@1 120 yoff = yoff or 0
farmbuyer@1 121 if anchor:sub(1,3) == "TOP" then
farmbuyer@1 122 yoff = yoff - ho
farmbuyer@1 123 elseif anchor:sub(1,6) == "BOTTOM" then
farmbuyer@1 124 yoff = yoff + to
farmbuyer@1 125 end
farmbuyer@1 126 return frame.realSetPoint(frame,anchor,other,otheranchor,xoff,yoff)
farmbuyer@1 127 end
farmbuyer@1 128 function ShiftingSetAllPoints(frame,other)
farmbuyer@1 129 ShiftingSetPoint(frame,"TOPLEFT",other,"TOPLEFT",0,0)
farmbuyer@1 130 ShiftingSetPoint(frame,"BOTTOMRIGHT",other,"BOTTOMRIGHT",0,0)
farmbuyer@1 131 end
farmbuyer@1 132
farmbuyer@1 133
farmbuyer@1 134 --[[-----------------------------------------------------------------------------
farmbuyer@1 135 Methods
farmbuyer@1 136 -------------------------------------------------------------------------------]]
farmbuyer@1 137 local methods = {
farmbuyer@1 138 -- --------------------------------------------------------------
farmbuyer@1 139 -- These are expected by AceGUI containers (and AceGUI users)
farmbuyer@1 140 --
farmbuyer@1 141 ["OnAcquire"] = function (self)
farmbuyer@1 142 -- Almost nothing can usefully be done here.
farmbuyer@1 143 self.head_offset = DEFAULT_OFFSET
farmbuyer@1 144 self.tail_offset = DEFAULT_OFFSET
farmbuyer@1 145 end,
farmbuyer@1 146
farmbuyer@1 147 ["OnRelease"] = function (self)
farmbuyer@1 148 if self.st then
farmbuyer@1 149 self.st.frame:ClearAllPoints()
farmbuyer@1 150 self.st:Hide()
farmbuyer@1 151 end
farmbuyer@1 152 self.st = nil
farmbuyer@1 153 -- XXX should also undo the frame hooks. would most likely be wasted
farmbuyer@1 154 -- cycles. if somebody actually wants to make an ST, include it inside
farmbuyer@1 155 -- an ace container, then hide the container and continue displaying
farmbuyer@1 156 -- the ST by other means, they can file a ticket
farmbuyer@1 157 end,
farmbuyer@1 158
farmbuyer@1 159 --[[
farmbuyer@1 160 STs don't use a "normal" SetWidth, if we define "normal" to be the
farmbuyer@1 161 behavior of the blizzard :SetWidth. Column width is passed in during
farmbuyer@1 162 creation of the whole ST. The SetWidth defined by an ST takes no
farmbuyer@1 163 arguments; "ReCalculateWidth" would be a more precise description of
farmbuyer@1 164 what it does.
farmbuyer@1 165
farmbuyer@1 166 Parts of AceGUI look for a .width field because a widget's SetWidth
farmbuyer@1 167 sets such. ST calculates a total width and dispatches it to its member
farmbuyer@1 168 frame... but doesn't store a local copy. We need to bridge these
farmbuyer@1 169 differences.
farmbuyer@1 170
farmbuyer@1 171 This widget wrapper does not make use of On{Width,Height}Set hooks,
farmbuyer@1 172 but the acegui widget base functions do. Since we're not inheriting
farmbuyer@1 173 them, we may as well supply them.
farmbuyer@1 174 ]]
farmbuyer@1 175 ["SetWidth"] = function (self)
farmbuyer@1 176 self.st:SetWidth() -- re-total the columns
farmbuyer@1 177 local w = self.st.frame:GetWidth() -- fetch the answer back
farmbuyer@1 178 self.frame.width = w -- store it for acegui
farmbuyer@1 179 if self.OnWidthSet then
farmbuyer@1 180 self:OnWidthSet(w)
farmbuyer@1 181 end
farmbuyer@1 182 end,
farmbuyer@1 183
farmbuyer@1 184 -- Everything said about SetWidth applies here too.
farmbuyer@1 185 ["SetHeight"] = function (self)
farmbuyer@1 186 self.st:SetHeight()
farmbuyer@1 187 local h = self.st.frame:GetHeight()
farmbuyer@1 188 self.frame.height = h
farmbuyer@1 189 if self.OnHeightSet then
farmbuyer@1 190 self:OnHeightSet(h)
farmbuyer@1 191 end
farmbuyer@1 192 end,
farmbuyer@1 193
farmbuyer@1 194 -- Some of the container layouts call Show/Hide on the innermost frame
farmbuyer@1 195 -- directly. We need to make sure the slightly-higher-level routine is
farmbuyer@1 196 -- also called.
farmbuyer@1 197 ["LayoutFinished"] = function (self)
farmbuyer@1 198 if self.frame:IsShown() then
farmbuyer@1 199 self.st:Show()
farmbuyer@1 200 else
farmbuyer@1 201 self.st:Hide()
farmbuyer@1 202 end
farmbuyer@1 203 end,
farmbuyer@1 204
farmbuyer@1 205 -- --------------------------------------------------------------
farmbuyer@1 206 -- Functions specific to this widget
farmbuyer@1 207 --
farmbuyer@1 208
farmbuyer@1 209 ["GetSTLibrary"] = function (self) -- Purely for convenience
farmbuyer@1 210 return LibST
farmbuyer@1 211 end,
farmbuyer@1 212
farmbuyer@1 213 --[[
farmbuyer@1 214 Replacement wrapper, so that instead of
farmbuyer@1 215 st = ScrollingTable:CreateST( args )
farmbuyer@1 216 the user should be able to do
farmbuyer@1 217 st = AceGUI:Create("lib-st"):CreateST( args )
farmbuyer@1 218 instead, without needing to get a lib-st handle.
farmbuyer@1 219 ]]
farmbuyer@1 220 ["CreateST"] = function (self, ...)
farmbuyer@1 221 return self:WrapST( LibST:CreateST(...) )
farmbuyer@1 222 end,
farmbuyer@1 223
farmbuyer@1 224 ["WrapST"] = WrapST,
farmbuyer@1 225 }
farmbuyer@1 226
farmbuyer@1 227
farmbuyer@1 228 --[[-----------------------------------------------------------------------------
farmbuyer@1 229 Constructor
farmbuyer@1 230 -------------------------------------------------------------------------------]]
farmbuyer@1 231 local function Constructor()
farmbuyer@1 232 -- .frame not done here, see WrapST
farmbuyer@1 233 local widget = {
farmbuyer@1 234 type = Type
farmbuyer@1 235 }
farmbuyer@1 236 for method, func in pairs(methods) do
farmbuyer@1 237 widget[method] = func
farmbuyer@1 238 end
farmbuyer@1 239
farmbuyer@1 240 for _,func in ipairs(oopsfuncs) do
farmbuyer@1 241 widget[func] = Oops
farmbuyer@1 242 end
farmbuyer@1 243
farmbuyer@1 244 -- AceGUI:RegisterAsWidget needs .frame
farmbuyer@1 245 return widget
farmbuyer@1 246 end
farmbuyer@1 247
farmbuyer@1 248 AceGUI:RegisterWidgetType(Type,Constructor,Version)
farmbuyer@1 249