comparison Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua @ 0:169f5211fc7f

First public revision. At this point ItemAuditor watches mail for auctions sold or purchased, watches for buy/sell (money and 1 item type change) and conversions/tradeskills. Milling isn't working yet because there is too much time between the first event and the last event.
author Asa Ayers <Asa.Ayers@Gmail.com>
date Thu, 20 May 2010 19:22:19 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:169f5211fc7f
1 --[[ $Id: AceGUIWidget-DropDown.lua 877 2009-11-02 15:56:50Z nevcairiel $ ]]--
2 local AceGUI = LibStub("AceGUI-3.0")
3
4 -- Lua APIs
5 local min, max, floor = math.min, math.max, math.floor
6 local select, pairs, ipairs = select, pairs, ipairs
7 local tsort = table.sort
8
9 -- WoW APIs
10 local UIParent, CreateFrame = UIParent, CreateFrame
11 local _G = _G
12
13 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
14 -- List them here for Mikk's FindGlobals script
15 -- GLOBALS: CLOSE
16
17 local function fixlevels(parent,...)
18 local i = 1
19 local child = select(i, ...)
20 while child do
21 child:SetFrameLevel(parent:GetFrameLevel()+1)
22 fixlevels(child, child:GetChildren())
23 i = i + 1
24 child = select(i, ...)
25 end
26 end
27
28 local function fixstrata(strata, parent, ...)
29 local i = 1
30 local child = select(i, ...)
31 parent:SetFrameStrata(strata)
32 while child do
33 fixstrata(strata, child, child:GetChildren())
34 i = i + 1
35 child = select(i, ...)
36 end
37 end
38
39 do
40 local widgetType = "Dropdown-Pullout"
41 local widgetVersion = 3
42
43 --[[ Static data ]]--
44
45 local backdrop = {
46 bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
47 edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
48 edgeSize = 32,
49 tileSize = 32,
50 tile = true,
51 insets = { left = 11, right = 12, top = 12, bottom = 11 },
52 }
53 local sliderBackdrop = {
54 bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
55 edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
56 tile = true, tileSize = 8, edgeSize = 8,
57 insets = { left = 3, right = 3, top = 3, bottom = 3 }
58 }
59
60 local defaultWidth = 200
61 local defaultMaxHeight = 600
62
63 --[[ UI Event Handlers ]]--
64
65 -- HACK: This should be no part of the pullout, but there
66 -- is no other 'clean' way to response to any item-OnEnter
67 -- Used to close Submenus when an other item is entered
68 local function OnEnter(item)
69 local self = item.pullout
70 for k, v in ipairs(self.items) do
71 if v.CloseMenu and v ~= item then
72 v:CloseMenu()
73 end
74 end
75 end
76
77 -- See the note in Constructor() for each scroll related function
78 local function OnMouseWheel(this, value)
79 this.obj:MoveScroll(value)
80 end
81
82 local function OnScrollValueChanged(this, value)
83 this.obj:SetScroll(value)
84 end
85
86 local function OnSizeChanged(this)
87 this.obj:FixScroll()
88 end
89
90 --[[ Exported methods ]]--
91
92 -- exported
93 local function SetScroll(self, value)
94 local status = self.scrollStatus
95 local frame, child = self.scrollFrame, self.itemFrame
96 local height, viewheight = frame:GetHeight(), child:GetHeight()
97
98 local offset
99 if height > viewheight then
100 offset = 0
101 else
102 offset = floor((viewheight - height) / 1000 * value)
103 end
104 child:ClearAllPoints()
105 child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
106 child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
107 status.offset = offset
108 status.scrollvalue = value
109 end
110
111 -- exported
112 local function MoveScroll(self, value)
113 local status = self.scrollStatus
114 local frame, child = self.scrollFrame, self.itemFrame
115 local height, viewheight = frame:GetHeight(), child:GetHeight()
116
117 if height > viewheight then
118 self.slider:Hide()
119 else
120 self.slider:Show()
121 local diff = height - viewheight
122 local delta = 1
123 if value < 0 then
124 delta = -1
125 end
126 self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
127 end
128 end
129
130 -- exported
131 local function FixScroll(self)
132 local status = self.scrollStatus
133 local frame, child = self.scrollFrame, self.itemFrame
134 local height, viewheight = frame:GetHeight(), child:GetHeight()
135 local offset = status.offset or 0
136
137 if viewheight < height then
138 self.slider:Hide()
139 child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
140 self.slider:SetValue(0)
141 else
142 self.slider:Show()
143 local value = (offset / (viewheight - height) * 1000)
144 if value > 1000 then value = 1000 end
145 self.slider:SetValue(value)
146 self:SetScroll(value)
147 if value < 1000 then
148 child:ClearAllPoints()
149 child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
150 child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
151 status.offset = offset
152 end
153 end
154 end
155
156 -- exported, AceGUI callback
157 local function OnAcquire(self)
158 self.frame:SetParent(UIParent)
159 --self.itemFrame:SetToplevel(true)
160 end
161
162 -- exported, AceGUI callback
163 local function OnRelease(self)
164 self:Clear()
165 self.frame:ClearAllPoints()
166 self.frame:Hide()
167 end
168
169 -- exported
170 local function AddItem(self, item)
171 self.items[#self.items + 1] = item
172
173 local h = #self.items * 16
174 self.itemFrame:SetHeight(h)
175 self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement
176
177 item.frame:SetPoint("LEFT", self.itemFrame, "LEFT")
178 item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT")
179
180 item:SetPullout(self)
181 item:SetOnEnter(OnEnter)
182 end
183
184 -- exported
185 local function Open(self, point, relFrame, relPoint, x, y)
186 local items = self.items
187 local frame = self.frame
188 local itemFrame = self.itemFrame
189
190 frame:SetPoint(point, relFrame, relPoint, x, y)
191
192
193 local height = 8
194 for i, item in pairs(items) do
195 if i == 1 then
196 item:SetPoint("TOP", itemFrame, "TOP", 0, -2)
197 else
198 item:SetPoint("TOP", items[i-1].frame, "BOTTOM", 0, 1)
199 end
200
201 item:Show()
202
203 height = height + 16
204 end
205 itemFrame:SetHeight(height)
206 fixstrata("TOOLTIP", frame, frame:GetChildren())
207 frame:Show()
208 self:Fire("OnOpen")
209 end
210
211 -- exported
212 local function Close(self)
213 self.frame:Hide()
214 self:Fire("OnClose")
215 end
216
217 -- exported
218 local function Clear(self)
219 local items = self.items
220 for i, item in pairs(items) do
221 AceGUI:Release(item)
222 items[i] = nil
223 end
224 end
225
226 -- exported
227 local function IterateItems(self)
228 return ipairs(self.items)
229 end
230
231 -- exported
232 local function SetHideOnLeave(self, val)
233 self.hideOnLeave = val
234 end
235
236 -- exported
237 local function SetMaxHeight(self, height)
238 self.maxHeight = height or defaultMaxHeight
239 if self.frame:GetHeight() > height then
240 self.frame:SetHeight(height)
241 elseif (self.itemFrame:GetHeight() + 34) < height then
242 self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem
243 end
244 end
245
246 -- exported
247 local function GetRightBorderWidth(self)
248 return 6 + (self.slider:IsShown() and 12 or 0)
249 end
250
251 -- exported
252 local function GetLeftBorderWidth(self)
253 return 6
254 end
255
256 --[[ Constructor ]]--
257
258 local function Constructor()
259 local count = AceGUI:GetNextWidgetNum(widgetType)
260 local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent)
261 local self = {}
262 self.count = count
263 self.type = widgetType
264 self.frame = frame
265 frame.obj = self
266
267 self.OnAcquire = OnAcquire
268 self.OnRelease = OnRelease
269
270 self.AddItem = AddItem
271 self.Open = Open
272 self.Close = Close
273 self.Clear = Clear
274 self.IterateItems = IterateItems
275 self.SetHideOnLeave = SetHideOnLeave
276
277 self.SetScroll = SetScroll
278 self.MoveScroll = MoveScroll
279 self.FixScroll = FixScroll
280
281 self.SetMaxHeight = SetMaxHeight
282 self.GetRightBorderWidth = GetRightBorderWidth
283 self.GetLeftBorderWidth = GetLeftBorderWidth
284
285 self.items = {}
286
287 self.scrollStatus = {
288 scrollvalue = 0,
289 }
290
291 self.maxHeight = defaultMaxHeight
292
293 frame:SetBackdrop(backdrop)
294 frame:SetBackdropColor(0, 0, 0)
295 frame:SetFrameStrata("FULLSCREEN_DIALOG")
296 frame:SetClampedToScreen(true)
297 frame:SetWidth(defaultWidth)
298 frame:SetHeight(self.maxHeight)
299 --frame:SetToplevel(true)
300
301 -- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame
302 local scrollFrame = CreateFrame("ScrollFrame", nil, frame)
303 local itemFrame = CreateFrame("Frame", nil, scrollFrame)
304
305 self.scrollFrame = scrollFrame
306 self.itemFrame = itemFrame
307
308 scrollFrame.obj = self
309 itemFrame.obj = self
310
311 local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame)
312 slider:SetOrientation("VERTICAL")
313 slider:SetHitRectInsets(0, 0, -10, 0)
314 slider:SetBackdrop(sliderBackdrop)
315 slider:SetWidth(8)
316 slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
317 slider:SetFrameStrata("FULLSCREEN_DIALOG")
318 self.slider = slider
319 slider.obj = self
320
321 scrollFrame:SetScrollChild(itemFrame)
322 scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
323 scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
324 scrollFrame:EnableMouseWheel(true)
325 scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
326 scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
327 scrollFrame:SetToplevel(true)
328 scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")
329
330 itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
331 itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
332 itemFrame:SetHeight(400)
333 itemFrame:SetToplevel(true)
334 itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
335
336 slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
337 slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
338 slider:SetScript("OnValueChanged", OnScrollValueChanged)
339 slider:SetMinMaxValues(0, 1000)
340 slider:SetValueStep(1)
341 slider:SetValue(0)
342
343 scrollFrame:Show()
344 itemFrame:Show()
345 slider:Hide()
346
347 self:FixScroll()
348
349 AceGUI:RegisterAsWidget(self)
350 return self
351 end
352
353 AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
354 end
355
356 do
357 local widgetType = "Dropdown"
358 local widgetVersion = 21
359
360 --[[ Static data ]]--
361
362 --[[ UI event handler ]]--
363
364 local function Control_OnEnter(this)
365 this.obj:Fire("OnEnter")
366 end
367
368 local function Control_OnLeave(this)
369 this.obj:Fire("OnLeave")
370 end
371
372 local function Dropdown_OnHide(this)
373 local self = this.obj
374 if self.open then
375 self.pullout:Close()
376 end
377 end
378
379 local function Dropdown_TogglePullout(this)
380 local self = this.obj
381 if self.open then
382 self.open = nil
383 self.pullout:Close()
384 AceGUI:ClearFocus()
385 else
386 self.open = true
387 self.pullout:SetWidth(self.frame:GetWidth())
388 self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0)
389 AceGUI:SetFocus(self)
390 end
391 end
392
393 local function OnPulloutOpen(this)
394 local self = this.userdata.obj
395 local value = self.value
396
397 if not self.multiselect then
398 for i, item in this:IterateItems() do
399 item:SetValue(item.userdata.value == value)
400 end
401 end
402
403 self.open = true
404 end
405
406 local function OnPulloutClose(this)
407 local self = this.userdata.obj
408 self.open = nil
409 self:Fire("OnClosed")
410 end
411
412 local function ShowMultiText(self)
413 local text
414 for i, widget in self.pullout:IterateItems() do
415 if widget.type == "Dropdown-Item-Toggle" then
416 if widget:GetValue() then
417 if text then
418 text = text..", "..widget:GetText()
419 else
420 text = widget:GetText()
421 end
422 end
423 end
424 end
425 self:SetText(text)
426 end
427
428 local function OnItemValueChanged(this, event, checked)
429 local self = this.userdata.obj
430
431 if self.multiselect then
432 self:Fire("OnValueChanged", this.userdata.value, checked)
433 ShowMultiText(self)
434 else
435 if checked then
436 self:SetValue(this.userdata.value)
437 self:Fire("OnValueChanged", this.userdata.value)
438 else
439 this:SetValue(true)
440 end
441 if self.open then
442 self.pullout:Close()
443 end
444 end
445 end
446
447 --[[ Exported methods ]]--
448
449 -- exported, AceGUI callback
450 local function OnAcquire(self)
451 local pullout = AceGUI:Create("Dropdown-Pullout")
452 self.pullout = pullout
453 pullout.userdata.obj = self
454 pullout:SetCallback("OnClose", OnPulloutClose)
455 pullout:SetCallback("OnOpen", OnPulloutOpen)
456 self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
457 fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
458
459 self:SetHeight(44)
460 self:SetWidth(200)
461 end
462
463 -- exported, AceGUI callback
464 local function OnRelease(self)
465 if self.open then
466 self.pullout:Close()
467 end
468 AceGUI:Release(self.pullout)
469 self.pullout = nil
470
471 self:SetText("")
472 self:SetLabel("")
473 self:SetDisabled(false)
474 self:SetMultiselect(false)
475
476 self.value = nil
477 self.list = nil
478 self.open = nil
479 self.hasClose = nil
480
481 self.frame:ClearAllPoints()
482 self.frame:Hide()
483 end
484
485 -- exported
486 local function SetDisabled(self, disabled)
487 self.disabled = disabled
488 if disabled then
489 self.text:SetTextColor(0.5,0.5,0.5)
490 self.button:Disable()
491 self.label:SetTextColor(0.5,0.5,0.5)
492 else
493 self.button:Enable()
494 self.label:SetTextColor(1,.82,0)
495 self.text:SetTextColor(1,1,1)
496 end
497 end
498
499 -- exported
500 local function ClearFocus(self)
501 if self.open then
502 self.pullout:Close()
503 end
504 end
505
506 -- exported
507 local function SetText(self, text)
508 self.text:SetText(text or "")
509 end
510
511 -- exported
512 local function SetLabel(self, text)
513 if text and text ~= "" then
514 self.label:SetText(text)
515 self.label:Show()
516 self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-18)
517 self.frame:SetHeight(44)
518 else
519 self.label:SetText("")
520 self.label:Hide()
521 self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0)
522 self.frame:SetHeight(26)
523 end
524 end
525
526 -- exported
527 local function SetValue(self, value)
528 if self.list then
529 self:SetText(self.list[value] or "")
530 end
531 self.value = value
532 end
533
534 -- exported
535 local function GetValue(self)
536 return self.value
537 end
538
539 -- exported
540 local function SetItemValue(self, item, value)
541 if not self.multiselect then return end
542 for i, widget in self.pullout:IterateItems() do
543 if widget.userdata.value == item then
544 if widget.SetValue then
545 widget:SetValue(value)
546 end
547 end
548 end
549 ShowMultiText(self)
550 end
551
552 -- exported
553 local function SetItemDisabled(self, item, disabled)
554 for i, widget in self.pullout:IterateItems() do
555 if widget.userdata.value == item then
556 widget:SetDisabled(disabled)
557 end
558 end
559 end
560
561 local function AddListItem(self, value, text)
562 local item = AceGUI:Create("Dropdown-Item-Toggle")
563 item:SetText(text)
564 item.userdata.obj = self
565 item.userdata.value = value
566 item:SetCallback("OnValueChanged", OnItemValueChanged)
567 self.pullout:AddItem(item)
568 end
569
570 local function AddCloseButton(self)
571 if not self.hasClose then
572 local close = AceGUI:Create("Dropdown-Item-Execute")
573 close:SetText(CLOSE)
574 self.pullout:AddItem(close)
575 self.hasClose = true
576 end
577 end
578
579 -- exported
580 local sortlist = {}
581 local function SetList(self, list)
582 self.list = list
583 self.pullout:Clear()
584 self.hasClose = nil
585 if not list then return end
586
587 for v in pairs(list) do
588 sortlist[#sortlist + 1] = v
589 end
590 tsort(sortlist)
591
592 for i, value in pairs(sortlist) do
593 AddListItem(self, value, list[value])
594 sortlist[i] = nil
595 end
596 if self.multiselect then
597 ShowMultiText(self)
598 AddCloseButton(self)
599 end
600 end
601
602 -- exported
603 local function AddItem(self, value, text)
604 if self.list then
605 self.list[value] = text
606 AddListItem(self, value, text)
607 end
608 end
609
610 -- exported
611 local function SetMultiselect(self, multi)
612 self.multiselect = multi
613 if multi then
614 ShowMultiText(self)
615 AddCloseButton(self)
616 end
617 end
618
619 -- exported
620 local function GetMultiselect(self)
621 return self.multiselect
622 end
623
624 --[[ Constructor ]]--
625
626 local function Constructor()
627 local count = AceGUI:GetNextWidgetNum(widgetType)
628 local frame = CreateFrame("Frame", nil, UIParent)
629 local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate")
630
631 local self = {}
632 self.type = widgetType
633 self.frame = frame
634 self.dropdown = dropdown
635 self.count = count
636 frame.obj = self
637 dropdown.obj = self
638
639 self.OnRelease = OnRelease
640 self.OnAcquire = OnAcquire
641
642 self.ClearFocus = ClearFocus
643
644 self.SetText = SetText
645 self.SetValue = SetValue
646 self.GetValue = GetValue
647 self.SetList = SetList
648 self.SetLabel = SetLabel
649 self.SetDisabled = SetDisabled
650 self.AddItem = AddItem
651 self.SetMultiselect = SetMultiselect
652 self.GetMultiselect = GetMultiselect
653 self.SetItemValue = SetItemValue
654 self.SetItemDisabled = SetItemDisabled
655
656 self.alignoffset = 31
657
658 frame:SetHeight(44)
659 frame:SetWidth(200)
660 frame:SetScript("OnHide",Dropdown_OnHide)
661
662 dropdown:ClearAllPoints()
663 dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0)
664 dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0)
665 dropdown:SetScript("OnHide", nil)
666
667 local left = _G[dropdown:GetName() .. "Left"]
668 local middle = _G[dropdown:GetName() .. "Middle"]
669 local right = _G[dropdown:GetName() .. "Right"]
670
671 middle:ClearAllPoints()
672 right:ClearAllPoints()
673
674 middle:SetPoint("LEFT", left, "RIGHT", 0, 0)
675 middle:SetPoint("RIGHT", right, "LEFT", 0, 0)
676 right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17)
677
678 local button = _G[dropdown:GetName() .. "Button"]
679 self.button = button
680 button.obj = self
681 button:SetScript("OnEnter",Control_OnEnter)
682 button:SetScript("OnLeave",Control_OnLeave)
683 button:SetScript("OnClick",Dropdown_TogglePullout)
684
685 local text = _G[dropdown:GetName() .. "Text"]
686 self.text = text
687 text.obj = self
688 text:ClearAllPoints()
689 text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2)
690 text:SetPoint("LEFT", left, "LEFT", 25, 2)
691
692 local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
693 label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
694 label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
695 label:SetJustifyH("LEFT")
696 label:SetHeight(18)
697 label:Hide()
698 self.label = label
699
700 AceGUI:RegisterAsWidget(self)
701 return self
702 end
703
704 AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
705 end