comparison gui.lua @ 1:822b6ca3ef89

Import of 2.15, moving to wowace svn.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Sat, 16 Apr 2011 06:03:29 +0000
parents
children fe437e761ef8
comparison
equal deleted inserted replaced
0:0f14a1e5364d 1:822b6ca3ef89
1 local addon = select(2,...)
2
3 --[[
4 Purely the AceGUI-related routines, and the subroutines needed for support.
5 ------ Constants
6 ------ Locals
7 ------ Behind the scenes routines
8 ------ Main GUI Window
9 ------ Popup dialogs
10 ]]
11
12 ------ Constants
13 local eoi_st_rowheight = 20
14 local eoi_st_displayed_rows = math.floor(366/eoi_st_rowheight)
15 local eoi_st_textured_item_format = "|T%s:"..(eoi_st_rowheight-2).."|t %s[%s]|r%s"
16 local eoi_st_otherrow_bgcolortable = {
17 wipe = { ["r"] = 0.3, ["g"] = 0.3, ["b"] = 0.3},
18 kill = { ["r"] = 0.2, ["g"] = 0.2, ["b"] = 0.2},
19 time = { ["r"] = 0x0/255, ["g"] = 0x0/255, ["b"] = 1, ["a"] = 0.3},
20 }
21 eoi_st_otherrow_bgcolortable[""] = eoi_st_otherrow_bgcolortable["kill"]
22 eoi_st_otherrow_bgcolortable["realm"] = eoi_st_otherrow_bgcolortable["time"]
23 local eoi_st_otherrow_bgcolortable_default
24 local eoi_st_lootrow_col3_colortable = {
25 [""] = { text = "", r = 1.0, g = 1.0, b = 1.0, a = 1.0 },
26 shard = { text = "shard", r = 0xa3/255, g = 0x35/255, b = 0xee/255, a = 1.0 },
27 offspec = { text = "offspec", r = 0.78, g = 0.61, b = 0.43, a = 1.0 },
28 gvault = { text = "guild vault", r = 0x33/255, g = 1.0, b = 0x99/255, a = 1.0 },
29 }
30 local function eoi_st_lootrow_col3_colortable_func (data, cols, realrow, column, table)
31 local disp = data[realrow].disposition
32 return eoi_st_lootrow_col3_colortable[disp or ""]
33 end
34 addon.time_column1_used_mt = { __index = {
35 [2] = {value=""},
36 [3] = {value=""},
37 } }
38 local time_column1_used_mt = addon.time_column1_used_mt
39
40
41 ------ Locals
42 local GUI = LibStub("AceGUI-3.0")
43 local flib = LibStub("LibFarmbuyer")
44
45 local g_loot = nil
46 local g_generated = nil
47
48 local pairs, ipairs, tinsert, tremove, tonumber = pairs, ipairs, table.insert, table.remove, tonumber
49
50 local pprint, tabledump = addon.pprint, flib.tabledump
51 local GetItemInfo = GetItemInfo
52
53 -- En masse forward decls of symbols defined inside local blocks
54 local _generate_text, _populate_text_specials
55 local _tabtexts, _taborder -- filled out in gui block scope
56
57 -- Working around this bug:
58 -- http://forums.wowace.com/showpost.php?p=295202&postcount=31
59 do
60 local function FixFrameLevel (level, ...)
61 for i = 1, select("#", ...) do
62 local button = select(i, ...)
63 button:SetFrameLevel(level)
64 end
65 end
66
67 local function FixMenuFrameLevels()
68 local f = DropDownList1
69 local i = 1
70 while f do
71 FixFrameLevel (f:GetFrameLevel() + 2, f:GetChildren())
72 i = i + 1
73 f = _G["DropDownList"..i]
74 end
75 end
76
77 -- To fix Blizzard's bug caused by the new "self:SetFrameLevel(2);"
78 hooksecurefunc("UIDropDownMenu_CreateFrames", FixMenuFrameLevels)
79 end
80
81
82 ------ Behind the scenes routines
83 -- Text generation
84 do
85 local next_insertion_position = 2 -- position in _taborder
86 local text_gen_funcs, specials_gen_funcs = {}, {}
87 local accumulator = {}
88
89 -- Can do clever things by passing other halting points as zero
90 function addon:zero_printed_fenceposts(zero)
91 for t in pairs(text_gen_funcs) do
92 g_loot.printed[t] = zero or g_loot.printed[t] or 0
93 end
94 end
95
96 -- This function is called during load, so be careful!
97 function addon:register_text_generator (text_type, title, description, generator, opt_specgen)
98 if type(generator) ~= 'function' then
99 error(("Generator for text type '%s' must be a function!"):format(text_type))
100 end
101 _tabtexts[text_type] = { title=title, desc=description }
102 tinsert (_taborder, next_insertion_position, text_type)
103 next_insertion_position = next_insertion_position + 1
104 text_gen_funcs[text_type] = generator
105 specials_gen_funcs[text_type] = opt_specgen
106 end
107
108 -- Called by tabs_generated_text_OGS
109 function _generate_text (text_type)
110 local f = text_gen_funcs[text_type]
111 if not f then
112 error(("Generator called for unregistered text type '%s'."):format(text_type))
113 end
114 g_generated = g_generated or {}
115 g_loot[text_type] = g_loot[text_type] or ""
116
117 if g_loot.printed[text_type] >= #g_loot then return false end
118 assert(addon.loot_clean == #g_loot, tostring(addon.loot_clean) .. " ~= " .. #g_loot)
119 -- if glc is nil, #==0 test already returned
120
121 local ok,ret = pcall (f, text_type, g_loot, g_loot.printed[text_type], g_generated, accumulator)
122 if not ok then
123 error(("ERROR: text generator '%s' failed: %s"):format(text_type, ret))
124 return false
125 end
126 if ret then
127 g_loot.printed[text_type] = #g_loot
128 g_generated[text_type] = (g_generated[text_type] or "") .. table.concat(accumulator,'\n') .. '\n'
129 end
130 wipe(accumulator)
131 return ret
132 end
133 function _populate_text_specials (editbox, specials, mkb, text_type)
134 local f = specials_gen_funcs[text_type]
135 if not f then return end
136 pcall (f, text_type, editbox, specials, mkb)
137 end
138 end
139
140 --[[
141 The g_loot table is populated only with "behavior-relevant" data (names,
142 links, etc). This function runs through it and fills out the "display-
143 relevant" bits (icons, user-friendly labels, etc). Everything from the
144 loot_clean index to the end of the table is filled out, loot_clean is
145 updated. Override the starting point with the argument.
146
147 XXX blizzard's scrolling update and lib-st keep finding some way of displaying
148 the grid without ever calling the hooked refresh, thereby skipping this
149 function and erroring on missing columnar data. fuckit. from now on
150 this function gets called everywhere, all the time, and loops over the
151 entire goddamn table each time. If we can't find blizz's scrollframe bugs,
152 we'll just work around them. Sorry for your smoking CPU.
153
154 FIXME just move this functionality to a per-entry function and call it once
155 in _addlootentry. --actually no, then the columnar data won't be updated once
156 the backend data is changed on the fly.
157 ]]
158 do
159 local grammar = { -- not worth making a mt for this
160 [2] = "nd",
161 [3] = "rd",
162 }
163
164 function addon:_fill_out_eoi_data (opt_starting_index)
165 if #g_loot < 1 then
166 --pprint('_f_o_e_d', "#g_loot<1")
167 self.loot_clean = nil
168 opt_starting_index = nil
169 end
170 for i = (opt_starting_index or self.loot_clean or 1), #g_loot do
171 local e = g_loot[i]
172 if e == nil then
173 self.loot_clean = nil
174 pprint('_f_o_e_d', "index",i,"somehow still in loop past",#g_loot,"bailing")
175 return
176 end
177
178 -- XXX FIXME a major weakness here is that we're constantly replacing
179 -- what's already been created. Lots of garbage. Trying to detect what
180 -- actually needs to be replaced is even worse. We'll live with
181 -- garbage for now.
182 if e.kind == 'loot' then
183 local textured = eoi_st_textured_item_format:format (e.itexture, self.quality_hexes[e.quality], e.itemname, e.count or "")
184 e.cols = {
185 {value = textured},
186 {value = e.person},
187 { color = eoi_st_lootrow_col3_colortable_func }
188 }
189 -- This is horrible. Must do better.
190 if e.extratext then for k,v in pairs(eoi_st_lootrow_col3_colortable) do
191 if v.text == e.extratext then
192 e.disposition = k
193 --e.extratext = nil, not feasible
194 break
195 end
196 end end
197 local ex = eoi_st_lootrow_col3_colortable[e.disposition or ""].text
198 if e.bcast_from and e.extratext then
199 ex = e.extratext .. " (from " .. e.bcast_from .. ")"
200 elseif e.bcast_from then
201 ex = "(from " .. e.bcast_from .. ")"
202 elseif e.extratext then
203 ex = e.extratext
204 end
205 e.cols[3].value = ex
206
207 elseif e.kind == 'boss' then
208 local v
209 if e.reason == 'kill' then
210 if e.attempts == 1 then
211 v = "one-shot"
212 else
213 v = ("kill on %d%s attempt"):format(e.attempts, grammar[e.attempts] or "th")
214 end
215 v = ("%s (%d:%.2d)"):format(v, math.floor(e.duration/60), math.floor(e.duration%60))
216 elseif e.reason == 'wipe' then
217 v = ("wipe (%d:%.2d)"):format(math.floor(e.duration/60), math.floor(e.duration%60))
218 end
219 e.cols = {
220 {value = e.bosskill},
221 {value = e.instance},
222 {value = v or ""},
223 }
224
225 elseif e.kind == 'time' then
226 e.cols = setmetatable({
227 {value=e.startday.text},
228 }, time_column1_used_mt)
229 --[[e.cols = {
230 {value=e.startday.text},
231 {value=""},
232 {value=""},
233 }]]
234
235 end
236 end
237 self.loot_clean = #g_loot
238 end
239 end
240
241 do
242 local offset
243 function addon:_fill_out_hist_data (opt_starting_index)
244 -- Clearing history finishes this function with #hist==0 and hist_clean==0.
245 -- The next call typically detects this (#<1) and handles it. If loot is
246 -- recorded before then, it results in hist_clean==0 and #hist==1, which
247 -- breaks the first iteration of the loop. Thus, the "extra" test here:
248 if #self.history < 1 or self.hist_clean == 0 then
249 self.hist_clean = nil
250 opt_starting_index = nil
251 end
252 if not self.history.st then
253 self.history.st = {
254 { kind = "realm",
255 cols = setmetatable({
256 { value = self.history.realm },
257 }, time_column1_used_mt)
258 }
259 }
260 offset = #self.history.st
261 end
262 local st = self.history.st
263 for i = (opt_starting_index or self.hist_clean or 1), #self.history do
264 local h = self.history[i]
265 local sti = i+offset
266 if not st[sti] then
267 st[sti] = { kind = "history" }
268 end
269 local sth = st[sti] -- corresponding ST entry for h
270
271 sth.cols = sth.cols or {
272 { value = h.name },
273 {},--{ value = h[1].id },
274 {},--{ value = h[1].when },
275 }
276
277 if sth.shown ~= h[1].id then
278 -- things have changed, redo the row with new data
279 local iname, ilink, iquality, _,_,_,_,_,_, itexture = GetItemInfo(h[1].id)
280 local textured = eoi_st_textured_item_format:format (itexture, self.quality_hexes[iquality], iname, h[1].count or "")
281 sth.cols[2].value = textured
282 sth.cols[3].value = h[1].when
283 sth.shown = h[1].id
284 end
285
286 end
287 self.hist_clean = #self.history
288 end
289 end
290
291
292 ------ Main GUI Window
293 -- Lots of shared data here, kept in a large local scope. For readability,
294 -- indentation of the scope as a whole is kicked left a notch.
295 do
296 local _d
297 local function setstatus(txt) _d:SetStatusText(txt) end
298 local function statusy_OnLeave() setstatus("") end
299 local tabgroup_tabs
300
301 --[[
302 Controls for the tabs on the left side of the main display.
303 ]]
304 _tabtexts = {
305 ["eoi"] = {title=[[Loot]], desc=[[Observed loot, plus boss kills and other events of interest]]},
306 ["hist"] = {title=[[History]], desc=[[A short semi-permanent record]]},
307 ["help"] = {title=[[Help]], desc=[[Instructions, reminders, and tips for non-obvious features]]},
308 ["opt"] = {title=[[Options]], desc=[[Options for fine-tuning behavior]]},
309 --["adv"] = {title=[[Advanced]], desc=[[Debugging and testing]]},
310 }
311 if addon.author_debug then
312 _taborder = { "eoi", "hist", "help", "opt" }
313 else _taborder = { "eoi", "help", "opt" } end
314
315 --[[
316 This is a table of callback functions, each responsible for drawing a tab
317 into the container passed in the first argument. Special-purpose buttons
318 can optionally be created (mkbutton) and added to the container in the second
319 argument.
320 ]]
321 local tabs_OnGroupSelected = {}
322 local mkbutton
323 local tabs_OnGroupSelected_func, tabs_generated_text_OGS
324
325 function addon:gui_init (loot_pointer)
326 g_loot = loot_pointer
327 g_generated = nil
328 tabgroup_tabs = {}
329 for _,v in ipairs(_taborder) do
330 tinsert (tabgroup_tabs, {value=v, text=_tabtexts[v].title})
331 -- By default, tabs are editboxes with generated text
332 if not tabs_OnGroupSelected[v] then
333 tabs_OnGroupSelected[v] = tabs_generated_text_OGS
334 end
335 end
336 end
337
338 -- Tab 1: Events Of Interest
339 -- This actually takes up quite a bit of the file.
340 local eoi_editcell
341
342 local function dropdownmenu_handler (ddbutton, subfunc, arg)
343 local i = _d:GetUserData("DD loot index")
344 subfunc(i,arg)
345 _d:GetUserData("eoiST"):OuroLoot_Refresh(i)
346 end
347
348 local function gen_easymenu_table (initial, list, funcs)
349 for _,tag in ipairs(list) do
350 local name, arg, tiptext
351 name, tiptext = strsplit('|',tag)
352 name, arg = strsplit('%',name)
353 if name == "--" then
354 tinsert (initial, {
355 disabled = true, text = "",
356 })
357 else
358 if not funcs[name] then
359 error(("'%s' not defined as a dropdown function"):format(name))
360 end
361 tinsert (initial, {
362 text = name,
363 func = dropdownmenu_handler,
364 arg1 = funcs[name],
365 arg2 = arg,
366 notCheckable = true,
367 tooltipTitle = tiptext and name or nil,
368 tooltipText = tiptext,
369 })
370 end
371 end
372 return initial
373 end
374
375 local dropdownmenuframe = CreateFrame("Frame", "OuroLootDropDownMenu", nil, "UIDropDownMenuTemplate")
376 local dropdownfuncs
377 dropdownfuncs = {
378 [CLOSE] = function() CloseDropDownMenus() end,
379
380 df_INSERT = function(rowi,text)
381 local which = (text == 'loot') and "OUROL_EOI_INSERT_LOOT" or "OUROL_EOI_INSERT"
382 local dialog = StaticPopup_Show(which,text)
383 dialog.wideEditBox:SetScript("OnTextChanged",StaticPopup_EditBoxOnTextChanged)
384 dialog.data = {rowindex=rowi, display=_d, kind=text}
385 end,
386
387 df_DELETE = function(rowi)
388 local gone = tremove(g_loot,rowi)
389 addon:Print("Removed %s.",
390 gone.itemlink or gone.bosskill or gone.startday.text)
391 end,
392
393 -- if kind is boss, also need to stop at new timestamp
394 ["Delete remaining entries for this day"] = function(rowi,kind)
395 local fencepost
396 local closest_time = addon._find_next_after('time',rowi)
397 if kind == 'time' then
398 fencepost = closest_time
399 elseif kind == 'boss' then
400 local closest_boss = addon._find_next_after('boss',rowi)
401 if not closest_boss then
402 fencepost = closest_time
403 elseif not closest_time then
404 fencepost = closest_boss
405 else
406 fencepost = math.min(closest_time,closest_boss)
407 end
408 end
409 local count = fencepost and (fencepost-rowi) or (#g_loot-rowi+1)
410 repeat
411 dropdownfuncs.df_DELETE(rowi)
412 count = count - 1
413 until count < 1
414 end,
415
416 ["Rebroadcast this loot entry"] = function(rowi)
417 local e = g_loot[rowi]
418 -- This only works because GetItemInfo accepts multiple argument formats
419 addon:broadcast('loot', e.person, e.itemlink, e.count, e.cols[3].value)
420 addon:Print("Rebroadcast entry",rowi,e.itemlink)
421 end,
422
423 ["Rebroadcast this boss"] = function(rowi,kind)
424 addon:Print("not implemented yet") -- TODO
425 end,
426
427 ["Mark as normal"] = function(rowi,disp) -- broadcast the change? ugh
428 g_loot[rowi].disposition = disp
429 g_loot[rowi].bcast_from = nil
430 g_loot[rowi].extratext = nil
431 end,
432
433 ["Show only this player"] = function(rowi)
434 local st = _d:GetUserData("eoiST")
435 _d:SetUserData("player filter name", g_loot[rowi].person)
436 st:SetFilter(_d:GetUserData("player filter by name"))
437 _d:GetUserData("eoi_filter_reset"):SetDisabled(false)
438 end,
439
440 ["Change from 'wipe' to 'kill'"] = function(rowi)
441 addon:_mark_boss_kill(rowi)
442 -- the fillout function called automatically will start too far down the list
443 _d:GetUserData("eoiST"):OuroLoot_Refresh()
444 end,
445
446 ["Edit note"] = function(rowi)
447 eoi_editcell (rowi, _d:GetUserData("DD loot cell"))
448 end,
449
450 df_REASSIGN = function(rowi,to_whom)
451 g_loot[rowi].person = to_whom
452 g_loot[rowi].person_class = select(2,UnitClass(to_whom))
453 CloseDropDownMenus() -- also need to close parent menu
454 end,
455 ["Enter name..."] = function(rowi)
456 local dialog = StaticPopup_Show "OUROL_REASSIGN_ENTER"
457 dialog.data = {index=rowi, display=_d}
458 end,
459 }
460 -- Would be better to move the %arg to this list rather than below, but
461 -- that's a lot of extra effort that doesn't buy much in return.
462 dropdownfuncs["Delete this loot event"] = dropdownfuncs.df_DELETE
463 dropdownfuncs["Delete this boss event"] = dropdownfuncs.df_DELETE
464 dropdownfuncs["Insert new loot entry"] = dropdownfuncs.df_INSERT
465 dropdownfuncs["Insert new boss kill event"] = dropdownfuncs.df_INSERT
466 dropdownfuncs["Mark as disenchanted"] = dropdownfuncs["Mark as normal"]
467 dropdownfuncs["Mark as guild vault"] = dropdownfuncs["Mark as normal"]
468 dropdownfuncs["Mark as offspec"] = dropdownfuncs["Mark as normal"]
469 dropdownfuncs["Delete remaining entries for this boss"] = dropdownfuncs["Delete remaining entries for this day"]
470 dropdownfuncs["Rebroadcast this day"] = dropdownfuncs["Rebroadcast this boss"]
471 local eoi_time_dropdown = gen_easymenu_table(
472 {{
473 -- this is the dropdown title, text filled in on the fly
474 isTitle = true,
475 notClickable = true,
476 notCheckable = true,
477 }},
478 {
479 "Rebroadcast this day%time|Broadcasts everything from here down until a new day",
480 "Delete remaining entries for this day%time|Erases everything from here down until a new day",
481 "Insert new loot entry%loot|Inserts new loot above this one, prompting you for information",
482 "Insert new boss kill event%boss|Inserts new event above this one, prompting you for information",
483 CLOSE
484 }, dropdownfuncs)
485 local eoi_loot_dropdown = gen_easymenu_table(
486 {{
487 -- this is the dropdown title, text filled in on the fly
488 notClickable = true,
489 notCheckable = true,
490 }},
491 {
492 "Mark as disenchanted%shard",
493 "Mark as offspec%offspec",
494 "Mark as guild vault%gvault",
495 "Mark as normal|This is the default. Selecting any 'Mark as <x>' action blanks out extra notes about who broadcast this entry, etc.",
496 "--",
497 "Rebroadcast this loot entry|Sends this loot event, including special notes, as if it just happened.",
498 "Delete this loot event|Permanent, no going back!",
499 "Delete remaining entries for this boss%boss|Erases everything from here down until a new boss/day",
500 "Insert new loot entry%loot|Inserts new loot above this one, prompting you for information",
501 "Insert new boss kill event%boss|Inserts new event above this one, prompting you for information",
502 "Edit note|Same as double-clicking in the notes column",
503 "--",
504 CLOSE
505 }, dropdownfuncs)
506 local eoi_player_dropdown = gen_easymenu_table(
507 {
508 {
509 -- this is the dropdown title, text filled in on the fly
510 isTitle = true,
511 notClickable = true,
512 notCheckable = true,
513 },
514 {
515 text = "Reassign to...",
516 hasArrow = true,
517 --menuList = filled in in the fly,
518 },
519 },
520 {
521 "Show only this player",
522 CLOSE
523 }, dropdownfuncs)
524 local eoi_boss_dropdown = gen_easymenu_table(
525 {{
526 -- this is the dropdown title, text filled in on the fly
527 isTitle = true,
528 notClickable = true,
529 notCheckable = true,
530 }},
531 {
532 "Change from 'wipe' to 'kill'|Also collapses other wipe entries",
533 "Rebroadcast this boss|Broadcasts the kill event and all subsequent loot until next boss",
534 "Delete this boss event|Permanent, no going back!",
535 "Delete remaining entries for this boss%boss|Erases everything from here down until a new boss/day",
536 "Insert new loot entry%loot|Inserts new loot above this one, prompting you for information",
537 "Insert new boss kill event%boss|Inserts new event above this one, prompting you for information",
538 "--",
539 CLOSE
540 }, dropdownfuncs)
541
542 --[[ quoted verbatim from lib-st docs:
543 rowFrame This is the UI Frame table for the row.
544 cellFrame This is the UI Frame table for the cell in the row.
545 data This is the data table supplied to the scrolling table (in case you lost it :) )
546 cols This is the cols table supplied to the scrolling table (again, in case you lost it :) )
547 row This is the number of the UI row that the event was triggered for.<br/> ex. If your scrolling table only shows ten rows, this number will be a number between 1 and 10.
548 realrow This is the exact row index (after sorting and filtering) in the data table of what data is displayed in the row you triggered the event in. (NOT the UI row!)
549 column This is the index of which column the event was triggered in.
550 table This is a reference to the scrollingtable table.
551 ... Any arguments generated by the '''NORMAL''' Blizzard event triggered by the frame are passed as is.
552 ]]
553 local function eoi_st_OnEnter (rowFrame, cellFrame, data, cols, row, realrow, column, table, button, ...)
554 if (row == nil) or (realrow == nil) then return end -- mouseover column header
555 local e = data[realrow]
556 local kind = e.kind
557
558 if kind == 'loot' and column == 1 then
559 GameTooltip:SetOwner (cellFrame, "ANCHOR_RIGHT", -20, 0)
560 GameTooltip:SetHyperlink (e.itemlink)
561
562 elseif kind == 'loot' and column == 2 then
563 GameTooltip:SetOwner (cellFrame, "ANCHOR_BOTTOMRIGHT", -50, 5)
564 GameTooltip:ClearLines()
565 GameTooltip:AddLine(e.person.." Loot:")
566 local counter = 0
567 for i,e2 in ipairs(data) do
568 if e2.person == e.person then -- would be awesome to test for alts
569 if counter > 10 then
570 GameTooltip:AddLine("...")
571 break
572 else
573 -- textures screw up too badly, strip them
574 local textured = e2.cols[1].value
575 local space = textured:find(" ")
576 GameTooltip:AddLine(textured:sub(space+1))
577 counter = counter + 1
578 end
579 end
580 end
581 GameTooltip:Show()
582
583 elseif kind == 'loot' and column == 3 then
584 setstatus(e.cols[column].value)
585
586 end
587
588 return false -- continue with default highlighting behavior
589 end
590 local function eoi_st_OnLeave (rowFrame, cellFrame, data, cols, row, realrow, column, table, button, ...)
591 GameTooltip:Hide()
592 if row and realrow and data[realrow].kind ~= 'loot' then
593 table:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable[data[realrow].reason or data[realrow].kind])
594 return true -- do not do anything further
595 else
596 --setstatus("")
597 return false -- continue with default un-highlighting behavior
598 end
599 end
600
601 local function eoi_st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
602 if (row == nil) or (realrow == nil) then return true end -- click column header, suppress reordering
603 local e = data[realrow]
604 local kind = e.kind
605
606 -- Check for shift-clicking a loot line
607 if IsModifiedClick("CHATLINK") and kind == 'loot' and column == 1 then
608 ChatEdit_InsertLink (e.itemlink)
609 return true -- do not do anything further
610 end
611
612 -- Remaining actions are all right-click
613 if button ~= "RightButton" then return true end
614 _d:SetUserData("DD loot index", realrow)
615
616 if kind == 'loot' and (column == 1 or column == 3) then
617 _d:SetUserData("DD loot cell", cellFrame)
618 eoi_loot_dropdown[1].text = e.itemlink
619 EasyMenu (eoi_loot_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
620
621 elseif kind == 'loot' and column == 2 then
622 eoi_player_dropdown[1].text = e.person
623 local raiders = {}
624 for i = 1, GetNumRaidMembers() do
625 tinsert (raiders, (GetRaidRosterInfo(i)))
626 end
627 table.sort(raiders)
628 for i = 1, #raiders do
629 local name = raiders[i]
630 raiders[i] = {
631 text = name,
632 func = dropdownmenu_handler,
633 arg1 = dropdownfuncs.df_REASSIGN,
634 arg2 = name,
635 notCheckable = true,
636 }
637 end
638 eoi_player_dropdown[2].menuList =
639 gen_easymenu_table (raiders, {"Enter name...",CLOSE}, dropdownfuncs)
640 --tabledump(eoi_player_dropdown)
641 EasyMenu (eoi_player_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
642
643 elseif kind == 'boss' then
644 eoi_boss_dropdown[1].text = e.bosskill
645 EasyMenu (eoi_boss_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
646
647 elseif kind == 'time' then
648 eoi_time_dropdown[1].text = e.startday.text
649 EasyMenu (eoi_time_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
650
651 end
652
653 return true -- do not do anything further
654 end
655
656 function eoi_editcell (row_index, cell_frame)
657 local e = g_loot[row_index]
658 if not e then return end -- how the hell could we get this far?
659 local celldata = e.cols[3]
660 local box = GUI:Create("EditBox")
661 box:SetText(celldata.value)
662 box:SetUserData("old show", box.editbox:GetScript("OnShow"))
663 box:SetUserData("old escape", box.editbox:GetScript("OnEscapePressed"))
664 box.editbox:SetScript("OnShow", box.editbox.SetFocus)
665 box.editbox:SetScript("OnEscapePressed", function(_be)
666 _be:ClearFocus()
667 _be.obj:Release()
668 end)
669 box:SetCallback("OnEnterPressed", function(_b,event,value)
670 e.extratext = value
671 celldata.value = value
672 e.bcast_from = nil -- things get screwy if this field is still present. sigh.
673 e.extratext_byhand = true
674 value = value and value:match("^(x%d+)")
675 if value then e.count = value end
676 _b:Release()
677 return _d:GetUserData("eoiST"):OuroLoot_Refresh(row_index)
678 end)
679 box:SetCallback("OnRelease", function(_b)
680 _b.editbox:ClearFocus()
681 _b.editbox:SetScript("OnShow", _b:GetUserData("old show"))
682 _b.editbox:SetScript("OnEscapePressed", _b:GetUserData("old escape"))
683 setstatus("")
684 end)
685 box.frame:SetAllPoints(cell_frame)
686 box.frame:SetParent(cell_frame)
687 box.frame:SetFrameLevel(cell_frame:GetFrameLevel()+1)
688 box.frame:Show()
689 setstatus("Press Enter or click Okay to accept changes, or press Escape to cancel them.")
690 end
691
692 local function eoi_st_OnDoubleClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
693 if (row == nil) or (realrow == nil) then return true end -- they clicked on column header, suppress reordering
694 local e = data[realrow]
695 local kind = e.kind
696
697 --_d:SetUserData("DD loot index", realrow)
698 if kind == 'loot' and column == 3 and button == "LeftButton" then
699 eoi_editcell (realrow, cellFrame)
700 end
701
702 return true -- do not do anything further
703 end
704
705 local function hist_st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
706 if (row == nil) or (realrow == nil) then return true end -- click column header, suppress reordering FOR NOW
707 local h = data[realrow]
708 local kind = h.kind
709
710
711 return true -- do not do anything further
712 end
713
714 local function hist_st_OnDoubleClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, ...)
715 if (row == nil) or (realrow == nil) then return true end -- they clicked on column header, suppress reordering
716 local h = data[realrow]
717 local kind = h.kind
718
719 return true -- do not do anything further
720 end
721
722 -- Used for EOI column 2 and Hist column 1. Both are player name columns.
723 local function eoi_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...)
724 if not fShow then
725 cellFrame.text:SetText("")
726 if cellFrame.icontexture then
727 cellFrame.icontexture:Hide()
728 end
729 return
730 end
731
732 local e = data[realrow]
733 local cell = e.cols[column]
734
735 cellFrame.text:SetText(cell.value)
736 cellFrame.text:SetTextColor(1,1,1,1)
737
738 if e.person_class then
739 local icon
740 if cellFrame.icontexture then
741 icon = cellFrame.icontexture
742 else
743 icon = cellFrame:CreateTexture(nil,"BACKGROUND")
744 icon:SetPoint("LEFT", cellFrame, "LEFT")
745 icon:SetHeight(eoi_st_rowheight-4)
746 icon:SetWidth(eoi_st_rowheight-4)
747 icon:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes")
748 cellFrame.icontexture = icon
749 end
750 icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[e.person_class]))
751 icon:Show()
752 cellFrame.text:SetPoint("LEFT", icon, "RIGHT", 1, 0)
753 else
754 if cellFrame.icontexture then
755 cellFrame.icontexture:Hide()
756 cellFrame.text:SetPoint("LEFT", cellFrame, "LEFT")
757 end
758 end
759
760 --if e.kind ~= 'loot' then
761 stable:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable[e.reason or e.kind or ""])
762 --else
763 -- table:SetHighLightColor (rowFrame, table:GetDefaultHighlightBlank())
764 --end
765 end
766
767 local eoi_st_cols = {
768 { -- col 1
769 name = "Item",
770 width = 250,
771 },
772 { -- col 2
773 name = "Player",
774 width = 130,
775 DoCellUpdate = eoi_st_col2_DoCellUpdate,
776 },
777 { -- col 3
778 name = "Notes",
779 width = 160,
780 },
781 }
782
783 local rowfilter_all
784 local rowfilter_by_name = function (st, e)
785 if e.kind ~= 'loot' then return true end
786 return e.person == _d:GetUserData("player filter name")
787 end
788
789 -- Tab 1: Events Of Interest (implementation)
790 tabs_OnGroupSelected["eoi"] = function(ocontainer,specials)
791 if (not addon.rebroadcast) and (not addon.enabled) and (#g_loot < 1) then
792 return addon.dprint('flow', "Nothing to show in first tab, skipping creation")
793 end
794
795 -- The first time this function is called, we set up a persistent ST
796 -- object and store it. Any other delayed setup work is done, and then
797 -- this function replaces itself with a smaller, sleeker, sexier one.
798 -- This function will later be garbage collected.
799 local ST = LibStub("ScrollingTable"):CreateST(eoi_st_cols,eoi_st_displayed_rows,eoi_st_rowheight)
800 _d:SetUserData("eoiST",ST)
801 if addon.author_debug then
802 _G.OLST = ST
803 end
804
805 if not eoi_st_otherrow_bgcolortable_default then
806 eoi_st_otherrow_bgcolortable_default = ST:GetDefaultHighlightBlank()
807 setmetatable(eoi_st_otherrow_bgcolortable, {__index = function (bg, key)
808 return eoi_st_otherrow_bgcolortable_default
809 end})
810 end
811
812 -- Calling SetData breaks (trying to call Refresh) if g_loot hasn't gone
813 -- through this loop.
814 addon:_fill_out_eoi_data(1)
815 -- safety check begin
816 for i,e in ipairs(g_loot) do
817 if type(e.cols) ~= 'table' then
818 addon:Print("ARGH, index",i,"bad in eoi_OGS, type",type(e.cols),
819 "entry kind", e.kind, "data", e.itemname or e.bosskill or e.startday.text,
820 "-- please take a screenshot and send to Farmbuyer.")
821 tabledump(e)
822 end
823 end
824 -- safety check end
825 ST:SetData(g_loot)
826 ST:RegisterEvents{
827 OnEnter = eoi_st_OnEnter,
828 OnLeave = eoi_st_OnLeave,
829 OnClick = eoi_st_OnClick,
830 OnDoubleClick = eoi_st_OnDoubleClick,
831 }
832
833 -- We want a single "update and redraw" function for the ST. Also, the
834 -- given refresh function is badly named and does nothing; the actual
835 -- function is SortData (also badly named when no sorting is being done),
836 -- which unconditionally calls the *hooked* Refresh.
837 local oldrefresh = ST.Refresh
838 ST.Refresh = function (self, opt_index)
839 addon:_fill_out_eoi_data(opt_index)
840 return oldrefresh(self)
841 end
842 ST.OuroLoot_Refresh = function (self, opt_index)
843 addon:_fill_out_eoi_data(opt_index)
844 -- safety check begin
845 for i,e in ipairs(g_loot) do
846 if type(e.cols) ~= 'table' then
847 addon:Print("ARGH, index",i,"bad in refresh, refreshed at", opt_index, "type",type(e.cols),
848 "entry kind", e.kind, "data", e.itemname or e.bosskill or e.startday.text,
849 "-- please take a screenshot and send to Farmbuyer.")
850 tabledump(e)
851 end
852 end
853 -- safety check end
854 self:SortData() -- calls hooked refresh
855 end
856
857 -- No need to keep creating function closures that all just "return true",
858 -- instead we grab the one made inside lib-st. There's no "get filter" API
859 -- so we just reach inside.
860 rowfilter_all = ST.Filter
861
862 -- Now set up the future drawing function...
863 tabs_OnGroupSelected["eoi"] = function(container,specials)
864 local st_widget = GUI:Create("lib-st")
865 local st = _d:GetUserData("eoiST")
866
867 -- This is actually required each time
868 _d:SetUserData ("player filter clear", rowfilter_all)
869 _d:SetUserData ("player filter by name", rowfilter_by_name)
870
871 st:OuroLoot_Refresh()
872 st_widget:WrapST(st)
873
874 if OuroLootSV_opts.scroll_to_bottom then
875 local scrollbar = _G[st.scrollframe:GetName().."ScrollBar"]
876 if scrollbar then
877 local _,max = scrollbar:GetMinMaxValues()
878 scrollbar:SetValue(max) -- also calls hooked Refresh
879 end
880 end
881
882 container:SetLayout("Fill")
883 container:AddChild(st_widget)
884
885 local b = mkbutton('eoi_filter_reset', "Reset Player Filter",
886 [[Return to showing complete loot information.]])
887 b:SetFullWidth(true)
888 b:SetCallback("OnClick", function (_b)
889 local st = _d:GetUserData("eoiST")
890 st:SetFilter(rowfilter_all)
891 _b:SetDisabled(true)
892 end)
893 b:SetDisabled(st.Filter == rowfilter_all)
894 specials:AddChild(b)
895
896 local people = { "<nobody>" }
897 for i=1,GetNumRaidMembers() do
898 tinsert(people,(GetRaidRosterInfo(i)))
899 end
900 table.sort(people)
901 local initial
902 for i,n in ipairs(people) do
903 if n == addon.sharder then initial = i end
904 end
905 b = mkbutton("Dropdown", nil, "",
906 [[If set, items received by this person will be automatically marked as disenchanted.]])
907 b:SetFullWidth(true)
908 b:SetLabel("Auto-mark as shard:")
909 b:SetList(people)
910 b:SetValue(initial or 1)
911 b:SetCallback("OnValueChanged", function(_dd,event,choice)
912 addon.sharder = (choice ~= 1) and people[choice] or nil
913 end)
914 specials:AddChild(b)
915
916 local b = mkbutton('eoi_bcast_req', "Request B'casters",
917 [[Sends out a request for others to enable loot rebroadcasting if they have not already done so.]])
918 b:SetFullWidth(true)
919 b:SetCallback("OnClick", function ()
920 addon:Print("Sending request!")
921 addon.requesting = true
922 addon:broadcast('bcast_req')
923 end)
924 b:SetDisabled(not addon.enabled)
925 specials:AddChild(b)
926 end
927 -- ...and call it.
928 return tabs_OnGroupSelected["eoi"](ocontainer,specials)
929 end
930
931 -- Tab 2/3 (generated text)
932 function tabs_generated_text_OGS (container, specials, text_kind)
933 container:SetLayout("Fill")
934 local box = GUI:Create("MultiLineEditBox")
935 box:SetFullWidth(true)
936 box:SetFullHeight(true)
937 box:SetLabel("Pressing the Escape key while typing will return keystroke control to the usual chat window.")
938 box:DisableButton(true)
939 addon:_fill_out_eoi_data(1)
940
941 -- Update the savedvar copy of the text before presenting it for editing,
942 -- then save it again when editing finishes. This way if the user goes
943 -- offline while editing, at least the unedited version is saved instead
944 -- of all the new text being lost entirely. (Yes, it's happened.)
945 --
946 -- No good local-ish place to store the cursor position that will also
947 -- survive the entire display being released. Abuse the generated text
948 -- cache for this purpose.
949 local pos = text_kind.."_pos"
950 if _generate_text(text_kind) then
951 g_loot[text_kind] = g_loot[text_kind] .. g_generated[text_kind]
952 g_generated[text_kind] = nil
953 end
954 box:SetText(g_loot[text_kind])
955 box.editBox:SetCursorPosition(g_generated[pos] or 0)
956 box.editBox:SetScript("OnShow", box.editBox.SetFocus)
957 box:SetCallback("OnRelease", function(_box)
958 box.editBox:ClearFocus()
959 g_loot[text_kind] = _box:GetText()
960 g_generated[pos] = _box.editBox:GetCursorPosition()
961 end)
962 container:AddChild(box)
963
964 local w = mkbutton("Regenerate",
965 [[+DISCARD> all text in this tab, and regenerate it from the current loot information.]])
966 w:SetFullWidth(true)
967 w:SetDisabled ((#g_loot == 0) and (box:GetText() == ""))
968 w:SetCallback("OnClick", function(_w)
969 box:SetText("")
970 g_loot[text_kind] = ""
971 g_loot.printed[text_kind] = 0
972 g_generated.last_instance = nil
973 g_generated[pos] = nil
974 addon:Print("'%s' has been regenerated.", _tabtexts[text_kind].title)
975 return addon:redisplay()
976 --return tabs_OnGroupSelected_func(container,"OnGroupSelected",text_kind)
977 end)
978 specials:AddChild(w)
979 _populate_text_specials (box, specials, mkbutton, text_kind)
980 end
981
982 -- Tab 4: History
983 -- Much of the implementation here follows a similar desgin for the first
984 -- tab's handling of ST objects.
985 do
986 local histST
987 local hist_st_cols = {
988 { -- col 1
989 name = "Player",
990 width = 130,
991 DoCellUpdate = eoi_st_col2_DoCellUpdate,
992 },
993 { -- col 2
994 name = "Most Recent Loot",
995 width = 250,
996 DoCellUpdate = hist_st_col2_DoCellUpdate,
997 },
998 { -- col 3
999 name = "When",
1000 width = 160,
1001 DoCellUpdate = hist_st_col3_DoCellUpdate,
1002 },
1003 }
1004
1005 -- Loot column
1006 local function hist_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...)
1007 end
1008
1009 -- Formatted timestamp column
1010 local function hist_st_col3_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable, ...)
1011 if not fShow then
1012 cellFrame.text:SetText("")
1013 return
1014 end
1015
1016 local d = data[realrow]
1017 local cell = d.cols[column]
1018
1019 cellFrame.text:SetText(cell.value)
1020 cellFrame.text:SetTextColor(1,1,1,1)
1021
1022 --if d.kind ~= 'loot' then
1023 stable:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable[d.kind])
1024 --else
1025 -- table:SetHighLightColor (rowFrame, table:GetDefaultHighlightBlank())
1026 --end
1027 end
1028
1029 tabs_OnGroupSelected["hist"] = function(container,specials)
1030 histST = LibStub("ScrollingTable"):CreateST(hist_st_cols,eoi_st_displayed_rows,eoi_st_rowheight)
1031 if addon.author_debug then
1032 _G.OLHST = histST
1033 end
1034
1035 if not eoi_st_otherrow_bgcolortable_default then
1036 eoi_st_otherrow_bgcolortable_default = histST:GetDefaultHighlightBlank()
1037 setmetatable(eoi_st_otherrow_bgcolortable, {__index = function (bg, key)
1038 return eoi_st_otherrow_bgcolortable_default
1039 end})
1040 end
1041
1042 addon:_build_history_names()
1043 addon:_fill_out_hist_data(1)
1044 histST:SetData(addon.history.st)
1045 histST:RegisterEvents{
1046 OnEnter = eoi_st_OnEnter,
1047 OnLeave = eoi_st_OnLeave,
1048 OnClick = hist_st_OnClick,
1049 --OnDoubleClick = eoi_st_OnDoubleClick,
1050 }
1051 local oldrefresh = histST.Refresh
1052 histST.Refresh = function (self, opt_index)
1053 addon:_fill_out_hist_data(opt_index)
1054 return oldrefresh(self)
1055 end
1056 histST.OuroLoot_Refresh = function (self, opt_index)
1057 addon:_fill_out_hist_data(opt_index)
1058 self:SortData() -- calls hooked refresh
1059 end
1060
1061 tabs_OnGroupSelected["hist"] = function(container,specials)
1062 local st_widget = GUI:Create("lib-st")
1063 histST:OuroLoot_Refresh()
1064 st_widget:WrapST(histST)
1065 container:SetLayout("Fill")
1066 container:AddChild(st_widget)
1067
1068 local b = mkbutton("Regenerate",
1069 [[Erases all history entries from current realm, and regenerate it from current loot information.]])
1070 b:SetFullWidth(true)
1071 b:SetDisabled (#addon.history == 0)
1072 b:SetCallback("OnClick", function(_b)
1073 addon:Print("%s history has been regenerated.", addon.history.realm)
1074 return addon:redisplay()
1075 --return tabs_OnGroupSelected_func(container,"OnGroupSelected","hist")
1076 end)
1077 specials:AddChild(b)
1078
1079 b = mkbutton('hist_clear_all', "Clear All History",
1080 [[Erases ALL history entries from all realms.]])
1081 b:SetFullWidth(true)
1082 b:SetCallback("OnClick", function (_b)
1083 local r = GetRealmName()
1084 -- new .history table:
1085 addon.history_all[r] = addon:_prep_new_history_category (nil, r)
1086 addon.history = addon.history_all[r]
1087 addon.hist_clean = nil
1088 -- new .history.st table:
1089 histST:OuroLoot_Refresh()
1090 histST:SetData(addon.history.st)
1091 addon:Print("You've clicked the history erase button!")
1092 return addon:redisplay()
1093 --return tabs_OnGroupSelected_func(container,"OnGroupSelected","hist")
1094 end)
1095 specials:AddChild(b)
1096
1097 b = mkbutton('hist_clear_old', "Clear Older",
1098 [[Preserves only the latest loot entry for each player, removing all others.]])
1099 b:SetFullWidth(true)
1100 b:SetCallback("OnClick", function (_b)
1101 addon:Print("All loot prior to the most recent entries has been erased.")
1102 return addon:redisplay()
1103 --return tabs_OnGroupSelected_func(container,"OnGroupSelected","hist")
1104 end)
1105 specials:AddChild(b)
1106 end
1107 return tabs_OnGroupSelected["hist"](container,specials)
1108 end
1109 end
1110
1111 -- Tab 5: Help (content in lootaux.lua)
1112 do
1113 local tabs_help_OnGroupSelected_func = function (treeg,event,category)
1114 treeg:ReleaseChildren()
1115 local txt = GUI:Create("Label")
1116 txt:SetFullWidth(true)
1117 txt:SetFontObject(GameFontNormal)--Highlight)
1118 txt:SetText(addon.helptext[category])
1119 local sf = GUI:Create("ScrollFrame")
1120 local sfstat = _d:GetUserData("help tab scroll status") or {}
1121 sf:SetStatusTable(sfstat)
1122 _d:SetUserData("help tab scroll status",sfstat)
1123 sf:SetLayout("Fill")
1124 -- This forces the scrolling area to be bigger than the visible area; else
1125 -- some of the text gets cut off.
1126 sf.content:SetHeight(700)
1127 sf:AddChild(txt)
1128 treeg:AddChild(sf)
1129 if treeg:GetUserData("help restore scroll") then
1130 sfstat = sfstat.scrollvalue
1131 if sfstat then sf:SetScroll(sfstat) end
1132 treeg:SetUserData("help restore scroll", false)
1133 else
1134 sf:SetScroll(0)
1135 end
1136 end
1137 tabs_OnGroupSelected["help"] = function(container,specials)
1138 container:SetLayout("Fill")
1139 local left = GUI:Create("TreeGroup")
1140 local leftstat = _d:GetUserData("help tab select status")
1141 or {treewidth=145}
1142 left:SetStatusTable(leftstat)
1143 _d:SetUserData("help tab select status",leftstat)
1144 left:SetLayout("Fill")
1145 left:SetFullWidth(true)
1146 left:SetFullHeight(true)
1147 left:EnableButtonTooltips(false)
1148 left:SetTree(addon.helptree)
1149 left:SetCallback("OnGroupSelected", tabs_help_OnGroupSelected_func)
1150 container:AddChild(left)
1151 leftstat = leftstat.selected
1152 if leftstat then
1153 left:SetUserData("help restore scroll", true)
1154 left:SelectByValue(leftstat)
1155 else
1156 left:SelectByValue("basic")
1157 end
1158 end
1159 end
1160
1161 -- Tab 6: Options / Advanced
1162 do
1163 local function mkoption (opt, label, width, desc, opt_func)
1164 local w = mkbutton("CheckBoxSmallLabel", nil, "", desc)
1165 w:SetRelativeWidth(width)
1166 w:SetType("checkbox")
1167 w:SetLabel(label)
1168 if opt then
1169 w:SetValue(OuroLootSV_opts[opt])
1170 w:SetCallback("OnValueChanged", opt_func or (function(_w,event,value)
1171 OuroLootSV_opts[opt] = value
1172 end))
1173 end
1174 return w
1175 end
1176
1177 local function adv_careful_OnTextChanged (ebox,event,value)
1178 -- The EditBox widget's code will call an internal ShowButton routine
1179 -- after this callback returns. ShowButton will test for this flag:
1180 ebox:DisableButton (value == "")
1181 end
1182
1183 -- Like the first tab, we use a pair of functions; first and repeating.
1184 local function adv_real (container, specials)
1185 local grp, w
1186
1187 grp = GUI:Create("InlineGroup")
1188 grp:SetLayout("Flow")
1189 grp:PauseLayout()
1190 grp:SetFullWidth(true)
1191 grp:SetTitle("Debugging/Testing Options [not saved across sessions]")
1192
1193 w = mkbutton("EditBox", 'comm_ident', addon.ident,
1194 [[Disable the addon, change this field (click Okay or press Enter), then re-enable the addon.]])
1195 w:SetRelativeWidth(0.2)
1196 w:SetLabel("Addon channel ID")
1197 w:SetCallback("OnTextChanged", adv_careful_OnTextChanged)
1198 w:SetCallback("OnEnterPressed", function(_w,event,value)
1199 -- if they set it to blank spaces, they're boned. oh well.
1200 -- Re-enabling will take care of propogating this new value.
1201 addon.ident = (value == "") and "OuroLoot2" or value
1202 _w:SetText(addon.ident)
1203 addon:Print("Addon channel ID set to '".. addon.ident.. "' for rebroadcasting and listening.")
1204 end)
1205 w:SetDisabled(addon.enabled or addon.rebroadcast)
1206 grp:AddChild(w)
1207
1208 w = mkbutton("EditBox", nil, addon.recent_messages.ttl, [[comm cache (only) ttl]])
1209 w:SetRelativeWidth(0.05)
1210 w:SetLabel("ttl")
1211 w:SetCallback("OnTextChanged", adv_careful_OnTextChanged)
1212 w:SetCallback("OnEnterPressed", function(_w,event,value)
1213 value = tonumber(value) or addon.recent_messages.ttl
1214 addon.recent_messages.ttl = value
1215 _w:SetText(tostring(value))
1216 end)
1217 grp:AddChild(w)
1218
1219 w = mkbutton("load nsaab1548", [[Cursed Darkhound]])
1220 w:SetRelativeWidth(0.25)
1221 w:SetCallback("OnClick", function()
1222 for i, v in ipairs(DBM.AddOns) do
1223 if v.modId == "DBM-NotScaryAtAll" then
1224 DBM:LoadMod(v)
1225 break
1226 end
1227 end
1228 local mod = DBM:GetModByName("NotScaryAtAll")
1229 if mod then
1230 mod:EnableMod()
1231 addon:Print("Now tracking ID",mod.creatureId)
1232 else addon:Print("Can do nothing; DBM testing mod wasn't loaded.") end
1233 end)
1234 w:SetDisabled(not addon.dbm_registered)
1235 grp:AddChild(w)
1236
1237 w = mkbutton("GC", [[full GC cycle]])
1238 w:SetRelativeWidth(0.1)
1239 w:SetCallback("OnClick", function() collectgarbage() end)
1240 grp:AddChild(w)
1241
1242 w = mkbutton("EditBox", nil, addon.loot_pattern:sub(17), [[]])
1243 w:SetRelativeWidth(0.35)
1244 w:SetLabel("CML pattern suffix")
1245 w:SetCallback("OnEnterPressed", function(_w,event,value)
1246 addon.loot_pattern = addon.loot_pattern:sub(1,16) .. value
1247 end)
1248 grp:AddChild(w)
1249
1250 local simple = GUI:Create("SimpleGroup")
1251 simple:SetLayout("List")
1252 simple:SetRelativeWidth(0.3)
1253 w = GUI:Create("CheckBoxSmallLabel")
1254 w:SetFullWidth(true)
1255 w:SetType("checkbox")
1256 w:SetLabel("master dtoggle")
1257 w:SetValue(addon.DEBUG_PRINT)
1258 w:SetCallback("OnValueChanged", function(_w,event,value) addon.DEBUG_PRINT = value end)
1259 simple:AddChild(w)
1260 w = mkbutton("Clear All & Reload",
1261 [[No confirmation! |cffff1010Erases absolutely all> Ouro Loot saved variables and reloads the UI.]])
1262 w:SetFullWidth(true)
1263 w:SetCallback("OnClick", function()
1264 addon:_clear_SVs()
1265 ReloadUI()
1266 end)
1267 simple:AddChild(w)
1268 grp:AddChild(simple)
1269
1270 simple = GUI:Create("SimpleGroup")
1271 simple:SetLayout("List")
1272 simple:SetRelativeWidth(0.5)
1273 for d,v in pairs(addon.debug) do
1274 w = GUI:Create("CheckBoxSmallLabel")
1275 w:SetFullWidth(true)
1276 w:SetType("checkbox")
1277 w:SetLabel(d)
1278 if d == "notraid" then
1279 w:SetDescription("Tick this before enabling to make the addon work outside of raid groups")
1280 end
1281 w:SetValue(v)
1282 w:SetCallback("OnValueChanged", function(_w,event,value) addon.debug[d] = value end)
1283 simple:AddChild(w)
1284 end
1285 grp:AddChild(simple)
1286 grp:ResumeLayout()
1287
1288 container:AddChild(grp)
1289 GUI:ClearFocus()
1290 end
1291
1292 -- Initial lower panel function
1293 local function adv_lower (container, specials)
1294 local speedbump = GUI:Create("InteractiveLabel")
1295 speedbump:SetFullWidth(true)
1296 speedbump:SetFontObject(GameFontHighlightLarge)
1297 speedbump:SetImage("Interface\\DialogFrame\\DialogAlertIcon")
1298 speedbump:SetImageSize(50,50)
1299 speedbump:SetText("The debugging/testing settings on the rest of this panel can"
1300 .." seriously bork up the addon if you make a mistake. If you're okay"
1301 .." with the possibility of losing data, click this warning to load the panel.")
1302 speedbump:SetCallback("OnClick", function (_sb)
1303 adv_lower = adv_real
1304 return addon:redisplay()
1305 --return tabs_OnGroupSelected_func(container.parent,"OnGroupSelected","opt")
1306 end)
1307 container:AddChild(speedbump)
1308 end
1309
1310 tabs_OnGroupSelected["opt"] = function(container,specials)
1311 --container:SetLayout("List")
1312 container:SetLayout("Fill")
1313 local scroll, grp, w
1314
1315 scroll = GUI:Create("ScrollFrame")
1316 scroll:SetLayout("Flow")
1317
1318 grp = GUI:Create("InlineGroup")
1319 grp:SetLayout("Flow")
1320 grp:SetFullWidth(true)
1321 grp:SetTitle("User Options [these are saved across sessions]")
1322
1323 -- reminder popup
1324 w = mkoption ('popup_on_join', "Show reminder popup", 0.35,
1325 [[When joining a raid and not already tracking, display a dialog asking for instructions.]])
1326 grp:AddChild(w)
1327
1328 -- toggle scroll-to-bottom on first tab
1329 w = mkoption('scroll_to_bottom', "Scroll to bottom when opening display", 0.60,
1330 [[Scroll to the bottom of the loot window (most recent entries) when displaying the GUI.]])
1331 grp:AddChild(w)
1332
1333 -- /loot option
1334 w = mkoption('register_slashloot', "Register /loot slash command on login", 0.45,
1335 [[Register "/loot" as a slash command in addition to the normal "/ouroloot". Relog to take effect.]])
1336 grp:AddChild(w)
1337
1338 -- chatty mode
1339 w = mkoption('chatty_on_kill', "Be chatty on boss kill", 0.30,
1340 [[Print something to chat output when DBM tells Ouro Loot about a successful boss kill.]])
1341 grp:AddChild(w)
1342
1343 -- less noise in main panel
1344 w = mkoption('no_tracking_wipes', "Do not track wipes", 0.25,
1345 [[Do not add 'wipe' entries on the main loot grid, or generate any text for them.]])
1346 grp:AddChild(w)
1347
1348 -- cutesy abbrevs
1349 w = mkoption('snarky_boss', "Use snarky boss names", 0.35,
1350 [[Irreverent replacement names for boss events.]])
1351 grp:AddChild(w)
1352
1353 -- possible keybindings
1354 do
1355 local pair = GUI:Create("SimpleGroup")
1356 pair:SetLayout("Flow")
1357 pair:SetRelativeWidth(0.6)
1358 local editbox, checkbox
1359 editbox = mkbutton("EditBox", nil, OuroLootSV_opts.keybinding_text,
1360 [[Keybinding text format is fragile! Relog to take effect.]])
1361 editbox:SetRelativeWidth(0.5)
1362 editbox:SetLabel("Keybinding text")
1363 editbox:SetCallback("OnEnterPressed", function(_w,event,value)
1364 OuroLootSV_opts.keybinding_text = value
1365 end)
1366 editbox:SetDisabled(not OuroLootSV_opts.keybinding)
1367 checkbox = mkoption('keybinding', "Register keybinding", 0.5,
1368 [[Register a keybinding to toggle the loot display. Relog to take effect.]],
1369 function (_w,_,value)
1370 OuroLootSV_opts.keybinding = value
1371 editbox:SetDisabled(not OuroLootSV_opts.keybinding)
1372 end)
1373 pair:AddChild(checkbox)
1374 pair:AddChild(editbox)
1375 grp:AddChild(pair)
1376 end
1377
1378 -- item filter
1379 w = GUI:Create("Spacer")
1380 w:SetFullWidth(true)
1381 w:SetHeight(20)
1382 grp:AddChild(w)
1383 do
1384 local list = {}
1385 for id in pairs(OuroLootSV_opts.itemfilter) do
1386 local iname, _, iquality = GetItemInfo(id)
1387 list[id] = addon.quality_hexes[iquality] .. iname .. "|r"
1388 end
1389 w = GUI:Create("EditBoxDropDown")
1390 w:SetRelativeWidth(0.4)
1391 w:SetText("Item filter")
1392 w:SetEditBoxTooltip("Link items which should no longer be tracked.")
1393 w:SetList(list)
1394 w:SetCallback("OnTextEnterPressed", function(_w, _, text)
1395 local iname, ilink, iquality = GetItemInfo(strtrim(text))
1396 if not iname then
1397 return addon:Print("Error: %s is not a valid item name/link!", text)
1398 end
1399 local id = tonumber(ilink:match("item:(%d+)"))
1400 list[id] = addon.quality_hexes[iquality] .. iname .. "|r"
1401 OuroLootSV_opts.itemfilter[id] = true
1402 addon:Print("Now filtering out", ilink)
1403 end)
1404 w:SetCallback("OnListItemClicked", function(_w, _, key_id, val_name)
1405 --local ilink = select(2,GetItemInfo(key_id))
1406 OuroLootSV_opts.itemfilter[tonumber(key_id)] = nil
1407 --addon:Print("No longer filtering out", ilink)
1408 addon:Print("No longer filtering out", val_name)
1409 end)
1410 grp:AddChild(w)
1411 end
1412
1413 scroll:AddChild(grp)
1414
1415 addon.sender_list.sort()
1416 if #addon.sender_list.namesI > 0 then
1417 local senders = table.concat(addon.sender_list.namesI,'\n') -- sigh
1418 -- If 39 other people in the raid are running this, the label will
1419 -- explode... is it likely enough to care about? No.
1420 w = GUI:Create("Spacer")
1421 w:SetFullWidth(true)
1422 w:SetHeight(20)
1423 grp:AddChild(w)
1424 w = GUI:Create("Label")
1425 w:SetRelativeWidth(0.4)
1426 w:SetText(addon.quality_hexes[3].."Echo from latest ping:|r\n"..senders)
1427 grp:AddChild(w)
1428 end
1429
1430 w = mkbutton("ReloadUI", [[Does what you think it does. Loot information is written out and restored.]])
1431 w:SetFullWidth(true)
1432 w:SetCallback("OnClick", ReloadUI)
1433 specials:AddChild(w)
1434
1435 w = mkbutton("Ping!",
1436 [[Asks other raid users for their addon version and current status. Results displayed on User Options panel.]])
1437 w:SetFullWidth(true)
1438 w:SetCallback("OnClick", function(_w)
1439 addon:Print("Give me a ping, Vasili. One ping only, please.")
1440 addon.sender_list.active = {}
1441 addon.sender_list.names = {}
1442 _w:SetText("5... 4... 3...")
1443 _w:SetDisabled(true)
1444 addon:broadcast('ping')
1445 addon:ScheduleTimer(function(b)
1446 if b:IsVisible() then
1447 return addon:redisplay()
1448 --return tabs_OnGroupSelected_func(container,"OnGroupSelected","opt")
1449 end
1450 end, 5, _w)
1451 end)
1452 specials:AddChild(w)
1453
1454 -- Add appropriate lower panel
1455 adv_lower (scroll, specials)
1456
1457 -- Finish up
1458 container:AddChild(scroll)
1459 end
1460 end
1461
1462
1463 -- Simply to avoid recreating the same function over and over
1464 local tabs_OnGroupSelected_func_args = { [2] = "OnGroupSelected" }
1465 tabs_OnGroupSelected_func = function (tabs,event,group)
1466 tabs_OnGroupSelected_func_args[1] = tabs
1467 tabs_OnGroupSelected_func_args[3] = group
1468 tabs:ReleaseChildren()
1469 local spec = tabs:GetUserData("special buttons group")
1470 spec:ReleaseChildren()
1471 local h = GUI:Create("Heading")
1472 h:SetFullWidth(true)
1473 h:SetText(_tabtexts[group].title)
1474 spec:AddChild(h)
1475 return tabs_OnGroupSelected[group](tabs,spec,group)
1476 --[====[
1477 Unfortunately, :GetHeight() called on anything useful out of a TabGroup
1478 returns the static default size (about 50 pixels) until the refresh
1479 cycle *after* all the frames are shown. Trying to fix it up after a
1480 single OnUpdate doesn't work either. So for now it's all hardcoded.
1481
1482 Using this to determine the actual height of the usable area.
1483 366 pixels
1484 if group == "eoi" then
1485 local stframe = tabs.children[1].frame
1486 print(stframe:GetTop(),"-",stframe:GetBottom(),"=",
1487 stframe:GetTop()-stframe:GetBottom())
1488 print(stframe:GetRight(),"-",stframe:GetLeft(),"=",
1489 stframe:GetRight()-stframe:GetLeft())
1490 end
1491 ]====]
1492 end
1493
1494 --[[
1495 mkbutton ("WidgetType", 'display key', "Text On Widget", "the mouseover display text")
1496 mkbutton ( [Button] 'display key', "Text On Widget", "the mouseover display text")
1497 mkbutton ( [Button] [text] "Text On Widget", "the mouseover display text")
1498 ]]
1499 do
1500 local replacement_colors = { ["+"]="|cffffffff", ["<"]="|cff00ff00", [">"]="|r" }
1501 function mkbutton (opt_widget_type, opt_key, label, status)
1502 if not label then
1503 opt_widget_type, opt_key, label, status = "Button", opt_widget_type, opt_widget_type, opt_key
1504 elseif not status then
1505 opt_widget_type, opt_key, label, status = "Button", opt_widget_type, opt_key, label
1506 end
1507 local button = GUI:Create(opt_widget_type)
1508 if button.SetText then button:SetText(tostring(label)) end
1509 status = status:gsub("[%+<>]",replacement_colors)
1510 button:SetCallback("OnEnter", function() setstatus(status) end) -- maybe factor that closure out
1511 button:SetCallback("OnLeave", statusy_OnLeave)
1512 -- retrieval key may be specified as nil if all the parameters are given
1513 if opt_key then _d:SetUserData (opt_key, button) end
1514 return button
1515 end
1516 end
1517
1518 --[[
1519 Creates the main window.
1520 ]]
1521 function addon:BuildMainDisplay (opt_tabselect)
1522 if self.display then
1523 -- try to get everything to update, rebuild, refresh... ugh, no
1524 self.display:Hide()
1525 end
1526
1527 local display = GUI:Create("Frame")
1528 if _d then
1529 display:SetUserData("eoiST",_d) -- warning! warning! kludge detected!
1530 end
1531 _d = display
1532 self.display = display
1533 display:SetTitle("Ouro Loot")
1534 display:SetStatusText(self.status_text)
1535 display:SetLayout("Flow")
1536 display:SetStatusTable{width=800}
1537 -- prevent resizing, also see ace3 ticket #80
1538 --[[
1539 display.sizer_se:SetScript("OnMouseDown",nil)
1540 display.sizer_se:SetScript("OnMouseUp",nil)
1541 display.sizer_s:SetScript("OnMouseDown",nil)
1542 display.sizer_s:SetScript("OnMouseUp",nil)
1543 display.sizer_e:SetScript("OnMouseDown",nil)
1544 display.sizer_e:SetScript("OnMouseUp",nil)
1545 ]]
1546 display:SetCallback("OnClose", function(_display)
1547 _d = _display:GetUserData("eoiST")
1548 self.display = nil
1549 GUI:Release(_display)
1550 collectgarbage()
1551 end)
1552
1553 ----- Right-hand panel
1554 local rhs_width = 0.20
1555 local control = GUI:Create("SimpleGroup")
1556 control:SetLayout("Flow")
1557 control:SetRelativeWidth(rhs_width)
1558 control.alignoffset = 25
1559 control:PauseLayout()
1560 local h,b
1561
1562 --- Main ---
1563 h = GUI:Create("Heading")
1564 h:SetFullWidth(true)
1565 h:SetText("Main")
1566 control:AddChild(h)
1567
1568 do
1569 b = mkbutton("Dropdown", nil, "",
1570 [[Enable full tracking, only rebroadcasting, or disable activity altogether.]])
1571 b:SetFullWidth(true)
1572 b:SetLabel("On/Off:")
1573 b:SetList{"Full Tracking", "Broadcasting", "Disabled"}
1574 b:SetValue(self.enabled and 1 or (self.rebroadcast and 2 or 3))
1575 b:SetCallback("OnValueChanged", function(_w,event,choice)
1576 if choice == 1 then self:Activate()
1577 elseif choice == 2 then self:Activate(nil,true)
1578 else self:Deactivate()
1579 end
1580 _w = display:GetUserData('comm_ident')
1581 if _w and _w:IsVisible() then
1582 _w:SetDisabled(self.enabled or self.rebroadcast)
1583 end
1584 _w = display:GetUserData('eoi_bcast_req')
1585 if _w and _w:IsVisible() then
1586 _w:SetDisabled(not self.enabled)
1587 end
1588 end)
1589 control:AddChild(b)
1590 end
1591
1592 b = mkbutton("Dropdown", 'threshold', "",
1593 [[Items greater than or equal to this quality will be tracked/rebroadcast.]])
1594 b:SetFullWidth(true)
1595 b:SetLabel("Threshold:")
1596 b:SetList(self.thresholds)
1597 b:SetValue(self.threshold)
1598 b:SetCallback("OnValueChanged", function(_dd,event,choice)
1599 self:SetThreshold(choice)
1600 end)
1601 control:AddChild(b)
1602
1603 b = mkbutton("Clear",
1604 [[+Erases> all current loot information and generated text (but not saved texts).]])
1605 b:SetFullWidth(true)
1606 b:SetCallback("OnClick", function()
1607 StaticPopup_Show("OUROL_CLEAR").data = self
1608 end)
1609 control:AddChild(b)
1610
1611 b = GUI:Create("Spacer")
1612 b:SetFullWidth(true)
1613 b:SetHeight(15)
1614 control:AddChild(b)
1615
1616 --[[
1617 --- Saved Texts ---
1618 [ Save Current As... ]
1619 saved1
1620 saved2
1621 ...
1622 [ Load ] [ Delete ]
1623 ]]
1624 h = GUI:Create("Heading")
1625 h:SetFullWidth(true)
1626 h:SetText("Saved Texts")
1627 control:AddChild(h)
1628 b = mkbutton("Save Current As...",
1629 [[Save forum/attendance/etc texts for later retrieval. Main loot information not included.]])
1630 b:SetFullWidth(true)
1631 b:SetCallback("OnClick", function()
1632 StaticPopup_Show "OUROL_SAVE_SAVEAS"
1633 _d:Hide()
1634 end)
1635 control:AddChild(b)
1636
1637 local saved = self:check_saved_table(--[[silent_on_empty=]]true)
1638 if saved then for i,s in ipairs(saved) do
1639 local il = GUI:Create("InteractiveLabel")
1640 il:SetFullWidth(true)
1641 il:SetText(s.name)
1642 il:SetUserData("num",i)
1643 il:SetHighlight(1,1,1,0.4)
1644 local str = ("%s %d entries %s"):format(s.date,s.count,s.name)
1645 il:SetCallback("OnEnter", function() setstatus(str) end)
1646 il:SetCallback("OnLeave", statusy_OnLeave)
1647 il:SetCallback("OnClick", function(_il)
1648 local prev = _d:GetUserData("saved selection")
1649 if prev then
1650 prev.highlight:Hide()
1651 prev:SetColor()
1652 end
1653 _il:SetColor(0,1,0)
1654 _il.highlight:Show()
1655 _d:SetUserData("saved selection",_il)
1656 _d:GetUserData("Load"):SetDisabled(false)
1657 _d:GetUserData("Delete"):SetDisabled(false)
1658 end)
1659 control:AddChild(il)
1660 end end
1661
1662 b = mkbutton("Load",
1663 [[Load previously saved text. +REPLACES> all current loot information!]])
1664 b:SetRelativeWidth(0.5)
1665 b:SetCallback("OnClick", function()
1666 local num = _d:GetUserData("saved selection"):GetUserData("num")
1667 self:save_restore(num)
1668 self:BuildMainDisplay()
1669 end)
1670 b:SetDisabled(true)
1671 control:AddChild(b)
1672 b = mkbutton("Delete",
1673 [[Delete previously saved text.]])
1674 b:SetRelativeWidth(0.5)
1675 b:SetCallback("OnClick", function()
1676 local num = _d:GetUserData("saved selection"):GetUserData("num")
1677 self:save_delete(num)
1678 self:BuildMainDisplay()
1679 end)
1680 b:SetDisabled(true)
1681 control:AddChild(b)
1682
1683 b = GUI:Create("Spacer")
1684 b:SetFullWidth(true)
1685 b:SetHeight(15)
1686 control:AddChild(b)
1687
1688 -- Other stuff on right-hand side
1689 local tab_specials = GUI:Create("SimpleGroup")
1690 tab_specials:SetLayout("Flow")
1691 tab_specials:SetFullWidth(true)
1692 control:AddChild(tab_specials)
1693 control:ResumeLayout()
1694
1695 ----- Left-hand group
1696 local tabs = GUI:Create("TabGroup")
1697 tabs:SetLayout("Flow")
1698 tabs.alignoffset = 25
1699 tabs.titletext:SetFontObject(GameFontNormalSmall) -- XXX
1700 do
1701 self.sender_list.sort()
1702 tabs.titletext:SetFormattedText("Received broadcast data from %d |4player:players;.",
1703 self.sender_list.activeI)
1704 end
1705 tabs:SetRelativeWidth(0.99-rhs_width)
1706 tabs:SetFullHeight(true)
1707 tabs:SetTabs(tabgroup_tabs)
1708 tabs:SetCallback("OnGroupSelected", tabs_OnGroupSelected_func)
1709 tabs:SetCallback("OnTabEnter", function(_tabs,event,value,tab)
1710 setstatus(_tabtexts[value].desc)
1711 end)
1712 tabs:SetCallback("OnTabLeave", statusy_OnLeave)
1713 tabs:SetUserData("special buttons group",tab_specials)
1714 tabs:SelectTab(opt_tabselect or "eoi")
1715
1716 display:AddChildren (tabs, control)
1717 display:ApplyStatus()
1718
1719 display:Show() -- without this, only appears every *other* function call
1720 return display
1721 end
1722
1723 function addon:OpenMainDisplayToTab (text)
1724 text = '^'..text
1725 for tab,v in pairs(_tabtexts) do
1726 if v.title:lower():find(text) then
1727 self:BuildMainDisplay(tab)
1728 return true
1729 end
1730 end
1731 end
1732
1733 -- Essentially a re-click on the current tab (if the current tab were clickable).
1734 function addon:redisplay ()
1735 tabs_OnGroupSelected_func (unpack(tabs_OnGroupSelected_func_args))
1736 end
1737
1738 end -- local 'do' scope
1739
1740
1741 ------ Popup dialogs
1742 -- Callback for each Next/Accept stage of inserting a new loot row via dropdown
1743 local function eoi_st_insert_OnAccept_boss (dialog, data)
1744 if data.all_done then
1745 -- It'll probably be the final entry in the table, but there might have
1746 -- been real loot happening at the same time.
1747 local boss_index = addon._addLootEntry{
1748 kind = 'boss',
1749 bosskill = (OuroLootSV_opts.snarky_boss and addon.boss_abbrev[data.name] or data.name) or data.name,
1750 reason = 'kill',
1751 instance = data.instance,
1752 duration = 0,
1753 }
1754 local entry = tremove(g_loot,boss_index)
1755 tinsert(g_loot,data.rowindex,entry)
1756 addon:_mark_boss_kill(data.rowindex)
1757 data.display:GetUserData("eoiST"):OuroLoot_Refresh(data.rowindex)
1758 dialog.data = nil -- free up memory
1759 addon:Print("Inserted %s %s (entry %d).", data.kind, data.name, data.rowindex)
1760 return
1761 end
1762
1763 local text = dialog.wideEditBox:GetText()
1764
1765 -- second click
1766 if data.name and text then
1767 data.instance = text
1768 data.all_done = true
1769 -- in future do one more thing, for now just jump to the check
1770 return eoi_st_insert_OnAccept_boss (dialog, data)
1771 end
1772
1773 -- first click
1774 if text then
1775 data.name = text
1776 local getinstance = StaticPopup_Show("OUROL_EOI_INSERT","instance")
1777 getinstance.data = data
1778 getinstance.wideEditBox:SetText(addon.instance_tag())
1779 -- This suppresses auto-hide (which would case the getinstance dialog
1780 -- to go away), but only when mouse clicking. OnEnter is on its own.
1781 return true
1782 end
1783 end
1784
1785 local function eoi_st_insert_OnAccept_loot (dialog, data)
1786 if data.all_done then
1787 --local real_rebroadcast, real_enabled = addon.rebroadcast, addon.enabled
1788 --g_rebroadcast, g_enabled = false, true
1789 data.display:Hide()
1790 local loot_index = addon:CHAT_MSG_LOOT ("manual", data.recipient, data.name, data.notes)
1791 --g_rebroadcast, g_enabled = real_g_rebroadcast, real_g_enabled
1792 local entry = tremove(g_loot,loot_index)
1793 tinsert(g_loot,data.rowindex,entry)
1794 --data.display:GetUserData("eoiST"):OuroLoot_Refresh(data.rowindex)
1795 addon:_fill_out_eoi_data(data.rowindex)
1796 addon:BuildMainDisplay()
1797 dialog.data = nil
1798 addon:Print("Inserted %s %s (entry %d).", data.kind, data.name, data.rowindex)
1799 return
1800 end
1801
1802 local text = dialog.wideEditBox:GetText():trim()
1803
1804 -- third click
1805 if data.name and data.recipient and text then
1806 data.notes = (text ~= "<none>") and text or nil
1807 data.all_done = true
1808 return eoi_st_insert_OnAccept_loot (dialog, data)
1809 end
1810
1811 -- second click
1812 if data.name and text then
1813 data.recipient = text
1814 local getnotes = StaticPopup_Show("OUROL_EOI_INSERT","notes")
1815 getnotes.data = data
1816 getnotes.wideEditBox:SetText("<none>")
1817 getnotes.wideEditBox:HighlightText()
1818 return true
1819 end
1820
1821 -- first click
1822 if text then
1823 data.name = text
1824 dialog:Hide() -- technically a "different" one about to be shown
1825 local getrecipient = StaticPopup_Show("OUROL_EOI_INSERT","recipient")
1826 getrecipient.data = data
1827 getrecipient.wideEditBox:SetText("")
1828 return true
1829 end
1830 end
1831
1832 local function eoi_st_insert_OnAccept (dialog, data)
1833 if data.kind == 'boss' then
1834 return eoi_st_insert_OnAccept_boss (dialog, data)
1835 elseif data.kind == 'loot' then
1836 return eoi_st_insert_OnAccept_loot (dialog, data)
1837 end
1838 end
1839
1840 StaticPopupDialogs["OUROL_CLEAR"] = flib.StaticPopup{
1841 text = "Clear current loot information and text?",
1842 button1 = ACCEPT,
1843 button2 = CANCEL,
1844 OnAccept = function (dialog, addon)
1845 addon:Clear(--[[verbose_p=]]true)
1846 end,
1847 }
1848
1849 StaticPopupDialogs["OUROL_REMIND"] = flib.StaticPopup{
1850 text = "Do you wish to activate Ouro Loot?\n\n(Hit the Escape key to close this window without clicking)",
1851 button1 = "Activate recording", -- "accept", left
1852 button3 = "Broadcast only", -- "alt", middle
1853 button2 = "Help", -- "cancel", right
1854 OnAccept = function (dialog, addon)
1855 addon:Activate()
1856 end,
1857 OnAlt = function (dialog, addon)
1858 addon:Activate(nil,true)
1859 end,
1860 OnCancel = function (dialog, addon)
1861 -- hitting escape also calls this, but the 3rd arg would be "clicked"
1862 -- in both cases, not useful here.
1863 local helpbutton = dialog.button2
1864 local ismousing = MouseIsOver(helpbutton)
1865 if ismousing then
1866 -- they actually clicked the button (or at least the mouse was over "Help"
1867 -- when they hit escape... sigh)
1868 addon:BuildMainDisplay('help')
1869 else
1870 addon.popped = true
1871 end
1872 end,
1873 }
1874
1875 -- The data member here is a table built with:
1876 -- {rowindex=<GUI row receiving click>, display=_d, kind=<loot/boss>}
1877 do
1878 local t = flib.StaticPopup{
1879 text = "Enter name of new %s, then click Next or press Enter:",
1880 button1 = "Next >",
1881 button2 = CANCEL,
1882 hasEditBox = true,
1883 hasWideEditBox = true,
1884 maxLetters = 50,
1885 noCancelOnReuse = true,
1886 --[[ XXX still needed?
1887 OnShow = function(dialog)
1888 dialog.wideEditBox:SetText("")
1889 dialog.wideEditBox:SetFocus()
1890 end,]]
1891 }
1892 t.EditBoxOnEnterPressed = function(editbox)
1893 local dialog = editbox:GetParent()
1894 if not eoi_st_insert_OnAccept (dialog, dialog.data) then
1895 dialog:Hide() -- replicate OnAccept click behavior
1896 end
1897 end
1898 t.enterClicksFirstButton = nil -- no effect with editbox focused
1899 t.OnAccept = eoi_st_insert_OnAccept
1900 StaticPopupDialogs["OUROL_EOI_INSERT"] = t
1901 end
1902
1903 -- This seems to be gratuitous use of metatables, really.
1904 do
1905 local OEIL = {
1906 text = "Paste the new item into here, then click Next or press Enter:",
1907 __index = StaticPopupDialogs["OUROL_EOI_INSERT"]
1908 }
1909 StaticPopupDialogs["OUROL_EOI_INSERT_LOOT"] = setmetatable(OEIL,OEIL)
1910
1911 hooksecurefunc("ChatEdit_InsertLink", function (link,...)
1912 local dialogname = StaticPopup_Visible "OUROL_EOI_INSERT_LOOT"
1913 if dialogname then
1914 _G[dialogname.."WideEditBox"]:SetText(link)
1915 return true
1916 end
1917 end)
1918 end
1919
1920 StaticPopupDialogs["OUROL_REASSIGN_ENTER"] = flib.StaticPopup{
1921 text = "Enter the player name:",
1922 button1 = ACCEPT,
1923 button2 = CANCEL,
1924 hasEditBox = true,
1925 --[[ XXX needed?
1926 OnShow = function(dialog)
1927 dialog.editBox:SetText("")
1928 dialog.editBox:SetFocus()
1929 end,]]
1930 OnAccept = function(dialog, data)
1931 local name = dialog.usertext --editBox:GetText()
1932 g_loot[data.index].person = name
1933 g_loot[data.index].person_class = select(2,UnitClass(name))
1934 addon:Print("Reassigned entry %d to '%s'.", data.index, name)
1935 data.display:GetUserData("eoiST"):OuroLoot_Refresh(data.index)
1936 end,
1937 }
1938
1939 StaticPopupDialogs["OUROL_SAVE_SAVEAS"] = flib.StaticPopup{
1940 text = "Enter a name for the loot collection:",
1941 button1 = ACCEPT,
1942 button2 = CANCEL,
1943 hasEditBox = true,
1944 maxLetters = 30,
1945 --[[ XXX
1946 OnShow = function(dialog)
1947 dialog.editBox:SetText("")
1948 dialog.editBox:SetFocus()
1949 end,]]
1950 OnAccept = function(dialog)--, data)
1951 local name = dialog.usertext --editBox:GetText()
1952 addon:save_saveas(name)
1953 addon:BuildMainDisplay()
1954 end,
1955 OnCancel = function(dialog)--, data, reason)
1956 addon:BuildMainDisplay()
1957 end,
1958 --[[XXX
1959 EditBoxOnEnterPressed = function(editbox)
1960 local dialog = editbox:GetParent()
1961 StaticPopupDialogs["OUROL_SAVE_SAVEAS"].OnAccept (dialog, dialog.data)
1962 dialog:Hide()
1963 end,]]
1964 }
1965
1966 -- vim:noet