parent
0a52c4036c
commit
2c1766968b
@ -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.
Binary file not shown.
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 128 KiB |
After Width: | Height: | Size: 256 KiB |
After Width: | Height: | Size: 256 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
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…
Reference in new issue