lotrointerface.com
Search Downloads

LoTROInterface SVN Reminders

[/] [trunk/] [Thurallor/] [Reminders/] [Event.lua] - Rev 8

Compare with Previous | Blame | View Log

Event = class(Turbine.Object);

-- static function (doesn't require instance)
function Event.GetCoords(locationStr)
    local y, yd = locationStr:match "(%d+%.?%d*)([NSns])";
    local x, xd = locationStr:match "(%d+%.?%d*)([EWOewo])";
    if (x and y) then
        local coords = string.upper(y .. yd .. ", " .. x .. xd);
        x, y = tonumber(x), tonumber(y);
        if (yd:upper() == "S") then
            y = -y;
        end
        if (xd:upper() == "W") then
            x = -x;
        end
        return x, y, coords;
    end
end

function Event:Constructor(tab, settings)
    Turbine.Object.Constructor(self);
    local player = Turbine.Gameplay.LocalPlayer.GetInstance();

    self.tab = tab;
    self.window = tab.window;
    self.loggedInCharID = Turbine.Engine.GetServerID() .. "." .. player:GetName();
    self.settings = settings;

    if (not settings.postpone) then
        settings.postpone = {
            method = self.window.settings.postpone.method;
            delay = self.window.settings.postpone.delay;
        };
    end

    self:SetWantsTicks(true);
end

function Event:GetCells()
    return self.cells;
end

function Event:GetToolTip()
    -- Temporarily enable "show negative times", because we always want to do so in the tooltip.
    local showNegativeTimes = self.window.settings.showNegativeTimes;
    self.window.settings.showNegativeTimes = true;
    self:UpdateTimeRemaining();

    -- Use the TableControl to construct the tooltip
    local rowContainer = self.tab.table:GetRow(self);
    local tooltip = self.tab.table:_GetToolTip(rowContainer);
    
    -- Restore the user's "show negative times" setting.
    self.window.settings.showNegativeTimes = showNegativeTimes;
    self:UpdateTimeRemaining();

    -- Apply the category color to all text in the tooltip
    local color = self:GetColor();
    local lines = tooltip:GetControls();
    for l = 1, lines:GetCount() do
        local line = lines:Get(l);
        local cells = line:GetControls();
        for c = 1, cells:GetCount() do
            local cell = cells:Get(c);
            cell:SetForeColor(color);
            cell:SetFontStyle(Turbine.UI.FontStyle.Outline);
            cell:SetOutlineColor(Turbine.UI.Color.Black);
            cell:SetMouseVisible(false);
        end
        line:SetMouseVisible(false);
    end

    -- Make a nice border / background
    local container = Turbine.UI.Control();
    local border = Turbine.UI.Lotro.TextBox();
    container:SetBackColor(self.tab:GetCellColor());
    border:SetMouseVisible(false);
    border:SetEnabled(false);
    local w, h = tooltip:GetSize();
    tooltip:SetBackColor(nil);
    container:SetSize(w, h + 6);
    border:SetSize(w, h + 6);
    border:SetParent(container);
    tooltip:SetParent(container);
    tooltip:SetPosition(0, 3);
    
    tooltip.MouseClick = function(_, args)
        container:MouseClick(args);
    end

    return container;
end

function Event:SelectionGained()
    if (self.popup) then
        self.popup:SelectionGained();
    end
end

function Event:SelectionLost()
    if (self.popup) then
        self.popup:SelectionLost();
    end
end

function Event:CleanupDropDowns()
    self.tab:CleanupDropDowns();
end

function Event:SetCells(cells)
    cells = cells or {};
    self.cells = cells;

    -- Event handlers for "Checkbox" cell
    local checkBox = Turbine.UI.Lotro.CheckBox();
    checkBox:SetParent(cells.checkbox);
    checkBox:SetZOrder(1);
    checkBox:SetSize(16, 16);
    checkBox.CheckedChanged = function(ctl)
        self.settings.checked = ctl:IsChecked();
        cells.checkbox.sortValue = (self.settings.checked and 1) or 0;
        self:SaveSettings();
        self.tab:ReapplySort("checkbox");
    end
    checkBox.FocusGained = function(ctl)
        self:CleanupDropDowns();
    end
    cells.checkbox.box = checkBox;
    cells.checkbox.FocusGained = checkBox.FocusGained;
    function cells.checkbox.SetWidth(ctl, width)
        Turbine.UI.Lotro.TextBox.SetWidth(ctl, width);
        ctl.box:SetPosition(width - 19, 4);
    end
    cells.checkbox.FocusGained = checkBox.FocusGained;
    cells.checkbox:SetWidth(cells.checkbox:GetWidth());
    
    -- Event handlers for "Description" cell
    cells.desc:SetReadOnly(false);
    cells.desc.FocusGained = function(ctl)
        self:CleanupDropDowns();
        ctl:SetForeColor(Turbine.UI.Color.White);
        ctl:SetWantsKeyEvents(true);
    end
    cells.desc.KeyDown = function(ctl, args)
        if (args.Action == Turbine.UI.Lotro.Action.EnterKey) then
            ctl:GetParent():Focus();
        elseif (args.Action == Turbine.UI.Lotro.Action.Escape) then
            ctl:SetText(self.settings.desc);
            ctl:GetParent():Focus();
        end
    end
    cells.desc.FocusLost = function(ctl)
        ctl:SetWantsKeyEvents(false);
        self:SetCategory(self.settings.category); -- restore color
        self.settings.desc = ctl:GetText();
        self:SaveSettings();
        self.tab:ReapplySort("desc");
    end

    -- Event handlers for "Location" cell
    cells.location:SetReadOnly(false);
    cells.location.FocusGained = function(ctl)
        self:CleanupDropDowns();
        ctl:SetForeColor(Turbine.UI.Color.White);
        Turbine.UI.Lotro.TextBox.SetText(ctl, ctl.fullText);
        ctl:SetWantsKeyEvents(true);
    end
    cells.location.KeyDown = function(ctl, args)
        if (args.Action == Turbine.UI.Lotro.Action.EnterKey) then
            ctl:GetParent():Focus();
        elseif (args.Action == Turbine.UI.Lotro.Action.Escape) then
            ctl:SetText(self.settings.location);
            ctl:GetParent():Focus();
        end
    end
    cells.location.FocusLost = function(ctl)
        ctl:SetWantsKeyEvents(false);
        self:SetCategory(self.settings.category); -- restore color
        local text = Turbine.UI.Lotro.TextBox.GetText(ctl);
        if (text == "") then
            text = nil;
        end
        ctl:SetText(text);
        self.settings.location = text;
        self:SaveSettings();
        self.tab:ReapplySort("location");
    end
    function cells.location.GetText(ctl)
        return ctl.fullText;
    end
    function cells.location.SetText(ctl, fullText)
        ctl.fullText = fullText;
        ctl.coords = nil;
        ctl.shortText = nil;
        if (fullText) then
            ctl.x, ctl.y, ctl.coords = Event.GetCoords(fullText);
            ctl.shortText = ctl.coords or fullText:match(": ([^:]+)$");
            local label = Turbine.UI.Label();
            label:SetText(fullText);
            label:SetFont(ctl:GetFont());
            label:AutoSize();
            ctl.fullWidth = label:GetWidth();
            ctl.sortValue = ctl.coords or ctl.fullText or "";
            ctl:SetWidth(ctl:GetWidth()); -- update text with coords or fulltext, based on width
        else
            Turbine.UI.Lotro.TextBox.SetText(ctl, "―");
        end
    end
    function cells.location.SetWidth(ctl, width)
        Turbine.UI.Lotro.TextBox.SetWidth(ctl, width);
        if (ctl.fullText) then
            Turbine.UI.Lotro.TextBox.SetText(ctl, ctl.fullText);
            if (ctl.fullWidth and (width < ctl.fullWidth) and ctl.shortText) then
                Turbine.UI.Lotro.TextBox.SetText(ctl, ctl.shortText);
            end
        end
    end

    -- Event handlers for "Distance" cell
    cells.distance.GetText = function(ctl)
        -- If distance is unknown, don't show it in the tooltip.
        if (ctl.sortValue ~= math.huge) then
            return Turbine.UI.Lotro.TextBox.GetText(ctl);
        end
    end
    
    -- Event handlers for "Character" cell
    cells.charName.FocusGained = function(ctl)
        self:CleanupDropDowns();
        local charNamesWithServers, charIDs = self.window:GetCharNamesWithServers()
        local dropDown = Thurallor.UI.DropDown(charNamesWithServers, self.window:GetCharNameWithServer(self:GetCharacterID()));
        dropDown.charIDs = charIDs;
        dropDown:SetParent(ctl);
        dropDown:SetFont(Turbine.UI.Lotro.Font.Verdana14);
        dropDown:SetZOrder(2);
        dropDown:SetPosition(1, 1);
        local width = ctl:GetWidth() - 2;
        dropDown:SetSize(ctl:GetWidth() - 2, ctl:GetHeight() - 2);
        dropDown:SetExpandedWidth(math.max(width, 200));
        dropDown.ItemChanged = function(dd, args)
            local nameWithServer = args.Text;
            local charID = dd.charIDs[nameWithServer];
            self:SetCharacterID(charID);
            self:UpdateTimeRemaining();        -- "remaining" can have different value depending on char
            self:SaveSettings();
            self.tab:ReapplySort("charName");
            self.tab:ReapplySort("serverID");
            self.tab:ReapplySort("remaining");
        end
        dropDown:SetWantsKeyEvents(true);
        dropDown.KeyDown = function(_, args)
            if ((args.Action == Turbine.UI.Lotro.Action.EnterKey) or
                (args.Action == Turbine.UI.Lotro.Action.Escape)) then
                self:CleanupDropDowns();
                local parent = ctl:GetParent();
                if (parent) then
                    parent:Focus();
                end
            end
        end
        ctl.dropDown = dropDown;
        self.tab.dropDownCtl = ctl;
    end
    function cells.charName.SetWidth(ctl, width)
        Turbine.UI.Lotro.TextBox.SetWidth(ctl, width);
        if (ctl.dropDown) then
            ctl.dropDown:SetWidth(width - 2);
        end
    end
    
    -- Event handlers for "Server" cell
    -- none (read only)
    
    -- Event handlers for "Remaining time" cell
    cells.remaining.FocusGained = function(ctl)
        self:CleanupDropDowns();
        local dialog = ExpireTimeDialog(self);
        dialog.Ok = function(_, args)
            self:SetExpirationTime(args.expTime);
            self:SaveSettings();
            self.tab:ReapplySort("remaining");
        end
        ctl:GetParent():Focus(); -- avoid reopening the dialog when the dialog closes and we regain focus
    end
    cells.remaining.GetText = function(ctl)
        -- if time is "never", don't show the time in the tooltip
        if (self.settings.expTime ~= -1) then
            return Turbine.UI.Lotro.TextBox.GetText(ctl);
        end
    end

    -- Event handlers for "Next reset" cell
    cells.resetTimes.FocusGained = function(ctl)
        self:CleanupDropDowns();
        local dialog = ResetTimesDialog(self);
        dialog.Ok = function(_, args)
            self:SetResetTimes(args.resetTimes);
            self:SetRotation(args.rotation);
            self:SaveSettings();
            self.tab:ReapplySort("resetTimes");
        end
        ctl:GetParent():Focus(); -- avoid reopening the dialog when the dialog closes and we regain focus
    end
    cells.resetTimes.GetText = function(ctl)
        -- if time is "never", don't show the time in the tooltip
        if (self.settings.resetTimes) then
            return Turbine.UI.Lotro.TextBox.GetText(ctl);
        end
    end

    -- Event handlers for "Category" cell
    cells.category.FocusGained = function(ctl)
        self:CleanupDropDowns();
        local catNames = self.window:GetUserCategories();
        local dropDown = Thurallor.UI.DropDown(catNames, self.settings.category);
        dropDown:SetParent(ctl);
        dropDown:SetFont(Turbine.UI.Lotro.Font.Verdana14);
        dropDown:SetZOrder(2);
        dropDown:SetPosition(1, 1);
        local width = ctl:GetWidth() - 2;
        dropDown:SetSize(ctl:GetWidth() - 2, ctl:GetHeight() - 2);
        dropDown:SetExpandedWidth(math.max(width, 200));
        dropDown.ItemChanged = function(_, args)
            self:SetCategory(args.Text);
            self:SaveSettings();
            self.tab:ReapplySort("category");
        end
        dropDown:SetWantsKeyEvents(true);
        dropDown.KeyDown = function(_, args)
            if ((args.Action == Turbine.UI.Lotro.Action.EnterKey) or
                (args.Action == Turbine.UI.Lotro.Action.Escape)) then
                self:CleanupDropDowns();
                ctl:GetParent():Focus();
            end
        end
        ctl.dropDown = dropDown;
        self.tab.dropDownCtl = ctl;
    end
    function cells.category.SetWidth(ctl, width)
        Turbine.UI.Lotro.TextBox.SetWidth(ctl, width);
        if (ctl.dropDown) then
            ctl.dropDown:SetWidth(width - 2);
        end
    end

    -- Event handlers for "Notes" cell
    cells.notes.FocusGained = function(ctl)
        self:CleanupDropDowns();
        local dialog = NotesDialog(self);
        dialog.Ok = function(_, args)
            if (args.text == "") then
                args.text = nil;
            end
            self:SetNotes(args.text);
            self:SaveSettings();
            self.tab:ReapplySort("notes");
        end
        ctl:GetParent():Focus(); -- avoid reopening the dialog when the dialog closes and we regain focus
    end
    cells.notes.GetText = function(ctl)
        return self.settings.notes;
    end

    -- Fill in the values
    self:SetChecked(self.settings.checked);
    self:SetDescription(self.settings.desc);
    self:SetCharacterID(self.settings.charID);
    self:SetExpirationTime(self.settings.expTime, true);
    self:SetResetTimes(self.settings.resetTimes);
    self:SetRotation(self.settings.rotation);
    self:SetCategory(self.settings.category);
    self:SetLocation(self.settings.location);
    self:SetNotes(self.settings.notes);
end

-- if 'ifOpen' is specified, then the window won't be opened if it wasn't already so, but you'll see the event selected next time you open the window
function Event:ZoomToEvent(fromCtl, ifOpen)
    local tab = self.tab;
    local window = tab.window;
    if (not ifOpen) then
        window:SetVisible(true);
    end
    window:BringTabToFront(tab.settings.name);
    tab:SetVisible(true);
    tab:SelectEvent(nil);
    tab:EnsureEventVisible(self);
    if (window:IsVisible()) then
        local tableRow = tab.table:GetRow(self);
        self.zoomer = Thurallor.UI.Zoomer(fromCtl, tableRow);
        self.zoomer.ZoomComplete = function()
            window:Activate();
            tab:SelectEvent(self);
            self.zoomer = nil;
        end
    else
        tab:SelectEvent(self);
    end
end

function Event:SaveSettings(now)
    self.tab:SaveSettings(now);
end

function Event:GetDescription()
    return self.settings.desc;
end

function Event:SetDescription(desc)
    self.settings.desc = desc;
    local cell = self.cells["desc"];
    if (cell) then
        cell:SetText(desc);
    end
end

function Event:GetLocation()
    local cell;
    if (self.cells) then
        cell = self.cells["location"];
    end
    return self.settings.location, cell and cell.coords;
end

function Event:SetLocation(loc)
    if (loc == "") then
        loc = nil;
    end
    self.settings.location = loc;
    local cell = self.cells["location"];
    if (cell) then
        cell:SetText(loc);
        cell.sortValue = cell.coords or cell.fullText or "";
    end
end

function Event:IsChecked()
    return self.settings.checked;
end

function Event:SetChecked(checked)
    self.settings.checked = checked;
    local cell = self.cells["checkbox"];
    if (cell) then
        cell.box:SetChecked(checked);
        cell.sortValue = (self.settings.checked and 1) or 0;
    end
end

function Event:GetCharacterID()
        return self.settings.charID;
end

function Event:SetCharacterID(charID)
    self.settings.charID = charID;
        local serverID, charName = charID:match("^(.*)%.(.*)$");
    local charCell, serverCell = self.cells.charName, self.cells.serverID;
    if (charCell) then
        charCell:SetText(charName);
    end
    if (serverCell) then
        local serverName = Turbine.Engine:GetServerName(serverID) or serverID;
        serverCell:SetText(serverName);
    end
end

function Event:GetExpirationTime()
    return self.settings.expTime;
end

function Event:GetResetTimes()
    return self.settings.resetTimes;
end

function Event:GetRotation()
    return self.settings.rotation;
end

-- If 'startup' is true, the 'expired' flag will be left alone.
function Event:SetExpirationTime(expTime, startup)
    self.settings.expTime = expTime;
    if (not startup) then
        self:SetExpired(false);
    end
    self:UpdateTimeRemaining();
    self.nextResetTime = nil;
    self:UpdateResetTimeRemaining();
end

function Event:SetResetTimes(resetTimes)
    self.settings.resetTimes = resetTimes;
    self:_CreateSchedule();
end

function Event:SetRotation(rotation)
    self.settings.rotation = rotation;
    self:_CreateSchedule();
end

function Event:_CreateSchedule()
    local timeSpec = self.settings.rotation or self.settings.resetTimes;
    if (timeSpec) then
        self.resetSchedule = Schedule(timeSpec);
    else
        self.resetSchedule = nil;
    end
    self.nextResetTime = nil;
    self:UpdateResetTimeRemaining();
end

function Event:GetCategory()
    return self.settings.category;
end

function Event:SetCategory(category)
    self.settings.category = category
    local cell = self.cells["category"];
    if (cell) then
        cell:SetText(category);
    end

    -- Set foreground color of all cells based on category
    local color = self:GetColor();
    for _, cell in pairs(self.cells) do
        cell:SetForeColor(color);
    end
end

function Event:GetCategory()
    return self.settings.category;
end

function Event:GetNotes()
    return self.settings.notes;
end

function Event:SetNotes(notes)
    self.settings.notes = notes;
    local cell = self.cells["notes"];
    if (cell) then
        if (notes) then
            -- Show an abbreviation of the cell contents
            local firstLine = string.gsub(notes, "%.*%c.*$", "...");
            cell:SetText(firstLine);
        else
            cell:SetText("―");
        end
    end
end

function Event:GetColor()
    return self.window:GetCategoryColor(self.settings.category);
end

-- Returns true if the event belongs to the currently logged in character
function Event:IsMine()
    return (self:GetCharacterID() == self.loggedInCharID);
end

-- Used for self.settings.postpone.method =="DelayFromExpiration" to find
-- the next time after the current time that is a multiple of the specified
-- delay interval from the previous expiration time.
function Event:GetNextDelayMultiple()
    local interval = self.settings.postpone.delay;
    local currentTime = Time();
    local nextTime = Time(0):SetGameTime(self.settings.expTime + interval);
    if (nextTime:IsBefore(currentTime)) then
        nextTime:RestrictToWindow(currentTime:JustAfter(), interval);
    end
    return nextTime:GetGameTime();
end

function Event:Postpone()
    local expTime;
    if (self.settings.postpone.method =="DelayFromNow") then
        expTime = Turbine.Engine.GetGameTime() + self.settings.postpone.delay;
    elseif (self.settings.postpone.method =="DelayFromExpiration") then
        expTime = self:GetNextDelayMultiple();
    elseif (self.settings.postpone.method =="DailyResetTime") then
        expTime = Time():GetNextServerResetTime(true):GetGameTime();
    elseif (self.settings.postpone.method =="ScheduledResetTime") then
        expTime = self.nextResetTime or -1;
    elseif (self.settings.postpone.method =="Never") then
        expTime = -1;
    else -- (self.settings.postpone.method =="AtNextLogin")
        expTime = 0;
    end
    self:SetExpirationTime(expTime);
end

function Event:GetPostponeStr()
    local prevContext = L:SetContext("/PostponeTimeDialog/Tooltip");
    local text = L:GetText(self.settings.postpone.method or "AtNextLogin");
    local delay = self.settings.postpone.delay;
    local intervalStr = Time.GetDelayStr(delay);
    if (self.settings.postpone.method == "DelayFromExpiration") then
        local newTime = self:GetNextDelayMultiple();
        local multiple = math.floor(0.5 + (newTime - self.settings.expTime) / delay);
        delay = newTime - Turbine.Engine.GetGameTime();
        if (multiple > 1) then
            intervalStr = multiple .. " × (" .. intervalStr .. ")";
        end
    elseif (self.settings.postpone.method == "ScheduledResetTime") then
        if (self.nextResetTime) then
            delay = self.nextResetTime - Turbine.Engine.GetGameTime();
        else
            text = L:GetText("Never");
        end
    elseif (self.settings.postpone.method == "DailyResetTime") then
        delay = Time():GetNextServerResetTime(true):GetGameTime() - Turbine.Engine.GetGameTime();
    end
    L:SetContext(prevContext);
    return text:gsub("<delay>", Time.GetDelayStr(delay)):gsub("<interval>", intervalStr);
end

function Event:UpdateTimeRemaining()
    local cell = self.cells.remaining;
    if (cell) then
        if (self.settings.expTime == -1) then
            -- Special handling for "never" events:
            self:SetExpired(false); -- remove alert from icon tooltip
            self:SetWantsTicks(false); -- no need for updates, either
            cell.sortValue = 10000000000001; -- sort at the end of the table
            cell:SetText("―"); -- "Never"
        elseif (self.settings.expTime == 0) then
            -- Special handling for "at next login" events:
            self:SetExpired(false); -- remove alert from icon tooltip
            self:SetWantsTicks(false); -- no need for updates, either
            if (self:IsMine()) then
                cell.sortValue = 10000000000000; -- sort at the end for the current character
            else
                cell.sortValue = -10000000000000; -- sort at the beginning for other characters
            end
            cell:SetText(L:GetText("/Time/TimeDisplay/NextLogin"));
        else
            local remaining = self.settings.expTime - Turbine.Engine.GetGameTime();
            if (remaining <= 0) then
                self.nextResetTime = nil;
                self:SetExpired(true);
            end
            cell.sortValue = remaining;
            cell:SetText(Time.GetDelayStr(remaining, false, self.window.settings.showNegativeTimes));
        end
    end
end

function Event:UpdateResetTimeRemaining()
    local cell = self.cells.resetTimes;
    if (cell) then
        if (not self.resetSchedule) then
            cell.sortValue = 10000000000001; -- sort at the end of the table
            cell:SetText("―"); -- "Never"
            self.nextResetTime = nil;
        else
            if (not self.nextResetTime) then
                local expTime = Time(0):SetGameTime(self.settings.expTime);
                local prevTime = Time.max(Time(), expTime):AddSeconds(59);
                self.nextResetTime = self.resetSchedule:GetNextTime(prevTime, true):GetGameTime();
                cell.sortValue = self.nextResetTime;
            end
            local currentTime = Turbine.Engine.GetGameTime();
            cell:SetText(Time.GetDelayStr(self.nextResetTime - currentTime, false, self.window.settings.showNegativeTimes));
        end
    end
end

function Event:SetWantsTicks(wantsTicks)
    if (self.Tick) then
        if (not wantsTicks) then
            self.window:RemoveTickFunc(self.Tick);
            self.Tick = nil;
        end
    else
        if (wantsTicks) then
            self.Tick = function()
                self:UpdateTimeRemaining();
                self:UpdateResetTimeRemaining();
            end
            self.window:AddTickFunc(self.Tick);
        end
    end
end

function Event:IsExpired()
    return self.settings.expired;
end

function Event:SetExpired(expired)
    local wasExpired = self.settings.expired or false;
    self.settings.expired = expired;
    self:SaveSettings();
    if (expired ~= wasExpired) then
        DoCallbacks(self, "ExpiredChanged", expired);
    end
    self:SetWantsTicks((not expired) or self.window.settings.showNegativeTimes);
end

function Event:SetLastAutomaticUpdate(charID, itemType, item)
    self.settings.automatic = { charID, itemType, item, Turbine.Engine.GetGameTime() };
end

function Event:GetLastAutomaticUpdate()
    return self.settings.automatic;
end

function Event:ShowPopUp()
    if (not self.popup) then
        self.popup = NotificationDialog(self);
    end
end

function Event:HidePopUp()
    if (self.popup) then
        self.popup:Close();
        self.popup = nil;
    end
end

function Event:Destroy()
    self:HidePopUp();
    self:SetWantsTicks(false);
    DoCallbacks(self, "Destroyed");
--Puts("Destroying event: " .. self.settings.desc);
end

Compare with Previous | Blame


All times are GMT -5. The time now is 07:25 AM.


Our Network
EQInterface | EQ2Interface | Minion | WoWInterface | ESOUI | LoTROInterface | MMOUI | Swtorui