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.

355 lines
12 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
local round = DiesalTools.Round
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, tonumber, select = type, tonumber, select
local pairs, ipairs, next = pairs, ipairs, next
local min, max = math.min, math.max
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Spinner |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "DiesalSpinner"
local Version = 3
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
["frame-background"] = {
type = "texture",
layer = "BACKGROUND",
color = "000000",
alpha = 0.6,
},
["frame-inline"] = {
type = "outline",
layer = "BORDER",
color = "000000",
alpha = 0.6,
},
["frame-outline"] = {
type = "outline",
layer = "BORDER",
color = "FFFFFF",
alpha = 0.02,
position = 1,
},
["frame-hover"] = {
type = "outline",
layer = "HIGHLIGHT",
color = "FFFFFF",
alpha = 0.25,
position = -1,
},
["editBox-font"] = {
type = "Font",
color = Colors.UI_TEXT,
},
["bar-background"] = {
type = "texture",
layer = "BACKGROUND",
gradient = { "VERTICAL", Colors.UI_A100, ShadeColor(Colors.UI_A100, 0.1) },
},
["bar-inline"] = {
type = "outline",
layer = "BORDER",
gradient = { "VERTICAL", "FFFFFF", "FFFFFF" },
alpha = { 0.07, 0.02 },
},
["bar-outline"] = {
type = "texture",
layer = "ARTWORK",
color = "000000",
alpha = 0.7,
width = 1,
position = { nil, 1, 0, 0 },
},
}
local wireFrame = {
["frame-white"] = {
type = "outline",
layer = "OVERLAY",
color = "ffffff",
},
["editBox-purple"] = {
type = "outline",
layer = "OVERLAY",
color = "aa00ff",
},
["buttonUp-yellow"] = {
type = "outline",
layer = "OVERLAY",
color = "fffc00",
},
["buttonDown-orange"] = {
type = "outline",
layer = "OVERLAY",
color = "ffd400",
},
["bar-green"] = {
type = "outline",
layer = "OVERLAY",
color = "55ff00",
},
}
-- | Internal Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---@param self Diesal.GUI.Object.Spinner
local function processNumber(self, number)
local settings = self.settings
local number, oldNumber = tonumber(number), self:GetNumber()
if not number then
number = oldNumber or settings.min
else
number = max(min(number, settings.max), settings.min)
end
settings.number = number
self.editBox:SetText((settings.prefix or "") .. number .. (settings.suffix or ""))
self.editBox:HighlightText(0, 0) -- clear any selcted text
self.editBox:SetCursorPosition(0)
self:UpdateBar()
if number ~= oldNumber then
return number
end
end
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---@class Diesal.GUI.Spinner.Methods
local methods = {
---@param self Diesal.GUI.Object.Spinner
OnAcquire = function(self)
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrame)
self:ApplySettings()
self:Show()
end,
---@param self Diesal.GUI.Object.Spinner
OnRelease = function(self) end,
---@param self Diesal.GUI.Object.Spinner
ApplySettings = function(self)
local settings = self.settings
local frame = self.frame
local buttonUp = self.buttonUp
local buttonDown = self.buttonDown
local editBox = self.editBox
local buttonsWidth = settings.buttons and settings.buttonsWidth or 0
local buttonHeight = round(settings.height / 2)
-- Apply Settings
self:SetWidth(settings.width)
self:SetHeight(settings.height)
editBox:EnableMouse(settings.mouse)
editBox:EnableMouseWheel(settings.mouseWheel)
editBox:SetPoint("BOTTOMRIGHT", -buttonsWidth, 0)
buttonUp[settings.buttons and "Show" or "Hide"](buttonUp)
buttonUp:EnableMouse(settings.mouse)
buttonUp:SetHeight(buttonHeight)
buttonUp:SetWidth(buttonsWidth)
buttonDown[settings.buttons and "Show" or "Hide"](buttonDown)
buttonDown:EnableMouse(settings.mouse)
buttonDown:SetHeight(buttonHeight)
buttonDown:SetWidth(buttonsWidth)
self:UpdateBar()
end,
---@param self Diesal.GUI.Object.Spinner
EnableMouse = function(self, enable)
self.settings.mouse = enable
self.buttonUp:EnableMouse(enable)
self.buttonDown:EnableMouse(enable)
self.editBox:EnableMouse(enable)
self.editBox:EnableMouseWheel(enable)
end,
---@param self Diesal.GUI.Object.Spinner
GetNumber = function(self)
return self.settings.number
end,
---@param self Diesal.GUI.Object.Spinner
SetNumber = function(self, number)
local newNumber = processNumber(self, number)
if newNumber then
self:FireEvent("OnValueChanged", false, newNumber)
end
end,
---@param self Diesal.GUI.Object.Spinner
SetPrefix = function(self, prefix)
self.settings.prefix = prefix
processNumber(self, self.settings.number)
end,
---@param self Diesal.GUI.Object.Spinner
SetSuffix = function(self, suffix)
self.settings.suffix = suffix
processNumber(self, self.settings.number)
end,
---@param self Diesal.GUI.Object.Spinner
OnSpin = function(self, delta)
local step = IsShiftKeyDown() and self.settings.shiftStep or self.settings.step
local oldNumber = self.settings.number
local newNumber
if delta > 0 then
newNumber = processNumber(self, round(oldNumber, step) + step)
else
newNumber = processNumber(self, round(oldNumber, step) - step)
end
if newNumber then
self:FireEvent("OnValueChanged", true, newNumber)
end
end,
---@param self Diesal.GUI.Object.Spinner
UpdateBar = function(self)
if not self.settings.bar then
return
end
local settings = self.settings
local barWidth = self:GetWidth() - (settings.buttons and settings.buttonsWidth or 0) - 2 -- bar padding
local number = settings.number or settings.min
local width = round(((number - settings.min) / (settings.max - settings.min) * barWidth))
if width == 0 then
self.bar:Hide()
else
self.bar:Show()
self.bar:SetWidth(width)
end
self.value = settings.number
end,
---@param self Diesal.GUI.Object.Spinner
SetTextColor = function(self, color, alpha)
alpha = alpha or 1
color = { DiesalTools.GetColor(color) }
self.editBox:SetTextColor(color[1], color[2], color[3], alpha)
end,
}
---@class DiesalSpinner : Diesal.GUI.Object.Spinner
---@class Diesal.GUI.Object.Spinner.Settings.Defaults
---@field bar boolean
---@field buttons boolean
---@field buttonsWidth number
---@field height number
---@field max number
---@field min number
---@field mouse boolean
---@field mouseWheel boolean
---@field prefix? string
---@field shiftStep number
---@field step number
---@field suffix? string
---@field width number
---@class Diesal.GUI.Object.Spinner.Settings: Diesal.GUI.Object.Spinner.Settings.Defaults
---@field number number
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
---@class Diesal.GUI.Object.Spinner : Diesal.GUI.ObjectBase, Diesal.GUI.Spinner.Methods
---@field settings Diesal.GUI.Object.Spinner.Settings
---@field bar Frame
---@field value number
---@field buttonUp Button
---@field buttonDown Button
---@field editBox EditBox
local self = DiesalGUI:Create(Type, true)
local frame = CreateFrame("Frame", nil, DiesalGUI.UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
height = 16,
width = 29,
mouse = true,
mouseWheel = true,
buttons = false,
buttonsWidth = 8,
bar = true,
min = 0,
max = 100,
step = 5,
shiftStep = 1,
}
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnHide", function(this)
self:FireEvent("OnHide")
end)
frame:SetScript("OnSizeChanged", function()
self:UpdateBar()
end)
local editBox = self:CreateRegion("EditBox", "editBox", frame) --[[ @as Diesal.GUI.Region.EditBox ]]
editBox:SetPoint("TOP")
editBox:SetPoint("BOTTOM")
editBox:SetAutoFocus(false)
editBox:SetJustifyH("CENTER")
editBox:SetJustifyV("MIDDLE")
editBox:SetTextInsets(0, 0, 0, 0)
editBox:SetNumber(self.defaults.min)
---@param this EditBox
editBox:SetScript("OnEnterPressed", function(this, ...)
local number = this:GetNumber() or self.settings.number -- if entered text or nothing revert to old value
local newNumber = processNumber(self, number)
if newNumber then
self:FireEvent("OnValueChanged", true, newNumber)
end
self:FireEvent("OnEnterPressed", ...)
DiesalGUI:ClearFocus()
end)
editBox:HookScript("OnEditFocusLost", function(this, ...)
processNumber(self, self.settings.number)
end)
editBox:HookScript("OnEditFocusGained", function(this)
this:SetText(self.settings.number)
this:HighlightText()
end)
editBox:SetScript("OnMouseWheel", function(this, delta)
DiesalGUI:OnMouse(this, "MouseWheel")
self:OnSpin(delta)
end)
editBox:SetScript("OnEnter", function(this, ...)
self:FireEvent("OnEnter", ...)
end)
editBox:SetScript("OnLeave", function(this, ...)
self:FireEvent("OnLeave", ...)
end)
local bar = self:CreateRegion("Frame", "bar", frame)
bar:SetPoint("TOPLEFT", 1, -1)
bar:SetPoint("BOTTOMLEFT", -1, 1)
local buttonUp = self:CreateRegion("Button", "buttonUp", frame)
buttonUp:SetPoint("TOP", 0, 0)
buttonUp:SetPoint("RIGHT")
buttonUp:SetScript("OnClick", function(this, button)
DiesalGUI:OnMouse(this, button)
PlaySound(799)
self:OnSpin(1)
end)
local buttonDown = self:CreateRegion("Button", "buttonDown", frame)
buttonDown:SetPoint("BOTTOM", 0, 0)
buttonDown:SetPoint("RIGHT")
buttonDown:SetScript("OnClick", function(this, button)
DiesalGUI:OnMouse(this, button)
PlaySound(799)
self:OnSpin(-1)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self:SetMethods(methods)
self:SetObj(self.frame)
--[[ for method, func in pairs(methods) do
self[method] = func
end ]]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type, Constructor, Version)