ck 1 year ago
parent 0a52c4036c
commit 2c1766968b
  1. 6
      .vscode/settings.json
  2. 524
      DiesalLibs/DiesalComm-1.0/ChatThrottleLib.lua
  3. 274
      DiesalLibs/DiesalComm-1.0/DiesalComm-1.0.lua
  4. 5
      DiesalLibs/DiesalComm-1.0/DiesalComm-1.0.xml
  5. 384
      DiesalLibs/DiesalGUI-1.0/DiesalGUI-1.0.lua
  6. 23
      DiesalLibs/DiesalGUI-1.0/DiesalGUI-1.0.xml
  7. 62
      DiesalLibs/DiesalGUI-1.0/Objects/Accordian.lua
  8. 217
      DiesalLibs/DiesalGUI-1.0/Objects/AccordianSection.lua
  9. 177
      DiesalLibs/DiesalGUI-1.0/Objects/Bar.lua
  10. 279
      DiesalLibs/DiesalGUI-1.0/Objects/Branch.lua
  11. 109
      DiesalLibs/DiesalGUI-1.0/Objects/Button.lua
  12. 163
      DiesalLibs/DiesalGUI-1.0/Objects/CheckBox.lua
  13. 282
      DiesalLibs/DiesalGUI-1.0/Objects/ComboBox.lua
  14. 122
      DiesalLibs/DiesalGUI-1.0/Objects/ComboBoxItem.lua
  15. 296
      DiesalLibs/DiesalGUI-1.0/Objects/DropDown.lua
  16. 137
      DiesalLibs/DiesalGUI-1.0/Objects/DropDownItem.lua
  17. 124
      DiesalLibs/DiesalGUI-1.0/Objects/Input.lua
  18. 163
      DiesalLibs/DiesalGUI-1.0/Objects/QuickDoc.lua
  19. 279
      DiesalLibs/DiesalGUI-1.0/Objects/ScrollFrame.lua
  20. 279
      DiesalLibs/DiesalGUI-1.0/Objects/ScrollingEditBox.lua
  21. 267
      DiesalLibs/DiesalGUI-1.0/Objects/ScrollingMessageFrame.lua
  22. 294
      DiesalLibs/DiesalGUI-1.0/Objects/Spinner.lua
  23. 174
      DiesalLibs/DiesalGUI-1.0/Objects/Toggle.lua
  24. 93
      DiesalLibs/DiesalGUI-1.0/Objects/Tree.lua
  25. 387
      DiesalLibs/DiesalGUI-1.0/Objects/Window.lua
  26. 69
      DiesalLibs/DiesalMenu-1.0/DiesalMenu-1.0.lua
  27. 6
      DiesalLibs/DiesalMenu-1.0/DiesalMenu-1.0.xml
  28. 132
      DiesalLibs/DiesalMenu-1.0/Objects/Menu.lua
  29. 157
      DiesalLibs/DiesalMenu-1.0/Objects/MenuItem.lua
  30. 1048
      DiesalLibs/DiesalStyle-1.0/DiesalStyle-1.0.lua
  31. BIN
      DiesalLibs/DiesalStyle-1.0/Media/DejaVuSansMono-Bold.ttf
  32. BIN
      DiesalLibs/DiesalStyle-1.0/Media/DejaVuSansMono.ttf
  33. BIN
      DiesalLibs/DiesalStyle-1.0/Media/DiesalButtonIcons32x128x512.tga
  34. BIN
      DiesalLibs/DiesalStyle-1.0/Media/DiesalGUIcons16x256x128.tga
  35. BIN
      DiesalLibs/DiesalStyle-1.0/Media/DiesalGUIcons32x256x256.tga
  36. BIN
      DiesalLibs/DiesalStyle-1.0/Media/DiesalGUIcons64x256x256.tga
  37. BIN
      DiesalLibs/DiesalStyle-1.0/Media/FFF Intelligent Thin Condensed.ttf
  38. BIN
      DiesalLibs/DiesalStyle-1.0/Media/FiraMono-Bold.ttf
  39. BIN
      DiesalLibs/DiesalStyle-1.0/Media/FiraMono-Medium.ttf
  40. BIN
      DiesalLibs/DiesalStyle-1.0/Media/FiraMono-Regular.ttf
  41. BIN
      DiesalLibs/DiesalStyle-1.0/Media/FiraSans-Regular.ttf
  42. BIN
      DiesalLibs/DiesalStyle-1.0/Media/Hack-Bold.ttf
  43. BIN
      DiesalLibs/DiesalStyle-1.0/Media/Hack-Regular.ttf
  44. BIN
      DiesalLibs/DiesalStyle-1.0/Media/Inconsolata-Bold.ttf
  45. BIN
      DiesalLibs/DiesalStyle-1.0/Media/Inconsolata-Regular.ttf
  46. BIN
      DiesalLibs/DiesalStyle-1.0/Media/LUCON.TTF
  47. BIN
      DiesalLibs/DiesalStyle-1.0/Media/OfficeCodePro-Bold.ttf
  48. BIN
      DiesalLibs/DiesalStyle-1.0/Media/OfficeCodePro-Medium.ttf
  49. BIN
      DiesalLibs/DiesalStyle-1.0/Media/OfficeCodePro-Regular.ttf
  50. BIN
      DiesalLibs/DiesalStyle-1.0/Media/RobotoMono-Bold.ttf
  51. BIN
      DiesalLibs/DiesalStyle-1.0/Media/RobotoMono-Medium.ttf
  52. BIN
      DiesalLibs/DiesalStyle-1.0/Media/RobotoMono-Regular.ttf
  53. BIN
      DiesalLibs/DiesalStyle-1.0/Media/SourceCodePro-Black.ttf
  54. BIN
      DiesalLibs/DiesalStyle-1.0/Media/SourceCodePro-Bold.ttf
  55. BIN
      DiesalLibs/DiesalStyle-1.0/Media/SourceCodePro-Medium.ttf
  56. BIN
      DiesalLibs/DiesalStyle-1.0/Media/SourceCodePro-Regular.ttf
  57. BIN
      DiesalLibs/DiesalStyle-1.0/Media/SourceCodePro-Semibold.ttf
  58. BIN
      DiesalLibs/DiesalStyle-1.0/Media/Standard0755.ttf
  59. BIN
      DiesalLibs/DiesalStyle-1.0/Media/UbuntuMono-B.ttf
  60. BIN
      DiesalLibs/DiesalStyle-1.0/Media/UbuntuMono-R.ttf
  61. BIN
      DiesalLibs/DiesalStyle-1.0/Media/calibrib.ttf
  62. BIN
      DiesalLibs/DiesalStyle-1.0/Media/monof55.ttf
  63. BIN
      DiesalLibs/DiesalStyle-1.0/Media/monof56.ttf
  64. BIN
      DiesalLibs/DiesalStyle-1.0/Media/shadow.tga
  65. BIN
      DiesalLibs/DiesalStyle-1.0/Media/shadowNoDist.tga
  66. 515
      DiesalLibs/DiesalTools-1.0/DiesalTools-1.0.lua

@ -0,0 +1,6 @@
{
"Lua.diagnostics.globals": [
"DEFAULT_CHAT_FRAME",
"ChatFrame1"
]
}

@ -0,0 +1,524 @@
--
-- ChatThrottleLib by Mikk
--
-- Manages AddOn chat output to keep player from getting kicked off.
--
-- ChatThrottleLib:SendChatMessage/:SendAddonMessage functions that accept
-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
--
-- Priorities get an equal share of available bandwidth when fully loaded.
-- Communication channels are separated on extension+chattype+destination and
-- get round-robinned. (Destination only matters for whispers and channels,
-- obviously)
--
-- Will install hooks for SendChatMessage and SendAddonMessage to measure
-- bandwidth bypassing the library and use less bandwidth itself.
--
--
-- Fully embeddable library. Just copy this file into your addon directory,
-- add it to the .toc, and it's done.
--
-- Can run as a standalone addon also, but, really, just embed it! :-)
--
-- LICENSE: ChatThrottleLib is released into the Public Domain
--
local CTL_VERSION = 23
local _G = _G
if _G.ChatThrottleLib then
if _G.ChatThrottleLib.version >= CTL_VERSION then
-- There's already a newer (or same) version loaded. Buh-bye.
return
elseif not _G.ChatThrottleLib.securelyHooked then
print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, <v16) in an addon somewhere. Get the addon updated or copy in a newer ChatThrottleLib.lua (>=v16) in it!")
-- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
-- ... and if someone has securehooked, they can kiss that goodbye too... >.<
_G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage
if _G.ChatThrottleLib.ORIG_SendAddonMessage then
_G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage
end
end
_G.ChatThrottleLib.ORIG_SendChatMessage = nil
_G.ChatThrottleLib.ORIG_SendAddonMessage = nil
end
if not _G.ChatThrottleLib then
_G.ChatThrottleLib = {}
end
ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
local ChatThrottleLib = _G.ChatThrottleLib
ChatThrottleLib.version = CTL_VERSION
------------------ TWEAKABLES -----------------
ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
local setmetatable = setmetatable
local table_remove = table.remove
local tostring = tostring
local GetTime = GetTime
local math_min = math.min
local math_max = math.max
local next = next
local strlen = string.len
local GetFramerate = GetFramerate
local strlower = string.lower
local unpack,type,pairs,wipe = unpack,type,pairs,wipe
local UnitInRaid,UnitInParty = UnitInRaid,UnitInParty
-----------------------------------------------------------------------
-- Double-linked ring implementation
local Ring = {}
local RingMeta = { __index = Ring }
function Ring:New()
local ret = {}
setmetatable(ret, RingMeta)
return ret
end
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
if self.pos then
obj.prev = self.pos.prev
obj.prev.next = obj
obj.next = self.pos
obj.next.prev = obj
else
obj.next = obj
obj.prev = obj
self.pos = obj
end
end
function Ring:Remove(obj)
obj.next.prev = obj.prev
obj.prev.next = obj.next
if self.pos == obj then
self.pos = obj.next
if self.pos == obj then
self.pos = nil
end
end
end
-----------------------------------------------------------------------
-- Recycling bin for pipes
-- A pipe is a plain integer-indexed queue of messages
-- Pipes normally live in Rings of pipes (3 rings total, one per priority)
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
local PipeBin = setmetatable({}, {__mode="k"})
local function DelPipe(pipe)
PipeBin[pipe] = true
end
local function NewPipe()
local pipe = next(PipeBin)
if pipe then
wipe(pipe)
PipeBin[pipe] = nil
return pipe
end
return {}
end
-----------------------------------------------------------------------
-- Recycling bin for messages
ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
local MsgBin = setmetatable({}, {__mode="k"})
local function DelMsg(msg)
msg[1] = nil
-- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
MsgBin[msg] = true
end
local function NewMsg()
local msg = next(MsgBin)
if msg then
MsgBin[msg] = nil
return msg
end
return {}
end
-----------------------------------------------------------------------
-- ChatThrottleLib:Init
-- Initialize queues, set up frame for OnUpdate, etc
function ChatThrottleLib:Init()
-- Set up queues
if not self.Prio then
self.Prio = {}
self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
end
-- v4: total send counters per priority
for _, Prio in pairs(self.Prio) do
Prio.nTotalSent = Prio.nTotalSent or 0
end
if not self.avail then
self.avail = 0 -- v5
end
if not self.nTotalSent then
self.nTotalSent = 0 -- v5
end
-- Set up a frame to get OnUpdate events
if not self.Frame then
self.Frame = CreateFrame("Frame")
self.Frame:Hide()
end
self.Frame:SetScript("OnUpdate", self.OnUpdate)
self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
self.OnUpdateDelay = 0
self.LastAvailUpdate = GetTime()
self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
if not self.securelyHooked then
-- Use secure hooks as of v16. Old regular hook support yanked out in v21.
self.securelyHooked = true
--SendChatMessage
hooksecurefunc("SendChatMessage", function(...)
return ChatThrottleLib.Hook_SendChatMessage(...)
end)
--SendAddonMessage
hooksecurefunc("SendAddonMessage", function(...)
return ChatThrottleLib.Hook_SendAddonMessage(...)
end)
end
self.nBypass = 0
end
-----------------------------------------------------------------------
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
local bMyTraffic = false
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
if bMyTraffic then
return
end
local self = ChatThrottleLib
local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
if bMyTraffic then
return
end
local self = ChatThrottleLib
local size = tostring(text or ""):len() + tostring(prefix or ""):len();
size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
end
-----------------------------------------------------------------------
-- ChatThrottleLib:UpdateAvail
-- Update self.avail with how much bandwidth is currently available
function ChatThrottleLib:UpdateAvail()
local now = GetTime()
local MAX_CPS = self.MAX_CPS;
local newavail = MAX_CPS * (now - self.LastAvailUpdate)
local avail = self.avail
if now - self.HardThrottlingBeginTime < 5 then
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
self.bChoking = true
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
avail = math_min(MAX_CPS, avail + newavail*0.5)
self.bChoking = true -- just a statistic
else
avail = math_min(self.BURST, avail + newavail)
self.bChoking = false
end
avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
self.avail = avail
self.LastAvailUpdate = now
return avail
end
-----------------------------------------------------------------------
-- Despooling logic
-- Reminder:
-- - We have 3 Priorities, each containing a "Ring" construct ...
-- - ... made up of N "Pipe"s (1 for each destination/pipename)
-- - and each pipe contains messages
function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring
while ring.pos and Prio.avail > ring.pos[1].nSize do
local msg = table_remove(ring.pos, 1)
if not ring.pos[1] then -- did we remove last msg in this pipe?
local pipe = Prio.Ring.pos
Prio.Ring:Remove(pipe)
Prio.ByName[pipe.name] = nil
DelPipe(pipe)
else
Prio.Ring.pos = Prio.Ring.pos.next
end
local didSend=false
local lowerDest = strlower(msg[3] or "")
if lowerDest == "raid" and not UnitInRaid("player") then
-- do nothing
elseif lowerDest == "party" and not UnitInParty("player") then
-- do nothing
else
Prio.avail = Prio.avail - msg.nSize
bMyTraffic = true
msg.f(unpack(msg, 1, msg.n))
bMyTraffic = false
Prio.nTotalSent = Prio.nTotalSent + msg.nSize
DelMsg(msg)
didSend = true
end
-- notify caller of delivery (even if we didn't send it)
if msg.callbackFn then
msg.callbackFn (msg.callbackArg, didSend)
end
-- USER CALLBACK MAY ERROR
end
end
function ChatThrottleLib.OnEvent(this,event)
-- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
local self = ChatThrottleLib
if event == "PLAYER_ENTERING_WORLD" then
self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
self.avail = 0
end
end
function ChatThrottleLib.OnUpdate(this,delay)
local self = ChatThrottleLib
self.OnUpdateDelay = self.OnUpdateDelay + delay
if self.OnUpdateDelay < 0.08 then
return
end
self.OnUpdateDelay = 0
self:UpdateAvail()
if self.avail < 0 then
return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
end
-- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
local n = 0
for prioname,Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
n = n + 1
end
end
-- Anything queued still?
if n<1 then
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
for prioname, Prio in pairs(self.Prio) do
self.avail = self.avail + Prio.avail
Prio.avail = 0
end
self.bQueueing = false
self.Frame:Hide()
return
end
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
local avail = self.avail/n
self.avail = 0
for prioname, Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
Prio.avail = Prio.avail + avail
if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
self:Despool(Prio)
-- Note: We might not get here if the user-supplied callback function errors out! Take care!
end
end
end
end
-----------------------------------------------------------------------
-- Spooling logic
function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname]
local pipe = Prio.ByName[pipename]
if not pipe then
self.Frame:Show()
pipe = NewPipe()
pipe.name = pipename
Prio.ByName[pipename] = pipe
Prio.Ring:Add(pipe)
end
pipe[#pipe + 1] = msg
self.bQueueing = true
end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
end
if callbackFn and type(callbackFn)~="function" then
error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end
local nSize = text:len()
if nSize>255 then
error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
end
nSize = nSize + self.MSG_OVERHEAD
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
bMyTraffic = true
_G.SendChatMessage(text, chattype, language, destination)
bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then
callbackFn (callbackArg, true)
end
-- USER CALLBACK MAY ERROR
return
end
-- Message needs to be queued
local msg = NewMsg()
msg.f = _G.SendChatMessage
msg[1] = text
msg[2] = chattype or "SAY"
msg[3] = language
msg[4] = destination
msg.n = 4
msg.nSize = nSize
msg.callbackFn = callbackFn
msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
end
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
end
if callbackFn and type(callbackFn)~="function" then
error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
end
local nSize = text:len();
if RegisterAddonMessagePrefix then
if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
end
else
nSize = nSize + prefix:len() + 1
if nSize>255 then
error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
end
end
nSize = nSize + self.MSG_OVERHEAD;
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
bMyTraffic = true
_G.SendAddonMessage(prefix, text, chattype, target)
bMyTraffic = false
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
if callbackFn then
callbackFn (callbackArg, true)
end
-- USER CALLBACK MAY ERROR
return
end
-- Message needs to be queued
local msg = NewMsg()
msg.f = _G.SendAddonMessage
msg[1] = prefix
msg[2] = text
msg[3] = chattype
msg[4] = target
msg.n = (target~=nil) and 4 or 3;
msg.nSize = nSize
msg.callbackFn = callbackFn
msg.callbackArg = callbackArg
self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
end
-----------------------------------------------------------------------
-- Get the ball rolling!
ChatThrottleLib:Init()
--[[ WoWBench debugging snippet
if(WOWB_VER) then
local function SayTimer()
print("SAY: "..GetTime().." "..arg1)
end
ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
end
]]

@ -0,0 +1,274 @@
--- allows you to send messages of unlimited length over the addon comm channels.
-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\
-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server.
-- **DiesalComm** can be embeded into your addon, either explicitly by calling DiesalComm:Embed(MyAddon) or by
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
-- and can be accessed directly, without having to explicitly call AceComm itself.\\
-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you
-- make into DiesalComm.
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
-- List them here for Mikk's FindGlobals script
-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix
-- $Id: AceComm-3.0.lua 1107 2014-02-19 16:40:32Z nevcairiel $
-- ~~| Initialize library |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local MAJOR, MINOR = "DiesalComm-1.0", 1
local DiesalComm, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not DiesalComm then return end
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local CTL = assert(ChatThrottleLib, "DiesalComm-1.0 requires ChatThrottleLib")
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, next, pairs, tostring = type, next, pairs, tostring
local strsub, strfind = string.sub, string.find
local match = string.match
local tinsert, tconcat = table.insert, table.concat
local error, assert = error, assert
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Ambiguate = Ambiguate
-- ~~| DiesalComm Values |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DiesalComm.embeds = DiesalComm.embeds or {}
DiesalComm.msg_spool = DiesalComm.msg_spool or {}
local COMM_MODES = {'single','first','next','last'}
local HEADER_SIZE = 14
local HEADER_FORMAT = '%[%x%x:%x%x%x%x:%x%x%x%x%]'
local MAX_CHUNK_SIZE = 240
--- Register for Addon Traffic on a specified prefix
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters
-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
function DiesalComm:RegisterComm(prefix, method)
if method == nil then method = "OnCommReceived" end
if #prefix > 15 then error("AceComm:RegisterComm(prefix,method): prefix length is limited to 15 characters") end
RegisterAddonMessagePrefix(prefix)
return DiesalComm.RegisterCallback(self, prefix, method)
end
local function formatValue(num,len)
num = format('%X',num)
for i = 1, len - #num do
num = "0"..num
end
return num
end
local function encodeHeader(mode, chunk ,totalChunks )
return '['..formatValue(mode,2)..':'..formatValue(chunk,4)..':'..formatValue(totalChunks,4)..']'
end
local function decodeHeader()
end
--- Send a message over the Addon Channel
-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- @param text Data to send, nils (\000) not allowed. Any length.
-- @param channel Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
-- @param target Destination for some distributions; see SendAddonMessage API
-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send.
-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified.
-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
function AceComm:SendCommMessage(prefix, text, channel, target, callbackFn, callbackArg, prio)
prio = prio or "NORMAL"
if type(prefix)~="string" and type(text)~="string" and type(channel)~="string" and (target==nil or type(target)~="string") and (prio~="BULK" or prio~="NORMAL" or prio~="ALERT") then
error('Usage: SendCommMessage(addon, "prefix", "text", "channel"[, "target"[, callbackFn, callbackarg[, "prio"]]])', 2)
end
local textlen = #text
local ctlCallback = callbackFn and function(sent) return callbackFn(callbackArg, sent, textlen) end or nil
if textlen <= MAX_CHUNK_SIZE then -- fits all in one message
text = '[0:0000:0000]'..text
CTL:SendAddonMessage(prio, prefix, text, channel, target, nil, ctlCallback, textlen)
else
-- first part
local chunk = strsub(text, 1, maxtextlen)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen)
-- continuation
local pos = 1+maxtextlen
while pos+maxtextlen <= textlen do
chunk = strsub(text, pos, pos+maxtextlen-1)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
pos = pos + maxtextlen
end
-- final part
chunk = strsub(text, pos)
CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen)
end
end
----------------------------------------
-- Message receiving
----------------------------------------
do
local compost = setmetatable({}, {__mode = "k"})
local function new()
local t = next(compost)
if t then
compost[t]=nil
for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
t[i]=nil
end
return t
end
return {}
end
local function lostdatawarning(prefix,sender,where)
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
end
function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
--[[
if spool[key] then
lostdatawarning(prefix,sender,"First")
-- continue and overwrite
end
--]]
spool[key] = message -- plain string for now
end
function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
if not olddata then
--lostdatawarning(prefix,sender,"Next")
return
end
if type(olddata)~="table" then
-- ... but what we have is not a table. So make it one. (Pull a composted one if available)
local t = new()
t[1] = olddata -- add old data as first string
t[2] = message -- and new message as second string
spool[key] = t -- and put the table in the spool instead of the old string
else
tinsert(olddata, message)
end
end
function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
if not olddata then
--lostdatawarning(prefix,sender,"End")
return
end
spool[key] = nil
if type(olddata) == "table" then
-- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
tinsert(olddata, message)
AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender)
compost[olddata] = true
else
-- if we've only received a "first", the spooled data will still only be a string
AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender)
end
end
end
----------------------------------------
-- Embed CallbackHandler
----------------------------------------
if not AceComm.callbacks then
AceComm.callbacks = CallbackHandler:New(AceComm,
"_RegisterComm",
"UnregisterComm",
"UnregisterAllComm")
end
AceComm.callbacks.OnUsed = nil
AceComm.callbacks.OnUnused = nil
local function OnEvent(self, event, prefix, message, distribution, sender)
if event == "CHAT_MSG_ADDON" then
sender = Ambiguate(sender, "none")
local control, rest = match(message, "^([\001-\009])(.*)")
if control then
if control==MSG_MULTI_FIRST then
AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender)
elseif control==MSG_MULTI_NEXT then
AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender)
elseif control==MSG_MULTI_LAST then
AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender)
elseif control==MSG_ESCAPE then
AceComm.callbacks:Fire(prefix, rest, distribution, sender)
else
-- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!)
end
else
-- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
AceComm.callbacks:Fire(prefix, message, distribution, sender)
end
else
assert(false, "Received "..tostring(event).." event?!")
end
end
AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
AceComm.frame:SetScript("OnEvent", OnEvent)
AceComm.frame:UnregisterAllEvents()
AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
----------------------------------------
-- Base library stuff
----------------------------------------
local mixins = {
"RegisterComm",
"UnregisterComm",
"UnregisterAllComm",
"SendCommMessage",
}
-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:..
-- @param target target object to embed AceComm-3.0 in
function AceComm:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
function AceComm:OnEmbedDisable(target)
target:UnregisterAllComm()
end
-- Update embeds
for target, v in pairs(AceComm.embeds) do
AceComm:Embed(target)
end

@ -0,0 +1,5 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="ChatThrottleLib.lua"/>
<Script file="DiesalComm-1.0"/>
</Ui>

@ -0,0 +1,384 @@
-- $Id: DiesalGUI-1.0.lua 61 2017-03-28 23:13:41Z diesal2010 $
local MAJOR, MINOR = "DiesalGUI-1.0", "$Rev: 61 $"
local DiesalGUI, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not DiesalGUI then return end -- No Upgrade needed.
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CallbackHandler = LibStub("CallbackHandler-1.0")
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, tonumber = type, select, tonumber
local setmetatable, getmetatable, next = setmetatable, getmetatable, next
local pairs, ipairs = pairs,ipairs
local tinsert, tremove = table.insert, table.remove
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent = CreateFrame, UIParent
-- ~~| DiesalGUI Values |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DiesalGUI.callbacks = DiesalGUI.callbacks or CallbackHandler:New(DiesalGUI)
DiesalGUI.ObjectFactory = DiesalGUI.ObjectFactory or {}
DiesalGUI.ObjectVersions = DiesalGUI.ObjectVersions or {}
DiesalGUI.ObjectPool = DiesalGUI.ObjectPool or {}
DiesalGUI.ObjectBase = DiesalGUI.ObjectBase or {}
-- ~~| DiesalGUI Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local ObjectFactory = DiesalGUI.ObjectFactory
local ObjectVersions = DiesalGUI.ObjectVersions
local ObjectPool = DiesalGUI.ObjectPool
local ObjectBase = DiesalGUI.ObjectBase
-- ~~| DiesalGUI Local Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function OnMouse(frame,button)
DiesalGUI:ClearFocus()
end
-- capture mouse clicks on the WorldFrame
local function WorldFrameOnMouse(frame,button)
OnMouse(frame,button)
end
_G.WorldFrame:HookScript("OnMouseDown", WorldFrameOnMouse )
-- Returns a new object
local function newObject(objectType)
if not ObjectFactory[objectType] then error("Attempt to construct unknown Object type", 2) end
ObjectPool[objectType] = ObjectPool[objectType] or {}
local newObj = next(ObjectPool[objectType])
if not newObj then
newObj = ObjectFactory[objectType](object)
else
ObjectPool[objectType][newObj] = nil
end
return newObj
end
-- Releases an object into ReleasedObjects
local function releaseObject(obj,objectType)
ObjectPool[objectType] = ObjectPool[objectType] or {}
if ObjectPool[objectType][obj] then
error("Attempt to Release Object that is already released", 2)
end
ObjectPool[objectType][obj] = true
end
-- ~~| Object Blizzard Base |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ObjectBase.Hide = function(self)
self.frame:Hide()
end
ObjectBase.Show = function(self)
self.frame:Show()
end
ObjectBase.SetParent = function(self, parent)
local frame = self.frame
frame:SetParent(nil)
frame:SetParent(parent)
self.settings.parent = parent
end
ObjectBase.SetWidth = function(self, width)
self.settings.width = width
self.frame:SetWidth(width)
self:FireEvent("OnWidthSet",width)
end
ObjectBase.SetHeight = function(self, height)
self.settings.height = height
self.frame:SetHeight(height)
self:FireEvent("OnHeightSet",height)
end
ObjectBase.SetSize = function(self, width, height)
self.settings.width = width
self.settings.height = height
self.frame:SetHeight(height)
self.frame:SetWidth(width)
self:FireEvent("OnWidthSet",width)
self:FireEvent("OnHeightSet",height)
end
ObjectBase.GetWidth = function(self)
return self.frame:GetWidth()
end
ObjectBase.GetHeight = function(self)
return self.frame:GetHeight()
end
ObjectBase.IsVisible = function(self)
return self.frame:IsVisible()
end
ObjectBase.IsShown = function(self)
return self.frame:IsShown()
end
ObjectBase.SetPoint = function(self, ...)
return self.frame:SetPoint(...)
end
ObjectBase.SetAllPoints = function(self, ...)
return self.frame:SetAllPoints(...)
end
ObjectBase.ClearAllPoints = function(self)
return self.frame:ClearAllPoints()
end
ObjectBase.GetNumPoints = function(self)
return self.frame:GetNumPoints()
end
ObjectBase.GetPoint = function(self, ...)
return self.frame:GetPoint(...)
end
-- ~~| Object Diesal Base |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ObjectBase.CreateRegion = function(self,regionType,regionName,parentRegion,defaultFontObject)
if regionType == 'FontString' then
local fontString = parentRegion:CreateFontString()
-- set Default font properties
if defaultFontObject then
fontString.defaultFontObject = defaultFontObject
else
fontString.defaultFontObject = DiesalFontNormal
end
fontString:SetFont(fontString.defaultFontObject:GetFont())
fontString:SetTextColor(fontString.defaultFontObject:GetTextColor())
fontString:SetSpacing(fontString.defaultFontObject:GetSpacing())
self[regionName] = fontString
self.fontStrings[regionName] = fontString
return fontString
end
if regionType == 'Texture' then
self[regionName] = parentRegion:CreateTexture()
return self[regionName]
end
if regionType == 'EditBox' then
local editBox = CreateFrame(regionType,nil,parentRegion)
-- set Default font properties
if defaultFontObject then
editBox.defaultFontObject = defaultFontObject
else
editBox.defaultFontObject = DiesalFontNormal
end
editBox:SetFont(editBox.defaultFontObject:GetFont())
editBox:SetTextColor(editBox.defaultFontObject:GetTextColor())
editBox:SetSpacing(editBox.defaultFontObject:GetSpacing())
editBox:HookScript('OnEscapePressed', function(this) DiesalGUI:ClearFocus(); end)
editBox:HookScript('OnEditFocusGained',function(this) DiesalGUI:SetFocus(this); GameTooltip:Hide(); end)
self[regionName] = editBox
return editBox
end
if regionType == 'ScrollingMessageFrame' then
local srollingMessageFrame = CreateFrame(regionType,nil,parentRegion)
-- set Default font properties
if defaultFontObject then
srollingMessageFrame.defaultFontObject = defaultFontObject
else
srollingMessageFrame.defaultFontObject = DiesalFontNormal
end
srollingMessageFrame:SetFont(srollingMessageFrame.defaultFontObject:GetFont())
srollingMessageFrame:SetTextColor(srollingMessageFrame.defaultFontObject:GetTextColor())
srollingMessageFrame:SetSpacing(srollingMessageFrame.defaultFontObject:GetSpacing())
self[regionName] = srollingMessageFrame
return srollingMessageFrame
end
self[regionName] = CreateFrame(regionType,nil,parentRegion)
return self[regionName]
end
ObjectBase.ResetFonts = function(self)
for name,fontString in pairs(self.fontStrings) do
fontString:SetFont(fontString.defaultFontObject:GetFont())
fontString:SetTextColor(fontString.defaultFontObject:GetTextColor())
fontString:SetSpacing(fontString.defaultFontObject:GetSpacing())
end
end
ObjectBase.AddChild = function(self, object)
tinsert(self.children, object)
end
ObjectBase.ReleaseChild = function(self,object)
local children = self.children
for i = 1,#children do
if children[i] == object then
children[i]:Release()
tremove(children,i)
break end
end
end
ObjectBase.ReleaseChildren = function(self)
local children = self.children
for i = 1,#children do
children[i]:Release()
children[i] = nil
end
end
ObjectBase.Release = function(self)
DiesalGUI:Release(self)
end
ObjectBase.SetParentObject = function(self, parent)
local frame = self.frame
local settings = self.settings
frame:SetParent(nil)
frame:SetParent(parent.content)
settings.parent = parent.content
settings.parentObject = parent
end
ObjectBase.SetSettings = function(self,settings,apply)
for key,value in pairs(settings) do
self.settings[key] = value
end
if apply then self:ApplySettings() end
end
ObjectBase.ResetSettings = function(self,apply)
self.settings = DiesalTools.TableCopy( self.defaults )
if apply then self:ApplySettings() end
end
ObjectBase.SetEventListener = function(self, event, listener)
if type(listener) == "function" then
self.eventListeners[event] = listener
else
error("listener is required to be a function", 2)
end
end
ObjectBase.ResetEventListeners = function(self)
for k in pairs(self.eventListeners) do
self.eventListeners[k] = nil
end
end
ObjectBase.FireEvent = function(self, event, ...)
if self.eventListeners[event] then
return self.eventListeners[event]( self, event, ...)
end
end
ObjectBase.SetStyle = function(self,name,style)
DiesalStyle:SetObjectStyle(self,name,style)
end
ObjectBase.UpdateStyle = function(self,name,style)
DiesalStyle:UpdateObjectStyle(self,name,style)
end
ObjectBase.UpdateStylesheet = function(self,Stylesheet)
DiesalStyle:UpdateObjectStylesheet(self,Stylesheet)
end
ObjectBase.SetStylesheet = function(self,Stylesheet)
DiesalStyle:SetObjectStylesheet(self,Stylesheet)
end
ObjectBase.ReleaseTexture = function(self,name)
if not self.textures[name] then return end
DiesalStyle:ReleaseTexture(self,name)
end
ObjectBase.ReleaseTextures = function(self)
DiesalStyle:ReleaseTextures(self)
end
-- ~~| DiesalGUI API |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Returns an Object Base
function DiesalGUI:CreateObjectBase(Type)
local object = {
type = Type,
fontStrings = {},
textures = {},
children = {},
eventListeners = {},
}
setmetatable(object, {__index = ObjectBase})
return object
end
-- Registers an Object constructor in the ObjectFactory
function DiesalGUI:RegisterObjectConstructor(Type, constructor, version)
assert(type(constructor) == "function")
assert(type(version) == "number")
local oldVersion = ObjectVersions[Type]
if oldVersion and oldVersion >= version then return end
ObjectVersions[Type] = version
ObjectFactory[Type] = constructor
end
-- Create a new Object
function DiesalGUI:Create(objectType,name)
if ObjectFactory[objectType] then
local object
if name then -- needs a specific name, bypass the objectPool and create a new object
object = ObjectFactory[objectType](name)
else
object = newObject(objectType)
end
object:ResetSettings()
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if object.OnAcquire then object:OnAcquire() end
return object
end
end
function DiesalGUI:CreateThrottle(duration, callback)
assert(callback and type(callback) == 'function','callback has to be a function ')
assert(duration and type(duration) == 'number','duration has to be a number ')
local throttle = CreateFrame("Frame", nil, UIParent):CreateAnimationGroup()
throttle.anim = throttle:CreateAnimation("Animation")
throttle.args = {}
local mt = getmetatable(throttle)
mt.__index.SetCallback = function(self,callback)
assert(callback and type(callback) == 'function','callback required to be a function ')
self:SetScript("OnFinished", function() callback(unpack(self.args)) end)
end
mt.__index.AddCallback = function(self,callback)
assert(callback and type(callback) == 'function','callback required to be a function ')
self:HookScript("OnFinished", function() callback(unpack(self.args)) end)
end
mt.__index.SetDuration = function(self,duration)
assert(duration and type(duration) == 'number','duration has to be a number ')
self.anim:SetDuration(duration)
end
mt.__call = function(self,...)
self.args = {...}
self:Stop()
self:Play()
end
setmetatable(throttle,mt)
throttle:SetScript("OnFinished", function() callback(unpack(throttle.args)) end)
throttle:SetDuration(duration)
return throttle
end
-- Releases an object ready for reuse by Create
function DiesalGUI:Release(object)
if object.OnRelease then object:OnRelease() end
object:FireEvent("OnRelease")
object:ReleaseChildren()
object:ReleaseTextures()
object:ResetFonts()
object:ResetEventListeners()
object.frame:ClearAllPoints()
object.frame:Hide()
object.frame:SetParent(UIParent)
releaseObject(object, object.type)
end
-- Set FocusedObject: Menu, Dropdown, editBox etc....
function DiesalGUI:SetFocus(object)
if self.FocusedObject and self.FocusedObject ~= object then DiesalGUI:ClearFocus() end
self.FocusedObject = object
end
-- clear focus from the FocusedObject
function DiesalGUI:ClearFocus()
local FocusedObject = self.FocusedObject
if FocusedObject then
if FocusedObject.ClearFocus then -- FocusedObject is Focusable Frame
FocusedObject:ClearFocus()
end
self.FocusedObject = nil
end
end
-- Mouse Input capture for any DiesalGUI interactive region
function DiesalGUI:OnMouse(frame,button)
-- print(button)
OnMouse(frame,button)
DiesalGUI.callbacks:Fire("DiesalGUI_OnMouse", frame, button)
end
DiesalGUI.counts = DiesalGUI.counts or {}
--- A type-based counter to count the number of widgets created.
function DiesalGUI:GetNextObjectNum(type)
if not self.counts[type] then
self.counts[type] = 0
end
self.counts[type] = self.counts[type] + 1
return self.counts[type]
end
--- Return the number of created widgets for this type.
function DiesalGUI:GetObjectCount(type)
return self.counts[type] or 0
end

@ -0,0 +1,23 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Script file="DiesalGUI-1.0.lua"/>
<!-- Objects -->
<Script file="Objects\Window.lua"/>
<Script file="Objects\ScrollFrame.lua"/>
<Script file="Objects\ScrollingEditBox.lua"/>
<Script file="Objects\ScrollingMessageFrame.lua"/>
<Script file="Objects\CheckBox.lua"/>
<Script file="Objects\Button.lua"/>
<Script file="Objects\Spinner.lua"/>
<Script file="Objects\Input.lua"/>
<Script file="Objects\Dropdown.lua"/>
<Script file="Objects\DropdownItem.lua"/>
<Script file="Objects\ComboBox.lua"/>
<Script file="Objects\ComboBoxItem.lua"/>
<Script file="Objects\Accordian.lua"/>
<Script file="Objects\AccordianSection.lua"/>
<Script file="Objects\Tree.lua"/>
<Script file="Objects\Branch.lua"/>
<Script file="Objects\Bar.lua"/>
<Script file="Objects\Toggle.lua"/>
</Ui>

@ -0,0 +1,62 @@
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Accordian |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "Accordian"
local Version = 2
-- ~~| Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
color = 'FF0000',
},
}
-- | Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
-- self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:ResetSettings(true)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
end,
['CollapseAll'] = function(self)
for i=1 , #self.children do
self.children[i]:Collapse()
end
end,
['ExpandAll'] = function(self)
for i=1 , #self.children do
self.children[i]:Expand()
end
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = { }
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnHeightChange
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local content = self:CreateRegion("Frame", 'content', frame)
content:SetAllPoints()
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,217 @@
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | AccordianSection |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'AccordianSection'
local Version = 3
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['button-background'] = {
type = 'texture',
layer = 'BACKGROUND',
gradient = {'VERTICAL',Colors.UI_400_GR[1],Colors.UI_400_GR[2]},
alpha = .95,
position = {0,0,-1,0},
},
['button-outline'] = {
type = 'outline',
layer = 'BACKGROUND',
color = '000000',
position = {1,1,0,1},
},
['button-inline'] = {
type = 'outline',
layer = 'ARTWORK',
gradient = {'VERTICAL','ffffff','ffffff'},
alpha = {.03,.02},
position = {0,0,-1,0},
},
['button-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'ffffff',
alpha = .1,
},
['button-leftExpandIcon'] = {
type = 'texture',
position = {0,nil,-1,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons',{3,6,16,256,128},HSL(Colors.UI_Hue,Colors.UI_Saturation,.65)},
alpha = 1,
},
['button-leftCollapseIcon'] = {
type = 'texture',
position = {0,nil,-1,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons',{4,6,16,256,128},HSL(Colors.UI_Hue,Colors.UI_Saturation,.65)},
alpha = 1,
},
['content-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_300,
alpha = .95,
position = {0,0,-1,0},
},
['content-topShadow'] = {
type = 'texture',
layer = 'ARTWORK',
gradient = {'VERTICAL','000000','000000'},
alpha = {.05,0},
position = {0,0,-1,nil},
height = 4,
},
['content-bottomShadow'] = {
type = 'texture',
layer = 'ARTWORK',
gradient = {'VERTICAL','000000','000000'},
alpha = {0,.05},
position = {0,0,nil,0},
height = 4,
},
['content-inline'] = {
type = 'outline',
layer = 'ARTWORK',
color = 'ffffff',
alpha = .02,
position = {0,0,-1,0},
},
['text-Font'] = {
type = 'font',
color = Colors.UI_F450,
},
}
local wireFrameSheet = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
alpha = 1,
},
['button-purple'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'aa00ff',
alpha = .5,
},
['content-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'fffc00',
alpha = .5,
},
}
-- | Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:SetStylesheet(Stylesheet)
self:Show()
end,
['OnRelease'] = function(self) end,
['ApplySettings'] = function(self)
self.button:SetHeight(self.settings.buttonHeight)
-- postion
self:ClearAllPoints()
if self.settings.position == 1 then
self:SetPoint('TOPLEFT')
self:SetPoint('RIGHT')
else
local anchor = self.settings.parentObject.children[self.settings.position-1].frame
self:SetPoint('TOPLEFT',anchor,'BOTTOMLEFT',0,0)
self:SetPoint('RIGHT')
end
-- set section name
self.text:SetText(self.settings.sectionName)
-- set section state
self[self.settings.expanded and 'Expand' or 'Collapse'](self)
-- set button visibility
self:SetButton(self.settings.button)
end,
['Collapse'] = function(self)
if not self.settings.button then self:UpdateHeight() return end
self.settings.expanded = false
self:FireEvent("OnStateChange", self.settings.position, 'Collapse')
self.textures['button-leftCollapseIcon']:SetAlpha(self.textures['button-leftCollapseIcon'].style.alpha[1])
self.textures['button-leftExpandIcon']:SetAlpha(0)
self.content:Hide()
self:UpdateHeight()
end,
['Expand'] = function(self)
self.settings.expanded = true
self:FireEvent("OnStateChange", self.settings.position, 'Expand')
self.textures['button-leftExpandIcon']:SetAlpha(self.textures['button-leftExpandIcon'].style.alpha[1])
self.textures['button-leftCollapseIcon']:SetAlpha(0)
self.content:Show()
self:UpdateHeight()
end,
['SetButton'] = function(self,state)
self.settings.button = state
self.button[state and 'Show' or 'Hide'](self.button)
if not state then
self:Expand()
else
self:UpdateHeight()
end
end,
['UpdateHeight'] = function(self)
local settings, children = self.settings, self.children
local contentHeight = 0
self.content:SetPoint('TOPLEFT',self.frame,0,settings.button and -settings.buttonHeight or 0)
if settings.expanded then
contentHeight = settings.contentPadding[3] + settings.contentPadding[4]
for i=1 , #children do contentHeight = contentHeight + children[i].frame:GetHeight() end
end
self.content:SetHeight(contentHeight)
self:SetHeight((settings.button and settings.buttonHeight or 0) + contentHeight)
self:FireEvent("OnHeightChange",contentHeight)
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
button = true,
contentPadding = {0,0,3,1 },
expanded = true,
buttonHeight = 16,
}
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local button = self:CreateRegion("Button", 'button', frame)
button:SetPoint('TOPRIGHT')
button:SetPoint('TOPLEFT')
button:SetScript("OnClick", function(this,button)
DiesalGUI:OnMouse(this,button)
self[self.settings.expanded and "Collapse" or "Expand"](self)
end)
local text = self:CreateRegion("FontString", 'text', button)
text:SetPoint("TOPLEFT",15,-2)
text:SetPoint("BOTTOMRIGHT",-15,0)
text:SetHeight(0)
text:SetJustifyH("MIDDLE")
text:SetJustifyH("LEFT")
text:SetWordWrap(false)
local content = self:CreateRegion("Frame", 'content', frame)
content:SetPoint('TOPLEFT',frame,0,0)
content:SetPoint('TOPRIGHT',frame,0,0)
content:SetHeight(10)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,177 @@
-- $Id: Bar.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- | Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- | 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 = "Bar"
local Version = 1
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .60,
},
['frame-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
position = 1,
},
['frame-inline'] = {
type = 'outline',
layer = 'BORDER',
color = '000000',
alpha = .60,
},
['bar-background'] = {
type = 'texture',
layer = 'BACKGROUND',
gradient = {'VERTICAL',Colors.UI_A100,ShadeColor(Colors.UI_A100,.1)},
position = 0,
},
['bar-inline'] = {
type = 'outline',
layer = 'BORDER',
gradient = {'VERTICAL','FFFFFF','FFFFFF'},
alpha = {.07,.02},
position = 0,
},
['bar-outline'] = {
type = 'texture',
layer = 'ARTWORK',
color = '000000',
alpha = .7,
width = 1,
position = {nil,1,0,0},
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['bar-green'] = {
type = 'outline',
layer = 'OVERLAY',
color = '55ff00',
},
}
-- | Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function round(num)
return floor((num + 1/2)/1) * 1
end
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:SetStylesheet(Stylesheet)
self:ApplySettings()
-- self:SetStylesheet(wireFrame)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
self:UpdateSize()
end,
['UpdateSize'] = function(self)
self:SetWidth(self.settings.width)
self:SetHeight(self.settings.height)
self.bar:SetPoint('TOPLEFT',self.settings.padding[1],-self.settings.padding[3])
self.bar:SetPoint('BOTTOMLEFT',self.settings.padding[1],self.settings.padding[4])
self.settings.barWidth = self.settings.width - self.settings.padding[1] - self.settings.padding[2]
self:UpdateBar()
end,
['SetColor'] = function(self, color, colorTop, gradientDirection)
end,
['SetSize'] = function(self, width, height)
width, height = tonumber(width), tonumber(height)
if not width then error('Bar:SetSize(width, height) width to be a number.',0) end
if not height then error('Bar:SetSize(width, height) height to be a number.',0) end
self.settings.width, self.settings.height = width, height
self:UpdateSize()
end,
['SetValue'] = function(self, number, min, max)
number, min, max = tonumber(number), tonumber(min), tonumber(max)
if not number then error('Bar:SetValue(number) number needs to be a number.',0) end
self.settings.min = min or self.settings.min
self.settings.max = max or self.settings.max
self.settings.value = number
self:UpdateBar()
end,
['SetMin'] = function(self, number)
number = tonumber(number)
if not number then error('Bar:SetMin(number) needs to be a number.',0) end
self.settings.min = number
self:UpdateBar()
end,
['SetMax'] = function(self, number)
number = tonumber(number)
if not number then error('Bar:SetMax(number) needs to be a number.',0) end
self.settings.max = number
self:UpdateBar()
end,
['UpdateBar'] = function(self)
local min, max, value, barWidth = self.settings.min, self.settings.max, self.settings.value, self.settings.barWidth
local width = round( (value - min) / (max - min) * barWidth )
if width == 0 then
self.bar:Hide()
else
self.bar:Show()
self.bar:SetWidth(width)
end
end,
['IsVisible'] = function(self)
return self.frame:IsVisible()
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
height = 14, -- frame height (not bar)
width = 96, -- frame width (not bar)
padding = {1,1,1,1}, -- left, right, top, bottom (bar padding from frame)
value = 0,
min = 0,
max = 100,
}
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnHide",function(this)
self:FireEvent("OnHide")
end)
local bar = self:CreateRegion("Frame", 'bar', frame)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,279 @@
-- $Id: Branch.lua 60 2016-11-04 01:34:23Z diesal2010 $
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub('DiesalStyle-1.0')
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local sub, format, match, lower = string.sub, string.format, string.match, string.lower
local tsort = table.sort
local tostring = tostring
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| TableExplorerBranch |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'Branch'
local Version = 1
-- ~~| Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['button-highlight'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'ffffff',
alpha = .1,
},
['button-selected'] = {
type = 'texture',
layer = 'BORDER',
color = '0059b3',
alpha = 0,
},
}
local wireFrameSheet = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['button-purple'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'aa00ff',
},
['content-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'fffc00',
},
}
-- ~~| Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
if not self.settings.position then return false end
local button = self.button
local content = self.content
button:SetHeight(self.settings.buttonHeight)
if not self.settings.leaf then
self[self.settings.expanded and "Expand" or "Collapse"](self)
else
self:UpdateLines()
self:UpdateHeight()
end
self:ClearAllPoints()
if self.settings.position == 1 then
self:SetPoint('TOPLEFT',self.settings.indent,0)
self:SetPoint('RIGHT')
else
local anchor = self.settings.parentObject.children[self.settings.position-1].frame
self:SetPoint('TOPLEFT',anchor,'BOTTOMLEFT',0,0)
self:SetPoint('RIGHT')
end
end,
['Collapse'] = function(self)
if self.settings.leaf then return end
self:FireEvent("OnStateChange",false)
self.settings.expanded = false
self:SetIconCollapsed()
self:UpdateLines()
self.content:Hide()
self:UpdateHeight()
end,
['Expand'] = function(self)
if self.settings.leaf then return end
self:FireEvent("OnStateChange",true)
self.settings.expanded = true
self:SetIconExpanded()
self:UpdateLines()
self.content:Show()
self:UpdateHeight()
end,
['UpdateHeight'] = function(self)
local contentHeight = 0
local settings = self.settings
local children = self.children
if settings.expanded then
for i=1 , #children do
contentHeight = contentHeight + children[i].frame:GetHeight()
end
end
self.content:SetHeight(contentHeight)
self:SetHeight(settings.buttonHeight + contentHeight)
settings.parentObject:UpdateHeight()
end,
['SetLabel'] = function(self,text)
self.text:SetText(text)
end,
['SetIconTexture'] = function(self,texture)
self.icon:SetTexture(texture)
end,
['SetIconCoords'] = function(self,left,right,top,bottom)
self.icon:SetTexCoord(left,right,top,bottom)
end,
['SetIconExpanded'] = function(self)
self.icon:SetTexCoord(DiesalTools.GetIconCoords(2,8,16,256,128))
end,
['SetIconCollapsed'] = function(self)
self.icon:SetTexCoord(DiesalTools.GetIconCoords(1,8,16,256,128))
end,
['SetSelected'] = function(self,state)
self:UpdateStyle('button-selected',{
type = 'texture',
alpha = state and 1 or 0,
})
end,
['UpdateLines'] = function(self)
if not self.settings.branches then return end
local foldColor = '353535'
local expandColor = '5a5a5a'
-- Frame Fold Line
if not self.settings.last and not self.settings.leaf then
self:UpdateStyle('frame-foldLine',{
type = 'texture',
layer = 'OVERLAY',
color = foldColor,
position = {6,nil,-11,2},
width = 1,
})
end
-- expandable Fold Lines
if not self.settings.leaf then
self:UpdateStyle('button-square',{
type = 'outline',
layer = 'BORDER',
color = foldColor,
position = {10,nil,-2,nil},
width = 9,
height = 9,
})
self:UpdateStyle('button-expandH',{
type = 'texture',
layer = 'BORDER',
color = expandColor,
position = {8,nil,-6,nil},
width = 5,
height = 1,
})
self:UpdateStyle('button-expandV',{
type = 'texture',
layer = 'BORDER',
color = expandColor,
position = {6,nil,-4,nil},
width = 1,
height = 5,
alpha = 1,
})
if self.settings.expanded then
self:UpdateStyle('button-expandV',{
type = 'texture',
alpha = 0,
})
end
else -- Leaf nodes
self:UpdateStyle('button-lineV',{
type = 'texture',
layer = 'BORDER',
color = foldColor,
position = {6,nil,-6,nil},
height = 1,
width = 6,
})
self:UpdateStyle('button-lineH',{
type = 'texture',
layer = 'BORDER',
color = foldColor,
position = {6,nil,0,0},
width = 1,
})
if self.settings.last then
self:UpdateStyle('button-lineH',{
type = 'texture',
position = {6,nil,0,-7},
})
end
end
end,
}
-- ~~| TableExplorerBranch Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
fontObject = DiesalFontNormal,
branches = true,
expanded = true,
buttonHeight = 14,
indent = 13,
expIconTex = 'DiesalGUIcons',
colIconTex = 'DiesalGUIcons',
expIconCoords = {DiesalTools.GetIconCoords(2,8,16,256,128)},
colIconCoords = {DiesalTools.GetIconCoords(1,8,16,256,128)},
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local button = self:CreateRegion("Button", 'button', frame)
button:SetPoint('TOPRIGHT')
button:SetPoint('TOPLEFT')
button:RegisterForClicks('RightButtonUp','LeftButtonUp')
button:RegisterForDrag( "LeftButton" )
button:SetScript("OnClick", function(this,button)
DiesalGUI:OnMouse(this,button)
if button == 'LeftButton' then self[not self.settings.expanded and "Expand" or "Collapse"](self) end
self:FireEvent("OnClick",button)
end)
button:SetScript( "OnDoubleClick", function(this,...)
self:FireEvent("OnDoubleClick",...)
end)
button:SetScript( "OnDragStart", function(this,...)
self:FireEvent("OnDragStart",...)
end)
button:SetScript( "OnDragStop", function(this,...)
self:FireEvent("OnDragStop",...)
end)
button:SetScript("OnEnter",function(this,...)
self:FireEvent("OnEnter",...)
end)
button:SetScript("OnLeave", function(this,...)
self:FireEvent("OnLeave",...)
end)
local icon = self:CreateRegion("Texture", 'icon', button)
DiesalStyle:StyleTexture(icon,{
position = {0,nil,2,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons'},
})
local text = self:CreateRegion("FontString", 'text', button)
text:SetPoint("TOPLEFT",14,-1)
text:SetPoint("BOTTOMRIGHT",-4,0)
text:SetHeight(0)
text:SetJustifyH("TOP")
text:SetJustifyH("LEFT")
text:SetWordWrap(false)
local content = self:CreateRegion("Frame", 'content', button)
content:SetPoint('TOPLEFT',button,'BOTTOMLEFT',0,0)
content:SetPoint('TOPRIGHT')
content:SetHeight(0)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,109 @@
-- $Id: Button.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| 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 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent, GetCursorPosition = CreateFrame, UIParent, GetCursorPosition
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
local GetSpellInfo, GetBonusBarOffset, GetDodgeChance = GetSpellInfo, GetBonusBarOffset, GetDodgeChance
local GetPrimaryTalentTree, GetCombatRatingBonus = GetPrimaryTalentTree, GetCombatRatingBonus
-- ~~| Button |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local TYPE = "Button"
local VERSION = 5
-- ~~| Button Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['text-color'] = {
type = 'Font',
color = 'b8c2cc',
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
}
-- ~~| Button Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
self:Enable()
-- self:SetStylesheet(wireFrameSheet)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
local settings = self.settings
local frame = self.frame
self:SetWidth(settings.width)
self:SetHeight(settings.height)
end,
["SetText"] = function(self, text)
self.text:SetText(text)
end,
["Disable"] = function(self)
self.settings.disabled = true
self.frame:Disable()
end,
["Enable"] = function(self)
self.settings.disabled = false
self.frame:Enable()
end,
["RegisterForClicks"] = function(self,...)
self.frame:RegisterForClicks(...)
end,
}
-- ~~| Button Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor(name)
local self = DiesalGUI:CreateObjectBase(TYPE)
local frame = CreateFrame('Button',name,UIParent)
self.frame = frame
self.defaults = {
height = 32,
width = 32,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnClick, OnEnter, OnLeave, OnDisable, OnEnable
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local text = self:CreateRegion("FontString", 'text', frame)
text:SetPoint("TOPLEFT", 4, -1) -- sits below center when rendered off by 1 pixel, fuck you blizzard
text:SetPoint("BOTTOMRIGHT", -4, 0)
text:SetJustifyV("MIDDLE")
text:SetJustifyH("CENTER")
frame:SetFontString(text)
frame:SetScript("OnClick", function(this,button,...)
DiesalGUI:OnMouse(this,button)
self:FireEvent("OnClick",button,...)
end)
frame:SetScript("OnEnter", function(this)
self:FireEvent("OnEnter")
end)
frame:SetScript("OnLeave", function(this)
self:FireEvent("OnLeave")
end)
frame:SetScript("OnDisable", function(this)
self:FireEvent("OnDisable")
end)
frame:SetScript("OnEnable", function(this)
self:FireEvent("OnEnable")
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(TYPE,Constructor,VERSION)

@ -0,0 +1,163 @@
-- $Id: CheckBox.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| 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 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent, GetCursorPosition = CreateFrame, UIParent, GetCursorPosition
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
local GetSpellInfo, GetBonusBarOffset, GetDodgeChance = GetSpellInfo, GetBonusBarOffset, GetDodgeChance
local GetPrimaryTalentTree, GetCombatRatingBonus = GetPrimaryTalentTree, GetCombatRatingBonus
-- ~~| Button |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local TYPE = "CheckBox"
local VERSION = 1
-- ~~| Button Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .60,
position = -2
},
['frame-inline'] = {
type = 'outline',
layer = 'BORDER',
color = '000000',
alpha = .6,
position = -2
},
['frame-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
position = -1,
},
}
local checkBoxStyle = {
base = {
type = 'texture',
layer = 'ARTWORK',
color = Colors.UI_A400,
position = -3,
},
disabled = {
type = 'texture',
color = HSL(Colors.UI_Hue,Colors.UI_Saturation,.35),
},
enabled = {
type = 'texture',
color = Colors.UI_A400,
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
}
-- ~~| Button Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
self:Enable()
-- self:SetStylesheet(wireFrameSheet)
self:Show()
end,
['OnRelease'] = function(self) end,
['ApplySettings'] = function(self)
local settings = self.settings
local frame = self.frame
self:SetWidth(settings.width)
self:SetHeight(settings.height)
end,
["SetChecked"] = function(self,value)
self.settings.checked = value
self.frame:SetChecked(value)
self[self.settings.disabled and "Disable" or "Enable"](self)
end,
["GetChecked"] = function(self)
return self.settings.checked
end,
["Disable"] = function(self)
self.settings.disabled = true
DiesalStyle:StyleTexture(self.check,checkBoxStyle.disabled)
self.frame:Disable()
end,
["Enable"] = function(self)
self.settings.disabled = false
DiesalStyle:StyleTexture(self.check,checkBoxStyle.enabled)
self.frame:Enable()
end,
["RegisterForClicks"] = function(self,...)
self.frame:RegisterForClicks(...)
end,
}
-- ~~| Button Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(TYPE)
local frame = CreateFrame('CheckButton', nil, UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
height = 11,
width = 11,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnValueChanged, OnEnter, OnLeave, OnDisable, OnEnable
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local check = self:CreateRegion("Texture", 'check', frame)
DiesalStyle:StyleTexture(check,checkBoxStyle.base)
frame:SetCheckedTexture(check)
frame:SetScript('OnClick', function(this,button,...)
DiesalGUI:OnMouse(this,button)
if not self.settings.disabled then
self:SetChecked(not self.settings.checked)
if self.settings.checked then
-- PlaySound("igMainMenuOptionCheckBoxOn")
else
-- PlaySound("igMainMenuOptionCheckBoxOff")
end
self:FireEvent("OnValueChanged", self.settings.checked)
end
end)
frame:SetScript('OnEnter', function(this)
self:FireEvent("OnEnter")
end)
frame:SetScript('OnLeave', function(this)
self:FireEvent("OnLeave")
end)
frame:SetScript("OnDisable", function(this)
self:FireEvent("OnDisable")
end)
frame:SetScript("OnEnable", function(this)
self:FireEvent("OnEnable")
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(TYPE,Constructor,VERSION)

@ -0,0 +1,282 @@
-- $Id: ComboBox.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local sub, format, lower, upper,gsub = string.sub, string.format, string.lower, string.upper, string.gsub
local tsort = table.sort
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| ComboBox |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'ComboBox'
local Version = 1
-- ~~| ComboBox Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .7,
},
['frame-inline'] = {
type = 'outline',
layer = 'BORDER',
color = '000000',
alpha = .7,
},
['frame-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
position = 1,
},
['button-background'] = {
type = 'texture',
layer = 'BACKGROUND',
gradient = {'VERTICAL',Colors.UI_500_GR[1],Colors.UI_500_GR[2]},
},
['button-outline'] = {
type = 'outline',
layer = 'ARTWORK',
color = '000000',
alpha = .9,
},
['button-inline'] = {
type = 'outline',
layer = 'BORDER',
gradient = {'VERTICAL','FFFFFF','FFFFFF'},
alpha = {.07,.02},
position = -1,
},
['button-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'ffffff',
alpha = .05,
},
['button-arrow'] = {
type = 'texture',
layer = 'BORDER',
image = {'DiesalGUIcons',{2,1,16,256,128}},
alpha = .5,
position = {nil,-4,-5,nil},
height = 4,
width = 5,
},
['editBox-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'ffffff',
alpha = .1,
position = {-1,0,-1,-1},
},
['editBox-font'] = {
type = 'Font',
color = Colors.UI_TEXT,
},
['dropdown-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_100,
alpha = .95,
},
['dropdown-inline'] = {
type = 'outline',
layer = 'BORDER',
color = 'ffffff',
alpha = .02,
position = -1,
},
['dropdown-shadow'] = {
type = 'shadow',
},
}
-- ~~| ComboBox 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
-- ~~| ComboBox Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:Show()
end,
['OnRelease'] = function(self) end,
['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)
self.editBox:SetPoint('RIGHT',-settings.buttonWidth,0)
self.button:SetWidth(settings.buttonWidth)
-- dropdown
content:SetPoint("TOPLEFT",settings.dropdownPadding[1],-settings.dropdownPadding[3])
content:SetPoint("BOTTOMRIGHT",-settings.dropdownPadding[2],settings.dropdownPadding[4])
local menuHeight = 0
for i=1 , #children do
menuHeight = menuHeight + children[i].frame:GetHeight()
end
dropdown:SetHeight(settings.dropdownPadding[3] + menuHeight + settings.dropdownPadding[4])
end,
['SetList'] = function(self,list,orderedKeys)
self:ReleaseChildren()
self:SetText('')
local settings = self.settings
local orderedKeys = sortList(list,orderedKeys)
settings.list = list
for position, key in ipairs(orderedKeys) do
local comboBoxItem = DiesalGUI:Create('ComboBoxItem')
self:AddChild(comboBoxItem)
comboBoxItem:SetParentObject(self)
comboBoxItem:SetSettings({
key = key,
value = list[key],
position = position,
},true)
end
self:ApplySettings()
end,
['SetValue'] = function(self,key)
for i=1,#self.children do
self.children[i]:SetSelected(false)
end
for i=1,#self.children do
if self.children[i].settings.key == key then
self.children[i]:SetSelected(true)
self:SetText(self.children[i].settings.value)
self.editBox:SetCursorPosition(0)
break end
end
end,
['SetText'] = function(self,text)
self.editBox:SetText(text)
end,
['SetJustify'] = function(self,j)
self.editBox:SetJustifyH(j)
end,
['SetFocus'] = function(self)
DiesalGUI:SetFocus(self)
end,
['ClearFocus'] = function(self)
self.dropdown:Hide()
end,
['ClearSelection'] = function(self)
for i=1,#self.children do
self.children[i]:SetSelected(false)
end
self:SetText('')
end,
}
-- ~~| ComboBox Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
width = 100,
height = 16,
buttonWidth = 16,
dropdownPadding = {4,4,4,4},
dropdownButtonWidth = 16,
}
-- ~~ Registered Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnValueSelected, OnRenameValue
-- OnEnter, OnLeave
-- OnButtonClick, OnButtonEnter, OnButtonLeave
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local editBox = self:CreateRegion("EditBox", 'editBox', frame)
editBox:SetPoint("TOPLEFT")
editBox:SetPoint("BOTTOMLEFT")
editBox:SetAutoFocus(false)
editBox:SetJustifyH("RIGHT")
editBox:SetJustifyV("CENTER")
editBox:SetTextInsets(1,2,2,0)
editBox:SetScript('OnEnterPressed', function(this)
local text = this:GetText()
DiesalGUI:ClearFocus()
if text ~= self.settings.oldValue then self:FireEvent("OnRenameValue",self.settings.selectedKey,text) end
end)
editBox:HookScript('OnEscapePressed', function(this,...)
this:SetText(self.settings.oldValue)
end)
editBox:HookScript('OnEditFocusGained', function(this)
self.settings.oldValue = this:GetText()
end)
editBox:HookScript('OnEditFocusLost', function(this,...)
self:SetText(self.settings.oldValue)
end)
editBox:SetScript("OnEnter",function(this)
self:FireEvent("OnEnter")
end)
editBox:SetScript("OnLeave", function(this)
self:FireEvent("OnLeave")
end)
local button = self:CreateRegion("Button", 'button', frame)
button:SetPoint('TOPRIGHT')
button:SetPoint('BOTTOMRIGHT')
button:SetScript("OnEnter",function(this)
self:FireEvent("OnButtonEnter")
end)
button:SetScript("OnLeave", function(this)
self:FireEvent("OnButtonLeave")
end)
button:SetScript("OnClick", function(this, button)
self:FireEvent("OnButtonClick")
local dropdown = self.dropdown
local visible = dropdown:IsVisible()
DiesalGUI:OnMouse(this,button)
dropdown[visible and "Hide" or 'Show'](dropdown)
end)
local dropdown = self:CreateRegion("Frame", 'dropdown', frame)
dropdown:SetFrameStrata("FULLSCREEN_DIALOG")
dropdown:SetPoint('TOPRIGHT',frame,'BOTTOMRIGHT',0,-2)
dropdown:SetPoint('TOPLEFT',frame,'BOTTOMLEFT',0,-2)
dropdown:SetScript("OnShow", function(this) self:SetFocus() end)
dropdown:Hide()
self:CreateRegion("Frame", 'content', dropdown)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,122 @@
-- $Id: ComboBoxItem.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| ComboBoxItem |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'ComboBoxItem'
local Version = 2
-- ~~| ComboBoxItem Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'b3d9ff',
alpha = .05,
},
}
-- ~~| ComboBoxItem Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| ComboBoxItem Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:Show()
end,
['OnRelease'] = function(self)
self.check:Hide()
end,
['ApplySettings'] = function(self)
if not self.settings.key then return end
local settings = self.settings
local comboBoxSettings = settings.parentObject.settings
local text = self.text
if settings.position == 1 then
self:SetPoint('TOPLEFT')
self:SetPoint('RIGHT')
else
self:SetPoint('TOPLEFT',settings.parentObject.children[settings.position-1].frame,'BOTTOMLEFT',0,0)
self:SetPoint('RIGHT')
end
self:SetHeight(comboBoxSettings.dropdownButtonWidth)
self:SetText(settings.value)
end,
['SetText'] = function(self,text)
self.text:SetText(text)
end,
['OnClick'] = function(self)
local settings = self.settings
local comboBox = settings.parentObject
local comboBoxSettings = comboBox.settings
local comboBoxItems = comboBox.children
for i=1,#comboBoxItems do
comboBoxItems[i]:SetSelected(false)
end
self:SetSelected(true)
comboBox.dropdown:Hide()
comboBox:SetText(settings.value)
comboBox:FireEvent("OnValueSelected",settings.key,settings.value)
end,
['SetSelected'] = function(self,selected)
if selected then
self.settings.parentObject.settings.selectedKey = self.settings.key
self.settings.selected = true
self.check:Show()
else
self.settings.selected = false
self.check:Hide()
end
end,
}
-- ~~| ComboBoxItem Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Button',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = { }
-- ~~ Registered Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnClick", function(this,button) self:OnClick() end)
frame:SetScript('OnEnter', function(this) end)
frame:SetScript('OnLeave', function(this) end)
local text = self:CreateRegion("FontString", 'text', frame)
text:SetPoint("TOPLEFT",12,-2)
text:SetPoint("BOTTOMRIGHT",0,0)
text:SetJustifyH("TOP")
text:SetJustifyH("LEFT")
text:SetWordWrap(false)
local check = self:CreateRegion("Texture", 'check', frame)
DiesalStyle:StyleTexture(check,{
position = {2,nil,0,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons', {10,5,16,256,128},'FFFF00'},
})
check:Hide()
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,296 @@
-- $Id: DropDown.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.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 = 'Dropdown'
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 = {.07,.02},
position = -1,
},
['frame-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'ffffff',
alpha = .05,
},
['frame-arrow'] = {
type = 'texture',
layer = 'BORDER',
image = {'DiesalGUIcons',{2,1,16,256,128}},
alpha = .5,
position = {nil,-5,-7,nil},
height = 3,
width = 5,
},
['text-color'] = {
type = 'Font',
color = Colors.UI_TEXT,
},
['dropdown-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_100,
alpha = .95,
},
['dropdown-inline'] = {
type = 'outline',
layer = 'BORDER',
color = 'ffffff',
alpha = .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
-- ~~| Dropdown Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:Show()
end,
['OnRelease'] = function(self)
end,
['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",settings.dropdownPadLeft,-settings.dropdownPadTop)
content:SetPoint("BOTTOMRIGHT",-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,
['SetList'] = function(self,list,orderedKeys)
self:ReleaseChildren()
self:SetText('')
local settings = self.settings
local orderedKeys = sortList(list,orderedKeys)
settings.list = list
for position, key in ipairs(orderedKeys) do
local dropdownItem = DiesalGUI:Create('DropdownItem')
self:AddChild(dropdownItem)
dropdownItem:SetParentObject(self)
dropdownItem:SetSettings({
key = key,
value = list[key],
position = position,
},true)
end
self:ApplySettings()
end,
['SetValue'] = function(self,key)
local selectionTable = {}
local selectedKey, dropdownText, selectedValue
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
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
self.children[i]:SetSelected(false)
if self.children[i].settings.key == key then
self.children[i]:SetSelected(true)
dropdownText = self.children[i].settings.value
selectionTable = {key}
selectedKey = key
selectedValue = value
end
end
end
else
self:ClearSelection()
end
if selectedKey then
self:SetText(dropdownText)
self:FireEvent("OnValueChanged",selectedKey,selectedValue,selectionTable)
else
self:SetText('')
self:FireEvent("OnValueChanged",selectedKey,selectedValue,selectionTable)
end
end,
['ClearSelection'] = function(self)
for i=1,#self.children do
self.children[i]:SetSelected(false)
end
self:SetText('')
end,
['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
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)
if dropdownText then
dropdownText = format('%s, %s',dropdownText,dropdownItem.settings.value)
else
dropdownText = dropdownItem.settings.value
end
selectionTable[#selectionTable+1] = dropdownItem.settings.key
end
end
end
self:FireEvent("OnValueChanged",nil,nil,selectionTable)
self:SetText(dropdownText)
end,
['SetMultiSelect'] = function(self,state)
self.settings.multiSelect = state
end,
['SetText'] = function(self,text)
self.text:SetText(text)
end,
['SetFocus'] = function(self)
DiesalGUI:SetFocus(self)
end,
['ClearFocus'] = function(self)
self.dropdown:Hide()
end,
['EnableMouse'] = function(self,state)
self.frame:EnableMouse(state)
end,
["RegisterForClicks"] = function(self,...)
self.frame:RegisterForClicks(...)
end,
['SetJustifyV'] = function(self,justify)
self.text:SetJustifyV(justify)
end,
['SetJustifyH'] = function(self,justify)
self.text:SetJustifyH(justify)
end,
}
-- ~~| Dropdown Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Button',nil,UIParent)
self.frame = frame
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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnMouseUp", function(this, button)
if button == 'LeftButton' then
local dropdown = self.dropdown
local visible = dropdown:IsVisible()
DiesalGUI:OnMouse(this,button)
dropdown[visible and "Hide" or 'Show'](dropdown)
end
end)
frame:SetScript("OnClick", function(this, ...)
self:FireEvent("OnClick", ...)
end)
frame:SetScript("OnEnter",function(this,...)
self:FireEvent("OnEnter",...)
end)
frame:SetScript("OnLeave", function(this,...)
self:FireEvent("OnLeave",...)
end)
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)
dropdown:SetFrameStrata("FULLSCREEN_DIALOG")
dropdown:SetPoint('TOPRIGHT',frame,'BOTTOMRIGHT',0,-2)
dropdown:SetPoint('TOPLEFT',frame,'BOTTOMLEFT',0,-2)
dropdown:SetScript("OnShow", function(this) self:SetFocus() end)
dropdown:Hide()
self:CreateRegion("Frame", 'content', dropdown)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,137 @@
-- $Id: DropDownItem.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local sub, format, lower, upper,gsub = string.sub, string.format, string.lower, string.upper, string.gsub
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| DropdownItem |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'DropdownItem'
local Version = 2
-- ~~| DropdownItem Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'b3d9ff',
alpha = .1,
},
}
-- ~~| DropdownItem Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:Show()
end,
['OnRelease'] = function(self)
self.check:Hide()
end,
['ApplySettings'] = function(self)
if not self.settings.key then return end
local settings = self.settings
local dropdownSettings = settings.parentObject.settings
local text = self.text
if settings.position == 1 then
self:SetPoint('TOPLEFT')
self:SetPoint('RIGHT')
else
self:SetPoint('TOPLEFT',settings.parentObject.children[settings.position-1].frame,'BOTTOMLEFT',0,0)
self:SetPoint('RIGHT')
end
self:SetHeight(dropdownSettings.itemHeight)
self:SetText(settings.value)
end,
['SetText'] = function(self,text)
self.text:SetText(text)
end,
['OnClick'] = function(self)
local settings = self.settings
local dropdown = settings.parentObject
local dropdownSettings= dropdown.settings
local dropdownItems = dropdown.children
local selectionTable = {}
local dropdownText
if settings.key ~= 'CLEAR' then
if dropdownSettings.multiSelect then
self:SetSelected(not settings.selected)
for i=1,#dropdownItems do
if dropdownItems[i].settings.selected then
if dropdownText then
dropdownText = format('%s, %s',dropdownText,dropdownItems[i].settings.value)
else
dropdownText = dropdownItems[i].settings.value
end
selectionTable[#selectionTable+1] = dropdownItems[i].settings.key
end
end
else
for i=1,#dropdownItems do
dropdownItems[i]:SetSelected(false)
end
self:SetSelected(true)
dropdownText = settings.value
selectionTable = {settings.key}
dropdown.dropdown:Hide()
end
else
dropdown.dropdown:Hide()
dropdown:ClearSelection()
end
dropdown:SetText(dropdownText)
dropdown:FireEvent("OnValueChanged",settings.key,settings.value,selectionTable)
dropdown:FireEvent("OnValueSelected",settings.key,settings.value,selectionTable)
end,
['SetSelected'] = function(self,selected)
if selected then
self.settings.selected = true
self.check:Show()
else
self.settings.selected = false
self.check:Hide()
end
end,
}
-- ~~| DropdownItem Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Button',nil,UIParent)
self.frame = frame
self.defaults = { }
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnClick", function(this,button) self:OnClick() end)
frame:SetScript('OnEnter', function(this) end)
frame:SetScript('OnLeave', function(this) end)
local text = self:CreateRegion("FontString", 'text', frame)
text:SetPoint("TOPLEFT",12,-2)
text:SetPoint("BOTTOMRIGHT",0,0)
text:SetJustifyH("TOP")
text:SetJustifyH("LEFT")
text:SetWordWrap(false)
local check = self:CreateRegion("Texture", 'check', frame)
DiesalStyle:StyleTexture(check,{
position = {2,nil,0,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons', {10,5,16,256,128},'FFFF00'},
})
check:Hide()
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,124 @@
-- $Id: Input.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Input |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "Input"
local Version = 1
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .6,
},
['editBox-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
position = 1,
},
['editBox-inline'] = {
type = 'outline',
layer = 'BORDER',
color = '000000',
alpha = .7,
},
['editBox-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = 'ffffff',
alpha = .05,
position = -1,
},
['editBox-font'] = {
type = 'Font',
color = Colors.UI_TEXT,
},
}
-- ~~| Spinner Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:SetStylesheet(Stylesheet)
self:ApplySettings()
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
self:SetWidth( self.settings.width)
self:SetHeight( self.settings.height)
end,
['GetText'] = function(self)
return self.editBox:GetText()
end,
['SetText'] = function(self,txt)
self.editBox:SetText(txt)
end,
['SetTextColor'] = function(self,color,alpha)
alpha = alpha or 1
color = {DiesalTools.GetColor(color)}
self.editBox:SetTextColor(color[1],color[2],color[3],alpha)
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
self.defaults = {
height = 16,
width = 50,
mouse = true,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnEnter, OnLeave, OnEnterPressed, OnValueChanged
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnHide",function(this)
self:FireEvent("OnHide")
end)
local editBox = self:CreateRegion("EditBox", 'editBox', frame)
editBox:SetAllPoints()
editBox:SetAutoFocus(false)
editBox:SetJustifyH("LEFT")
editBox:SetJustifyV("CENTER")
editBox:SetTextInsets(3,0,2,0)
editBox:SetScript('OnEnterPressed', function(this,...)
self:FireEvent("OnEnterPressed",...)
DiesalGUI:ClearFocus()
end)
editBox:HookScript('OnEscapePressed', function(this,...)
self:FireEvent("OnEscapePressed",...)
end)
editBox:HookScript('OnEditFocusLost', function(this,...)
self:FireEvent("OnEditFocusLost",...)
end)
editBox:HookScript('OnEditFocusGained', function(this,...)
self:FireEvent("OnEditFocusGained",...)
end)
editBox:SetScript("OnEnter",function(this,...)
self:FireEvent("OnEnter",...)
end)
editBox:SetScript("OnLeave", function(this,...)
self:FireEvent("OnLeave",...)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,163 @@
-- $Id: QuickDoc.lua 60 2016-11-04 01:34:23Z diesal2010 $
-- | Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
local DiesalGUI = LibStub("DiesalGUI-1.0")
local DiesalMenu = LibStub('DiesalMenu-1.0')
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local print, type, select, tostring, tonumber = print, type, select, tostring, tonumber
local sub, format, match, lower = string.sub, string.format, string.match, string.lower
local table_sort = table.sort
local abs = math.abs
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | TableExplorer |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local QuickDoc
local Type = "QuickDoc"
local Version = 1
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local windowStylesheet = {
['content-background'] = {
type = 'texture',
color = '131517',
},
}
-- | Local |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local doc = {
{ type = 'section',
margin = {0,0,0,0},
padding = {0,0,0,0},
style = {},
{ type = 'single-line', text = 'Editor',
font = nil.
fontSize = 14,
text = 'Editor',
},
{ type = 'columns', text = 'Editor',
font = nil.
fontSize = 14,
text = 'Editor',
},
}
}
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self.settings = DiesalTools.TableCopy( self.defaults )
self:ApplySettings()
self:Show()
end,
['OnRelease'] = function(self)
self.tree:ReleaseChildren()
end,
['ApplySettings'] = function(self)
end,
['BuildDoc'] = function(self,doc)
if #doc == 0 then error('BuildDoc(doc) doc requires atleast one section')
local settings = self.settings
-- reset
self:ReleaseChildren()
-- setup
settings.doc = doc
if #doc == 0 then
tree:UpdateHeight()
self.statusText:SetText('|cffff0000Table is empty.')
return end
-- sort tree table
local sortedTable = sortTable(settings.exploredTable)
-- build Tree Branches
for position, key in ipairs(sortedTable) do
if self.settings.endtime <= time() then self:Timeout() return end
self:BuildBranch(self.tree,key[2],settings.exploredTable[key[2]],position,1,position == #sortedTable)
end
end,
['BuildSection'] = function(self,parent,key,value,position,depth,last)
local tree = self.tree
local leaf = type(value) ~= 'table' or next(value) == nil or depth >= self.settings.maxDepth
local branch = DiesalGUI:Create('Branch')
-- | Reset Branch |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
branch:ReleaseChildren()
-- | setup Branch |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
branch:SetParentObject(parent)
parent:AddChild(branch)
branch:SetSettings({
key = key,
value = value,
position = position,
depth = depth,
last = last,
leaf = leaf,
})
branch:SetEventListener('OnClick',function(this,event,button)
if button =='RightButton' then
if not next(this.settings.menuData) then return end
DiesalMenu:Menu(this.settings.menuData,this.frame,10,-10)
end
end)
self:SetBranchLabel(branch,key,value,leaf)
self:SetBranchMenu(branch,key,value)
self:SetBranchIcon(branch,type(value))
if value == tree or leaf then branch:ApplySettings() return end
-- | sort Branch Table |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local sortedTable = sortTable(value)
-- | build Branch Branches |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for position, key in ipairs(sortedTable) do
if self.settings.endtime <= time() then self:Timeout() return end
self:BuildBranch(branch,key[2],value[key[2]],position,depth+1,position == #sortedTable)
end
-- | Update Branch | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
branch:ApplySettings()
end,
['Show'] = function(self)
self.window:Show()
end,
}
-- ~~| TableExplorer Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
QuickDoc = DiesalGUI:CreateObjectBase(Type)
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
QuickDoc.defaults = {
}
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local window = DiesalGUI:Create('Window')
window:SetSettings({
header = false,
footer = false,
top = UIParent:GetHeight() - 100,
left = 100,
height = 300,
width = 400,
minWidth = 200,
minHeight = 200,
},true)
window:SetStylesheet(windowStylesheet)
-- ~~ Frames ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
QuickDoc.window = window
QuickDoc.content = window.content
QuickDoc.frame = window.frame
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do QuickDoc[method] = func end
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return QuickDoc
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,279 @@
-- $Id: ScrollFrame.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber = type, select, pairs, tonumber
local setmetatable, getmetatable, next = setmetatable, getmetatable, next
local sub, format, lower, upper = string.sub, string.format, string.lower, string.upper
local floor, ceil, min, max, abs, modf = math.floor, math.ceil, math.min, math.max, math.abs, math.modf
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local GetCursorPosition = GetCursorPosition
-- ~~| ScrollFrame |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'ScrollFrame'
local Version = 3
-- ~~| ScrollFrame Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['track-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .3,
},
['grip-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_400,
},
['grip-inline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['scrollFrameContainer-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffff00',
},
['scrollFrame-orange'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ff7f00',
},
['scrollBar-blue'] = {
type = 'outline',
layer = 'OVERLAY',
color = '0080ff',
},
['track-green'] = {
type = 'outline',
layer = 'OVERLAY',
color = '00ff00',
},
['grip-purple'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'a800ff',
},
}
-- ~~| ScrollFrame Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local internal
-- ~~| ScrollFrame Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
--self:SetStylesheet(wireFrame)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
local settings = self.settings
local scrollFrame = self.scrollFrame
scrollFrame:SetPoint('TOPLEFT',settings.contentPadding[1],-settings.contentPadding[3])
scrollFrame:SetPoint('BOTTOMRIGHT',-settings.contentPadding[2],settings.contentPadding[4])
self.scrollBar:SetWidth(settings.scrollBarWidth)
self.scrollBar:SetPoint('TOPRIGHT',-settings.scrollBarPadding[2],-settings.scrollBarPadding[3])
self.scrollBar:SetPoint('BOTTOMRIGHT',-settings.scrollBarPadding[2],settings.scrollBarPadding[4])
if settings.scrollBarButtons then
self.track:SetPoint('TOP',0,-settings.scrollBarButtonHeight)
self.track:SetPoint('BOTTOM',0,settings.scrollBarButtonHeight)
self.buttonDown:SetHeight(settings.scrollBarButtonHeight)
self.buttonUp:SetHeight(settings.scrollBarButtonHeight)
self.buttonUp:Show()
self.buttonDown:Show()
else
self.track:SetPoint('TOP',0,0)
self.track:SetPoint('BOTTOM',0,0)
self.buttonUp:Hide()
self.buttonDown:Hide()
end
self.content:SetHeight(settings.contentHeight)
end,
['SetContentHeight'] = function(self,height)
height = height < 1 and 1 or height -- height of 0 wont hide scrollbar
self.settings.contentHeight = height
self.content:SetHeight(height)
end,
['SetGripSize'] = function(self)
local contentSize = self.scrollFrame:GetVerticalScrollRange() + self.scrollFrame:GetHeight()
local windowSize = self.scrollFrame:GetHeight()
local trackSize = self.track:GetHeight()
local windowContentRatio = windowSize / contentSize
local gripSize = DiesalTools.Round(trackSize * windowContentRatio)
gripSize = max(gripSize, 10) -- might give this a setting?
gripSize = min(gripSize, trackSize)
self.grip:SetHeight(gripSize)
end,
['SetScrollThumbPosition'] = function(self)
local verticalScrollRange = self.scrollFrame:GetVerticalScrollRange() -- windowScrollAreaSize (rounded no need to round)
if verticalScrollRange < 1 then self.grip:SetPoint('TOP',0,0) return end
local verticalScroll = self.scrollFrame:GetVerticalScroll() -- windowPosition
local trackSize = self.track:GetHeight()
local gripSize = self.grip:GetHeight()
local windowPositionRatio = verticalScroll / verticalScrollRange
local trackScrollAreaSize = trackSize - gripSize
local gripPositionOnTrack = DiesalTools.Round(trackScrollAreaSize * windowPositionRatio)
self.grip:SetPoint('TOP',0,-gripPositionOnTrack)
end,
['ShowScrollBar'] = function(self,show)
if show then
self.scrollFrameContainer:SetPoint('BOTTOMRIGHT',-(self.settings.scrollBarWidth + self.settings.scrollBarPadding[1] + self.settings.scrollBarPadding[2]),0)
self.scrollBar:Show()
else
self.scrollBar:Hide()
self.scrollFrameContainer:SetPoint('BOTTOMRIGHT',0,0)
end
end,
['ScrollToBottom'] = function(self)
local scrollRange = self.scrollFrame:GetVerticalScrollRange()
if scrollRange > 0 and scrollRange ~= self.scrollFrame:GetVerticalScroll() then
self.scrollFrame:SetVerticalScroll(scrollRange)
end
end,
['SetVerticalScroll'] = function(self,num)
self.scrollFrame:SetVerticalScroll(num)
end,
['GetVerticalScroll'] = function(self)
return self.scrollFrame:GetVerticalScroll()
end,
['GetVerticalScrollRange'] = function(self)
return self.scrollFrame:GetVerticalScrollRange()
end,
['VerticallyScroll'] = function(self,num)
if num < 0 then
self.scrollFrame:SetVerticalScroll(max( self.scrollFrame:GetVerticalScroll() + num, 0))
else
self.scrollFrame:SetVerticalScroll(min( self.scrollFrame:GetVerticalScroll() + num, self.scrollFrame:GetVerticalScrollRange()))
end
end,
}
-- ~~| ScrollFrame Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
height = 300,
width = 500,
scrollBarButtonHeight = 4,
scrollBarWidth = 4,
scrollBarButtons = false,
scrollBarPadding = {0,0,0,0},
contentPadding = {0,0,0,0},
contentHeight = 1,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnHide
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnHide",function(this)
self:FireEvent("OnHide")
end)
local scrollFrameContainer = self:CreateRegion("Frame", 'scrollFrameContainer', frame)
scrollFrameContainer:SetAllPoints()
local scrollFrame = self:CreateRegion("ScrollFrame", 'scrollFrame', scrollFrameContainer)
scrollFrame:EnableMouseWheel(true)
scrollFrame:SetScript("OnMouseWheel", function(this,delta)
DiesalGUI:OnMouse(this,'MouseWheel')
if delta > 0 then
self:VerticallyScroll(-25)
else
self:VerticallyScroll(25)
end
end)
scrollFrame:SetScript("OnVerticalScroll", function(this,offset)
-- self.scrollFrame:GetVerticalScrollRange() windowScrollAreaSize
if this:GetVerticalScrollRange() < 1 then -- nothing to scroll
self:ShowScrollBar(false)
else
self:ShowScrollBar(true)
end
self:SetScrollThumbPosition()
end)
scrollFrame:SetScript("OnScrollRangeChanged", function(this,horizontalScrollRange, verticalScrollRange)
if verticalScrollRange < 1 then -- nothing to scroll
this:SetVerticalScroll(0)
self:ShowScrollBar(false)
return end
this:SetVerticalScroll(min(this:GetVerticalScroll(),verticalScrollRange))
self:ShowScrollBar(true)
self:SetGripSize()
self:SetScrollThumbPosition()
end)
scrollFrame:SetScript("OnSizeChanged", function(this,width,height)
self.content:SetWidth(width)
end)
scrollFrame:SetScrollChild(self:CreateRegion("Frame", 'content', scrollFrame))
scrollFrame:RegisterForDrag("LeftButton")
scrollFrame:SetScript( "OnDragStart", function(this,...)
self:FireEvent("OnDragStart",...)
end)
local scrollBar = self:CreateRegion("Frame", 'scrollBar', frame)
scrollBar:Hide()
local buttonUp = self:CreateRegion("Frame", 'buttonUp', scrollBar)
buttonUp:SetPoint('TOPLEFT')
buttonUp:SetPoint('TOPRIGHT')
local buttonDown = self:CreateRegion("Frame", 'buttonDown', scrollBar)
buttonDown:SetPoint('BOTTOMLEFT')
buttonDown:SetPoint('BOTTOMRIGHT')
local track = self:CreateRegion("Frame", 'track', scrollBar)
track:SetPoint('LEFT')
track:SetPoint('RIGHT')
local grip = self:CreateRegion("Frame", 'grip', track)
grip:SetPoint('LEFT')
grip:SetPoint('RIGHT')
grip:SetPoint('TOP')
grip:EnableMouse(true)
grip:SetScript("OnMouseDown", function(this,button)
DiesalGUI:OnMouse(this,button)
if button ~= 'LeftButton' then return end
local MouseY = select(2, GetCursorPosition()) / this:GetEffectiveScale()
local effectiveScale = this:GetEffectiveScale()
local trackScrollAreaSize = track:GetHeight() - this:GetHeight()
local gripPositionOnTrack = abs(select(5,this:GetPoint(1)))
this:SetScript("OnUpdate", function(this)
local newGripPosition = gripPositionOnTrack + (MouseY - (select(2, GetCursorPosition()) / effectiveScale ))
newGripPosition = min(max(newGripPosition,0),trackScrollAreaSize)
-- local newGripPositionRatio = newGripPosition / trackScrollAreaSize
-- local windowPosition = newGripPositionRatio * scrollArea:GetVerticalScrollRange()
scrollFrame:SetVerticalScroll((newGripPosition / trackScrollAreaSize) * scrollFrame:GetVerticalScrollRange())
end)
end)
grip:SetScript("OnMouseUp", function(this,button)
this:SetScript("OnUpdate", function(this) end)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,279 @@
-- $Id: ScrollingEditBox.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber = type, select, pairs, tonumber
local setmetatable, getmetatable, next = setmetatable, getmetatable, next
local sub, format, lower, upper = string.sub, string.format, string.lower, string.upper
local floor, ceil, min, max, abs, modf = math.floor, math.ceil, math.min, math.max, math.abs, math.modf
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local GetCursorPosition = GetCursorPosition
-- ~~| ScrollingEditBox |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'ScrollingEditBox'
local Version = 3
-- ~~| ScrollingEditBox Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['track-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .3,
},
['grip-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_400,
},
['grip-inline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['scrollFrameContainer-yellow'] = {
type = 'outline',
layer = 'BACKGROUND',
color = 'fffc00',
},
['scrollFrame-orange'] = {
type = 'outline',
layer = 'BORDER',
color = 'ffd400',
},
['editBox-red'] = {
type = 'outline',
layer = 'ARTWORK',
color = 'ff0000',
aplha = .5,
},
['scrollBar-blue'] = {
type = 'outline',
layer = 'OVERLAY',
color = '00aaff',
},
['track-green'] = {
type = 'outline',
layer = 'OVERLAY',
color = '55ff00',
},
}
-- ~~| ScrollingEditBox Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| ScrollingEditBox Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrame)
self:Show()
end,
['OnRelease'] = function(self) end,
['ApplySettings'] = function(self)
local settings = self.settings
self.scrollFrame:SetPoint('TOPLEFT',settings.contentPadding[1],-settings.contentPadding[3])
self.scrollFrame:SetPoint('BOTTOMRIGHT',-settings.contentPadding[2],settings.contentPadding[4])
self.scrollBar:SetPoint('TOPRIGHT',0,-settings.contentPadding[3] + 1)
self.scrollBar:SetPoint('BOTTOMRIGHT',0,settings.contentPadding[4] - 1)
self.scrollBar:SetWidth(settings.scrollBarWidth)
self.buttonDown:SetHeight(settings.scrollBarButtonHeight)
self.buttonUp:SetHeight(settings.scrollBarButtonHeight)
self.editBox:SetJustifyH(settings.justifyH)
self.editBox:SetJustifyV(settings.justifyV)
end,
['ShowScrollBar'] = function(self,show)
if show then
self.scrollFrameContainer:SetPoint('BOTTOMRIGHT',-(self.settings.scrollBarWidth + 1),0)
self.scrollBar:Show()
else
self.scrollBar:Hide()
self.scrollFrameContainer:SetPoint('BOTTOMRIGHT',0,0)
end
end,
['SetContentHeight'] = function(self,height)
self.settings.contentHeight = height
self.content:SetHeight(height)
end,
['SetGripSize'] = function(self)
local contentSize = self.scrollFrame:GetVerticalScrollRange() + self.scrollFrame:GetHeight()
local windowSize = self.scrollFrame:GetHeight()
local trackSize = self.track:GetHeight()
local windowContentRatio = windowSize / contentSize
local gripSize = DiesalTools.Round(trackSize * windowContentRatio)
gripSize = max(gripSize, 10) -- might give this a setting?
gripSize = min(gripSize, trackSize)
self.grip:SetHeight(gripSize)
end,
['SetScrollThumbPosition'] = function(self)
local verticalScrollRange = self.scrollFrame:GetVerticalScrollRange() -- windowScrollAreaSize (rounded no need to round)
if verticalScrollRange < 1 then self.grip:SetPoint('TOP',0,0) return end
local verticalScroll = self.scrollFrame:GetVerticalScroll() -- windowPosition
local trackSize = self.track:GetHeight()
local gripSize = self.grip:GetHeight()
local windowPositionRatio = verticalScroll / verticalScrollRange
local trackScrollAreaSize = trackSize - gripSize
local gripPositionOnTrack = DiesalTools.Round(trackScrollAreaSize * windowPositionRatio)
self.grip:SetPoint('TOP',0,-gripPositionOnTrack)
end,
['SetVerticalScroll'] = function(self,scroll) -- user scrolled only
self.settings.forceScrollBottom = DiesalTools.Round(scroll) == DiesalTools.Round(self.scrollFrame:GetVerticalScrollRange())
self.scrollFrame:SetVerticalScroll(scroll)
end,
['SetText'] = function(self,txt)
self.settings.text = txt
self.editBox:SetText(txt or '')
end,
}
-- ~~| ScrollingEditBox Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
scrollBarButtonHeight = 1,
scrollBarWidth = 4,
contentPadding = {0,0,0,0},
justifyH = "LEFT",
justifyV = "TOP",
forceScrollBottom = true,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnHide
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnHide",function(this) self:FireEvent("OnHide") end)
local scrollFrameContainer = self:CreateRegion("Frame", 'scrollFrameContainer', frame)
scrollFrameContainer:SetAllPoints()
local scrollFrame = self:CreateRegion("ScrollFrame", 'scrollFrame', scrollFrameContainer)
scrollFrame:EnableMouseWheel(true)
scrollFrame:SetScript("OnMouseWheel", function(this,delta)
DiesalGUI:OnMouse(this,'MouseWheel')
if delta > 0 then
self:SetVerticalScroll(max( this:GetVerticalScroll() - 50, 0))
else
self:SetVerticalScroll(min( this:GetVerticalScroll() + 50, this:GetVerticalScrollRange()))
end
end)
scrollFrame:SetScript("OnVerticalScroll", function(this,offset)
-- self.scrollFrame:GetVerticalScrollRange() windowScrollAreaSize
if this:GetVerticalScrollRange() < 1 then -- nothing to scroll
self:ShowScrollBar(false)
else
self:ShowScrollBar(true)
end
self:SetScrollThumbPosition()
end)
scrollFrame:SetScript("OnScrollRangeChanged", function(this,xOffset, verticalScrollRange)
if verticalScrollRange < 1 then -- nothing to scroll
this:SetVerticalScroll(0)
self:ShowScrollBar(false)
return end
if self.settings.forceScrollBottom then
this:SetVerticalScroll(verticalScrollRange)
else
this:SetVerticalScroll(min(this:GetVerticalScroll(),verticalScrollRange))
end
self:ShowScrollBar(true)
self:SetGripSize()
self:SetScrollThumbPosition()
end)
scrollFrame:SetScript("OnSizeChanged", function(this,width,height)
self.editBox:SetWidth(width)
end)
local editBox = self:CreateRegion("EditBox", 'editBox', scrollFrame)
editBox:SetPoint("TOPLEFT")
editBox:SetPoint("TOPRIGHT")
editBox:SetAutoFocus(false)
editBox:SetMultiLine(true)
editBox:HookScript('OnEditFocusLost',function(this)
this:HighlightText(0,0)
-- this:SetText(self.settings.text)
end)
editBox:HookScript('OnEditFocusGained',function(this)
self:FireEvent("OnEditFocusGained")
end)
editBox:HookScript('OnEscapePressed',function(this)
self:FireEvent("OnEscapePressed")
end)
editBox:HookScript('OnTabPressed',function(this)
self:FireEvent("OnTabPressed")
end)
editBox:HookScript('OnCursorChanged',function(this,...)
self:FireEvent("OnCursorChanged",...)
end)
editBox:HookScript('OnTextChanged',function(this)
self:FireEvent("OnTextChanged")
end)
scrollFrame:SetScrollChild(editBox)
local scrollBar = self:CreateRegion("Frame", 'scrollBar', frame)
scrollBar:Hide()
local buttonUp = self:CreateRegion("Frame", 'buttonUp', scrollBar)
buttonUp:SetPoint('TOPLEFT')
buttonUp:SetPoint('TOPRIGHT')
local buttonDown = self:CreateRegion("Frame", 'buttonDown', scrollBar)
buttonDown:SetPoint('BOTTOMLEFT')
buttonDown:SetPoint('BOTTOMRIGHT')
local track = self:CreateRegion("Frame", 'track', scrollBar)
track:SetPoint('LEFT')
track:SetPoint('RIGHT')
track:SetPoint('TOP',buttonUp,'BOTTOM',0,0)
track:SetPoint('BOTTOM',buttonDown,'TOP',0,0)
local grip = self:CreateRegion("Frame", 'grip', track)
grip:SetPoint('LEFT')
grip:SetPoint('RIGHT')
grip:SetPoint('TOP')
grip:EnableMouse(true)
grip:SetScript("OnMouseDown", function(this,button)
DiesalGUI:OnMouse(this,button)
if button ~= 'LeftButton' then return end
local MouseY = select(2, GetCursorPosition()) / this:GetEffectiveScale()
local effectiveScale = this:GetEffectiveScale()
local trackScrollAreaSize = track:GetHeight() - this:GetHeight()
local gripPositionOnTrack = abs(select(5,this:GetPoint(1)))
this:SetScript("OnUpdate", function(this)
local newGripPosition = gripPositionOnTrack + (MouseY - (select(2, GetCursorPosition()) / effectiveScale ))
newGripPosition = min(max(newGripPosition,0),trackScrollAreaSize)
-- local newGripPositionRatio = newGripPosition / trackScrollAreaSize
-- local windowPosition = newGripPositionRatio * scrollArea:GetVerticalScrollRange()
self:SetVerticalScroll((newGripPosition / trackScrollAreaSize) * scrollFrame:GetVerticalScrollRange())
end)
end)
grip:SetScript("OnMouseUp", function(this,button)
this:SetScript("OnUpdate", function(this) end)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,267 @@
-- $Id: ScrollingMessageFrame.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub('DiesalGUI-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber = type, select, pairs, tonumber
local setmetatable, getmetatable, next = setmetatable, getmetatable, next
local sub, format, lower, upper = string.sub, string.format, string.lower, string.upper
local floor, ceil, min, max, abs, modf = math.floor, math.ceil, math.min, math.max, math.abs, math.modf
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local GetCursorPosition = GetCursorPosition
-- ~~| ScrollingMessageFrame |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'ScrollingMessageFrame'
local Version = 1
-- ~~| ScrollingMessageFrame Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['track-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '0e0e0e',
},
['track-outline'] = {
type = 'outline',
layer = 'BORDER',
color = '060606',
},
['grip-background'] = {
type = 'texture',
layer = 'BACKGROUND',
gradient = 'HORIZONTAL',
color = '5d5d5d',
colorEnd = '252525',
},
['grip-outline'] = {
type = 'outline',
layer = 'BORDER',
color = '060606',
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['scrollFrameContainer-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'fffc00',
},
['scrollFrame-orange'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffd400',
},
['scrollingMessageFrame-red'] = {
type = 'outline',
layer = 'BORDER',
color = 'ff0000',
aplha = .5,
},
['scrollBar-blue'] = {
type = 'outline',
layer = 'OVERLAY',
color = '00aaff',
},
['track-green'] = {
type = 'outline',
layer = 'OVERLAY',
color = '55ff00',
},
}
-- ~~| ScrollingMessageFrame Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| ScrollingMessageFrame Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
self:SetStylesheet(wireFrame)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
local settings = self.settings
local scrollFrame = self.scrollFrame
scrollFrame:SetPoint('TOPLEFT',settings.contentPadLeft,-settings.contentPadTop)
scrollFrame:SetPoint('BOTTOMRIGHT',-settings.contentPadRight,settings.contentPadBottom)
self.scrollBar:SetWidth(settings.scrollBarWidth)
self.buttonDown:SetHeight(settings.scrollBarButtonHeight)
self.buttonUp:SetHeight(settings.scrollBarButtonHeight)
end,
['ShowScrollBar'] = function(self,show)
if show then
self.scrollFrameContainer:SetPoint('BOTTOMRIGHT',-(self.settings.scrollBarWidth + 1),0)
self.scrollBar:Show()
else
self.scrollBar:Hide()
self.scrollFrameContainer:SetPoint('BOTTOMRIGHT',0,0)
end
end,
['SetContentHeight'] = function(self,height)
self.settings.contentHeight = height
self.content:SetHeight(height)
end,
['SetGripSize'] = function(self)
local contentSize = self.scrollFrame:GetVerticalScrollRange() + self.scrollFrame:GetHeight()
local windowSize = self.scrollFrame:GetHeight()
local trackSize = self.track:GetHeight()
local windowContentRatio = windowSize / contentSize
local gripSize = DiesalTools.Round(trackSize * windowContentRatio)
gripSize = max(gripSize, 10) -- might give this a setting?
gripSize = min(gripSize, trackSize)
self.grip:SetHeight(gripSize)
end,
['SetScrollThumbPosition'] = function(self)
local verticalScrollRange = self.scrollFrame:GetVerticalScrollRange() -- windowScrollAreaSize (rounded no need to round)
if verticalScrollRange < 1 then self.grip:SetPoint('TOP',0,0) return end
local verticalScroll = self.scrollFrame:GetVerticalScroll() -- windowPosition
local trackSize = self.track:GetHeight()
local gripSize = self.grip:GetHeight()
local windowPositionRatio = verticalScroll / verticalScrollRange
local trackScrollAreaSize = trackSize - gripSize
local gripPositionOnTrack = DiesalTools.Round(trackScrollAreaSize * windowPositionRatio)
self.grip:SetPoint('TOP',0,-gripPositionOnTrack)
end,
['SetVerticalScroll'] = function(self,scroll) -- user scrolled only
self.settings.forceScrollBottom = DiesalTools.Round(scroll) == DiesalTools.Round(self.scrollFrame:GetVerticalScrollRange())
self.scrollFrame:SetVerticalScroll(scroll)
end,
['AddMessage'] = function(self,msg)
if not msg then return end
self.scrollingMessageFrame:AddMessage(msg)
ChatFrame1:AddMessage(self.scrollingMessageFrame:GetNumRegions() )
end,
['SetText'] = function(self,txt)
-- self.editBox:SetText(txt or '')
end,
}
-- ~~| ScrollingMessageFrame Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
scrollBarButtonHeight = 1,
scrollBarWidth = 6,
contentPadLeft = 0,
contentPadRight = 0,
contentPadTop = 0,
contentPadBottom = 0,
forceScrollBottom = true,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnHide
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnHide",function(this) self:FireEvent("OnHide") end)
local scrollFrameContainer = self:CreateRegion("Frame", 'scrollFrameContainer', frame)
scrollFrameContainer:SetAllPoints()
local scrollFrame = self:CreateRegion("ScrollFrame", 'scrollFrame', scrollFrameContainer)
scrollFrame:EnableMouseWheel(true)
scrollFrame:SetScript("OnMouseWheel", function(this,delta)
DiesalGUI:OnMouse(this,'MouseWheel')
if delta > 0 then
self:SetVerticalScroll(max( this:GetVerticalScroll() - 50, 0))
else
self:SetVerticalScroll(min( this:GetVerticalScroll() + 50, this:GetVerticalScrollRange()))
end
end)
scrollFrame:SetScript("OnVerticalScroll", function(this,offset)
-- self.scrollFrame:GetVerticalScrollRange() windowScrollAreaSize
if this:GetVerticalScrollRange() < 1 then -- nothing to scroll
self:ShowScrollBar(false)
else
self:ShowScrollBar(true)
end
self:SetScrollThumbPosition()
end)
scrollFrame:SetScript("OnScrollRangeChanged", function(this,xOffset, verticalScrollRange)
if verticalScrollRange < 1 then -- nothing to scroll
this:SetVerticalScroll(0)
self:ShowScrollBar(false)
return end
if self.settings.forceScrollBottom then
this:SetVerticalScroll(verticalScrollRange)
else
this:SetVerticalScroll(min(this:GetVerticalScroll(),verticalScrollRange))
end
self:ShowScrollBar(true)
self:SetGripSize()
self:SetScrollThumbPosition()
end)
scrollFrame:SetScript("OnSizeChanged", function(this,width,height)
self.scrollingMessageFrame:SetWidth(width)
end)
local scrollingMessageFrame = self:CreateRegion("ScrollingMessageFrame", 'scrollingMessageFrame', scrollFrame)
scrollingMessageFrame:SetPoint("TOPLEFT")
scrollingMessageFrame:SetPoint("TOPRIGHT")
scrollingMessageFrame:SetJustifyH("LEFT")
scrollingMessageFrame:SetJustifyV("TOP")
scrollingMessageFrame:SetInsertMode("BOTTOM")
scrollingMessageFrame:SetMaxLines(500)
scrollingMessageFrame:SetHeight(500)
scrollingMessageFrame:SetFading(false)
scrollFrame:SetScrollChild(scrollingMessageFrame)
local scrollBar = self:CreateRegion("Frame", 'scrollBar', frame)
scrollBar:SetPoint('TOPRIGHT')
scrollBar:SetPoint('BOTTOMRIGHT')
scrollBar:Hide()
local buttonUp = self:CreateRegion("Frame", 'buttonUp', scrollBar)
buttonUp:SetPoint('TOPLEFT')
buttonUp:SetPoint('TOPRIGHT')
local buttonDown = self:CreateRegion("Frame", 'buttonDown', scrollBar)
buttonDown:SetPoint('BOTTOMLEFT')
buttonDown:SetPoint('BOTTOMRIGHT')
local track = self:CreateRegion("Frame", 'track', scrollBar)
track:SetPoint('LEFT')
track:SetPoint('RIGHT')
track:SetPoint('TOP',buttonUp,'BOTTOM',0,0)
track:SetPoint('BOTTOM',buttonDown,'TOP',0,0)
local grip = self:CreateRegion("Frame", 'grip', track)
grip:SetPoint('LEFT')
grip:SetPoint('RIGHT')
grip:SetPoint('TOP')
grip:EnableMouse(true)
grip:SetScript("OnMouseDown", function(this,button)
DiesalGUI:OnMouse(this,button)
if button ~= 'LeftButton' then return end
local MouseY = select(2, GetCursorPosition()) / this:GetEffectiveScale()
local effectiveScale = this:GetEffectiveScale()
local trackScrollAreaSize = track:GetHeight() - this:GetHeight()
local gripPositionOnTrack = abs(select(5,this:GetPoint(1)))
this:SetScript("OnUpdate", function(this)
local newGripPosition = gripPositionOnTrack + (MouseY - (select(2, GetCursorPosition()) / effectiveScale ))
newGripPosition = min(max(newGripPosition,0),trackScrollAreaSize)
-- local newGripPositionRatio = newGripPosition / trackScrollAreaSize
-- local windowPosition = newGripPositionRatio * scrollArea:GetVerticalScrollRange()
self:SetVerticalScroll((newGripPosition / trackScrollAreaSize) * scrollFrame:GetVerticalScrollRange())
end)
end)
grip:SetScript("OnMouseUp", function(this,button)
this:SetScript("OnUpdate", function(this) end)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,294 @@
-- $Id: Spinner.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- | Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.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 = "Spinner"
local Version = 3
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
alpha = .6,
},
['frame-inline'] = {
type = 'outline',
layer = 'BORDER',
color = '000000',
alpha = .6,
},
['frame-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .02,
position = 1,
},
['frame-hover'] = {
type = 'outline',
layer = 'HIGHLIGHT',
color = 'FFFFFF',
alpha = .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,.1)},
},
['bar-inline'] = {
type = 'outline',
layer = 'BORDER',
gradient = {'VERTICAL','FFFFFF','FFFFFF'},
alpha = {.07,.02},
},
['bar-outline'] = {
type = 'texture',
layer = 'ARTWORK',
color = '000000',
alpha = .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 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrame)
self:ApplySettings()
self:Show()
end,
['OnRelease'] = function(self) end,
['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,
['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,
['GetNumber'] = function(self)
return self.settings.number
end,
['SetNumber'] = function(self,number)
local newNumber = processNumber(self, number)
if newNumber then self:FireEvent("OnValueChanged",false,newNumber) end
end,
['SetPrefix'] = function(self,prefix)
self.settings.prefix = prefix
processNumber(self, self.settings.number)
end,
['SetSuffix'] = function(self,suffix)
self.settings.suffix = suffix
processNumber(self, self.settings.number)
end,
['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,
['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
end,
['SetTextColor'] = function(self,color,alpha)
alpha = alpha or 1
color = {DiesalTools.GetColor(color)}
self.editBox:SetTextColor(color[1],color[2],color[3],alpha)
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,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)
editBox:SetPoint("TOPLEFT")
editBox:SetAutoFocus(false)
editBox:SetJustifyH("CENTER")
editBox:SetJustifyV("CENTER")
editBox:SetTextInsets(1,0,2,0)
editBox:SetText(self.defaults.min)
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)
DiesalGUI:OnMouse(this,button)
PlaySound("gsTitleOptionExit")
self:OnSpin(1)
end)
local buttonDown = self:CreateRegion("Button", 'buttonDown', frame)
buttonDown:SetPoint('BOTTOM',0,0)
buttonDown:SetPoint('RIGHT')
buttonDown:SetScript("OnClick", function(this)
DiesalGUI:OnMouse(this,button)
PlaySound("gsTitleOptionExit")
self:OnSpin(-1)
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,174 @@
-- $Id: Toggle.lua 60 2018-09-22 08:28:01Z DarkRotations $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- ~~| 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 |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent, GetCursorPosition = CreateFrame, UIParent, GetCursorPosition
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
local GetSpellInfo, GetBonusBarOffset, GetDodgeChance = GetSpellInfo, GetBonusBarOffset, GetDodgeChance
local GetPrimaryTalentTree, GetCombatRatingBonus = GetPrimaryTalentTree, GetCombatRatingBonus
-- ~~| Button |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local TYPE = "Toggle"
local VERSION = 1
-- ~~| Button Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '333333',
alpha = .95,
position = -2
},
['frame-inline'] = {
type = 'outline',
layer = 'BORDER',
color = '000000',
alpha = .6,
position = -2
},
['frame-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .1,
position = -1,
},
}
local checkBoxStyle = {
base = {
type = 'texture',
layer = 'ARTWORK',
color = '00FF00',
position = -3,
},
disabled = {
type = 'texture',
color = '00FFFF',
},
enabled = {
type = 'texture',
color = Colors.UI_A400,
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
}
-- ~~| Button Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
self:Enable()
-- self:SetStylesheet(wireFrameSheet)
self.fontString:SetFontObject("DiesalFontNormal")
self.fontString:SetText()
self:Show()
end,
['OnRelease'] = function(self) end,
['ApplySettings'] = function(self)
local settings = self.settings
local frame = self.frame
self:SetWidth(settings.width)
self:SetHeight(settings.height)
end,
["SetChecked"] = function(self,value)
self.settings.checked = value
self.frame:SetChecked(value)
self[self.settings.disabled and "Disable" or "Enable"](self)
end,
["GetChecked"] = function(self)
return self.settings.checked
end,
["Disable"] = function(self)
self.settings.disabled = true
DiesalStyle:StyleTexture(self.check,self.checkBoxStyle and self.checkBoxStyle.disabled or checkBoxStyle.disabled)
self.frame:Disable()
end,
["Enable"] = function(self)
self.settings.disabled = false
DiesalStyle:StyleTexture(self.check,self.checkBoxStyle and self.checkBoxStyle.enabled or checkBoxStyle.enabled)
self.frame:Enable()
end,
["RegisterForClicks"] = function(self,...)
self.frame:RegisterForClicks(...)
end,
["SetText"] = function(self, text)
self.fontString:SetText(text)
end,
}
-- ~~| Button Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(TYPE)
local frame = CreateFrame('CheckButton', nil, UIParent)
local fontString = frame:CreateFontString()
self.frame = frame
self.fontString = fontString
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
height = 11,
width = 11,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnValueChanged, OnEnter, OnLeave, OnDisable, OnEnable
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local check = self:CreateRegion("Texture", 'check', frame)
self.check = check
DiesalStyle:StyleTexture(check,self.checkBoxStyle and self.checkBoxStyle.base or checkBoxStyle.base)
frame:SetCheckedTexture(check)
frame:SetScript('OnClick', function(this,button,...)
DiesalGUI:OnMouse(this,button)
if not self.settings.disabled then
self:SetChecked(not self.settings.checked)
if self.settings.checked then
----PlaySound("igMainMenuOptionCheckBoxOn")
else
----PlaySound("igMainMenuOptionCheckBoxOff")
end
self:FireEvent("OnValueChanged", self.settings.checked)
end
end)
frame:SetScript('OnEnter', function(this)
self:FireEvent("OnEnter")
end)
frame:SetScript('OnLeave', function(this)
self:FireEvent("OnLeave")
end)
frame:SetScript("OnDisable", function(this)
self:FireEvent("OnDisable")
end)
frame:SetScript("OnEnable", function(this)
self:FireEvent("OnEnable")
end)
fontString:SetPoint("TOPLEFT", check, "TOPRIGHT", 5, 2)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(TYPE,Constructor,VERSION)

@ -0,0 +1,93 @@
-- $Id: Tree.lua 60 2016-11-04 01:34:23Z diesal2010 $
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalGUI = LibStub("DiesalGUI-1.0")
local DiesalTools = LibStub("DiesalTools-1.0")
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local sub, format, match, lower = string.sub, string.format, string.match, string.lower
local tsort = table.sort
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| Tree |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "Tree"
local Version = 4
-- ~~| Tree Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['content-background'] = {
type = 'texture',
color = 'ffffff',
alpha = .01,
},
}
-- ~~| Tree Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function collapse(branch)
if branch.Collapse then branch:Collapse() end
if branch.children and next(branch.children) then
for i=1, #branch.children do
collapse(branch.children[i])
end
end
end
-- ~~| Tree Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
-- self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrameSheet)
self:ApplySettings()
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
end,
['UpdateHeight'] = function(self)
local height = 0
for i=1 , #self.children do
height = height + self.children[i].frame:GetHeight()
end
height = DiesalTools.Round(height)
if self.settings.height ~= height then
self.settings.height = height
self:SetHeight(height)
self:FireEvent("OnHeightChange",height)
end
end,
['CollapseAll'] = function(self, subBranches)
if subBranches then
collapse(self)
else
for i=1, #self.children do
self.children[i]:Collapse()
end
end
end,
['ExpandAll'] = function(self)
for i=1 , #self.children do
self.children[i]:Expand()
end
end,
}
-- ~~| Tree Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = { depth = 0 }
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnHeightChange
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local content = self:CreateRegion("Frame", 'content', frame)
content:SetAllPoints()
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,387 @@
-- $Id: Window.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- | Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
local Colors = DiesalStyle.Colors
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber = type, select, pairs, tonumber
local floor, ceil = math.floor, math.ceil
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Window |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = "Window"
local Version = 14
-- ~~| Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-outline'] = {
type = 'outline',
layer = 'BACKGROUND',
color = '000000',
},
['frame-shadow'] = {
type = 'shadow',
},
['titleBar-color'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_400_GR[2],
alpha = .95,
},
-- ['titleBar-background'] = {
-- type = 'texture',
-- layer = 'BACKGROUND',
-- gradient = {'VERTICAL',Colors.UI_400_GR[1],Colors.UI_400_GR[2]},
-- alpha = .95,
-- position = {-1,-1,-1,0},
-- },
['titletext-Font'] = {
type = 'font',
color = 'd8d8d8',
},
['closeButton-icon'] = {
type = 'texture',
layer = 'ARTWORK',
image = {'DiesalGUIcons', {9,5,16,256,128}},
alpha = .3,
position = {-2,nil,-1,nil},
width = 16,
height = 16,
},
['closeButton-iconHover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
image = {'DiesalGUIcons', {9,5,16,256,128}, 'b30000'},
alpha = 1,
position = {-2,nil,-1,nil},
width = 16,
height = 16,
},
['header-background'] = {
type = 'texture',
layer = 'BACKGROUND',
gradient = {'VERTICAL',Colors.UI_400_GR[1],Colors.UI_400_GR[2]},
alpha = .95,
position = {0,0,0,-1},
},
['header-inline'] = {
type = 'outline',
layer = 'BORDER',
gradient = {'VERTICAL','ffffff','ffffff'},
alpha = {.05,.02},
position = {0,0,0,-1},
},
['header-divider'] = {
type = 'texture',
layer = 'BORDER',
color = '000000',
alpha = 1,
position = {0,0,nil,0},
height = 1,
},
['content-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_100,
alpha = .95,
},
['content-outline'] = {
type = 'outline',
layer = 'BORDER',
color = 'FFFFFF',
alpha = .01
},
['footer-background'] = {
type = 'texture',
layer = 'BACKGROUND',
gradient = {'VERTICAL',Colors.UI_400_GR[1],Colors.UI_400_GR[2]},
alpha = .95,
position = {0,0,-1,0},
},
['footer-divider'] = {
type = 'texture',
layer = 'BACKGROUND',
color = '000000',
position = {0,0,0,nil},
height = 1,
},
['footer-inline'] = {
type = 'outline',
layer = 'BORDER',
gradient = {'VERTICAL','ffffff','ffffff'},
alpha = {.05,.02},
position = {0,0,-1,0},
debug = true,
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['titleBar-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'fffc00',
},
['closeButton-orange'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffd400',
},
['header-blue'] = {
type = 'outline',
layer = 'OVERLAY',
color = '00aaff',
},
['footer-green'] = {
type = 'outline',
layer = 'OVERLAY',
color = '55ff00',
},
}
local sizerWireFrame = {
['sizerR-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'fffc00',
},
['sizerB-green'] = {
type = 'outline',
layer = 'OVERLAY',
color = '55ff00',
},
['sizerBR-blue'] = {
type = 'outline',
layer = 'OVERLAY',
color = '00aaff',
},
}
-- | Window Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function round(num)
if num >= 0 then return floor(num+.5)
else return ceil(num-.5) end
end
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(sizerWireFrame)
self:Show()
end,
['OnRelease'] = function(self) end,
['SetTopLevel'] = function(self)
DiesalGUI:SetTopLevel(self.frame)
end,
['SetContentHeight'] = function(self, height)
local contentHeight = round(self.content:GetHeight())
self.frame:SetHeight( (self.settings.height - contentHeight) + height )
end,
['ApplySettings'] = function(self)
local settings = self.settings
local frame = self.frame
local titleBar = self.titleBar
local closeButton = self.closeButton
local header = self.header
local content = self.content
local footer = self.footer
local headerHeight = settings.header and settings.headerHeight or 0
local footerHeight = settings.footer and settings.footerHeight or 0
frame:SetMinResize(settings.minWidth,settings.minHeight)
frame:SetMaxResize(settings.maxWidth,settings.maxHeight)
self:UpdatePosition()
self:UpdateSizers()
titleBar:SetHeight(settings.titleBarHeight)
closeButton:SetHeight(settings.titleBarHeight)
closeButton:SetWidth(settings.titleBarHeight)
content:SetPoint("TOPLEFT",settings.padding[1],-(settings.titleBarHeight + headerHeight))
content:SetPoint("BOTTOMRIGHT",-settings.padding[2],footerHeight + settings.padding[4])
header:SetHeight(headerHeight)
footer:SetHeight(footerHeight)
header[settings.header and "Show" or "Hide"](header)
footer[settings.footer and "Show" or "Hide"](footer)
header:SetPoint("TOPLEFT",self.titleBar,"BOTTOMLEFT",settings.padding[1],0)
header:SetPoint("TOPRIGHT",self.titleBar,"BOTTOMRIGHT",-settings.padding[2],0)
footer:SetPoint("BOTTOMLEFT",settings.padding[1],settings.padding[4])
footer:SetPoint("BOTTOMRIGHT",-settings.padding[2],settings.padding[4])
end,
['UpdatePosition'] = function(self)
self.frame:ClearAllPoints()
if self.settings.top and self.settings.left then
self.frame:SetPoint("TOP",UIParent,"BOTTOM",0,self.settings.top)
self.frame:SetPoint("LEFT",UIParent,"LEFT",self.settings.left,0)
else
self.frame:SetPoint("CENTER",UIParent,"CENTER")
end
self.frame:SetWidth(self.settings.width)
self.frame:SetHeight(self.settings.height)
end,
['UpdateSizers'] = function(self)
local settings = self.settings
local frame = self.frame
local sizerB = self.sizerB
local sizerR = self.sizerR
local sizerBR = self.sizerBR
sizerBR[settings.sizerBR and "Show" or "Hide"](sizerBR)
sizerBR:SetSize(settings.sizerBRWidth,settings.sizerBRHeight)
sizerB[settings.sizerB and "Show" or "Hide"](sizerB)
sizerB:SetHeight(settings.sizerHeight)
sizerB:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-settings.sizerBRWidth,0)
sizerR[settings.sizerR and "Show" or "Hide"](sizerR)
sizerR:SetWidth(settings.sizerWidth)
sizerR:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,-settings.titleBarHeight)
sizerR:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,settings.sizerBRHeight)
end,
['SetTitle'] = function(self,title,subtitle)
local settings = self.settings
settings.title = title or settings.title
settings.subTitle = subtitle or settings.subTitle
self.titletext:SetText(('%s |cff7f7f7f%s'):format(settings.title,settings.subTitle))
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
self.defaults = {
height = 300,
width = 500,
minHeight = 200,
minWidth = 200,
maxHeight = 9999,
maxWidth = 9999,
left = nil,
top = nil,
titleBarHeight= 18,
title = '',
subTitle = '',
padding = {1,1,0,1},
header = false,
headerHeight = 21,
footer = false,
footerHeight = 21,
sizerR = true,
sizerB = true,
sizerBR = true,
sizerWidth = 6,
sizerHeight = 6,
sizerBRHeight = 6,
sizerBRWidth = 6,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- OnSizeChanged, OnDragStop, OnHide, OnShow, OnClose
-- ~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:EnableMouse()
frame:SetMovable(true)
frame:SetResizable(true)
frame:SetScript("OnMouseDown", function(this,button)
DiesalGUI:OnMouse(this,button)
end)
frame:SetScript("OnSizeChanged", function(this,width,height)
self.settings.width = DiesalTools.Round(width)
self.settings.height = DiesalTools.Round(height)
self:FireEvent( "OnSizeChanged", self.settings.width, self.settings.height )
end)
frame:SetScript("OnHide",function(this)
self:FireEvent("OnHide")
end)
frame:SetScript("OnShow",function(this)
self:FireEvent("OnShow")
end)
frame:SetToplevel(true)
frame.obj = self
local titleBar = self:CreateRegion("Button", 'titleBar', frame)
titleBar:SetPoint("TOPLEFT")
titleBar:SetPoint("TOPRIGHT")
titleBar:EnableMouse()
titleBar:SetScript("OnMouseDown",function(this,button)
DiesalGUI:OnMouse(this,button)
frame:StartMoving()
end)
titleBar:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self.settings.top = DiesalTools.Round(frame:GetTop())
self.settings.left = DiesalTools.Round(frame:GetLeft())
self:UpdatePosition()
self:FireEvent( "OnDragStop", self.settings.left, self.settings.top )
end)
local closeButton = self:CreateRegion("Button", 'closeButton', titleBar)
closeButton:SetPoint("TOPRIGHT", -1, 1)
closeButton:SetScript("OnClick", function(this,button)
DiesalGUI:OnMouse(this,button)
--PlaySound("gsTitleOptionExit")
self:FireEvent("OnClose")
self:Hide()
end)
local titletext = self:CreateRegion("FontString", 'titletext', titleBar)
titletext:SetWordWrap(false)
titletext:SetPoint("TOPLEFT", 4, -5)
titletext:SetPoint("TOPRIGHT", -20, -5)
titletext:SetJustifyH("TOP")
titletext:SetJustifyH("LEFT")
self:CreateRegion("Frame", 'header', frame)
self:CreateRegion("Frame", 'content', frame)
self:CreateRegion("Frame", 'footer', frame)
local sizerBR = self:CreateRegion("Frame", 'sizerBR', frame)
sizerBR:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
sizerBR:EnableMouse()
sizerBR:SetScript("OnMouseDown",function(this,button)
DiesalGUI:OnMouse(this,button)
frame:StartSizing("BOTTOMRIGHT")
end)
sizerBR:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self:UpdatePosition()
self:FireEvent( "OnSizeStop", self.settings.width, self.settings.height )
end)
local sizerB = self:CreateRegion("Frame", 'sizerB', frame)
sizerB:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
sizerB:EnableMouse()
sizerB:SetScript("OnMouseDown",function(this,button)
DiesalGUI:OnMouse(this,button)
frame:StartSizing("BOTTOM")
end)
sizerB:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self:UpdatePosition()
self:FireEvent( "OnSizeStop", self.settings.width, self.settings.height )
end)
local sizerR = self:CreateRegion("Frame", 'sizerR', frame)
sizerR:EnableMouse()
sizerR:SetScript("OnMouseDown",function(this,button)
DiesalGUI:OnMouse(this,button)
frame:StartSizing("RIGHT")
end)
sizerR:SetScript("OnMouseUp", function(this)
frame:StopMovingOrSizing()
self:UpdatePosition()
self:FireEvent( "OnSizeStop", self.settings.width, self.settings.height )
end)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,69 @@
-- $Id: DiesalMenu-1.0.lua 53 2016-07-12 21:56:30Z diesal2010 $
local MAJOR, MINOR = "DiesalMenu-1.0", "$Rev: 53 $"
local DiesalMenu, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not DiesalMenu then return end -- No Upgrade needed.
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub("DiesalTools-1.0")
local DiesalStyle = LibStub("DiesalStyle-1.0")
local DiesalGUI = LibStub("DiesalGUI-1.0")
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, tonumber = type, select, tonumber
local setmetatable, getmetatable, next = setmetatable, getmetatable, next
local sub, format, lower, upper, match = string.sub, string.format, string.lower, string.upper, string.match
local pairs, ipairs = pairs,ipairs
local tinsert, tremove, tconcat, tsort = table.insert, table.remove, table.concat, table.sort
local floor, ceil, abs, modf = math.floor, math.ceil, math.abs, math.modf
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent = CreateFrame, UIParent
-- ~~| DiesalMenu Values |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| DiesalMenu Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| DiesalStyle Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local MENU
local CLOSEDELAY = 2
local closeTimer = CreateFrame('Frame')
closeTimer:Hide()
closeTimer:SetScript('OnUpdate', function(this,elapsed)
if this.count < 0 then
DiesalMenu:Close()
this:Hide()
else
this.count = this.count - elapsed
end
end)
-- ~~| DiesalMenu Local Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| DiesalMenu API |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DiesalMenu:Menu(menuData,anchor,x,y,closeDelay)
MENU = MENU or DiesalGUI:Create('Menu')
MENU:ResetSettings()
if not MENU:BuildMenu(menuData) then MENU:Hide() return end
MENU:Show()
MENU:ClearAllPoints()
MENU:SetPoint('TOPLEFT',anchor,'TOPLEFT',x,y)
closeTimer.closeDelay = closeDelay or CLOSEDELAY
DiesalMenu:StartCloseTimer()
DiesalMenu:SetFocus()
end
function DiesalMenu:Close()
DiesalMenu:StopCloseTimer()
if not MENU or not MENU:IsVisible() then return end
MENU:ResetSettings()
MENU:ReleaseChildren()
MENU:Hide()
MENU:ClearAllPoints()
end
function DiesalMenu:StartCloseTimer()
closeTimer.count = closeTimer.closeDelay
closeTimer:Show()
end
function DiesalMenu:StopCloseTimer()
closeTimer:Hide()
end
function DiesalMenu:ClearFocus()
DiesalMenu:Close()
end
function DiesalMenu:SetFocus()
DiesalGUI:SetFocus(DiesalMenu)
end

@ -0,0 +1,6 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
<Script file="DiesalMenu-1.0.lua"/>
<!-- Objects -->
<Script file="Objects\Menu.lua"/>
<Script file="Objects\MenuItem.lua"/>
</Ui>

@ -0,0 +1,132 @@
-- $Id: Menu.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalMenu = LibStub('DiesalMenu-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalGUI = LibStub('DiesalGUI-1.0')
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local ipairs, pairs, table_sort = ipairs, pairs, table.sort
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Menu |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'Menu'
local Version = 2
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-background'] = {
type = 'texture',
layer = 'BACKGROUND',
color = Colors.UI_100,
alpha = .95,
},
['frame-inline'] = {
type = 'outline',
layer = 'BORDER',
color = 'ffffff',
alpha = .02,
position = -1,
},
['frame-shadow'] = {
type = 'shadow',
},
}
local wireFrame = {
['frame-white'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'ffffff',
},
['content-yellow'] = {
type = 'outline',
layer = 'OVERLAY',
color = 'fffc00',
},
}
-- | Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function compare(a,b)
return a[1] < b[1]
end
local function sortTable(t)
local st = {}
for key, val in pairs(t) do
st[#st + 1] = {val.order, key}
end
table_sort(st,compare)
return st
end
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrame)
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
self:UpdatePosition()
end,
['UpdatePosition'] = function(self)
self.content:SetPoint("TOPLEFT",self.settings.padding[1],-self.settings.padding[3])
self.content:SetPoint("BOTTOMRIGHT",-self.settings.padding[2],self.settings.padding[4])
end,
['UpdateSize'] = function(self)
local menuHeight = 0
for i=1, #self.children do
menuHeight = menuHeight + self.children[i].frame:GetHeight()
end
self.frame:SetHeight(self.settings.padding[3] + menuHeight + self.settings.padding[4])
self.frame:SetWidth(self.settings.padding[1] + self.settings.itemWidth + self.settings.padding[2])
end,
['BuildMenu'] = function(self, menuData)
if menuData then self.settings.menuData = menuData else menuData = self.settings.menuData end
if not menuData then return end
-- reset menu
self:ReleaseChildren()
self:SetWidth(1)
-- set menu properties
for key in pairs(menuData) do
if menuData[key].check then self.settings.check = true end
if menuData[key].menuData then self.settings.arrow = true end
end
-- create menuItems
local sortedTable = sortTable(menuData)
for i = 1, #sortedTable do
local menuItem = DiesalGUI:Create('MenuItem')
self:AddChild(menuItem)
menuItem:SetParentObject(self)
menuItem:SetSettings({
itemData = menuData[sortedTable[i][2]],
position = i,
},true)
end
self:UpdateSize()
return true
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Frame',nil,UIParent)
self.frame = frame
self.defaults = {
itemWidth = 0,
padding = {4,4,8,8},
}
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetClampedToScreen( true )
frame:SetScript('OnEnter', function(this) DiesalMenu:StopCloseTimer() end)
frame:SetScript('OnLeave', function(this) DiesalMenu:StartCloseTimer() end)
self:CreateRegion("Frame", 'content', frame)
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

@ -0,0 +1,157 @@
-- $Id: MenuItem.lua 60 2016-11-04 01:34:23Z diesal2010 $
local DiesalMenu = LibStub('DiesalMenu-1.0')
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local DiesalTools = LibStub('DiesalTools-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
local DiesalGUI = LibStub('DiesalGUI-1.0')
local DiesalStyle = LibStub("DiesalStyle-1.0")
-- ~~| Diesal Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Colors = DiesalStyle.Colors
local HSL, ShadeColor, TintColor = DiesalTools.HSL, DiesalTools.ShadeColor, DiesalTools.TintColor
-- | Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | MenuItem |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Type = 'MenuItem'
local Version = 2
-- | Stylesheets |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local Stylesheet = {
['frame-hover'] = {
type = 'texture',
layer = 'HIGHLIGHT',
color = Colors.UI_1000,
alpha = .1,
},
['text-color'] = {
type = 'Font',
color = 'cbcbcb',
},
}
-- | Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- | Methods |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local methods = {
['OnAcquire'] = function(self)
self:ApplySettings()
self:SetStylesheet(Stylesheet)
-- self:SetStylesheet(wireFrame)
self:Show()
end,
['OnRelease'] = function(self)
end,
['ApplySettings'] = function(self)
if not self.settings.itemData then return false end
local settings = self.settings
local menuSettings= settings.parentObject.settings
local itemData = settings.itemData
local text = self.text
local check = self.check
local arrow = self.arrow
local checkWidth = menuSettings.check and settings.checkWidth or settings.textPadLeft
local arrowWidth = menuSettings.arrow and settings.arrowWidth or settings.textPadRight
local textWidthMax = settings.widthMax - arrowWidth - checkWidth
if settings.position == 1 then
self:SetPoint('TOPLEFT')
self:SetPoint('RIGHT')
else
self:SetPoint('TOPLEFT',settings.parentObject.children[settings.position-1].frame,'BOTTOMLEFT',0,0)
self:SetPoint('RIGHT')
end
if itemData.type == 'spacer' then
self.frame:EnableMouse(false)
self:SetHeight(settings.spacerHeight)
else
self.frame:EnableMouse(true)
self:SetHeight(settings.height)
end
self:SetText(itemData.name)
text:SetPoint("LEFT",checkWidth, 0)
text:SetPoint("RIGHT",-arrowWidth, 0)
arrow[menuSettings.arrow and itemData.menuData and "Show" or "Hide"](arrow)
check[menuSettings.check and itemData.check and itemData.check() and "Show" or "Hide"](check)
local textWidth = DiesalTools.Round(text:GetStringWidth()) + 10
local itemWidth = checkWidth + textWidth + arrowWidth
menuSettings.itemWidth = min(max(menuSettings.itemWidth,itemWidth),settings.widthMax)
end,
['SetText'] = function(self,text)
self.text:SetText(text or '')
end,
['OnClick'] = function(self)
local onClick = self.settings.itemData.onClick
if onClick then onClick() end
end,
['OnEnter'] = function(self)
DiesalMenu:StopCloseTimer()
local menuChildren = self.settings.parentObject.children
local menuData = self.settings.itemData.menuData
for i=1, #menuChildren do menuChildren[i]:ReleaseChildren() end
self:BuildSubMenu(menuData)
end,
['BuildSubMenu'] = function(self,menuData)
if not menuData then return end
local subMenu = DiesalGUI:Create('Menu')
if not subMenu:BuildMenu(menuData) then DiesalGUI:Release(subMenu) return end
self:AddChild(subMenu)
subMenu:SetParent(self.frame)
subMenu:ClearAllPoints()
subMenu:SetPoint('TOPLEFT',self.frame,'TOPRIGHT',0,0)
subMenu:Show()
end,
}
-- | Constructor |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local function Constructor()
local self = DiesalGUI:CreateObjectBase(Type)
local frame = CreateFrame('Button',nil,UIParent)
self.frame = frame
-- ~~ Default Settings ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
self.defaults = {
widthMax = 250,
height = 16,
spacerHeight = 5,
checkWidth = 14,
arrowWidth = 14,
textPadLeft = 2,
textPadRight = 2,
}
-- ~~ Events ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- OnAcquire, OnRelease, OnHeightSet, OnWidthSet
-- ~~ Construct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
frame:SetScript("OnClick", function(this,button) DiesalGUI:OnMouse(this,button); self:OnClick() end)
frame:SetScript('OnEnter', function(this) self:OnEnter() end)
frame:SetScript('OnLeave', function(this) DiesalMenu:StartCloseTimer() end)
local text = self:CreateRegion("FontString", 'text', frame)
text:SetPoint("TOP",0,-2)
text:SetPoint("BOTTOM",0,0)
text:SetJustifyH("TOP")
text:SetJustifyH("LEFT")
text:SetWordWrap(false)
local check = self:CreateRegion("Texture", 'check', frame)
DiesalStyle:StyleTexture(check,{
position = {1,nil,0,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons', {10,5,16,256,128},'FFFF00'},
})
local arrow = self:CreateRegion("Texture", 'arrow', frame)
DiesalStyle:StyleTexture(arrow,{
position = {nil,2,-1,nil},
height = 16,
width = 16,
image = {'DiesalGUIcons', {7,5,16,256,128},'FFFF00'},
})
-- ~~ Methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
for method, func in pairs(methods) do self[method] = func end
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
return self
end
DiesalGUI:RegisterObjectConstructor(Type,Constructor,Version)

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

@ -0,0 +1,515 @@
-- $Id: DiesalTools-1.0.lua 61 2017-03-28 23:13:41Z diesal2010 $
local MAJOR, MINOR = "DiesalTools-1.0", "$Rev: 61 $"
local DiesalTools, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
if not DiesalTools then return end -- No Upgrade needed.
-- ~~| Libraries |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- ~~| Lua Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local type, select, pairs, tonumber, tostring = type, select, pairs, tonumber, tostring
local table_concat = table.concat
local setmetatable, getmetatable, next = setmetatable, getmetatable, next
local sub, format, lower, upper,gsub = string.sub, string.format, string.lower, string.upper, string.gsub
local floor, ceil, abs, modf = math.floor, math.ceil, math.abs, math.modf
-- ~~| WoW Upvalues |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local CreateFrame, UIParent, GetCursorPosition = CreateFrame, UIParent, GetCursorPosition
local GetScreenWidth, GetScreenHeight = GetScreenWidth, GetScreenHeight
-- ~~| Locals |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
local escapeSequences = {
[ "\a" ] = "\\a", -- Bell
[ "\b" ] = "\\b", -- Backspace
[ "\t" ] = "\\t", -- Horizontal tab
[ "\n" ] = "\\n", -- Newline
[ "\v" ] = "\\v", -- Vertical tab
[ "\f" ] = "\\f", -- Form feed
[ "\r" ] = "\\r", -- Carriage return
[ "\\" ] = "\\\\", -- Backslash
[ "\"" ] = "\\\"", -- Quotation mark
[ "|" ] = "||",
}
local lua_keywords = {
["and"] = true, ["break"] = true, ["do"] = true,
["else"] = true, ["elseif"] = true, ["end"] = true,
["false"] = true, ["for"] = true, ["function"] = true,
["if"] = true, ["in"] = true, ["local"] = true,
["nil"] = true, ["not"] = true, ["or"] = true,
["repeat"] = true, ["return"] = true, ["then"] = true,
["true"] = true, ["until"] = true, ["while"] = true
}
local sub_table = {
}
local colors = {
blue = '|cff'..'00aaff',
darkblue = '|cff'..'004466',
orange = '|cff'..'ffaa00',
darkorange = '|cff'..'4c3300',
grey = '|cff'..'7f7f7f',
darkgrey = '|cff'..'414141',
white = '|cff'..'ffffff',
red = '|cff'..'ff0000',
green = '|cff'..'00ff2b',
yellow = '|cff'..'ffff00',
lightyellow = '|cff'..'ffea7f',
}
local formattedArgs = {}
local function GetCaller(level)
-- ADDON:LogMessage(debugstack(10,2, 0))
for trace in debugstack(level,2, 0):gmatch("(.-)\n") do
-- Blizzard Sandbox
local match, _, file, line = trace:find("^.*\\(.-):(%d+)")
if match then return format('%s[%s%s: %s%s%s]|r',colors.orange,colors.yellow,file,colors.lightyellow,line,colors.orange) end
-- PQI DataFile
local match, _, file,line = trace:find('^%[string "[%s%-]*(.-%.lua).-"%]:(%d+)')
if match then return format('%s[%s%s: %s%s%s]|r',colors.orange,colors.yellow,file,colors.lightyellow,line,colors.orange) end
-- PQR Ability code
local match, _, file,line = trace:find('^%[string "(.-)"%]:(%d+)')
if match then return format('%s[%s%s: %s%s%s]|r',colors.orange,colors.yellow,file,colors.lightyellow,line,colors.orange) end
end
return format('%s[%sUnknown Caller%s]|r',colors.orange,colors.red,colors.orange)
end
local function round(number, base)
base = base or 1
return floor((number + base/2)/base) * base
end
local function getRGBColorValues(color,g,b)
if type(color) == 'number' and type(g) == 'number' and type(b) == 'number' then
if color <= 1 and g <= 1 and b <= 1 then
return round(color*255), round(g*255), round(b*255)
end
return color[1], color[2], color[3]
elseif type(color) == 'table' and type(color[1]) == 'number' and type(color[2]) == 'number' and type(color[3]) == 'number' then
if color[1] <= 1 and color[2] <= 1 and color[3] <= 1 then
return round(color[1]*255), round(color[2]*255), round(color[3]*255)
end
return color[1], color[2], color[3]
elseif type(color) == 'string' then
return tonumber(sub(color, 1, 2),16), tonumber(sub(color, 3, 4),16), tonumber(sub(color, 5, 6),16)
end
end
function DiesalTools.GetColor(value)
if not value then return end
if type(value) == 'table' and #value >= 3 then
return value[1]/255, value[2]/255, value[3]/255
elseif type(value) == 'string' then
return tonumber(sub(value,1,2),16)/255, tonumber(sub(value,3,4),16)/255, tonumber(sub(value,5,6),16)/255
end
end
-- ~~| API |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DiesalTools.Stack()
print("|r------------------------------| Stack Trace |-------------------------------")
local stack = debugstack(1,12, 0)
for trace in stack:gmatch("(.-)\n") do
match, _, file, line, func = trace:find("^.*\\(.-):(%d+).-`(.*)'$")
if match then print(format("%s[%s%s: %s%s%s] %sfunction|r %s|r",colors.orange,colors.yellow,file,colors.lightyellow,line,colors.orange,colors.blue,func)) end
end
print("|r--------------------------------------------------------------------------------")
end
--[[ copy = TableCopy(src, dest, metatable)
@Arguments:
dest Table to copy to
src Table to copy
metatable if true copies the metatable as well (boolean)
@Returns:
table copy of table
--]]
function DiesalTools.TableCopy(src,dest,metatable)
if type(src) == 'table' then
if not dest then dest = {} end
for sk, sv in next, src, nil do
dest[DiesalTools.TableCopy(sk)] = DiesalTools.TableCopy(sv)
end
if metatable then setmetatable(dest, DiesalTools.TableCopy(getmetatable(src))) end
else -- number, string, boolean, etc
dest = src
end
return dest
end
--[[ red, blue, green = GetColor(value)
@Arguments:
value Hex color code or a table contating R,G,B color values
@Returns:
red Red component of color (0-1) (number)
green Green component of color(0-1) (number)
blue Blue component of color (0-1) (number)
-- ]]
-- | Color Tools |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- converts a color from RGB[0-1], RGB[0-255], HEX or HSL to RGB[0-1], RGB[0-255] or HEX
function DiesalTools.ConvertColor(from,to,v1,v2,v3)
if not from or not to or not v1 then return end
if type(v1) == 'table' then v1,v2,v3 = v1[1],v1[2],v1[3] end
local r, g, b
from, to = from:lower(), to:lower()
if from == 'rgb255' and type(v1) == 'number' and type(v2) == 'number' and type(v3) == 'number' then
r,g,b = v1, v2, v3
elseif from == 'rgb1' and type(v1) == 'number' and type(v2) == 'number' and type(v3) == 'number' then
r,g,b = round(v1*255), round(v2*255), round(v3*255)
elseif from == 'hex' and type(v1) == 'string' and #v1 > 5 then
r,g,b = tonumber(sub(v1, 1, 2),16), tonumber(sub(v1, 3, 4),16), tonumber(sub(v1, 5, 6),16)
elseif from == 'hsl' and type(v1) == 'number' and type(v2) == 'number' and type(v3) == 'number' then
if v2 == 0 then
v3 = round(v3 * 255)
r,g,b = v3,v3,v3
else
v1, v2, v3 = v1/360*6, min(max(0, v2), 1), min(max(0, v3), 1)
local c = (1-abs(2*v3-1))*v2
local x = (1-abs(v1%2-1))*c
local m = (v3-.5*c)
r,g,b = 0,0,0
if v1 < 1 then r,g,b = c,x,0
elseif v1 < 2 then r,g,b = x,c,0
elseif v1 < 3 then r,g,b = 0,c,x
elseif v1 < 4 then r,g,b = 0,x,c
elseif v1 < 5 then r,g,b = x,0,c
else r,g,b = c,0,x end
r,g,b = round((r+m)*255),round((g+m)*255),round((b+m)*255)
end
else
return
end
r,g,b = min(255,max(0,r)), min(255,max(0,g)), min(255,max(0,b))
if to == 'rgb255' then
return r,g,b
elseif to == 'rgb1' then
return r/255,g/255,b/255
elseif to == 'hex' then
return format("%02x%02x%02x",r,g,b)
end
end
-- Mixes a color with pure white to produce a lighter color
function DiesalTools.TintColor(color, percent, to, from)
percent = min(1,max(0,percent))
from, to = from or 'hex', to and to:lower() or 'hex'
local r,g,b = DiesalTools.ConvertColor(from,'rgb255',color)
if to == 'rgb255' then
return round((255-r)*percent+r), round((255-g)*percent+g), round((255-b)*percent+b)
elseif to == 'rgb1' then
return round( ((255-r)*percent+r) / 255 ), round( ((255-g)*percent+g) / 255 ), round( ((255-b)*percent+b) / 255 )
elseif to == 'hex' then
return format("%02x%02x%02x", round((255-r)*percent+r), round((255-g)*percent+g), round((255-b)*percent+b) )
end
-- return format("%02x%02x%02x", round((255-r)*percent+r), round((255-g)*percent+g), round((255-b)*percent+b) )
end
-- Mixes a color with pure black to produce a darker color
function DiesalTools.ShadeColor(color, percent, to, from)
percent = min(1,max(0,percent))
from, to = from or 'hex', to and to:lower() or 'hex'
local r,g,b = DiesalTools.ConvertColor(from,'rgb255',color)
if to == 'rgb255' then
return round(-r*percent+r), round(-g*percent+g), round(-b*percent+b)
elseif to == 'rgb1' then
return round( (-r*percent+r) / 255 ), round( (-g*percent+g) / 255 ), round( (-b*percent+b) / 255 )
elseif to == 'hex' then
return format("%02x%02x%02x", round(-r*percent+r), round(-g*percent+g), round(-b*percent+b) )
end
end
-- Mixes a color with the another color to produce an intermediate color.
function DiesalTools.MixColors(color1, color2, percent, to, from)
percent = min(1,max(0,percent))
from, to = from or 'hex', to and to:lower() or 'hex'
-- to = to and to:lower() or 'hex'
local r1, g1, b1 = DiesalTools.ConvertColor(from,'rgb255',color1)
local r2, g2, b2 = DiesalTools.ConvertColor(from,'rgb255',color2)
if to == 'rgb255' then
return round((r2-r1)*percent)+r1, round((g2-g1)*percent)+g1, round((b2-b1)*percent)+b1
elseif to == 'rgb1' then
return round( ((r2-r1)*percent+r1) / 255 ), round( ((g2-g1)*percent+g1) / 255 ), round( ((b2-b1)*percent+b1) / 255 )
elseif to == 'hex' then
return format("%02x%02x%02x", round((r2-r1)*percent)+r1, round((g2-g1)*percent)+g1, round((b2-b1)*percent)+b1 )
end
end
--- converts color HSL to HEX
function DiesalTools.HSL(v1,v2,v3)
if not v1 then return end
if type(v1) == 'table' then v1,v2,v3 = v1[1],v1[2],v1[3] end
local r, g, b
if v2 == 0 then
v3 = round(v3 * 255)
r,g,b = v3,v3,v3
else
v1, v2, v3 = v1/360*6, min(max(0, v2), 1), min(max(0, v3), 1)
local c = (1-abs(2*v3-1))*v2
local x = (1-abs(v1%2-1))*c
local m = (v3-.5*c)
r,g,b = 0,0,0
if v1 < 1 then r,g,b = c,x,0
elseif v1 < 2 then r,g,b = x,c,0
elseif v1 < 3 then r,g,b = 0,c,x
elseif v1 < 4 then r,g,b = 0,x,c
elseif v1 < 5 then r,g,b = x,0,c
else r,g,b = c,0,x end
r,g,b = round((r+m)*255),round((g+m)*255),round((b+m)*255)
end
r,g,b = min(255,max(0,r)), min(255,max(0,g)), min(255,max(0,b))
return format("%02x%02x%02x",r,g,b)
end
--[[ GetTxtColor(value)
@Arguments:
value Hex color code or a table contating R,G,B color values
@Returns:
text coloring escape sequence (|cFFFFFFFF)
-- ]]
function DiesalTools.GetTxtColor(value)
if not value then return end
if type(value) =='table' then value = string.format("%02x%02x%02x", value[1], value[2], value[3]) end
return format('|cff%s',value)
end
-- | Texture Tools |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[[ Get a piece of a texture as a cooridnate refernce
-- @Param column the column in the texture
-- @Param row the row in the texture
-- @Param size the size in the texture
-- @Param textureWidth total texture width
-- @Param textureHeight total texture height
-- @Return edge coordinates for image cropping, plugs directly into Texture:SetTexCoord(left, right, top, bottom) ]]
function DiesalTools.GetIconCoords(column,row,size,textureWidth,textureHeight)
size = size or 16
textureWidth = textureWidth or 128
textureHeight = textureHeight or 16
return (column * size - size) / textureWidth, (column * size) / textureWidth, (row * size - size) / textureHeight, (row * size) / textureHeight
end
-- | String Tools |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[[ Capitalize a string
-- @Param str the string to capatilize
-- @Return the capitilized string ]]
function DiesalTools.Capitalize(str)
return (str:gsub("^%l", upper))
end
--[[ Escape all formatting in a WoW-lua string
-- @Param str the string to escape
-- @Return the escaped string ]]
function DiesalTools.EscapeString(string)
return string:gsub( "[%z\1-\31\"\\|\127-\255]", escapeSequences )
end
--[[ ID = CreateID(s)
-- @Param s string to parse
-- @Return ID string stripped of all non letter characters and color codes.]]
function DiesalTools.CreateID(s)
return gsub(s:gsub('c%x%x%x%x%x%x%x%x', ''), '[^%a%d]', '')
end
--[[ str = TrimString(s)
-- @Param s string to parse
-- @Return str string stripped of leading and trailing spaces.]]
function DiesalTools.TrimString(s)
return s:gsub("^%s*(.-)%s*$", "%1")
end
--[[ string = SpliceString(string, start, End, txt)
@Arguments:
string string to splice
start starting index of splice
End ending index of splice
txt new text to splice in (string)
@Returns:
string resulting string of the splice
@example:
DiesalTools.SpliceString("123456789",2,4,'NEW') -- returns: "1NEW56789"
--]]
function DiesalTools.SpliceString(string,start,End,txt)
return string:sub(1, start-1)..txt..string:sub(End+1,-1)
end
--[[ string = Serialize(table)
@Param table - table to to serialize
@Return string - serialized table (string)
@deserialization:
local func,err = loadstring('serialized table')
if err then error(err) end
return func()
]]
local function serialize_number(number)
-- no argument checking - called very often
local text = ("%.17g"):format(number)
-- on the same platform tostring() and string.format()
-- return the same results for 1/0, -1/0, 0/0
-- so we don't need separate substitution table
return sub_table[text] or text
end
local function impl(t, cat, visited)
local t_type = type(t)
if t_type == "table" then
if not visited[t] then
visited[t] = true
cat("{")
-- Serialize numeric indices
local next_i = 0
for i, v in ipairs(t) do
if i > 1 then -- TODO: Move condition out of the loop
cat(",")
end
impl(v, cat, visited)
next_i = i
end
next_i = next_i + 1
-- Serialize hash part
-- Skipping comma only at first element iff there is no numeric part.
local need_comma = (next_i > 1)
for k, v in pairs(t) do
local k_type = type(k)
if k_type == "string" then
if need_comma then
cat(",")
end
need_comma = true
-- TODO: Need "%q" analogue, which would put quotes
-- only if string does not match regexp below
if not lua_keywords[k] and ("^[%a_][%a%d_]*$"):match(k) then
cat(k) cat("=")
else
cat(format("[%q]=", k))
end
impl(v, cat, visited)
else
if
k_type ~= "number" or -- non-string non-number
k >= next_i or k < 1 or -- integer key in hash part of the table
k % 1 ~= 0 -- non-integer key
then
if need_comma then
cat(",")
end
need_comma = true
cat("[")
impl(k, cat, visited)
cat("]=")
impl(v, cat, visited)
end
end
end
cat("}")
visited[t] = nil
else
-- this loses information on recursive tables
cat('"table (recursive)"')
end
elseif t_type == "number" then
cat(serialize_number(t))
elseif t_type == "boolean" then
cat(tostring(t))
elseif t == nil then
cat("nil")
else
-- this converts non-serializable (functions) types to strings
cat(format("%q", tostring(t)))
end
end
local function tstr_cat(cat, t)
impl(t, cat, {})
end
function DiesalTools.Serialize(t)
local buf = {}
local cat = function(v) buf[#buf + 1] = v end
impl(t, cat, {})
return format('return %s',table_concat(buf))
end
-- | Math Tools |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[[ Round a number
-- @Param number the number to round
-- @Param base the number to round to (can be a decimal) [Default:1]
-- @Return the rounded number to base ]]
function DiesalTools.Round(number, base)
base = base or 1
return floor((number + base/2)/base) * base
end
--[[ Round a number for printing
-- @Param number the number to round
-- @Param idp number of decimal points to round to [Default:1]
-- @Return the rounded number ]]
function DiesalTools.RoundPrint(num, idp)
return string.format("%." .. (idp or 0) .. "f", num)
end
-- | Frame Tools |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[[ GetFrameQuadrant(frame)
@Arguments:
frame frame?!!
@Returns:
quadrant quadrant of the screen frames center is in
-- ]]
function DiesalTools.GetFrameQuadrant(frame)
if not frame:GetCenter() then return "UNKNOWN", frame:GetName() end
local x, y = frame:GetCenter()
local screenWidth = GetScreenWidth()
local screenHeight = GetScreenHeight()
local quadrant
if (x > (screenWidth / 4) and x < (screenWidth / 4)*3) and y > (screenHeight / 4)*3 then
quadrant = "TOP"
elseif x < (screenWidth / 4) and y > (screenHeight / 4)*3 then
quadrant = "TOPLEFT"
elseif x > (screenWidth / 4)*3 and y > (screenHeight / 4)*3 then
quadrant = "TOPRIGHT"
elseif (x > (screenWidth / 4) and x < (screenWidth / 4)*3) and y < (screenHeight / 4) then
quadrant = "BOTTOM"
elseif x < (screenWidth / 4) and y < (screenHeight / 4) then
quadrant = "BOTTOMLEFT"
elseif x > (screenWidth / 4)*3 and y < (screenHeight / 4) then
quadrant = "BOTTOMRIGHT"
elseif x < (screenWidth / 4) and (y > (screenHeight / 4) and y < (screenHeight / 4)*3) then
quadrant = "LEFT"
elseif x > (screenWidth / 4)*3 and y < (screenHeight / 4)*3 and y > (screenHeight / 4) then
quadrant = "RIGHT"
else
quadrant = "CENTER"
end
return quadrant
end
-- | Misc Tools |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--[[ Pack(...) blizzard dosnt use 5.2 yet so will have to create this one
@Arguments:
... arguments to pack into a table
@Returns:
a new table with all parameters stored into keys 1, 2, etc. and with a field "n" with the total number of parameters
]]
function DiesalTools.Pack(...)
return { n = select("#", ...), ... }
end
--[[ Unpack(...)
@Arguments:
t table to unpack
@Returns:
... list of arguments
]]
function DiesalTools.Unpack(t)
if t.n then
return unpack(t,1,t.n)
end
return unpack(table)
end
Loading…
Cancel
Save