local parent, ns = ...
local lib = ns.chern_config
lib.list = lib.list or {}
local media = lib.media
UIDROPDOWNMENU_BUTTON_HEIGHT = lib.widget.select_items
-- methods
local methods = {
-- set value to profile[key]
['set'] = function(self, value, text)
self.save = self.module:get_save()
if (not value) then value = self:get() end
self.save[self.key] = value
self.callback(self.dropdown)
self.selected = value
end,
-- return value from profile[key]
['get'] = function(self)
self.save = self.module:get_save()
return self.save[self.key] or self.selected
end,
['setvalue'] = function(self)
if not text and self.items and type(self.items[1]) == 'table' then
for i=1, #self.items do
if self.items[i].value == value then
text = self.items[i].text
break
end
end
end
self.dropdown.value:SetText(value)
end,
-- table list
['setlist'] = function(self, list)
if type(list) ~= 'table' then list = nil end
self.items = list
end,
-- dropdown click
['onenter'] = function(self)
if self.OnEnter then
self:OnEnter()
elseif self.tooltipText then
GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
GameTooltip:SetText(self.tooltipText, nil, nil, nil, nil, true)
GameTooltip:Show()
end
end,
['onleave'] = function(self)
if self.OnLeave then
self:OnLeave()
else
GameTooltip:Hide()
end
end,
['onhide'] = function(self)
if self.list then
self.list:Hide()
end
end
}
-- list hide function
local function CloseDropdowns(_,_,dropDownFrame,_,_,_,_,clickedButton)
for i=1, #lib.list do
lib.list[i]:set_fade_out(.2, 0)
lib.list[i].fadeInfo.finishedFunc = function()
lib.list[i]:Hide()
end
end
end
hooksecurefunc('CloseDropDownMenus', CloseDropdowns)
hooksecurefunc('ToggleDropDownMenu', CloseDropdowns) -- WIP
-- onclick action
local function ListButton_OnClick(self)
local dropdown = self:GetParent():GetParent()
dropdown.selected = self.value
dropdown.list:set_fade_out(.2, 0)
dropdown.list.fadeInfo.finishedFunc = function()
dropdown.list:Hide()
end
dropdown.value:SetText(self:GetText() or self.value)
-- dropdown.button:SetNormalTexture(dropdown.button.normal)
local callback = dropdown.callback
if callback then
callback(dropdown, self.value, self:GetText())
end
PlaySoundFile(media.gui_out, 'Master')
end
-- if list is empty
local is_empty = {
{ text = GRAY_FONT_COLOR_CODE..EMPTY, value = EMPTY, disabled = true, empty = true }
}
local function update_list(self)
local buttons = self.buttons
local dropdown = self:GetParent()
local items = dropdown.items
if #items == 0 then items = is_empty end
local listSize = min(#items, lib.widget.select_maxlist)
local scrollFrame = self.scrollFrame
local offset = scrollFrame.offset
FauxScrollFrame_Update(scrollFrame, #items, listSize, UIDROPDOWNMENU_BUTTON_HEIGHT)
local selected = dropdown.selected
local width = 0
local spec_width = scrollFrame:IsShown() and 42 or 52
for i = 1, #items do
local item = items[i]
if type(item) == 'table' then
self.text:SetText(item.text or item.value)
else
self.text:SetText(item)
end
width = max(width, spec_width * 2)
end
local EXTRA_WIDTH = scrollFrame:IsShown() and 50 or 30
width = max(width + 27 + EXTRA_WIDTH, dropdown:GetWidth() - lib.get_pixel)
self:width(dropdown:GetWidth())
width = width - EXTRA_WIDTH
self:height((listSize * UIDROPDOWNMENU_BUTTON_HEIGHT) + (UIDROPDOWNMENU_BORDER_HEIGHT * 1.5))
for i = 1, listSize do
local index = i + offset
local button = buttons[i]
local item = items[index]
if item then
button.value = item
button.label:SetText(item)
if item == selected then
button.check:Show()
else
button.check:Hide()
end
if item.disabled then
button.label:SetTextColor(GameFontDisable:GetTextColor())
else
button.label:SetTextColor(GameFontHighlight:GetTextColor())
end
button:SetWidth(width)
button:Show()
else
button.value = nil
button.label:SetText()
button.label:SetTextColor(GameFontHighlight:GetTextColor())
button.check:Hide()
button:Hide()
end
end
for i = listSize + 1, #buttons do
buttons[i]:Hide()
end
end
local skin = function(frame)
local pixel = lib.get_pixel
-- frame:SetFrameLevel(frame:GetFrameLevel() + 54)
frame:set_backdrop('Transparent')
frame:set_blur()
-- frame.Backdrop:SetFrameLevel(frame:GetFrameLevel() + 54)
frame.Backdrop:SetBackdropColor(.015, .015, .015, 0.45)
frame.Backdrop:SetBackdropBorderColor(.03, .03, .03, 1)
-- local overlay = CreateFrame('Frame', nil, frame)
-- overlay:SetAllPoints(frame)
-- overlay:set_backdrop('Transparent')
-- overlay.Backdrop:SetPoint('TOPLEFT', overlay, 'TOPLEFT', 4, -4)
-- overlay.Backdrop:SetPoint('BOTTOMRIGHT', overlay, 'BOTTOMRIGHT', -4, 4)
-- overlay.Backdrop:setbordercolor(unpack(media.active))
local scrollbar = _G[frame.scrollFrame:GetName().."ScrollBar"]
local thumb = _G[frame.scrollFrame:GetName()..'ScrollBarThumbTexture']
local button_up = _G[frame.scrollFrame:GetName()..'ScrollBarScrollUpButton']
local button_down = _G[frame.scrollFrame:GetName()..'ScrollBarScrollDownButton']
button_up:strip_textures()
button_down:strip_textures()
scrollbar:size(6, 28)
scrollbar:set_backdrop()
scrollbar.Backdrop:SetBackdropColor(.015, .015, .015, .95)
scrollbar.Backdrop:setbordercolor(.21, .21, .21, 1)
thumb:width(6)
thumb:SetTexture(media.flat)
thumb:SetVertexColor(unpack(media.active))
end
-- create dropdown list
local count = 0
local function create_list(dropdown)
if dropdown.list then
return dropdown.list
end
count = count + 1
local name = parent..'_list'
local list = CreateFrame("Button", name .. count, dropdown)
list:SetFrameStrata("FULLSCREEN_DIALOG")
list:SetToplevel(true)
list:Raise()
list:Hide()
list:set_point('TOPLEFT', dropdown, 'BOTTOMLEFT', 0, 75)
list:SetScript("OnShow", update_list)
list.text = list:CreateFontString()
list.text:SetFont((GameFontNormal:GetFont()), UIDROPDOWNMENU_DEFAULT_TEXT_HEIGHT + 2)
-- categories
list.buttons = setmetatable({}, { __index = function(t, i)
local bg = CreateFrame('Frame', nil, list)
bg:set_backdrop()
local button = CreateFrame('Button', nil, list)
button:height(UIDROPDOWNMENU_BUTTON_HEIGHT)
-- button:set_backdrop()
if i > 1 then
button:SetPoint('TOPLEFT', t[i-1], 'BOTTOMLEFT', 0, -2)
else
button:SetPoint('TOPLEFT', 5, -5)
end
t[i] = button
bg:SetAllPoints(button)
local label = button:CreateFontString(nil, 'OVERLAY', 'GameFontNormal')
label:SetPoint('LEFT', button, 2, 0)
label:SetJustifyH('LEFT', button)
button:SetFontString(label)
button.label = label -- DEPRECATED
local check = button:CreateTexture(nil, 'ARTWORK')
check:size(24, 24)
check:SetAllPoints()
check:SetTexture(media.flat)
check:SetVertexColor(unpack(media.active))
button.check = check
local highlight = button:CreateTexture(nil, 'HIGHLIGHT')
highlight:SetAllPoints(button)
highlight:SetTexture(1, 1, 1, .04)
highlight:Hide()
button:SetHighlightTexture(highlight)
button:SetScript('OnClick', ListButton_OnClick)
return button
end })
-- create scroll
list.scrollFrame = CreateFrame('ScrollFrame', list:GetName()..'ScrollFrame', list, 'FauxScrollFrameTemplate')
list.scrollFrame:SetPoint('TOPLEFT', 6, 2)
list.scrollFrame:SetPoint('BOTTOMRIGHT', -24, -2)
list.scrollFrame:SetScript('OnVerticalScroll', function(self, delta)
FauxScrollFrame_OnVerticalScroll(self, delta, UIDROPDOWNMENU_BUTTON_HEIGHT, function()
update_list(list)
end)
end)
skin(list)
table.insert(lib.list, list)
dropdown.list = list
return list
end
local function button_OnClick(self)
PlaySoundFile(media.gui_info)
local dropdown = self:GetParent()
local list = dropdown.list
if(not list) then
list = create_list(dropdown)
dropdown.list = list
end
local show = not list:IsShown()
CloseDropDownMenus()
if show then
list:Raise()
list:Show()
list:set_fade_in(.2, 1)
local selectedIndex
local items, selected = dropdown.items, dropdown.selected
for i=1, #items do
if items[i] == selected then
selectedIndex = i
break
end
end
if selectedIndex then
local scrollbar = _G[list.scrollFrame:GetName().."ScrollBar"]
local _, maxScroll = scrollbar:GetMinMaxValues()
scrollbar:SetValue((maxScroll / (#items - 15)) * (selectedIndex - 5))
end
end
end
-- spawn elements
local function create(options, parent)
options.size = options.size or 'half'
local container = lib:create_container(options, parent, 48)
local name = options.name..'_'..options.key
-- objects
local dropdown = CreateFrame('Frame', name, container)
dropdown:size(142, 26)
dropdown:SetPoint('TOPLEFT', 11, -22)
dropdown:set_border(false, true)
dropdown:EnableMouse(true)
dropdown:SetScript('OnEnter', function() container:onenter() end)
dropdown:SetScript('OnLeave', function() container:onleave() end)
dropdown:SetScript('OnHide', function() container:onhide() end)
local label = dropdown:CreateFontString(nil, 'ARTWORK', 'GameFontNormal')
label:SetPoint("TOPLEFT", 5, 20)
label:SetPoint("TOPRIGHT", -5, 20)
label:SetJustifyH("LEFT")
label:SetText(options.label)
label:SetAlpha(media.muted)
-- value text
local valueText = dropdown:CreateFontString(nil, "ARTWORK", 'GameFontHighlightSmall')
valueText:SetPoint('LEFT', 6, -2)
-- dropdown.value:SetAlpha(media.muted)
dropdown.value = valueText
-- arrow
local BUTTONSIZE = lib.widget.select_button
local button = CreateFrame('Button', nil, dropdown)
button:size(BUTTONSIZE, BUTTONSIZE)
button:SetPoint('TOPLEFT', dropdown, 2, -2)
button:SetPoint('TOPRIGHT', dropdown, 2, -2)
local normal = button:CreateTexture(nil, 'BORDER')
normal:size(18, 18)
normal:SetPoint('RIGHT', -8, 2)
normal:SetTexture(media.arrow_down)
button:SetNormalTexture(normal)
local disabled = button:CreateTexture(nil, 'BORDER')
disabled:size(18, 18)
disabled:SetPoint('RIGHT', -8, 2)
disabled:SetTexture(media.arrow_down)
button:SetDisabledTexture(disabled)
local highlight = button:CreateTexture(nil, 'HIGHLIGHT')
highlight:size(14, 14)
highlight:SetPoint('RIGHT', -10, 0)
highlight:SetVertexColor(unpack(media.class))
highlight:SetBlendMode('ADD')
button:SetHighlightTexture(highlight)
function button:OnEnter()
return container:onenter(dropdown)
end
function button:OnLeave()
return container:onleave(dropdown)
end
button:SetScript('OnEnter', button.OnEnter)
button:SetScript('OnLeave', button.OnLeave)
button:SetScript('OnClick', button_OnClick)
-- Mixin methods, reference variables
container.save = options.save
container.key = options.key
container.module = options.module
container.dropdown = dropdown
container.callback = options.callback
container.module = options.module
Mixin(container, methods)
-- callback
local get_value = container:get()
dropdown.callback = function(self)
local value = self.value:GetText() or options.value
container:set(value)
end
-- hook into actions for updates
if (options.action) then
lib:add_action(options.action, function(value)
local results = options.lookup()
options.options = results
end)
end
-- default variables
dropdown.items = items or options.options
dropdown.value:SetText(get_value or options.value)
dropdown.button = button
dropdown.button.normal = normal
dropdown.selected = get_value or options.value
dropdown.tooltipText = tooltipText
return container
end
lib:register_element('select', create)