You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

543 lines
18 KiB

1 year ago
---@type Diesal.GUI
local DiesalGUI = LibStub("DiesalGUI-2.0")
---@type Diesal.Tools
local DiesalTools = LibStub("DiesalTools-2.0")
---@type Diesal.Style
local DiesalStyle = LibStub("DiesalStyle-2.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local tsort = table.sort
local sub, format, lower, upper, gsub = string.sub, string.format, string.lower, string.upper, string.gsub
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| Dropdown |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "DiesalDropDown"
local Version = 2
-- ~~| Dropdown Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
["frame-background"] = {
type = "texture",
layer = "BACKGROUND",
gradient = { "VERTICAL", Colors.UI_400_GR[1], Colors.UI_400_GR[2] },
},
["frame-outline"] = {
type = "outline",
layer = "BORDER",
color = "000000",
},
["frame-inline"] = {
type = "outline",
layer = "BORDER",
gradient = { "VERTICAL", "FFFFFF", "FFFFFF" },
alpha = { 0.07, 0.02 },
position = -1,
},
["frame-hover"] = {
type = "texture",
layer = "HIGHLIGHT",
color = "ffffff",
alpha = 0.05,
},
["text-color"] = {
type = "Font",
color = Colors.UI_TEXT,
},
["dropdown-background"] = {
type = "texture",
layer = "BACKGROUND",
color = Colors.UI_100,
alpha = 0.95,
},
["dropdown-inline"] = {
type = "outline",
layer = "BORDER",
color = "ffffff",
alpha = 0.02,
position = -1,
},
["dropdown-shadow"] = {
type = "shadow",
},
}
-- ~~| Dropdown Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function compare(a, b)
return a.value < b.value
end
local function sortList(list, orderedKeys)
if orderedKeys then
return orderedKeys
end
local sortedList = {}
local orderedKeys = {}
for key, value in pairs(list) do
sortedList[#sortedList + 1] = { key = key, value = value }
end
tsort(sortedList, compare)
for i, value in ipairs(sortedList) do
orderedKeys[#orderedKeys + 1] = value.key
end
return orderedKeys
end
7 months ago
local function OnPulloutOpen(this)
local self = this.userdata.obj
local value = self.value
if not self.multiselect then
for i, item in this:IterateItems() do
--item:SetValue(item.userdata.value == value)
end
end
self.open = true
self:FireEvent("OnOpened")
end
local function OnPulloutClose(this)
local self = this.userdata.obj
self.open = nil
self:FireEvent("OnClosed")
end
local function fixlevels(parent, ...)
local i = 1
local child = select(i, ...)
while child do
child:SetFrameLevel(parent:GetFrameLevel() + 1)
fixlevels(child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
local function fixstrata(strata, parent, ...)
local i = 1
local child = select(i, ...)
parent:SetFrameStrata(strata)
while child do
fixstrata(strata, child, child:GetChildren())
i = i + 1
child = select(i, ...)
end
end
1 year ago
-- ~~| Dropdown Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---@class Diesal.GUI.DropDown.Methods
local methods = {
---@param self Diesal.GUI.Object.DropDown
OnAcquire = function(self)
7 months ago
--local pullout = DiesalGUI:Create("DiesalDropDownPullout")
--self.pullout = pullout
--self.pullout.userdata.obj = self
--self.pullout:SetEventListener("OnClose", OnPulloutClose)
--self.pullout:SetEventListener("OnOpen", OnPulloutOpen)
--self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
--fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
1 year ago
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:Show()
11 months ago
self:SetFrameStrata("TOOLTIP")
1 year ago
end,
---@param self Diesal.GUI.Object.DropDown
7 months ago
OnRelease = function(self)
if self.pullout then
self.pullout:Release()
end
end,
1 year ago
---@param self Diesal.GUI.Object.DropDown
ApplySettings = function(self)
local settings = self.settings
local content = self.content
local frame = self.frame
local children = self.children
local dropdown = self.dropdown
frame:SetWidth(settings.width)
frame:SetHeight(settings.height)
content:SetPoint("TOPLEFT", dropdown, settings.dropdownPadLeft, -settings.dropdownPadTop)
content:SetPoint("BOTTOMRIGHT", dropdown, -settings.dropdownPadRight, settings.dropdownPadBottom)
local menuHeight = 0
for i = 1, #children do
menuHeight = menuHeight + children[i].frame:GetHeight()
end
dropdown:SetHeight(settings.dropdownPadTop + menuHeight + settings.dropdownPadBottom)
end,
---@param self Diesal.GUI.Object.DropDown
8 months ago
---@param list Diesal.GUI.DropDownItem.Settings[]
11 months ago
SetList = function(self, list)
1 year ago
self:ReleaseChildren()
self:SetText("")
local settings = self.settings
settings.list = list
local foldColor = "353535"
local expandColor = "5a5a5a"
11 months ago
self.dropdown:SetFrameStrata("TOOLTIP")
7 months ago
self.pullout.settings.items = {}
self.pullout:Clear()
8 months ago
for position, item in ipairs(settings.list) do
1 year ago
local dropdownItem = DiesalGUI:Create("DiesalDropDownItem")
11 months ago
DiesalGUI:OnMouse(dropdownItem.frame, "LeftButton")
dropdownItem:SetParentObject(self, true)
1 year ago
dropdownItem:SetSettings({
key = item.key,
value = item.value,
position = position,
clickable = item.clickable,
indent = item.indent or 0,
icon2 = item.icon2,
1 year ago
}, true)
dropdownItem.text:SetPoint("TOPLEFT", 12 + (item.indent * 6), -2)
11 months ago
if item.indent and item.indent > 0 then
1 year ago
local leftOffset = -6 + (-6 * item.indent)
dropdownItem:UpdateStyle("frame-lineV", {
type = "texture",
layer = "BORDER",
color = foldColor,
position = { leftOffset, nil, -8, nil },
height = 1,
width = 6,
})
dropdownItem:UpdateStyle("frame-lineH", {
type = "texture",
layer = "BORDER",
color = foldColor,
position = { leftOffset, nil, 0, 0 },
width = 1,
})
if item.last then
dropdownItem:UpdateStyle("frame-lineH", {
type = "texture",
position = { leftOffset, nil, 0, -7 },
})
end
end
7 months ago
self.pullout:AddItem(dropdownItem, true)
1 year ago
end
self:ApplySettings()
end,
---@param self Diesal.GUI.Object.DropDown
SetValue = function(self, key)
local selectionTable = {}
local selectedKey, dropdownText, selectedValue
11 months ago
local selectedCount = 0
1 year ago
if key ~= "CLEAR" then
if self.settings.multiSelect then
for i = 1, #self.children do
if self.children[i].settings.key == key then
selectedKey = key
self.children[i]:SetSelected(true)
end
if self.children[i].settings.selected then
11 months ago
selectedCount = selectedCount + 1
1 year ago
if dropdownText then
dropdownText = format("%s, %s", dropdownText, self.children[i].settings.value)
else
dropdownText = self.children[i].settings.value
end
selectionTable[#selectionTable + 1] = self.children[i].settings.key
end
end
else
for i = 1, #self.children do
local child = self.children[i]
child:SetSelected(false)
if child.settings.icon2 then
child.icon2:Show()
else
child.icon2:Hide()
end
1 year ago
if child.settings.key == key then
child:SetSelected(true)
dropdownText = child.settings.value
selectionTable = { key }
selectedKey = key
selectedValue = self.value
end
end
end
else
self:ClearSelection()
end
11 months ago
if self.settings.multiSelect then
dropdownText = string.format("+%d", selectedCount)
end
1 year ago
if selectedKey then
self:SetText(dropdownText)
self:FireEvent("OnValueChanged", selectedKey, selectedValue, selectionTable)
else
self:SetText("")
self:FireEvent("OnValueChanged", selectedKey, selectedValue, selectionTable)
end
end,
---@param self Diesal.GUI.Object.DropDown
ClearSelection = function(self)
for i = 1, #self.children do
self.children[i]:SetSelected(false)
end
self:SetText("")
end,
---@param self Diesal.GUI.Object.DropDown
SetValueTable = function(self, keyTable)
if not self.settings.multiSelect or type(keyTable) ~= "table" then
return
end
local dropdownItems = self.children
local selectionTable = {}
local selectedKey
local dropdownText
11 months ago
local selectedCount = 0
1 year ago
for i = 1, #dropdownItems do
local dropdownItem = dropdownItems[i]
dropdownItem:SetSelected(false)
for _, key in ipairs(keyTable) do
if dropdownItem.settings.key == key then
dropdownItem:SetSelected(true)
11 months ago
selectedCount = selectedCount + 1
if not self.settings.multiSelect then
5 months ago
dropdownText = dropdownText and format("%s, %s", dropdownText, dropdownItem.settings.value) or
dropdownItem.settings.value
11 months ago
end
1 year ago
selectionTable[#selectionTable + 1] = dropdownItem.settings.key
end
end
end
self:FireEvent("OnValueChanged", nil, nil, selectionTable)
11 months ago
if self.settings.multiSelect then
dropdownText = string.format("+%d", selectedCount)
end
1 year ago
self:SetText(dropdownText)
end,
---@param self Diesal.GUI.Object.DropDown
SetMultiSelect = function(self, state)
self.settings.multiSelect = state
end,
---@param self Diesal.GUI.Object.DropDown
SetText = function(self, text)
self.text:SetText(text)
for i = 1, #self.children do
local child = self.children[i]
if child.settings.value == text then
self.value = child.settings.key
end
end
end,
---@param self Diesal.GUI.Object.DropDown
SetFocus = function(self)
DiesalGUI:SetFocus(self)
end,
---@param self Diesal.GUI.Object.DropDown
ClearFocus = function(self)
11 months ago
self.dropdownShown = false
1 year ago
self.dropdown:Hide()
end,
---@param self Diesal.GUI.Object.DropDown
EnableMouse = function(self, state)
self.frame:EnableMouse(state)
end,
---@param self Diesal.GUI.Object.DropDown
RegisterForClicks = function(self, ...)
self.frame:RegisterForClicks(...)
end,
---@param self Diesal.GUI.Object.DropDown
SetJustifyV = function(self, justify)
self.text:SetJustifyV(justify)
end,
---@param self Diesal.GUI.Object.DropDown
SetJustifyH = function(self, justify)
self.text:SetJustifyH(justify)
end,
11 months ago
---@param self Diesal.GUI.Object.DropDown
ShowDropDown = function(self)
self.dropdown:SetFrameStrata("TOOLTIP")
self.dropdown:SetParent(self.frame)
self.dropdown:Show()
self.dropdownShown = true
end,
---@param self Diesal.GUI.Object.DropDown
HideDropDown = function(self)
self.dropdown:Hide()
self.dropdownShown = false
end,
---@param self Diesal.GUI.Object.DropDown
ToggleDropDown = function(self)
if self.dropdownShown then
self:HideDropDown()
else
self:ShowDropDown()
end
end,
---@param self Diesal.GUI.Object.DropDown
---@param strata FrameStrata
---@param parent Frame
---@param children Frame[]
FixStrata = function(self, strata, parent, children)
parent:SetFrameStrata(strata)
parent:Raise()
for i, child in ipairs(children) do
self:FixStrata(strata, child, {
child:GetChildren() --[[@as Frame]],
})
end
end,
7 months ago
---@param self Diesal.GUI.Object.DropDown
5 months ago
---@param button mouseButton
7 months ago
---@param down boolean
OnClick = function(self, button, down)
if button == "LeftButton" then
if self.open then
self.open = false
self.pullout:Close()
self.arrow:SetRotation(0)
DiesalGUI:ClearFocus()
else
self.open = true
self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, 0)
DiesalGUI:SetFocus(self.pullout)
self.arrow:SetRotation(math.pi)
end
end
end,
1 year ago
}
---@class Diesal.GUI.Object.DropDown.Settings : Diesal.GUI.ObjectBase.Settings
1 year ago
---@field dropdownPadLeft number
---@field dropdownPadRight number
---@field dropdownPadTop number
---@field dropdownPadBottom number
---@field itemHeight number
---@field width number
---@field height number
8 months ago
---@field list? Diesal.GUI.DropDownItem.Settings[]
---@field multiSelect? boolean
---@field dropdownWidth? number
1 year ago
---@class DiesalDropDown : Diesal.GUI.Object.DropDown
-- ~~| Dropdown Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
---@class Diesal.GUI.Object.DropDown : Diesal.GUI.ObjectBase, Diesal.GUI.DropDown.Methods
---@field arrow Texture
11 months ago
---@field settings Diesal.GUI.Object.DropDown.Settings
1 year ago
---@field children Diesal.GUI.Object.DropDown.Item[]
---@field text FontString
---@field dropdown Frame
---@field content Frame
---@field value string
7 months ago
---@field pullout DiesalDropDownPullout
1 year ago
local self = DiesalGUI:Create(Type, true)
11 months ago
self:SetMethods(methods)
7 months ago
self.dropdownShown = false
self.open = false
1 year ago
local frame = CreateFrame("Button", nil, DiesalGUI.UIParent)
11 months ago
frame:SetFrameStrata("TOOLTIP")
frame:SetClampedToScreen(true)
1 year ago
self.frame = frame
self.isContainer = true
self.defaults = {
dropdownPadLeft = 4,
dropdownPadRight = 4,
dropdownPadTop = 4,
dropdownPadBottom = 4,
itemHeight = 16,
width = 100,
height = 16,
}
-- ~~ Registered Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnValueChanged(event,selectedKey,selectedValue,selectionTable)
-- OnValueSelected(event,selectedKey,selectedValue,selectionTable)
-- OnEnter, OnLeave
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 months ago
frame:RegisterForClicks("AnyDown")
11 months ago
frame:SetScript("OnClick", function(this, button, down)
7 months ago
self:OnClick(button, down)
11 months ago
self:FireEvent("OnClick", button, down)
1 year ago
end)
frame:SetScript("OnEnter", function(this, ...)
self:FireEvent("OnEnter", ...)
end)
frame:SetScript("OnLeave", function(this, ...)
self:FireEvent("OnLeave", ...)
end)
local arrow = self:CreateRegion("Texture", "arrow", frame)
arrow:SetVertexColor(1, 1, 1, 0.5)
arrow:SetDrawLayer("BORDER")
arrow:SetAtlas("uitools-icon-chevron-down")
arrow:SetPoint("TOPRIGHT", -7, -3)
arrow:SetSize(10, 10)
1 year ago
local text = self:CreateRegion("FontString", "text", frame)
text:ClearAllPoints()
text:SetPoint("TOPLEFT", 4, -1)
text:SetPoint("BOTTOMRIGHT", -14, 1)
text:SetJustifyV("MIDDLE")
text:SetJustifyH("LEFT")
local dropdown = self:CreateRegion("Frame", "dropdown", frame)
11 months ago
dropdown:SetFrameStrata("TOOLTIP")
dropdown:SetFrameLevel(dropdown:GetFrameLevel() + 2)
1 year ago
dropdown:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", 0, -2)
dropdown:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, -2)
dropdown:SetScript("OnShow", function(this)
self:SetFocus()
end)
11 months ago
dropdown:SetScript("OnHide", function(this)
self.dropdownShown = false
7 months ago
if self.pullout then
self.pullout:Close()
end
self.arrow:SetRotation(0)
DiesalGUI:ClearFocus()
11 months ago
end)
1 year ago
dropdown:Hide()
11 months ago
self.dropdown = dropdown
1 year ago
self:CreateRegion("Frame", "content", dropdown)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 months ago
--self:SetMethods(methods)
1 year ago
--[[ for method, func in pairs(methods) do
self[method] = func
end ]]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 months ago
self.pullout = DiesalGUI:Create("DiesalDropDownPullout")
self.pullout.userdata.obj = self
self.pullout:SetEventListener("OnClose", OnPulloutClose)
self.pullout:SetEventListener("OnOpen", OnPulloutOpen)
self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
self.pullout:SetDropDown(self)
8 months ago
self:SetObj(self.frame)
1 year ago
return self
end
DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)