annotate Gui.lua @ 68:a177b863ed6c

Event chaining from the data storage to the GUI elements
author John@Yosemite-PC
date Wed, 28 Mar 2012 23:29:36 -0400
parents 8387dc2ff658
children b7352f007028
rev   line source
John@38 1 local AceGUI = LibStub("AceGUI-3.0")
John@42 2 local bsk=bsk
John@42 3 local _G=_G
John@42 4 local table=table
John@42 5 local pairs=pairs
John@65 6 local setmetatable=setmetatable
John@42 7 local ipairs=ipairs
John@42 8 local string=string
John@67 9 local sformat=string.format
John@42 10 local tostring=tostring
John@42 11 local type=type
John@42 12 local getn=getn
John@42 13 setfenv(1,bsk)
John@1 14
John@56 15 local copy = function(t)
John@56 16 local c = {}
John@56 17 if not t then return c end
John@56 18 for i,v in pairs(t) do c[i] = v end
John@56 19 return c
John@56 20 end
John@56 21 local colorize = function(str,color)
John@56 22 if str==nil or str=="" then return "" end
John@56 23 if type(color) == "table" then
John@56 24 color = string.format("%02x%02x%02x",255*color.r,255*color.g,255*color.b)
John@56 25 end
John@56 26 if color == nil then return str end
John@56 27 return "|cff"..tostring(color or "ffffff")..str.."|r"
John@56 28 end
John@1 29
John@63 30 local CreateListSelector = function(SListPopulator)
John@56 31 PersonList:RefreshRaidList()
John@56 32 local pulldown = AceGUI:Create("Dropdown")
John@56 33 local pull = {}
John@56 34 local ltemp = 0
John@56 35 local lids = LootLists:GetAllIds()
John@56 36 for _,v in pairs(lids) do
John@56 37 local l = LootLists:Select(v)
John@56 38 pull[l:GetId()] = l:GetName()
John@56 39 --local entry = {value=i,text=v.name}
John@56 40 if l:GetLength() > 0 then
John@56 41 pulldown:SetItemDisabled(i,true)
John@56 42 if ltemp == 0 then
John@56 43 ltemp = l:GetId()
John@51 44 end
John@51 45 end
John@1 46 end
John@56 47 pulldown:SetWidth(175)
John@56 48 pulldown:SetList(pull)
John@68 49 pulldown:SetCallback("OnValueChanged", function(_,_,value) SListPopulator:SelectList(value) end)
John@68 50 if ltemp > 0 then pulldown:SetValue(ltemp); SListPopulator:SelectList(ltemp) end -- sadly, SetValue doesn't fire a OnValueChanged
John@56 51 return pulldown
John@1 52 end
John@1 53
John@65 54 local f, right
John@59 55 local escapeButton =
John@59 56 {
John@59 57 shown = false,
John@59 58 ["IsShown"] = function(self) return self.shown end,
John@60 59 ["Hide"] = function(self) if f then AceGUI:Release(f); self.shown=false end end
John@59 60 }
John@38 61
John@63 62
John@65 63 SelectorListEventDispatcher =
John@63 64 {
John@65 65 listeners = nil,
John@63 66 target = nil,
John@67 67 line = nil,
John@63 68 ["SetTarget"] = function(self,other)
John@63 69 self.target = other
John@65 70 self.target:SetCallback("OnSelectionCleared",function(...) self:OnSelectionCleared(...) end)
John@65 71 self.target:SetCallback("OnSelection",function(...) self:OnSelection(...) end)
John@63 72 end,
John@63 73 ["RegisterListener"] = function(self,other) table.insert(self.listeners,other) end,
John@63 74 ["OnSelectionCleared"] = function(self,_)
John@67 75 self.line = nil
John@63 76 self:Event("OnSelectionCleared")
John@63 77 end,
John@65 78 ["OnSelection"] = function(self,_,_,line)
John@67 79 self.line = line
John@63 80 self:Event("OnSelection",line)
John@63 81 end,
John@63 82 ["Event"] = function(self,event,arg)
John@63 83 if not self.target then error("Event called with no listener...") end
John@63 84 if not self.listeners then return end
John@63 85 for i,v in pairs(self.listeners) do
John@67 86 --bsk.print("listener")
John@63 87 if type(v) == "table" then
John@63 88 if v[event] then
John@63 89 v[event](v,arg)
John@63 90 end
John@63 91 elseif type(v) == "function" then
John@63 92 v(event,arg)
John@63 93 elseif type(v) ~= "nil" then -- allow nils to pass quietly
John@63 94 _G.error("Bad listener - "..type(v))
John@63 95 end
John@63 96 end
John@63 97 end,
John@67 98 ["Release"] = function(self) self.listeners = {}; self.target=nil; self.line=nil end,
John@67 99 ["LatestValue"] = function(self) return self.line end
John@63 100 }
John@65 101 function SelectorListEventDispatcher:new()
John@65 102 local t = {}
John@65 103 setmetatable(t,SelectorListEventDispatcher)
John@65 104 self.__index = self
John@65 105 t.listeners = {}
John@65 106 return t
John@63 107 end
John@65 108
John@65 109 SListEventDispatch = SelectorListEventDispatcher:new()
John@65 110 LListEventDispatch = SelectorListEventDispatcher:new()
John@67 111 RListEventDispatch = SelectorListEventDispatcher:new()
John@65 112
John@63 113 local SListPopulator =
John@63 114 {
John@63 115 filtered = false,
John@63 116 widget = nil,
John@63 117 data = nil,
John@63 118 lref = nil,
John@63 119
John@63 120 ["Release"] = function(self) self.filtered, self.widget, self.data, self.lref = false, nil, nil, nil end,
John@63 121 ["Redraw"] = function(self)
John@63 122 if self.lref == nil or self.widget == nil then return end -- don't do work if not fully initialized
John@63 123 self.data = {}
John@63 124 for le in self.lref:OrderedListEntryIter() do
John@63 125 local disabled = not PersonList:IsActive(le:GetId())
John@63 126 if not self.filtered or not disabled then
John@63 127 local line = {value=le:GetId(),text=le:GetName(),icon=[[Interface\Glues\CharacterCreate\UI-CharacterCreate-Classes]]}
John@63 128 line.iconCoords=_G.CLASS_ICON_TCOORDS[le:GetClass()]
John@67 129 line.textPlain = line.text
John@63 130 line.text=colorize(line.text,_G.RAID_CLASS_COLORS[le:GetClass()])
John@63 131 line.disabled = disabled
John@63 132 table.insert(self.data,line)
John@63 133 end
John@63 134 end
John@63 135 self.widget:SetList(self.data)
John@65 136 SListEventDispatch:Event("Redraw")
John@63 137 end,
John@63 138 ["SetWidget"] = function(self,w)
John@65 139 if type(w) ~= "table" or type(w.SetList) ~= "function" then
John@63 140 _G.error("Bad SetWidget")
John@63 141 end
John@63 142 self.widget = w
John@63 143 end,
John@63 144 ["SetFiltered"] = function(self,value)
John@63 145 self.filtered = value
John@63 146 self:Redraw()
John@63 147 end,
John@68 148 ["SelectList"] = function(self,value)
John@63 149 self.lref = LootLists:Select(value)
John@63 150 self:Redraw()
John@68 151 end,
John@68 152 ["DataEvent"] = function(self)
John@68 153 self:Redraw()
John@63 154 end
John@63 155 }
John@63 156
John@68 157 DataEventDispatch =
John@68 158 {
John@68 159 -- todo: batch events
John@68 160 listeners = {},
John@68 161 ["DataEvent"] = function(self,_) --todo: pass along the received event
John@68 162 for i,v in pairs(self.listeners) do
John@68 163 if v and v["DataEvent"] then
John@68 164 v:DataEvent()
John@68 165 end
John@68 166 end
John@68 167 end,
John@68 168 ["RegisterListener"] = function(self,listener)
John@68 169 if not listener or not listener["DataEvent"] then
John@68 170 _G.error("Bad listener")
John@68 171 end
John@68 172 table.insert(self.listeners,listener)
John@68 173 end
John@68 174 }
John@68 175
John@68 176 function OnInitializeSetStaticData()
John@68 177 SetChangeListener(DataEventDispatch)
John@68 178 DataEventDispatch:RegisterListener(SListPopulator)
John@68 179 end
John@68 180
John@42 181 function CreateGUI()
John@59 182 -- special registration procedure to be closable with the escape button
John@59 183 --escapeButton.shown = true
John@59 184 --_G["BSK_ESCAPEBUTTON"] = escapeButton
John@59 185 --table.insert(_G.UISpecialFrames, "BSK_ESCAPEBUTTON")
John@59 186
John@60 187 if f then return end -- no second gui please
John@60 188 local admin = bsk.admin or true
John@59 189 f = AceGUI:Create("Frame")
John@1 190
John@67 191 f:SetCallback("OnClose",function(widget) escapeButton.shown = false; AceGUI:Release(widget); f=nil; right=nil; SListEventDispatch:Release(); LListEventDispatch:Release(); SListPopulator:Release(); RListEventDispatch:Release() end)
John@56 192 f:SetTitle("BSK")
John@56 193 f:SetLayout("Flow")
John@56 194 f:SetHeight(680)
John@56 195 f:SetWidth(580)
John@1 196
John@56 197 local left = AceGUI:Create("InlineGroup")
John@56 198 left:SetLayout("List")
John@56 199 left:SetWidth(175)
John@56 200 left:SetFullHeight(true)
John@56 201 left.alignoffset=0.25 -- hack, as per http://forums.wowace.com/showthread.php?t=17114
John@1 202
John@65 203 right = AceGUI:Create("InlineGroup")
John@56 204 right:SetLayout("Flow")
John@56 205 right:SetWidth(700-175-160)
John@56 206 right:SetFullHeight(true)
John@56 207 right.alignoffset=0.25
John@38 208
John@56 209 local t1 = AceGUI:Create("SelectorList")
John@56 210 t1:SetNumLines(25)
John@56 211 t1:SetFullWidth(true)
John@56 212 t1:SetInteractive(admin)
John@63 213 SListPopulator:SetWidget(t1)
John@63 214 SListEventDispatch:SetTarget(t1)
John@38 215
John@63 216 local p1 = CreateListSelector(SListPopulator)
John@56 217 p1:SetFullWidth(true)
John@38 218
John@56 219 left:AddChild(p1)
John@56 220 left:AddChild(t1)
John@38 221
John@56 222 local t2 = AceGUI:Create("SelectorList")
John@56 223 t2:SetNumLines(7)
John@56 224 t2:SetFullWidth(true)
John@56 225 t2:EnableButtonTooltips(true)
John@56 226 t2:SetList({
John@56 227 {
John@56 228 value=1,
John@56 229 text = "|cffa335ee|Hitem:77109:4080:4009:0:0:0:0:0:85:0|h[Band of Reconstruction]|h|r",
John@56 230 link = "|cffa335ee|Hitem:77109:4080:4009:0:0:0:0:0:85:0|h[Band of Reconstruction]|h|r",
John@56 231 },
John@56 232 {
John@56 233 value=2,
John@56 234 text = "|cffa335ee|Hitem:19351:0:0:0:0:0:0:0:85:0|h[Maladath, Runed Blade of the Black Flight]|h|r",
John@56 235 link = "|cffa335ee|Hitem:19351:0:0:0:0:0:0:0:85:0|h[Maladath, Runed Blade of the Black Flight]|h|r"
John@56 236 },
John@56 237 {
John@56 238 value=3,
John@56 239 text = "|cffa335ee|Hitem:31986:0:0:0:0:0:0:0:85:0|h[Merciless Gladiator's Crossbow of the Phoenix]|h|r",
John@56 240 link = "|cffa335ee|Hitem:31986:0:0:0:0:0:0:0:85:0|h[Merciless Gladiator's Crossbow of the Phoenix]|h|r"
John@56 241 },
John@56 242 {
John@56 243 value=4,
John@56 244 text = "|cffa335ee|Hitem:65003:0:0:0:0:0:0:0:85:0|h[Reclaimed Ashkandi, Greatsword of the Brotherhood]|h|r",
John@56 245 link = "|cffa335ee|Hitem:65003:0:0:0:0:0:0:0:85:0|h[Reclaimed Ashkandi, Greatsword of the Brotherhood]|h|r"
John@56 246 },
John@56 247 {
John@56 248 value=5,
John@56 249 text = "|cffff8000|Hitem:19019:0:0:0:0:0:0:0:85:0|h[Thunderfury, Blessed Blade of the Windseeker]|h|r",
John@56 250 link = "|cffff8000|Hitem:19019:0:0:0:0:0:0:0:85:0|h[Thunderfury, Blessed Blade of the Windseeker]|h|r"
John@56 251 },
John@56 252 })
John@65 253 LListEventDispatch:SetTarget(t2)
John@65 254
John@65 255 local biddingZone = AceGUI:Create("SimpleGroup")
John@65 256 biddingZone:SetLayout("Flow")
John@65 257 biddingZone:SetFullWidth(true)
John@38 258
John@60 259 local alb1, alb2, alb3
John@60 260 if admin then
John@60 261 alb1 = AceGUI:Create("Button")
John@60 262 alb1:SetWidth(100)
John@60 263 alb1:SetText("Open Bids")
John@65 264 alb1.userdata =
John@65 265 {
John@65 266 state = false,
John@65 267 widget = alb1,
John@65 268 ["Redraw"] = function(self,_) self.widget:SetDisabled(true); self.item = nil end,
John@65 269 ["OnSelection"] = function(self,value) self.widget:SetDisabled(false); self.item = value end,
John@65 270 ["OnSelectionCleared"] = function(self) self.widget:SetDisabled(true); self.item = nil end
John@65 271 }
John@65 272 alb1:SetDisabled(true)
John@65 273 LListEventDispatch:RegisterListener(alb1.userdata)
John@65 274 alb1:SetCallback("OnClick",
John@65 275 function(widget)
John@65 276 if widget.userdata.state then -- we were bidding when the button was pressed
John@65 277 biddingZone:ReleaseChildren()
John@68 278 widget:SetText("Open Bids")
John@67 279 RListEventDispatch:Release()
John@65 280 else
John@68 281 widget:SetText("Close bids")
John@65 282 local spacer = AceGUI:Create("Label")
John@65 283 spacer:SetText(" ")
John@65 284 spacer:SetFullWidth(true)
John@65 285 local spacer2 = AceGUI:Create("Label")
John@65 286 spacer2:SetText(" ")
John@65 287 spacer2:SetFullWidth(true)
John@65 288
John@65 289 local label = AceGUI:Create("Label")
John@65 290 label:SetText("Bidding now open for ...")
John@65 291 local biddingOn = AceGUI:Create("InteractiveLabel")
John@67 292 biddingOn.userdata = { LListEventDispatch:LatestValue().link }
John@65 293 biddingOn:SetText(biddingOn.userdata[1])
John@65 294 biddingOn:SetFullWidth(true)
John@65 295 biddingOn:SetCallback("OnEnter", function(widget) _G.GameTooltip:SetOwner(widget.frame,"ANCHOR_RIGHT"); _G.GameTooltip:SetHyperlink(widget.userdata[1]); _G.GameTooltip:Show() end )
John@65 296 biddingOn:SetCallback("OnLeave", function(widget) _G.GameTooltip:Hide() end )
John@65 297 local b1 = AceGUI:Create("SelectorList")
John@65 298 b1:SetNumLines(6)
John@65 299 b1:SetInteractive(admin)
John@65 300 local bidTitle = AceGUI:Create("Label")
John@65 301 bidTitle:SetText("Current bids")
John@65 302 bidTitle:SetFullWidth(true)
John@65 303
John@65 304 local bidRetractButton = AceGUI:Create("Button")
John@65 305 bidRetractButton:SetText("Place Bid")
John@65 306 bidRetractButton:SetWidth(100)
John@65 307 local rollButton = AceGUI:Create("Button")
John@65 308 rollButton:SetText("Offset Roll")
John@65 309 rollButton:SetWidth(100)
John@65 310
John@67 311 local dummydata= {}
John@67 312 local tree =SListPopulator.data
John@67 313 for i,v in pairs(tree) do dummydata[i] = copy(v); dummydata[i].disabled = false end
John@67 314 if dummydata[2] then dummydata[2].text = dummydata[2].text .. " (roll 73)" end
John@67 315 b1:SetList(dummydata)
John@67 316
John@65 317 local g1
John@65 318 if admin then
John@67 319 RListEventDispatch:SetTarget(b1)
John@65 320 b1.alignoffset = 0.25 -- or else g1 won't align well
John@65 321 g1 = AceGUI:Create("SimpleGroup")
John@65 322 g1.alignoffset = 0.25
John@65 323 g1:SetWidth(120)
John@65 324 g1:SetLayout("List")
John@65 325
John@67 326 -- todo: convoluted and repetitive - surely there's a
John@67 327 -- better way than this ...
John@65 328 adminForce = AceGUI:Create("Button")
John@67 329 if SListEventDispatch:LatestValue() then
John@67 330 adminForce:SetText(sformat("Force bid (%s)",SListEventDispatch:LatestValue().textPlain))
John@67 331 adminForce:SetDisabled(false)
John@67 332 else
John@67 333 adminForce:SetText("Force bid")
John@67 334 adminForce:SetDisabled(true)
John@67 335 end
John@67 336 adminForce:SetWidth(160)
John@67 337 adminForce.userdata =
John@67 338 {
John@67 339 widget = adminForce,
John@67 340 ["Redraw"] = function(self,_) self.widget:SetDisabled(true); self.widget:SetText("Force bid") end,
John@67 341 ["OnSelection"] = function(self,_) self.widget:SetDisabled(false); self.widget:SetText(sformat("Force bid (%s)",SListEventDispatch:LatestValue().textPlain)) end,
John@67 342 ["OnSelectionCleared"] = function(self) self.widget:SetDisabled(true); self.widget:SetText("Force bid") end
John@67 343 }
John@67 344 SListEventDispatch:RegisterListener(adminForce.userdata)
John@65 345
John@65 346 adminRetract = AceGUI:Create("Button")
John@67 347 if RListEventDispatch:LatestValue() then
John@67 348 adminRetract:SetText(sformat("Retract bid (%s)",RListEventDispatch:LatestValue().textPlain))
John@67 349 adminRetract:SetDisabled(false)
John@67 350 else
John@67 351 adminRetract:SetText("Retract bid")
John@67 352 adminRetract:SetDisabled(true)
John@67 353 end
John@67 354 adminRetract:SetWidth(160)
John@67 355 adminRetract.userdata =
John@67 356 {
John@67 357 widget = adminRetract,
John@67 358 ["Redraw"] = function(self,_) self.widget:SetDisabled(true); self.widget:SetText("Retract bid") end,
John@67 359 ["OnSelection"] = function(self,_) self.widget:SetDisabled(false); self.widget:SetText(sformat("Retract bid (%s)",RListEventDispatch:LatestValue().textPlain)) end,
John@67 360 ["OnSelectionCleared"] = function(self) self.widget:SetDisabled(true); self.widget:SetText("Retract bid") end
John@67 361 }
John@67 362 RListEventDispatch:RegisterListener(adminRetract.userdata)
John@67 363 adminRetract:SetDisabled(true)
John@65 364
John@65 365 g1:AddChildren(adminForce,adminRetract)
John@65 366 end
John@65 367
John@65 368 biddingZone:AddChildren(spacer,label,biddingOn,bidRetractButton,rollButton,spacer2,bidTitle,b1)
John@65 369 if admin then biddingZone:AddChildren(g1) end
John@65 370 end
John@65 371 widget.userdata.state = not widget.userdata.state
John@65 372 end
John@65 373 )
John@60 374
John@60 375 alb2 = AceGUI:Create("Button")
John@60 376 alb2:SetWidth(100)
John@60 377 alb2:SetText("Assign")
John@65 378 alb2.userdata =
John@65 379 {
John@65 380 widget = alb2,
John@65 381 ["OnUpdate"] = function(self) self.widget:SetDisabled(not (self.slist.checked and self.llist.checked)) end,
John@65 382 }
John@65 383 alb2.userdata.slist =
John@65 384 {
John@65 385 parent = alb2.userdata,
John@65 386 checked = false,
John@65 387 ["Redraw"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 388 ["OnSelection"] = function(self) self.checked = true; self.parent:OnUpdate() end,
John@65 389 ["OnSelectionCleared"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 390 }
John@65 391 alb2.userdata.llist =
John@65 392 {
John@65 393 parent = alb2.userdata,
John@65 394 checked = false,
John@65 395 ["Redraw"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 396 ["OnSelection"] = function(self) self.checked = true; self.parent:OnUpdate() end,
John@65 397 ["OnSelectionCleared"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 398 }
John@65 399 SListEventDispatch:RegisterListener(alb2.userdata.slist)
John@65 400 LListEventDispatch:RegisterListener(alb2.userdata.llist)
John@60 401
John@60 402 alb3 = AceGUI:Create("Button")
John@60 403 alb3:SetWidth(100)
John@60 404 alb3:SetText("Suicide")
John@65 405 alb3.userdata = -- TODO: holy hell, come up with a pattern or something for this ....
John@65 406 {
John@65 407 widget = alb3,
John@65 408 ["OnUpdate"] = function(self) self.widget:SetDisabled(not (self.slist.checked and self.llist.checked)) end,
John@65 409 }
John@65 410 alb3.userdata.slist =
John@65 411 {
John@65 412 parent = alb3.userdata,
John@65 413 checked = false,
John@65 414 ["Redraw"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 415 ["OnSelection"] = function(self) self.checked = true; self.parent:OnUpdate() end,
John@65 416 ["OnSelectionCleared"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 417 }
John@65 418 alb3.userdata.llist =
John@65 419 {
John@65 420 parent = alb3.userdata,
John@65 421 checked = false,
John@65 422 ["Redraw"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 423 ["OnSelection"] = function(self) self.checked = true; self.parent:OnUpdate() end,
John@65 424 ["OnSelectionCleared"] = function(self) self.checked = false; self.parent:OnUpdate() end,
John@65 425 }
John@65 426 SListEventDispatch:RegisterListener(alb3.userdata.slist)
John@65 427 LListEventDispatch:RegisterListener(alb3.userdata.llist)
John@60 428 end
John@38 429
John@65 430 local suicideSelected, undo
John@60 431 if admin then
John@60 432
John@60 433 suicideSelected = AceGUI:Create("Button")
John@60 434 suicideSelected:SetFullWidth(true)
John@60 435 suicideSelected:SetText("Suicide")
John@68 436 suicideSelected:SetCallback("OnClick",
John@68 437 function(_)
John@68 438 local p = SListEventDispatch:LatestValue()
John@68 439 local lref = SListPopulator.lref
John@68 440 lref:SuicidePerson(p.value)
John@68 441 end
John@68 442 )
John@68 443
John@63 444 -- use userdata + SListEventDispatch to toggle state
John@63 445 suicideSelected.userdata =
John@63 446 {
John@63 447 widget = suicideSelected,
John@65 448 ["Redraw"] = function(self,_) self.widget:SetDisabled(true) end,
John@63 449 ["OnSelection"] = function(self,_) self.widget:SetDisabled(false) end,
John@63 450 ["OnSelectionCleared"] = function(self) self.widget:SetDisabled(true) end
John@63 451 }
John@63 452 SListEventDispatch:RegisterListener(suicideSelected.userdata)
John@60 453
John@60 454 undo = AceGUI:Create("Button")
John@63 455 undo:SetText("Undo / out of order")
John@60 456 undo:SetFullWidth(true)
John@63 457 undo:SetDisabled(true)
John@60 458 end
John@60 459
John@56 460 local filter = AceGUI:Create("CheckBox")
John@56 461 filter:SetLabel("Only show active")
John@56 462 filter:SetFullWidth(true)
John@63 463 filter:SetValue(false)
John@63 464 SListPopulator:SetFiltered(false)
John@63 465 filter:SetCallback("OnValueChanged",function(widget,_,value) SListPopulator:SetFiltered(value) end)
John@56 466
John@56 467 left:AddChildren(filter)
John@56 468 if admin then left:AddChildren(suicideSelected,undo) end
John@56 469 right:AddChildren(t2)
John@56 470 if admin then right:AddChildren(alb1,alb2,alb3) end
John@56 471 right:AddChildren(biddingZone)
John@56 472 f:AddChildren(left,right)
John@58 473
John@58 474
John@1 475 end