You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
8.8 KiB
309 lines
8.8 KiB
-- NotifyFrame.lua
|
|
-- @Author : DengSir (tdaddon@163.com)
|
|
-- @Link : https://dengsir.github.io
|
|
-- @Date : 9/22/2018, 11:26:58 AM
|
|
|
|
local MAJOR, MINOR = 'NotifyFrame', 3
|
|
local GUI = LibStub('tdGUI-1.0')
|
|
local NotifyFrame, oldminor, ns = GUI:NewClass(MAJOR, MINOR, 'Button', 'Backdrop')
|
|
if not NotifyFrame then return end
|
|
|
|
NotifyFrame.opts = {}
|
|
|
|
local DEFAULT_ICON = [[Interface\Icons\INV_Misc_QuestionMark]]
|
|
local BACKGROP = {
|
|
bgFile = [[Interface\BUTTONS\WHITE8X8]],
|
|
edgeFile = [[Interface\BUTTONS\WHITE8X8]],
|
|
tile = true,
|
|
tileSize = 1,
|
|
edgeSize = 1,
|
|
insets = {left = 1, right = 1, top = 1, bottom = 1}
|
|
}
|
|
|
|
function NotifyFrame:Constructor()
|
|
self:Hide()
|
|
self:SetSize(350, 50)
|
|
self:SetFrameStrata('DIALOG')
|
|
self:RegisterForClicks('LeftButtonUp', 'RightButtonUp')
|
|
self:SetBackdrop(BACKGROP)
|
|
self:SetBackdropBorderColor(0, 0, 0, 1)
|
|
self:SetBackdropColor(0, 0, 0, 0.6)
|
|
|
|
self:SetScript('OnClick', self.OnClick)
|
|
self:SetScript('OnHide', self.OnHide)
|
|
|
|
local Close = CreateFrame('Button', nil, self, GUI.BackdropTemplate) do
|
|
Close:SetBackdrop(BACKGROP)
|
|
Close:SetBackdropBorderColor(0, 0, 0, 1)
|
|
Close:SetBackdropColor(0, 0, 0, 0.4)
|
|
Close:SetPoint('TOPRIGHT', 0, 0)
|
|
Close:SetSize(16, 16)
|
|
Close:SetScript('OnClick', function()
|
|
self:OnClick('RightButton')
|
|
end)
|
|
|
|
local padding = 4
|
|
|
|
local Line1 = Close:CreateLine(nil, 'ARTWORK') do
|
|
Line1:SetThickness(1)
|
|
Line1:SetStartPoint('TOPLEFT', padding, -padding)
|
|
Line1:SetEndPoint('BOTTOMRIGHT', -padding, padding)
|
|
Line1:SetColorTexture(0.5, 0.5, 0.5)
|
|
end
|
|
|
|
local Line2 = Close:CreateLine(nil, 'ARTWORK') do
|
|
Line2:SetThickness(1)
|
|
Line2:SetStartPoint('TOPRIGHT', -padding, -padding)
|
|
Line2:SetEndPoint('BOTTOMLEFT', padding, padding)
|
|
Line2:SetColorTexture(0.5, 0.5, 0.5)
|
|
end
|
|
end
|
|
|
|
local Icon = self:CreateTexture(nil, 'ARTWORK') do
|
|
Icon:SetPoint('LEFT', 4, 0)
|
|
Icon:SetSize(42, 42)
|
|
Icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
|
|
end
|
|
|
|
local Text = self:CreateFontString(nil, 'ARTWORK', 'GameFontHighlightLeft') do
|
|
Text:SetPoint('TOPRIGHT', -25, -5)
|
|
Text:SetPoint('LEFT', Icon, 'RIGHT', 5, 0)
|
|
end
|
|
|
|
local HelpText = self:CreateFontString(nil, 'ARTWORK', 'GameFontNormalLeft') do
|
|
HelpText:SetWordWrap(false)
|
|
HelpText:SetPoint('BOTTOM', 0, 4)
|
|
HelpText:SetPoint('LEFT', Icon, 'RIGHT', 5, 0)
|
|
HelpText:SetFont(HelpText:GetFont(), 11)
|
|
HelpText:SetTextColor(0.8, 0.8, 0.3)
|
|
end
|
|
|
|
local Anim = self:CreateAnimationGroup() do
|
|
Anim:SetToFinalAlpha(true)
|
|
Anim:SetScript('OnFinished', function()
|
|
if self:GetAlpha() == 0 then
|
|
self:Hide()
|
|
end
|
|
end)
|
|
end
|
|
|
|
local Alpha = Anim:CreateAnimation('Alpha') do
|
|
Alpha:SetDuration(0.5)
|
|
end
|
|
|
|
local IgnoreButton = CreateFrame('Button', nil, self, GUI.BackdropTemplate) do
|
|
IgnoreButton:SetBackdrop(BACKGROP)
|
|
IgnoreButton:SetBackdropBorderColor(0, 0, 0, 1)
|
|
IgnoreButton:SetBackdropColor(0, 0, 0, 0.4)
|
|
IgnoreButton:SetSize(80, 16)
|
|
IgnoreButton:SetPoint('BOTTOMRIGHT')
|
|
IgnoreButton:SetScript('OnClick', function()
|
|
self:OnIgnoreClick()
|
|
end)
|
|
|
|
local Text = IgnoreButton:CreateFontString(nil, 'OVERLAY', 'GameFontNormalGraySmall') do
|
|
Text:SetFont(Text:GetFont(), 11)
|
|
Text:SetPoint('CENTER')
|
|
IgnoreButton:SetFontString(Text)
|
|
IgnoreButton:SetHighlightFontObject('GameFontHighlightSmall')
|
|
IgnoreButton:SetNormalFontObject('GameFontNormalGraySmall')
|
|
end
|
|
end
|
|
|
|
self.Anim = Anim
|
|
self.Alpha = Alpha
|
|
self.Text = Text
|
|
self.Icon = Icon
|
|
self.HelpText = HelpText
|
|
self.IgnoreButton = IgnoreButton
|
|
end
|
|
|
|
function NotifyFrame:SetText(text)
|
|
self.Text:SetText(text)
|
|
self:SetHeight(max(50, self.Text:GetStringHeight() + self.HelpText:GetStringHeight() + 12))
|
|
end
|
|
|
|
function NotifyFrame:FadeIn()
|
|
self:Show()
|
|
self.Anim:Stop()
|
|
self.Alpha:SetFromAlpha(0)
|
|
self.Alpha:SetToAlpha(1)
|
|
self.Anim:Play()
|
|
end
|
|
|
|
function NotifyFrame:FadeOut()
|
|
self.Anim:Stop()
|
|
self.Alpha:SetFromAlpha(1)
|
|
self.Alpha:SetToAlpha(0)
|
|
self.Anim:Play()
|
|
end
|
|
|
|
function NotifyFrame:OnClick(click)
|
|
if self.Anim:IsPlaying() then
|
|
return
|
|
end
|
|
|
|
self:CallOptions(click == 'LeftButton' and 'OnAccept' or 'OnCancel')
|
|
self:FadeOut()
|
|
end
|
|
|
|
function NotifyFrame:OnIgnoreClick()
|
|
if self.Anim:IsPlaying() then
|
|
return
|
|
end
|
|
self:CallOptions('OnIgnore')
|
|
self:FadeOut()
|
|
end
|
|
|
|
function NotifyFrame:OnHide()
|
|
self.opts = nil
|
|
self:Fire('OnHide')
|
|
end
|
|
|
|
function NotifyFrame:SetOptions(opts)
|
|
self.opts = opts
|
|
self.Icon:SetTexture(opts.icon or DEFAULT_ICON)
|
|
self.IgnoreButton:SetText(opts.ignore or '')
|
|
self.IgnoreButton:SetShown(opts.ignore)
|
|
self.IgnoreButton:SetWidth(self.IgnoreButton:GetTextWidth() + 10)
|
|
self.HelpText:SetText(opts.help or 'Right click to close')
|
|
self:SetText(opts.text)
|
|
end
|
|
|
|
function NotifyFrame:GetOptions()
|
|
return self.opts
|
|
end
|
|
|
|
function NotifyFrame:CallOptions(method)
|
|
if type(self.opts[method]) == 'function' then
|
|
self.opts[method](self.opts)
|
|
end
|
|
end
|
|
|
|
-- public
|
|
|
|
local MAX_NOTIFIES = 4
|
|
|
|
ns.used = ns.used or {}
|
|
ns.unused = ns.unused or {}
|
|
ns.queue = ns.queue or {}
|
|
|
|
local NotifyManager = {}
|
|
local TYPES = {ONCE = true, DAY = true}
|
|
|
|
function NotifyManager:CheckOptions(opts)
|
|
if opts.ignore and self:GetStorage(opts, 'ignore') then
|
|
return
|
|
end
|
|
|
|
if opts.type then
|
|
local last = self:GetStorage(opts, 'last')
|
|
if last then
|
|
if opts.type == 'ONCE' then
|
|
return
|
|
end
|
|
if opts.type == 'DAY' and last == date('%Y/%m/%d') then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
function NotifyManager:SaveStorage(opts, key, value)
|
|
opts.storage[opts.id] = opts.storage[opts.id] or {}
|
|
opts.storage[opts.id][key] = value
|
|
end
|
|
|
|
function NotifyManager:GetStorage(opts, key)
|
|
return opts.storage[opts.id] and opts.storage[opts.id][key]
|
|
end
|
|
|
|
function NotifyManager:Pop()
|
|
while self:Update() do
|
|
end
|
|
self:UpdatePosition()
|
|
end
|
|
|
|
function NotifyManager:UpdatePosition()
|
|
for i, frame in ipairs(ns.used) do
|
|
if i == 1 then
|
|
frame:SetPoint('BOTTOMRIGHT', -25, 90)
|
|
else
|
|
frame:SetPoint('BOTTOMRIGHT', ns.used[i-1], 'TOPRIGHT', 0, 2)
|
|
end
|
|
end
|
|
end
|
|
|
|
function NotifyManager:Update()
|
|
if #ns.used >= MAX_NOTIFIES then
|
|
return
|
|
end
|
|
|
|
local opts = table.remove(ns.queue, 1)
|
|
if not opts then
|
|
return
|
|
end
|
|
|
|
if not self:CheckOptions(opts) then
|
|
return true
|
|
end
|
|
|
|
local notify = table.remove(ns.unused, 1) or NotifyFrame:New(UIParent)
|
|
notify:SetPoint('BOTTOMRIGHT', -25, 90)
|
|
notify:SetCallback('OnHide', function(notify)
|
|
tDeleteItem(ns.used, notify)
|
|
table.insert(ns.unused, notify)
|
|
self:Pop()
|
|
end)
|
|
notify:SetOptions(opts)
|
|
notify:FadeIn()
|
|
if opts.duration ~= -1 then
|
|
C_Timer.After(opts.duration or 5, function() notify:FadeOut() end)
|
|
end
|
|
|
|
table.insert(ns.used, notify)
|
|
|
|
if opts.type then
|
|
self:SaveStorage(opts, 'last', date('%Y/%m/%d'))
|
|
end
|
|
end
|
|
|
|
function GUI:Notify(opts)
|
|
if type(opts) ~= 'table' then
|
|
error(format([[bad argument #1 to 'Notify' (table expected, got %s]], type(opts)), 2)
|
|
end
|
|
if type(opts.text) ~= 'string' then
|
|
error(format([[bad argument opts.text to 'Notify' (string expected, got %s)]], type(opts.text)), 2)
|
|
end
|
|
if opts.type or opts.ignore then
|
|
if opts.type and not TYPES[opts.type] then
|
|
error(format([[bad argument opts.type to 'Notify' (ONCE|DAY)]]), 2)
|
|
end
|
|
if type(opts.storage) ~= 'table' then
|
|
error(format([[bad argument opts.storage to 'Notify' (table expected, got %s)]], type(opts.storage)), 2)
|
|
end
|
|
if not opts.id then
|
|
error(format([[bad argument opts.storage to 'Notify']]), 2)
|
|
end
|
|
end
|
|
|
|
if opts.ignore then
|
|
opts.OnIgnore = function(opts)
|
|
NotifyManager:SaveStorage(opts, 'ignore', true)
|
|
end
|
|
end
|
|
|
|
table.insert(ns.queue, opts)
|
|
NotifyManager:Pop()
|
|
end
|
|
|
|
function GUI:NotifyOnce(opts)
|
|
opts.type = 'ONCE'
|
|
return self:Notify(opts)
|
|
end
|
|
|
|
function GUI:NotifyDay(opts)
|
|
opts.type = 'DAY'
|
|
return self:Notify(opts)
|
|
end
|
|
|