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.
414 lines
15 KiB
414 lines
15 KiB
---@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 = "DiesalDropDownPullout"
|
|
local Version = 1
|
|
|
|
---@type backdropInfo
|
|
local backdrop = {
|
|
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
|
edgeSize = 8,
|
|
tileSize = 8,
|
|
tile = true,
|
|
insets = { left = 2, right = 2, top = 2, bottom = 2 },
|
|
}
|
|
|
|
local sliderBackdrop = {
|
|
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
|
|
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
|
|
tile = true,
|
|
tileSize = 8,
|
|
edgeSize = 8,
|
|
insets = { left = 3, right = 3, top = 3, bottom = 3 },
|
|
}
|
|
|
|
local Stylesheet = {
|
|
["frame-background"] = {
|
|
type = "texture",
|
|
layer = "BACKGROUND",
|
|
color = Colors.UI_100,
|
|
alpha = 0.95,
|
|
},
|
|
["frame-inline"] = {
|
|
type = "outline",
|
|
layer = "BORDER",
|
|
color = "ffffff",
|
|
alpha = 0.02,
|
|
position = -1,
|
|
},
|
|
["frame-shadow"] = {
|
|
type = "shadow",
|
|
},
|
|
}
|
|
|
|
local defaultWidth = 200
|
|
local defaultMaxItems = 20
|
|
|
|
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
|
|
|
|
-- HACK: This should be no part of the pullout, but there
|
|
-- is no other 'clean' way to response to any item-OnEnter
|
|
-- Used to close Submenus when an other item is entered
|
|
local function OnEnter(item)
|
|
local self = item.pullout
|
|
for k, v in ipairs(self.settings.items) do
|
|
if v.CloseMenu and v ~= item then
|
|
v:CloseMenu()
|
|
end
|
|
end
|
|
end
|
|
|
|
---@class Diesal.GUI.DropDownPullout.Methods
|
|
local methods = {
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
OnAcquire = function(self)
|
|
self.frame:SetParent(DiesalGUI.UIParent)
|
|
end,
|
|
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
OnRelease = function(self)
|
|
self:ClearAllPoints()
|
|
self:Hide()
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
ApplySettings = function(self) end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
GetItemsHeight = function(self)
|
|
local itemHeight = 0
|
|
for i, item in ipairs(self.settings.items) do
|
|
itemHeight = itemHeight + item.text:GetStringHeight()
|
|
end
|
|
return itemHeight
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
GetMaxHeight = function(self)
|
|
local maxHeight = 0
|
|
for i, item in ipairs(self.settings.items) do
|
|
if i <= self.maxItems then
|
|
maxHeight = maxHeight + item:GetHeight(false)
|
|
end
|
|
end
|
|
return maxHeight
|
|
--return self:GetMaxItemHeight() * min(self.maxItems, #self.settings.items)
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
---@param item DiesalDropDownItem
|
|
---@param setPoints? boolean
|
|
AddItem = function(self, item, setPoints)
|
|
table.insert(self.settings.items, item)
|
|
local maxWidth = 8 + (item.settings.indent * 6) + (16 * 2)
|
|
if item.text then
|
|
maxWidth = maxWidth + item.text:GetUnboundedStringWidth()
|
|
end
|
|
if item.check then
|
|
maxWidth = maxWidth + item.check:GetWidth() + 4
|
|
end
|
|
self.settings.maxItemWidth = max(self.settings.maxItemWidth, maxWidth)
|
|
--self.frame:SetHeight(min(self:GetItemsHeight() + 28, self:GetMaxHeight() + 28))
|
|
if setPoints then
|
|
item:SetPoint("LEFT", self.itemFrame, "LEFT", 20, 0)
|
|
item:SetPoint("RIGHT", self.itemFrame, "RIGHT", 0, 0)
|
|
end
|
|
item:SetPullout(self)
|
|
--item:SetScript("OnEnter", OnEnter)
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
---@param value number
|
|
SetScroll = function(self, value)
|
|
local status = self.scrollStatus
|
|
local scrollFrame, itemFrame = self.scrollFrame, self.itemFrame
|
|
local height, viewheight = scrollFrame:GetHeight(), itemFrame:GetHeight()
|
|
--local minVal, maxVal = self.slider:GetMinMaxValues()
|
|
local minVal, maxVal = height, viewheight
|
|
local offset
|
|
if height > viewheight then
|
|
offset = 0
|
|
self.slider2:Hide()
|
|
else
|
|
offset = floor(maxVal * value)
|
|
self.slider2:Show()
|
|
end
|
|
itemFrame:ClearAllPoints()
|
|
itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, offset)
|
|
itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", self.slider2:IsShown() and -6 or 0, offset)
|
|
status.offset = offset
|
|
status.scrollvalue = (maxVal * value)
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
---@param value number
|
|
MoveScroll = function(self, value)
|
|
local status = self.scrollStatus
|
|
local frame, child = self.scrollFrame, self.itemFrame
|
|
local height, viewheight = frame:GetHeight(), child:GetHeight()
|
|
--local minVal, maxVal = self.slider:GetMinMaxValues()
|
|
local minVal, maxVal = height, self:GetItemsHeight()
|
|
--child:SetHeight(self:GetItemsHeight())
|
|
if height > viewheight then
|
|
self.slider2:Hide()
|
|
else
|
|
self.slider2:Show()
|
|
local diff = height - viewheight
|
|
local delta = 1
|
|
if value < 0 then
|
|
delta = -1
|
|
end
|
|
local scrollToVal = min(max(status.scrollvalue + delta * (maxVal / (diff / self.settings.itemHeight)), 0), maxVal)
|
|
self.slider2:SetScrollPercentage(scrollToVal/maxVal)
|
|
--self.slider:SetValue(scrollToVal)
|
|
end
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
FixScroll = function(self)
|
|
local status = self.scrollStatus
|
|
local frame, child = self.scrollFrame, self.itemFrame
|
|
local height, viewheight = frame:GetHeight(), child:GetHeight()
|
|
local offset = status.offset or 0
|
|
local minVal, maxVal = height, viewheight
|
|
if viewheight < height then
|
|
self.slider2:Hide()
|
|
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
|
|
self.scrollFrame:SetVerticalScroll(0)
|
|
else
|
|
self.slider2:Show()
|
|
local value = (offset / (viewheight - height) * maxVal)
|
|
--self.slider:SetValue(value)
|
|
self:SetScroll(value)
|
|
if value < maxVal then
|
|
child:ClearAllPoints()
|
|
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
|
|
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
|
|
status.offset = offset
|
|
end
|
|
end
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
---@param point FramePoint
|
|
---@param relFrame Frame
|
|
---@param relPoint FramePoint
|
|
---@param x number
|
|
---@param y number
|
|
Open = function(self, point, relFrame, relPoint, x, y)
|
|
local items = self.settings.items
|
|
local frame = self.frame
|
|
local itemFrame = self.itemFrame
|
|
|
|
frame:SetPoint(point, relFrame, relPoint, x, y)
|
|
local maxWidth = self.settings.maxItemWidth + self.slider2:GetWidth()
|
|
if self.dropdown.settings.dropdownWidth then
|
|
if self.dropdown.settings.dropdownWidth > maxWidth then
|
|
frame:SetWidth(self.dropdown.settings.dropdownWidth)
|
|
else
|
|
frame:SetWidth(maxWidth)
|
|
end
|
|
else
|
|
frame:SetWidth(max(maxWidth, self.dropdown.frame:GetWidth()))
|
|
--frame:SetPoint("TOPRIGHT", relFrame, "BOTTOMRIGHT", x, y)
|
|
end
|
|
local height = 0
|
|
for i, item in ipairs(items) do
|
|
item:SetPoint("TOPLEFT", i == 1 and itemFrame or items[i - 1].frame, i == 1 and "TOPLEFT" or "BOTTOMLEFT", 0, 0)
|
|
item:Show()
|
|
height = height + item.text:GetStringHeight()
|
|
end
|
|
frame:Show()
|
|
frame:SetHeight(self:GetMaxHeight())
|
|
itemFrame:SetHeight(self:GetItemsHeight())
|
|
self.scrollFrame:SetScrollChild(itemFrame)
|
|
fixstrata("TOOLTIP", self.scrollFrame, self.scrollFrame:GetChildren())
|
|
self:FireEvent("OnOpen")
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
Close = function(self)
|
|
self.frame:Hide()
|
|
self:FireEvent("OnClose")
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
Clear = function(self)
|
|
local items = self.settings.items
|
|
for i, item in ipairs(items) do
|
|
items[i] = nil
|
|
end
|
|
for i,item in ipairs(self.itemFrame) do
|
|
end
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
IterateItems = function(self)
|
|
return ipairs(self.settings.items)
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
SetHideOnLeave = function(self, val)
|
|
self.hideOnLeave = val
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
GetRightBorderWidth = function(self)
|
|
return 6 + (self.slider:IsShown() and 12 or 0)
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
GetLeftBorderWidth = function(self)
|
|
return 6
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
ClearFocus = function(self)
|
|
self:Hide()
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
---@param height? number
|
|
SetItemHeight = function(self, height)
|
|
self.settings.itemHeight = height or self.defaults.itemHeight
|
|
end,
|
|
---@param self Diesal.GUI.Object.DropDownPullout
|
|
SetDropDown = function (self, dropdown)
|
|
self.dropdown = dropdown
|
|
end
|
|
}
|
|
|
|
---@class Diesal.GUI.Object.DropDownPullout.Settings : Diesal.GUI.ObjectBase.Settings
|
|
---@field width number
|
|
---@field itemHeight number
|
|
---@field sliderWidth number
|
|
---@field hideOnLeave boolean
|
|
---@field items DiesalDropDownItem[]
|
|
---@field maxItemWidth number
|
|
|
|
---@class DiesalDropDownPullout : Diesal.GUI.Object.DropDownPullout
|
|
|
|
local function Constructor()
|
|
---@class Diesal.GUI.Object.DropDownPullout : Diesal.GUI.ObjectBase, Diesal.GUI.DropDownPullout.Methods
|
|
---@field settings Diesal.GUI.Object.DropDownPullout.Settings
|
|
---@field items DiesalDropDownItem[]
|
|
---@field dropdown DiesalDropDown
|
|
local self = DiesalGUI:Create(Type, true)
|
|
self:SetMethods(methods)
|
|
local frame = CreateFrame("Frame", nil, DiesalGUI.UIParent, "BackdropTemplate")
|
|
self.frame = frame
|
|
self:SetObj(self.frame)
|
|
|
|
self.defaults = {
|
|
width = 200,
|
|
itemHeight = 12,
|
|
sliderWidth = 10,
|
|
hideOnLeave = true,
|
|
items = {},
|
|
maxItemWidth = 0,
|
|
}
|
|
|
|
self.scrollStatus = {
|
|
scrollvalue = 0,
|
|
}
|
|
self.hideOnLeave = false
|
|
self.maxItems = 20
|
|
|
|
frame:SetBackdrop(backdrop)
|
|
frame:SetBackdropColor(0, 0, 0, 1)
|
|
frame:SetBackdropBorderColor(0.2, 0.2, 0.2, 1)
|
|
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
frame:SetClampedToScreen(true)
|
|
frame:SetWidth(self.defaults.width)
|
|
frame:SetHeight(34)
|
|
frame:SetScript("OnHide", function(this)
|
|
self.dropdown.open = nil
|
|
self.dropdown.arrow:SetRotation(0)
|
|
DiesalGUI:ClearFocus()
|
|
end)
|
|
|
|
self:CreateRegion("Frame", "content", frame)
|
|
|
|
local scrollFrame = CreateFrame("ScrollFrame", nil, frame, "ScrollFrameTemplate")
|
|
local itemFrame = CreateFrame("Frame", nil, scrollFrame)
|
|
|
|
self.scrollFrame = scrollFrame
|
|
self.itemFrame = itemFrame
|
|
|
|
self:SetObj(self.scrollFrame)
|
|
self:SetObj(self.itemFrame)
|
|
|
|
---@type MinimalScrollBar
|
|
local slider2 = scrollFrame.ScrollBar
|
|
self.slider2 = slider2
|
|
self.slider2:SetPoint("TOPLEFT", self.scrollFrame, "TOPRIGHT", -20, -2)
|
|
self.slider2:SetPoint("BOTTOMLEFT", self.scrollFrame, "BOTTOMRIGHT", -20, 5)
|
|
self.scrollFrame:SetVerticalScroll(0)
|
|
self.slider2:SetVisibleExtentPercentage(0.25)
|
|
self.slider2:SetThumbExtent(0.25)
|
|
self.slider2:RegisterCallback("OnScroll", function(this, percent)
|
|
self:SetScroll(percent)
|
|
end, self.slider2)
|
|
--local slider = CreateFrame("Slider", nil, scrollFrame, "BackdropTemplate")
|
|
--slider:SetOrientation("VERTICAL")
|
|
--slider:SetHitRectInsets(0, 0, -10, 0)
|
|
--slider:SetBackdrop(sliderBackdrop)
|
|
--slider:SetWidth(8)
|
|
--slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
|
|
--slider:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
--self.slider = slider
|
|
--self:SetObj(self.slider)
|
|
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT")
|
|
scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT")
|
|
scrollFrame:EnableMouseWheel(true)
|
|
--[[ scrollFrame:SetScript("OnMouseWheel", function(this, value)
|
|
self:MoveScroll(value)
|
|
self:FireEvent("OnMouseWheel", value)
|
|
end) ]]
|
|
scrollFrame:SetToplevel(true)
|
|
scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
|
|
itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
|
|
itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -6, 0)
|
|
--itemFrame:SetHeight(400)
|
|
itemFrame:SetToplevel(true)
|
|
itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
|
scrollFrame.ItemFrame = itemFrame
|
|
scrollFrame:SetScrollChild(scrollFrame.ItemFrame)
|
|
|
|
--slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
|
|
--slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
|
|
--slider:SetScript("OnValueChanged", function(this, value)
|
|
--self:SetScroll(value)
|
|
--end)
|
|
--slider:SetMinMaxValues(0, 1)
|
|
--slider:SetValueStep(1)
|
|
--slider:SetValue(0)
|
|
|
|
scrollFrame:Show()
|
|
itemFrame:Show()
|
|
--slider:Hide()
|
|
|
|
self:FixScroll()
|
|
|
|
return self
|
|
end
|
|
DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)
|
|
|