WoWInterface SVN RaidWatch2

[/] [trunk/] [RaidWatch_Plugins/] [MessageFrame.lua] - Rev 22

Compare with Previous | Blame | View Log

--[[
Plugin that shows popup messages
]]

----------------------------------
-- Create plugin

local RW = LibStub("AceAddon-3.0"):GetAddon("Raid Watch")
local plugin = RW:Plugin("MessageFrame", "LibSink-2.0")
if not plugin then return end

----------------------------------
-- Locals 

local L = LibStub("AceLocale-3.0"):GetLocale("RW2-Plugin-Messages")
local LB = LibStub("AceLocale-3.0"):GetLocale("RW2-Plugin-Base")
local LSM = LibStub("LibSharedMedia-3.0")
local Colors
local Utils = RW.Utils

local nrSlots = 5

local db

----------------------------------
-- Init

function plugin:OnRegister()
        local defaults = {
                profile = {
                        Width = 180,
                        PluginEnabled = true,
                        GrowUp = true,
                        Font = "accid",
                        FontSize = 23,
                        FontFlags = "OUTLINE",
                        FadeOutTime = 10,
                        SlotHeight = 30,
                        sink20OutputSink = "RW",
                        ScaleUpTime = 0.3,
                        ScaleDownTime = 0.6,
                        DefaultSound = "RW: Bell",
                        PlaySound = true,
                        ChatOutput = true,
                        DefaultColor = {0.39, 0.67, 0.87, 1},
                        x = 0,
                        y = 0,
                }
        }
        self.db = RW.db:RegisterNamespace(self:GetName(), defaults)
        db = self.db.profile
        
        -- Register for LibSink for message output selection
        self:SetSinkStorage(self.db.profile)
        self:RegisterSink("RW", "Raid Watch", "Messages trough RW", "AddMessage")
        
        local t = {
                type = "group",
                name = "test",
                args = {
                        sink = plugin:GetSinkAce3OptionsDataTable()
                }
        }
        
        t.args.sink.guiInline = true
        
        LibStub("AceConfig-3.0"):RegisterOptionsTable("RW-Messages", t) 
        
        Colors = RW:GetPlugin("Colors")
        
        self.db.RegisterCallback(self, "OnProfileChanged", "Reset")
        self.db.RegisterCallback(self, "OnProfileCopied", "Reset")
        self.db.RegisterCallback(self, "OnProfileReset", "Reset")
end

function plugin:PluginEnable()
        if not db.PluginEnabled then
                self:Disable()
                return
        end
        self:RegisterCallback("ConfigMode")
        self:RegisterCallback("MessageShow")
end

function plugin:PluginDisable()
end

----------------------------------
-- Anchor

local function dragStart(self)
        self:StartMoving()
end
local function dragStop(self)
        self:StopMovingOrSizing()
        local scale = self:GetEffectiveScale() / UIParent:GetEffectiveScale()
        
        local x, y = self:GetCenter()
        x, y = x * scale, y * scale
        
        x = x - GetScreenWidth()/2
        y = y - GetScreenHeight()/2
        
        db.x = x
        db.y = y
        
        RW.Callbacks:Fire("RefreshOptions")
end

local function onUpdate(self, elapsed)
        local showing = false
        for i, s in next, plugin.slots do
                if s:IsShown() then
                        showing = true
                        s.ScaleTime = s.ScaleTime + elapsed
                        -- Scale the text up untill ScaleUpTime is reached
                        if s.ScaleTime < db.ScaleUpTime then
                                s:SetScale(s:GetScale() + elapsed * 3)
                        -- Scale down untill ScaleDownTime is reached
                        elseif s.ScaleTime <= db.ScaleDownTime then
                                local newScale = s:GetScale() - elapsed * 3
                                s:SetScale(newScale > 0 and newScale or 0.01)
                        -- Else reset the scale and text size
                        else
                                s:SetScale(1)
                        end
                        FadingFrame_OnUpdate(s)
                else
                end
        end
        if not showing then self:SetScript("OnUpdate", nil) end
end
        
function plugin:CreateAnchor()          
        local frame = Utils:CreateAnchor("MessageAnchor", UIParent, "Messages")
        local s = frame:GetEffectiveScale()
        frame:SetScript("OnDragStart", dragStart)
        frame:SetScript("OnDragStop", dragStop)
        
        self.anchor = frame
        
        self:Reset()
        
        local updateFrame = CreateFrame("Frame", nil, UIParent) 
        self.eventFrame = updateFrame
end

function plugin:Reset(var1, var2, var3)
        db = self.db.profile
        self:SetSinkStorage(self.db.profile)
        if self.anchor then
                local frame = self.anchor
                local scale = frame:GetEffectiveScale() / UIParent:GetEffectiveScale()
                frame:ClearAllPoints()
                frame:SetPoint("CENTER", UIParent, "CENTER", db.x / scale, db.y / scale)                
                frame:SetWidth(db.Width)
                
                if self.slots then
                        for i, slot in pairs(self.slots) do
                                slot:SetHeight(db.SlotHeight)
                                slot.icon:SetWidth(db.SlotHeight - 4)
                                slot.icon:SetHeight(db.SlotHeight - 4)
                                slot.text:SetFont(LSM:Fetch("font", db.Font), db.FontSize, db.FontFlags)
                        end
                end
        end
end

----------------------------------
-- Frame handling

-- Creates and returns one message slot
function plugin:GetMessageFrame()
        if not self.anchor then self:CreateAnchor() end
        
        -- Create message slots
        if not self.slots then
                self.slots = {}
                for i = 1, nrSlots do
                        local frame = CreateFrame("Frame", "SlotFrame_"..i, self.eventFrame)
                        frame:SetWidth(1)
                        frame:SetHeight(db.SlotHeight)
                        local str = frame:CreateFontString("RWMessageSlot_"..i, "ARTWORK")
                        str:SetPoint("CENTER")
                        str:SetFont(LSM:Fetch("font", db.Font), db.FontSize, db.FontFlags)
                        
                        local icon = frame:CreateTexture(nil, "OVERLAY")
                        icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
                        icon:SetPoint("RIGHT", str, "LEFT", -4, 0)
                        icon:SetWidth(db.SlotHeight - 4)
                        icon:SetHeight(db.SlotHeight - 4)
                        
                        local iconback = frame:CreateTexture(nil, "ARTOWRK")
                        iconback:SetTexture(0, 0, 0, 1)
                        iconback:SetPoint("TOPLEFT", icon, -3, 3)
                        iconback:SetPoint("BOTTOMRIGHT", icon, 3, -3)
                        
                        FadingFrame_SetFadeInTime(frame, 0.4)
                        FadingFrame_SetFadeOutTime(frame, 3)
                        
                        frame.text = str
                        frame.icon = icon
                        
                        frame:Hide()
                        self.slots[i] = frame
                end
        end

        -- Re-arrange slot, so that slot 1 is always the next one to be used (n:th slot becomes slot nr 1)
        local slots = self.slots
        local old = slots[#slots]
        for i = #slots, 1, -1 do
                if i > 1 then
                        slots[i] = slots[i-1]
                else
                        slots[i] = old
                end
        end
        
        -- Position the slots according to the slots order visually
        for i, t in pairs(self.slots) do
                t:ClearAllPoints()
                if i == 1 then
                        t:SetPoint(db.GrowUp and "BOTTOM" or "TOP", self.anchor, db.GrowUp and "TOP" or "BOTTOM", 0, db.GrowUp and 3 or -3)
                else
                        t:SetPoint(db.GrowUp and "BOTTOM" or "TOP", self.slots[i-1], db.GrowUp and "TOP" or "BOTTOM", 0, db.GrowUp and 3 or -3)
                end
                FadingFrame_SetHoldTime(t, db.FadeOutTime)
        end     

        -- Return the "oldest" slot to be re-used
        return self.slots[1]
end

-- Internal function that is called from LibSink
function plugin:AddMessage(addon, text, r, g, b, font, size, outline, sticky, loc, icon)
        local slot = self:GetMessageFrame()
        slot.text:SetText(text)
        slot.text:SetTextColor(r, g, b)
        slot.icon:SetTexture(icon)
        slot.ScaleTime = 0
        FadingFrame_Show(slot)
        
        if not self.eventFrame:GetScript("OnUpdate") then self.eventFrame:SetScript("OnUpdate", onUpdate) end
end

----------------------------------
-- Message Handling

--- Show a new message as popup
-- @param text The text to be shown
-- @param r Red component to the color
-- @param g Green component to the color
-- @param b Blue component to the color
-- @param a Alpha component to the color
-- @param icon Optional icon to show
function plugin:MessageShow(event, text, r, g, b, a, icon, sound, module)
        if not r or not g or not b then
                r, g, b, a = unpack(db.DefaultColor)
        end
        if db.PlaySound then
                PlaySoundFile(LSM:Fetch("sound", sound or db.DefaultSound))
        end
        if db.ChatOutput and module then
                module:Msg((icon and "|T"..icon..":20|t " or "")..("|cff%x%x%x"..(text or "").."|r"):format(r*255, g*255, b*255))
        end
        
        self:Pour(text or "Test message", r, g, b, nil, nil, nil, nil, nil, icon)
end

-- Enter configuration mode
function plugin:ConfigMode(event, start)
        local function randomMessage()
                local spellName, rank, icon = Utils:GetRandomSpell()
                plugin:MessageShow("MessageShow", spellName ..((rank ~= "" or not rank) and (" ("..rank..")" ) or "" ), math.random(), math.random(), math.random(), math.random(), icon, "None")
        end
        if not self.anchor then self:CreateAnchor() end
        if start then
                self.anchor:Show()
                self:ScheduleRepeatingTimer(randomMessage, 2)
        else
                self.anchor:Hide()
                self:CancelAllTimers()
        end
end
---------------------------------------------

do
        function plugin:GetOptions()
                return LB.PLUGINS, LB.ALERT_PLUGINS, L.NAME, self.GetGUI, [[Interface\Icons\INV_MISC_NOTE_02]]
        end

        local function changeCallback()
                db.SlotHeight = db.FontSize
                plugin:Reset()
        end
        
        local LastTab
        local TabSelected
        
        function plugin:GetGUI()
                local self = self or plugin
                local UIF = LibStub("LibGUIFactory-1.0"):GetFactory("RW")
                local AceGUI = LibStub("AceGUI-3.0")
                
                local group, label, slider, check, igroup, button, color, select
                
                group = AceGUI:Create("ScrollFrame")
                group:SetLayout("Flow")
                
                label = UIF:MainTitleLabel(L.NAME)
                group:AddChild(label)           
                
                igroup = UIF:InlineGroup("")
                group:AddChild(igroup)  
                
                label = UIF:NormalText(L.DESC)
                label:SetImage([[Interface\Icons\INV_MISC_NOTE_02]])
                igroup:AddChild(label)          
                
                check = UIF:CheckBox(LB.ENABLED, db, "PluginEnabled", function() 
                        if not db.PluginEnabled then
                                self:Disable()
                        else
                                self:Enable()
                        end
                end)
                group:AddChild(check)
                
                local tgroup = UIF:TabGroup()
                group:AddChild(tgroup)
                tgroup:SetTabs({
                        {text = "Misc", value = "Misc"},
                        {text = LB.POSITION, value = "Position"},
                        {text = "Output", value = "Output"},
                        {text = LB.FONT, value = "Font"},
                })
                tgroup:SetCallback("OnGroupSelected", TabSelected)
                tgroup:SelectTab(LastTab or "Misc")                             
                
                button = UIF:Button(LB.TEST, function() 
                        local spellName, rank, icon = Utils:GetRandomSpell()
                        RW.Callbacks:Fire("MessageShow", spellName ..((rank ~= "" or not rank) and (" ("..rank..")" ) or "" ), nil, nil, nil, nil, icon, nil, plugin)
                end)
                group:AddChild(button)
                        
                button = UIF:Button(LB.RESET, function() 
                        plugin.db:ResetProfile() 
                end)
                button:SetUserData("confirm", true)
                button:SetUserData("TriggerGlobalUpdate", true)
                group:AddChild(button)          
                
                group:FixScroll()
                
                return group
        end
        
        TabSelected = function(self, evemt, tab)
                local UIF = LibStub("LibGUIFactory-1.0"):GetFactory("RW")
                local AceGUI = LibStub("AceGUI-3.0")
                
                self:ReleaseChildren()
                
                LastTab = tab
                
                if tab == "Misc" then
                        local check = UIF:CheckBox(LB.PLAY_SOUND, db, "PlaySound")
                        check:SetFullWidth(false)
                        self:AddChild(check)
                        
                        local select = AceGUI:Create("LSM30_Sound")
                        select:SetLabel(LB.DEFAULT_SOUND)
                        select:SetList()
                        select:SetValue(db["DefaultSound"])
                        select:SetUserData("db", db)
                        select:SetUserData("key", "DefaultSound")
                        select:SetCallback("OnValueChanged", function(widget, event, value)
                                db["DefaultSound"] = value
                        end)
                        self:AddChild(select)
                        
                        check = UIF:CheckBox(LB.GROW_UP, db, "GrowUp")
                        check:SetDescription(LB.GROW_UP_DESC)
                        check:SetFullWidth(false)
                        self:AddChild(check)
                        
                        check = UIF:CheckBox(L.CHAT_OUTPUT, db, "ChatOutput")
                        check:SetDescription("Should the messages also be output to your chatwindow?")
                        check:SetFullWidth(false)
                        self:AddChild(check)
                        
                        local color = UIF:ColorSelect(LB.DEFAULT_COLOR, db, "DefaultColor")
                        self:AddChild(color)
                        
                        local slider = UIF:Slider(L.FADE_OUT_TIME, db,  "FadeOutTime", 1, 15, 0.5, changeCallback)
                        self:AddChild(slider)
                
                elseif tab == "Position" then
                        self:AddChild(UIF:Slider("X", db, "x", 
                                -floor(GetScreenWidth() * UIParent:GetEffectiveScale()), 
                                floor(GetScreenWidth() * UIParent:GetEffectiveScale()),
                                1, changeCallback, 0.5))
                        
                        self:AddChild(UIF:Slider("Y", db, "y", 
                                -floor(GetScreenHeight() * UIParent:GetEffectiveScale()), 
                                floor(GetScreenHeight() * UIParent:GetEffectiveScale()),
                                1, changeCallback, 0.5))
                
                elseif tab == "Output" then
                        local sinkgroup = AceGUI:Create("SimpleGroup")
                        sinkgroup:SetLayout("Fill")
                        sinkgroup:SetFullWidth(true)
                        self:AddChild(sinkgroup)
                        LibStub("AceConfigDialog-3.0"):Open("RW-Messages", sinkgroup)
                
                elseif tab == "Font" then                       
                        self:AddChild(UIF:LSMDropdown("font", LB.FONT, db, "Font", changeCallback, 0.5))                        
                        self:AddChild(UIF:Dropdown(LB.FONT_OUTLINE, db, "FontFlags", changeCallback, Utils.Constants.FontFlagList, 0.5))                        
                        self:AddChild(UIF:Slider(LB.FONT_SIZE, db, "FontSize", 1, 50, 1, changeCallback, 0.5))
                        
                end
                
                self:DoLayout()
                self.parent:DoLayout()
        end
end

Compare with Previous | Blame