---@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)