WoWInterface SVN BearinMind

[/] [trunk/] [Bear in Mind/] [BiM.lua] - Rev 9

Compare with Previous | Blame | View Log

local addonName, BiM = ...
BiM.anchor = CreateFrame("Frame", "BearInMindAnchor", UIParent)
local anchor = BiM.anchor
BiM.eventFrame = CreateFrame("Frame")
local eventFrame = BiM.eventFrame
local LSM = LibStub("LibSharedMedia-3.0")

local tinsert = table.insert
local tremove = table.remove
local strformat = string.format
local db, pcdb, _
local calIcon = "Interface\\Addons\\Bear in Mind\\calendar"

numLines = 0    --just #lines ?
inUse = 0
BiM.lines = {}
local lines = BiM.lines
sRD = {}        --shownReminderData (as reminders in our DB get shown, their data is added to this table)

local function CreateNew()
        --factory function to make a new line
        local line = CreateFrame("Frame", nil, anchor)
        if inUse >1 then
                line:SetPoint("TOPLEFT", lines[inUse-1], "BOTTOMLEFT", 0, -5)
        else
                line:SetPoint("TOPLEFT", anchor, "TOPLEFT", 5, -5)
        end
        line:SetSize(270, 40)
        
        line.icon = CreateFrame("Button", nil, line)    --need to test to make sure it's created properly
        local icon = line.icon
        icon:SetPoint("LEFT")
        icon:SetSize(40, 40)
        icon:RegisterForClicks("RightButtonUp")
        icon:SetScript("OnClick", function() BiM.HideReminder(line) end)
        
        line.text = line:CreateFontString()
        local text = line.text
        text:SetPoint("LEFT", icon, "RIGHT", 5, 0)
        text:SetSize(225, 40)
        text:SetJustifyH("LEFT")
        text:SetFont(LSM:Fetch("font", db.font), db.fSize)      --, "OUTLINE")
        text:SetShadowColor(0, 0, 0)
        text:SetShadowOffset(1, -1)
        text:SetTextColor(db.fColor.r, db.fColor.g, db.fColor.b)
        
        tinsert(lines, line)    --insert our new line at the end of the table
        numLines = #lines       --now we have this many lines created
        line.index = numLines   --index will increase as lines are created and added to our table
        
        return line
end

function BiM.ConfigureLine(line, data)
        line.data = data
        local icon = data.icon or "Interface\\AddOns\\Bear in Mind\\BiM-icon"
        local text = data.text or "Remember... something?"
        line.icon:SetNormalTexture(icon)
        line.text:SetText(text)
        if data.sound then
                PlaySoundFile(LSM:Fetch("sound", data.sound))
        end
        data.shown = true
end

function BiM.DisplayReminder(data, sample)
        --if this is a sample, let's put it in the table to avoid errors
        if sample then tinsert(sRD, data) end
        
        inUse = inUse + 1       --we have one more used
        local line
        --get a line to display
        if numLines < inUse then
                line = CreateNew()      --we need to make a new line
        else
                line = lines[inUse]     --use the next available line (if 2 were in use, then 3 is what we're on now)
                line:Show()
        end
        BiM.ConfigureLine(line, data)   --moved to own function for reuse
end

function BiM.HideReminder(line)
        lines[inUse]:Hide()     --hide last one
        inUse = inUse - 1       --now we're using one less
        line.data.shown = false --the reminder associated with this line is no longer shown
        tremove(sRD, line.index)
        --reconfigure all lines so that the reminders still showing are in the right spots
        --(in case the 1st of 3 was dismissed, for example)
        for i = 1, inUse do
                BiM.ConfigureLine(lines[i], sRD[i])     --make them all match up
        end
end

local function ShouldShowReminder(reminder)
        local show = false
        if not reminder.data.shown then --if not currently shown
                if reminder.charName and reminder.charName ~= BiM.charName then --if only for a certain char, and not THIS char, then don't show
                        return
                end
                --local _, m, d, y = CalendarGetDate()
                local dateTable = C_Calendar.GetDate()
                --local curDate = strformat("%d-%d-%d", m, d, y)
                local curDate = strformat("%d-%d-%d", dateTable.month, dateTable.monthDay, dateTable.year)
                --if show always or haven't shown yet today
                if reminder.showAlways or reminder.lastShown ~= curDate then
                        show = true
                        reminder.lastShown = curDate
                end
        end
        return show
end

local function CheckForZoneReminders()
        --will fire for ZONE_CHANGED, ZONE_CHANGED_NEW_AREA, ZONE_CHANGED_INDOORS and PLAYER_ENTERING_WORLD
        local realZone = GetRealZoneText()
        local subZone = GetSubZoneText()
        local zone = GetZoneText()
        
        local zoneReminders = db.reminders.zone
        for i = 1, #zoneReminders do
                local reminder = zoneReminders[i]
                local remindAt = reminder.zone
                if remindAt == realZone or remindAt == subZone or remindAt == zone then
                        --found a reminder, now should we show it?
                        if ShouldShowReminder(reminder) then
                                tinsert(sRD, reminder.data)     --backup which reminders are showing (data.icon, data.text, data.sound)
                                BiM.DisplayReminder(reminder.data)
                        end
                end
        end
end

local function CheckForOnEventReminders(event)
        --will fire for any additional events registered
        local eventReminders = db.reminders.event
        for i = 1, #eventReminders do
                local reminder = eventReminders[i]
                if event == reminder.event then
                        if ShouldShowReminder(reminder) then
                                tinsert(sRD, reminder.data)
                                BiM.DisplayReminder(reminder.data)
                        end
                end
        end
end

local function CheckForCertainDayReminders()
        --will fire at login to check the day
        local dayReminders = db.reminders.day
        for i = 1, #dayReminders do
                local reminder = dayReminders[i]
                --if reminder.day == CalendarGetDate() and ShouldShowReminder(reminder)then     --stored and recalled as the weekday index (1-7)
                if reminder.day == C_Calendar.GetDate().weekday and ShouldShowReminder(reminder)then    --stored and recalled as the weekday index (1-7)
                        tinsert(sRD, reminder.data)
                        BiM.DisplayReminder(reminder.data)
                end
        end
end

local function CheckForCertainTimeReminders()
        --will fire at one-minute intervals to check the time
        if #db.reminders.time > 0 then
                local timeReminders = db.reminders.time
                for i = 1, #timeReminders do
                        local reminder = timeReminders[i]
                        if reminder.time == GameTime_GetTime(true) and ShouldShowReminder(reminder) then
                                tinsert(sRD, reminder.data)
                                BiM.DisplayReminder(reminder.data)
                        end
                end
        end
        C_Timer.After(60, CheckForCertainTimeReminders) --keep polling every minute
end

local function CheckForLoginReminders()
        --will fire at at login
        local loginReminders = db.reminders.login
        for i = 1, #loginReminders do
                local reminder = loginReminders[i]
                if ShouldShowReminder(reminder) then
                        tinsert(sRD, reminder.data)
                        BiM.DisplayReminder(reminder.data)
                end
        end
end

local function CheckForCalendarEvents(dateTable)
        --will fire at login if calendar checks enabled
        local curYear, curMonth, curDate = dateTable.year, dateTable.month, dateTable.monthDay
        local curDateStamp = string.format("%d%d%d", curYear, curMonth, curDate)
        local calReminders = db.calReminders
        
        --[[CalendarSetAbsMonth(curMonth, curYear)
        OpenCalendar()
        --
        CalendarFrame_Update()]]--
        
        --collect the day's events
        --local numEvents = CalendarGetNumDayEvents(0, curDate)
        local numEvents = C_Calendar.GetNumDayEvents(0, curDate)
        --print(numEvents, "today")
        local curEvents = {}
        for i = 1, numEvents do
                --local title, _,_, calType = CalendarGetDayEvent(0, curDate, i)
                local eventTable = C_Calendar.GetDayEvent(0, curDate, i)
                --tinsert(curEvents, {name = "Calendar"..i, data = {text = title, icon = calIcon}})
                tinsert(curEvents, {name = "Calendar"..i, data = {text = eventTable.title, icon = calIcon}})
        end
        
        --loop through saved list
        for i, r in pairs(calReminders) do
                r.current = false
                for j, event in pairs(curEvents) do     --compare with current day's events
                        if r.data.text == event.data.text then  --if a previously shown event is a current event
                                --print(r.data.text, "still ongoing")
                                curEvents[j] = nil      --remove from this table, already matched
                                r.current = true
                                break   --break out of loop (match found) and leave in calReminders table
                        end
                end
                if r.lastShown and curDateStamp - r.lastShown > 0 then
                        if not r.current then   --not a current day's event
                                --print("old event -", r.data.text, "- last shown", curDateStamp - r.lastShown, "days ago", "- current:", r.current)
                                calReminders[i] = nil   --remove from saved table - old event
                        end
                end
        end
        
        --if there are new current events today (that wouldn't have been matched with the saved table)
        if #curEvents > 0 then
                for k, v in pairs(curEvents) do
                        --print("new event - adding", v.data.text)
                        tinsert(calReminders, v)        --add to saved list
                end
        end
        
        --display reminders
        local crNum, crShow = 0, 0
        for k, v in pairs(calReminders) do
                crNum = crNum+1
                if db.calendarShowAlways or v.lastShown ~= curDateStamp then    --one last check to see if we want to show the saved event
                        v.lastShown = curDateStamp      --shown today - update date stamp
                        tinsert(sRD, v.data)
                        BiM.DisplayReminder(v.data)
                        crShow = crShow+1
                end
        end
        --print("showing", crShow, "/", crNum, "total")
end

function BiM.PlayerLogin()
        db = BearInMindDB
        pcdb = BearInMindPCDB
        
        --set up anchor frame
        anchor:SetSize(280, 50)
        anchor:SetPoint(db.anchor, UIParent, db.anchor, db.offsetX, db.offsetY)
        anchor:SetScale(db.scale)
        anchor.bg = anchor:CreateTexture()
        anchor.bg:SetAllPoints(anchor)
        anchor:SetClampedToScreen(true)
        if db.lock then
                anchor.bg:SetColorTexture(0,0,1,0)
                anchor:EnableMouse(false)
        else
                anchor.bg:SetColorTexture(0,0,1,.4)
                anchor:EnableMouse(true)
                anchor:SetMovable(true)
        end
        anchor:SetScript("OnMouseDown", function(self)
                        if not db.lock then
                                anchor:StartMoving()
                        end
                end)
        anchor:SetScript("OnMouseUp", function(self)
                        self:StopMovingOrSizing()
                        db.anchor, _, _, db.offsetX, db.offsetY = anchor:GetPoint()
                end)
        
        --check for at login reminders
        CheckForLoginReminders()
        --check for any reminders for today specifically
        CheckForCertainDayReminders()
        --check for login/current zone reminders
        CheckForZoneReminders()
        --listen for event reminders
        local eventReminders = db.reminders.event
        for i = 1, #eventReminders do
                if eventReminders[i].event then
                        eventFrame:RegisterEvent(eventReminders[i].event)
                end
        end
        --check for any reminders for a certain time and start C_Timer.After
        CheckForCertainTimeReminders()
        --check for calendar events
        if db.calendar then
                --local _, curMonth, curDate, curYear = CalendarGetDate()
                local dateTable = C_Calendar.GetDate()
                --CalendarSetAbsMonth(curMonth, curYear)
                C_Calendar.SetAbsMonth(dateTable.month, dateTable.year)
                --OpenCalendar()
                C_Calendar.OpenCalendar()
                --
                CalendarFrame_Update()

                --C_Timer.After(2, function() CheckForCalendarEvents(curMonth, curDate, curYear) end)
                C_Timer.After(2, function() CheckForCalendarEvents(dateTable) end)
                --CheckForCalendarEvents(curMonth, curDate, curYear)
        end
end

local zoneEvents = {
        ["ZONE_CHANGED"] = true,
        ["ZONE_CHANGED_NEW_AREA"] = true,
        ["ZONE_CHANGED_INDOORS"] = true,
        ["PLAYER_ENTERING_WORLD"] = true,
}
for k,v in pairs(zoneEvents) do
        eventFrame:RegisterEvent(k)
end

eventFrame:SetScript("OnEvent", function(self, event, ...)
        if zoneEvents[event] then
                CheckForZoneReminders()
        end
        CheckForOnEventReminders(event)
end)

Compare with Previous | Blame