lotrointerface.com
Search Downloads

LoTROInterface SVN Reminders

[/] [trunk/] [Thurallor/] [Reminders/] [Tab.lua] - Rev 9

Compare with Previous | Blame | View Log

Tab = class(Thurallor.UI.TabCard);

local importPath = getfenv(1)._.Name;
local imagePath = string.gsub(string.gsub(importPath, "%.Tab$", ""), "%.", "/") .. "/Images/";

function Tab:Constructor(window, settings)
    Thurallor.UI.TabCard.Constructor(self, false, false, true, true);
    self.window = window;

    AddCallback(self.tabText, "MouseEnter", function(ctl)
        self.window.shimmering:Remove(ctl);
    end);

    self.settings = self:UpdateSettings(settings);
    self:SetTabText(settings.name);
    self:SetTabLeft(settings.tabLeft);

    self.table = Thurallor.UI.TableControl();

    -- Apply user's color preference to tab and table
    color = Thurallor.Utils.Color(unpack(self.settings.color));
    self.color = color;
    local H, S, V = color:GetHSV();
    color:SetHSV(H, S, 1);
    local A, R, G, B = 1, color.R, color.G, color.B;
    self:SetTabColor(Turbine.UI.Color(A, R, G, B));
    self:SetBackColor(Turbine.UI.Color(A, R/6, G/6, B/6));
    local style = self.table:GetStyle();
    style.heading.BackColor = Turbine.UI.Color(A, R*2/3, G*2/3, B*2/3);
    style.heading.HighlightColor = Turbine.UI.Color(A, R, G, B);
    style.cell.BackColor = Turbine.UI.Color(A, R/3, G/3, B/3);
    style.cell.HighlightColor = Turbine.UI.Color(A, R, G, B);
    style.edgeMover.BackColor = Turbine.UI.Color(A*3/4, R/3, G/3, B/3);
    style.marquee.Color = color:SetHSV(H, S, 0.75);
    style.marquee.AntsEnabled = window.settings.marqueeAntsEnabled or false;
    self.table:SetStyle(style);
    
    self.table:SetParent(self);
    local function valueSort(a, b)
        local aValue, bValue = a.sortValue, b.sortValue;
        if (aValue < bValue) then
            return -1;
        elseif (aValue > bValue) then
            return 1;
        else
            return 0;
        end
    end
    local prevContext = L:SetContext("/MainWindow/ColumnHeadings");
    self.table:AddColumn("checkbox", L:GetText("Checkbox"), 0.5, valueSort);
    self.table:AddColumn("desc", L:GetText("Description"), 2, nil);
    self.table:AddColumn("location", L:GetText("Location"), 1, valueSort);
    self.table:AddColumn("distance", L:GetText("Distance"), 1, valueSort);
    self.table:AddColumn("category", L:GetText("Category"), 1, nil);
    self.table:AddColumn("charName", L:GetText("Character"), 1, nil);
    self.table:AddColumn("serverID", L:GetText("Server"), 0, nil);
    self.table:AddColumn("remaining", L:GetText("Time"), 1, valueSort);
    self.table:AddColumn("resetTimes", L:GetText("NextReset"), 1, valueSort);
    self.table:AddColumn("notes", L:GetText("Notes"), 0, nil);
    AddCallback(self.table, "PresentationChanged", function(_, args)
        self.settings.presentation = self.table:GetPresentation();
        self:SaveSettings();
    end);
    AddCallback(self.table, "SelectionChanged", function(_, args)
        self:SelectionChanged(args);
    end);
    
    -- Configure the column heading for the "Checkbox" column
    local heading = self.table:GetHeading("checkbox");
    heading:SetText("");
    heading.GetText = function() return L:GetText("/MainWindow/ColumnHeadings/Checkbox"); end;
    local checkBox = Turbine.UI.Lotro.CheckBox();
    checkBox:SetParent(heading);
    checkBox:SetZOrder(1);
    checkBox:SetSize(16, 16);
    checkBox.CheckedChanged = function(ctl)
        if (not self.table.IsColumnLocked("checkbox")) then
            local checked = ctl:IsChecked();
            self:ForEachEventDo(function(event) event:SetChecked(checked); end);
        end
    end
    function heading.SetWidth(ctl, width)
        Turbine.UI.Lotro.TextBox.SetWidth(ctl, width);
        checkBox:SetPosition(width - 19, 4);
    end
    heading:SetWidth(heading:GetWidth());

    -- Configure the column heading for the "Distance" column
    local heading = self.table:GetHeading("distance");
    AddCallback(heading, "MouseEnter", function(ctl)
        if (not self.table:IsColumnLocked("distance")) then
            self.calc_icon:SetBackground(self.calc_icon.bgNormal);
            self.calc_icon:SetParent(ctl:GetParent());
            self.calc_icon:SetVisible(true);
            self.calc_icon:SetPosition(ctl:GetLeft() + ctl:GetWidth() - 23, 1);
            self.calc_icon:SetZOrder(4);
            self.window.LocationChanged = function()
                self:UpdateDistanceColumn(self.window.location);
            end
            ctl:SetWantsUpdates(true);
        end
    end);
    -- In lieu of MouseLeave event handler:
    AddCallback(heading, "Update", function(ctl)
        local x, y = ctl:GetMousePosition();
        local w, h = ctl:GetSize();
        if ((x < 0) or (y < 0) or (x >= w) or (y >= h)) then
            self.calc_icon:SetVisible(false);
            ctl:SetWantsUpdates(false);
        end
    end);
    L:SetContext(prevContext);
    
    self:SetInteriorControl(self.table);
    self:SetInteriorAlignment(Turbine.UI.ContentAlignment.TopLeft);
    
    -- Create row overlay icons: X, settings, reset, target, waypoint, calculate
    self.x_icon = self:CreateIcon(Turbine.UI.Control(), "x.tga", "x_highlight.tga");
    Thurallor.UI.Tooltip(L:GetText("/MainWindow/DeleteThisReminder")):Attach(self.x_icon);
    self.settings_icon = self:CreateIcon(Turbine.UI.Control(), "settings.tga", "settings_highlight.tga");
    Thurallor.UI.Tooltip(function()
        local _, _, _, gameTime = unpack(self.settings_icon.event:GetLastAutomaticUpdate());
        local interval = Turbine.Engine.GetGameTime() - gameTime;
        local intervalStr = Time.GetDelayStr(interval, false, true);
        return L:GetText("/MainWindow/AutomaticReminderSettings"):gsub("<interval>", intervalStr);
    end):Attach(self.settings_icon);
    self.reset_icon = self:CreateIcon(Turbine.UI.Control(), "next_login.tga", "next_login_highlight.tga");
    Thurallor.UI.Tooltip(function()
        return self.reset_icon.event:GetPostponeStr() .. "\n" .. L:GetText("/PostponeTimeDialog/TooltipRightClick");
    end):Attach(self.reset_icon);
    local cmd = "/" .. L:GetText("/ShellCommand/Command") .. " " .. L:GetText("/ShellCommand/SetLoc") .. " " .. L:GetClientLanguageText("/Chat/loc");
    local baseCtl = Thurallor.UI.TrickButton(cmd, Turbine.ChatType.Standard, nil);
    self.target_icon = self:CreateIcon(baseCtl, "location.tga", "location_highlight.tga");
    local tooltip = Thurallor.UI.Tooltip(L:GetText("/MainWindow/DetectLocation"));
    tooltip:Attach(self.target_icon);
    tooltip:SetWantsUpdates(true);
    baseCtl = Thurallor.UI.TrickButton(cmd, Turbine.ChatType.Standard, nil);
    self.calc_icon = self:CreateIcon(baseCtl, "calc.tga", "calc_highlight.tga");
    Thurallor.UI.Tooltip(L:GetText("/MainWindow/CalculateDistances")):Attach(self.calc_icon);
    baseCtl = Thurallor.UI.TrickButton("/way", Turbine.ChatType.Standard, nil);
    self.waypoint_icon = self:CreateIcon(baseCtl, "waypoint.tga", "waypoint_highlight.tga");
    Thurallor.UI.Tooltip(L:GetText("/MainWindow/SetWaypointTarget")):Attach(self.waypoint_icon);
    
    self.events = {};
    self:SendToBack();
    self:CreateSavedEvents();
    self:UpdateDistanceColumn();
    self.table:SetPresentation(self.settings.presentation);
end

function Tab:GetHighlightColor()
    local style = self.table:GetStyle();
    return style.cell.HighlightColor;
end

function Tab:GetCellColor()
    local style = self.table:GetStyle();
    return style.cell.BackColor;
end

function Tab:Click(args)
    if (args.Button == Turbine.UI.MouseButton.Left) then
        self.window.settings.frontTab = self.settings.name;
        self:SaveSettings();
    elseif (args.Button == Turbine.UI.MouseButton.Right) then
        self:ShowTabContextMenu();
    end
end

function Tab:DoubleClick(args)
    if (args.Button == Turbine.UI.MouseButton.Left) then
        self:OpenRenameDialog();
    end
end

-- Fill in any new settings that have been added if the plugin has been updated
function Tab:UpdateSettings(settings)

    settings = settings or {};
    settings.color = settings.color or { 1, 0, 0.57, 1};
    settings.presentation = settings.presentation or {};
    settings.presentation.columns = settings.presentation.columns or {
        { "desc", 3 }, { "category", 1 }, { "charName", 1 }, { "remaining", 1 },
    };
    settings.tabLeft = settings.tabLeft or 0;
    settings.events = settings.events or {};
    if (settings.updateIcon == nil) then
        settings.updateIcon = true;
    end

    return settings;
end

function Tab:ShowTabContextMenu(fromSettingsWindow)
    local contextMenu = Turbine.UI.ContextMenu();
    local menuItems, item = contextMenu:GetItems();
    local prevContext = L:SetContext("/MainWindow/TabContextMenu");

    if (not fromSettingsWindow) then
        item = Turbine.UI.MenuItem(L:GetText("CreateTab"));
        item.Click = function()
            self.window:CreateNewTab();
        end
        menuItems:Add(item);
    end

    item = Turbine.UI.MenuItem(L:GetText("CreateItinerary") .. "...");
    item.Click = function()
        self:OpenItineraryDialog();
    end
    menuItems:Add(item);

    item = Turbine.UI.MenuItem(L:GetText("RenameTab"));
    item.Click = function()
        self:OpenRenameDialog();
    end
    menuItems:Add(item);

    item = Turbine.UI.MenuItem(L:GetText("Color"));
    item.Click = function()
        self:OpenColorPicker();
    end
    menuItems:Add(item);
    
    item = Turbine.UI.MenuItem(L:GetText("CloneTab"));
    item.Click = function()
        self.window:CloneTab(self.settings.name);
    end
    menuItems:Add(item);

    local tabNames = self.window:GetUserTabs();
    if (#tabNames > 1) then
        item = Turbine.UI.MenuItem(L:GetText("MergeWithOtherTab"));
        menuItems:Add(item);
        local subItems = item:GetItems();
        for _, name in ipairs(tabNames) do
            if (name ~= self.settings.name) then
                local subItem = Turbine.UI.MenuItem(name);
                subItem.Click = function(ctl)
                    self.window:MergeTabs(self.settings.name, ctl:GetText());
                end
                subItems:Add(subItem);
            end
        end
    end
    
    item = Turbine.UI.MenuItem(L:GetText("DeleteTab"));
    item.Click = function()
        if (self.window.settings.askBeforeDeleting) then
            if (not self.confirmDialog) then
                self.confirmDialog = ConfirmDialog(self.window, L:GetText("/MainWindow/TabContextMenu/DeleteTab"));
                self.confirmDialog.Yes = function(_, arg)
                    self.window:DeleteTab(self.settings.name);
                    self.confirmDialog = nil;
                end
                self.confirmDialog.No = function(_, arg)
                    self.confirmDialog = nil;
                end
            end
        else
            self.window:DeleteTab(self.settings.name);
        end
    end
    menuItems:Add(item);
    if (self.window:GetNumUserTabs() < 2) then
        -- Can't delete last remaining tab.
        item:SetEnabled(false);
    end

    item = Turbine.UI.MenuItem(L:GetText("OtherOptions"));
    item.Click = function(ctl)
        self.window.optionsPanel:ShowTabSettings(self.settings.name);
        self.window.optionsPanel:SetVisible(false);
        self.zoomer = Thurallor.UI.Zoomer(self.tabText, self.window.optionsPanel);
        AddCallback(self.zoomer, "ZoomComplete", function()
            self.window.optionsPanel:SetVisible(true);
        end);
    end;
    menuItems:Add(item);

    L:SetContext(prevContext);
    contextMenu:ShowMenu();
end

function Tab:ShowEventContextMenu(event)
    local contextMenu = Turbine.UI.ContextMenu();
    local menuItems, item = contextMenu:GetItems();
    local prevContext = L:SetContext("/MainWindow/EventContextMenu");

    item = Turbine.UI.MenuItem(L:GetText("MoveToOtherTab"));
    menuItems:Add(item);
    if (self.window:GetNumUserTabs() == 1) then
        item:SetEnabled(false);
    else
        -- Submenu with a list of tabs
        local subMenuItems = item:GetItems();
        local tabNames = self.window:GetUserTabs();
        for _, name in ipairs(tabNames) do
            if (name ~= self.settings.name) then
                local subItem = Turbine.UI.MenuItem(name);
                subItem.Click = function()
                    local otherTab = self.window:GetTab(name);
                    otherTab:CloneEvent(event);
                    self:DeleteEvent(event);
                end
                subMenuItems:Add(subItem);
            end
        end
    end

    item = Turbine.UI.MenuItem(L:GetText("CopyToOtherTab"));
    menuItems:Add(item);
    if (self.window:GetNumUserTabs() == 1) then
        item:SetEnabled(false);
    else
        -- Submenu with a list of tabs
        local subMenuItems = item:GetItems();
        local tabNames = self.window:GetUserTabs();
        for _, name in ipairs(tabNames) do
            if (name ~= self.settings.name) then
                local subItem = Turbine.UI.MenuItem(name);
                subItem.Click = function()
                    local otherTab = self.window:GetTab(name);
                    otherTab:CloneEvent(event);
                end
                subMenuItems:Add(subItem);
            end
        end
    end
    
    local item = Turbine.UI.MenuItem(L:GetText("Clone"));
    item.Click = function()
        self:CloneEvent(event);
    end
    menuItems:Add(item);

    local item = Turbine.UI.MenuItem(L:GetText("Delete"));
    item.Click = function()
        self:DeleteEvent(event);
    end
    menuItems:Add(item);

    local item = Turbine.UI.MenuItem(L:GetText("AddDay"));
    item.Click = function()
        event:SetExpirationTime(event:GetExpirationTime() + 24 * 60 * 60);
        self:SaveSettings();
    end
    menuItems:Add(item);

    local item = Turbine.UI.MenuItem(L:GetText("AddWeek"));
    item.Click = function()
        event:SetExpirationTime(event:GetExpirationTime() + 7 * 24 * 60 * 60);
        self:SaveSettings();
    end
    menuItems:Add(item);
    
    L:SetContext(prevContext);
    contextMenu:ShowMenu();
end

function Tab:SetTabLeft(left)
    Thurallor.UI.TabCard.SetTabLeft(self, left);
    self.settings.tabLeft = left;
    self:SaveSettings();
end

function Tab:Rename(newName)
    if (newName ~= self.settings.name) then
        self.window:RenameTab(self.settings.name, newName);
    end    
end

function Tab:OpenRenameDialog()
    local win = Turbine.UI.Lotro.Window();
    win:SetText(L:GetText("/RenameTabDialog/Title"));
    win:SetSize(250, 100);
    win:SetVisible(true);
    win:SetZOrder(self.window:GetZOrder() + 1);
    local textBox = Turbine.UI.Lotro.TextBox();
    textBox:SetParent(win);
    textBox:SetPosition(5, 44);
    textBox:SetSize(240, 24);
    textBox:SetFont(Turbine.UI.Lotro.Font.Verdana14);
    textBox:SetTextAlignment(Turbine.UI.ContentAlignment.MiddleCenter);
    textBox:SetMultiline(false);
    textBox:SetText(self.settings.name);
    textBox:SelectAll();
    textBox:Focus();
    EnableEnterEscHandling(win);
    win.EnterKeyPressed = function(w)
        local newName = textBox:GetText();
        if ((newName == "") or (self.window:GetTab(newName) and (newName ~= self.settings.name))) then
            -- Unacceptable.
            textBox:SetText(self.settings.name);
            textBox:SelectAll();
            return;
        end
        w:Close();
        self:Rename(newName);
    end
    win.EscapeKeyPressed = function(w)
        w:Close();
    end
    win:Activate();
    self.window:WaitForChild(win);
    -- Position the window over the mouse cursor:
    self.window.mask:MouseClick();
end

function Tab:OpenItineraryDialog()
    local dialog = ItineraryDialog(self.window);
    self.window:WaitForChild(dialog);
    -- Position the window over the mouse cursor:
    self.window.mask:MouseClick();
end

function Tab:OpenColorPicker()
    local picker = Thurallor.UI.ColorPicker(self:GetTabColor());
    picker:SetZOrder(self.window:GetZOrder() + 1);
    picker:FreezeDimension("V", 0.6);
    picker.Accepted = function(p)
        local color = p:GetColor();
        self.settings.color = { color.A, color.R, color.G, color.B };
        self.window:RebuildTabs();
    end
    self.window:WaitForChild(picker);
    -- Position the window over the mouse cursor:
    self.window.mask:MouseClick();
end

function Tab:CreateIcon(baseControl, normalImage, highlightImage)
    local icon = baseControl;
    icon:SetBlendMode(Turbine.UI.BlendMode.Overlay);
    icon:SetSize(22, 22);
    icon.bgNormal = Turbine.UI.Graphic(imagePath .. normalImage);
    icon.bgHighlight = Turbine.UI.Graphic(imagePath .. highlightImage);
    
    function icon.IsMouseOver(ctl)
        local x, y = ctl:GetMousePosition();
        return ((x >= 0) and (y >= 0) and (x < 22) and (y < 22));
    end
    
    AddCallback(icon, "MouseEnter", function(ctl)
        ctl:SetBackground(ctl.bgHighlight);
    end);
    AddCallback(icon, "MouseLeave", function(ctl)
        ctl:SetBackground(ctl.bgNormal);
    end);
    
    return icon;
end

function Tab:ShowResetIcon(parent, left, top, event)
    self.reset_icon.event = event; -- needed for tooltip
    self.reset_icon:SetBackground(self.reset_icon.bgNormal);
    self.reset_icon:SetParent(parent);
    self.reset_icon:SetVisible(true);
    self.reset_icon:SetPosition(left, top);
    self.reset_icon:SetZOrder(4); -- in front of mask
    self.reset_icon.MouseClick = function(b, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            event:Postpone();
            self:ReapplySort("remaining");                    
            event:SaveSettings();
            b:SetVisible(false);
        elseif (args.Button == Turbine.UI.MouseButton.Right) then
            if (b.dialog) then
                b.dialog:Close();
            end
            b.dialog = PostponeTimeDialog(event);
            AddCallback(b.dialog, "Closing", function()
                b.dialog = nil;
            end);
        end
    end
    return self.reset_icon;
end

function Tab:ShowTargetIcon(parent, left, top, event)
    self.target_icon:SetBackground(self.target_icon.bgNormal);
    self.target_icon:SetParent(parent);
    self.target_icon:SetVisible(true);
    self.target_icon:SetPosition(left, top);
    self.target_icon:SetZOrder(4); -- in front of mask
    self.window.LocationChanged = function()
        event:SetLocation(self.window.location);
        event:SaveSettings();
    end
    return self.target_icon;
end

function Tab:ShowWaypointIcon(parent, left, top, event)
    local _, coords = event:GetLocation();
    if (coords and Turbine.Shell.IsCommand("waypoint")) then
        self.waypoint_icon:SetBackground(self.waypoint_icon.bgNormal);
        self.waypoint_icon:SetParent(parent);
        self.waypoint_icon:SetVisible(true);
        self.waypoint_icon:SetPosition(left, top);
        self.waypoint_icon:SetZOrder(4); -- in front of mask
        self.waypoint_icon:SetCommand("/way target " .. coords);
    end
    return self.waypoint_icon;
end

function Tab:ShowXIcon(parent, left, top, event)
    self.x_icon:SetBackground(self.x_icon.bgNormal);
    self.x_icon:SetParent(parent);
    self.x_icon:SetVisible(true);
    self.x_icon:SetPosition(left, top);
    self.x_icon:SetZOrder(4); -- in front of mask
    self.x_icon.MouseClick = function(ctl, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            if (self.window.settings.askBeforeDeleting) then
                if (not ctl.confirmDialog) then
                    ctl.confirmDialog = ConfirmDialog(self.window, L:GetText("/MainWindow/DeleteThisReminder"));
                    ctl.confirmDialog.Yes = function(_, arg)
                        self:DeleteEvent(event);
                        ctl.confirmDialog = nil;
                    end
                    ctl.confirmDialog.No = function(_, arg)
                        ctl.confirmDialog = nil;
                    end
                end
            else
                self:DeleteEvent(event);
            end
        end
    end
    return self.x_icon;
end

function Tab:ShowSettingsIcon(parent, left, top, event)
    local charID = unpack(event:GetLastAutomaticUpdate() or {});
    if (charID) then
        local charSettings = self.window.settings.characters[charID];
        if (not charSettings) then
            -- If the settings for this character no longer exist, we can't display them
            return;
        end
    end

    self.settings_icon.event = event; -- needed for tooltip
    self.settings_icon:SetBackground(self.settings_icon.bgNormal);
    self.settings_icon:SetParent(parent);
    self.settings_icon:SetVisible(true);
    self.settings_icon:SetPosition(left, top);
    self.settings_icon:SetZOrder(4); -- in front of mask
    self.settings_icon.MouseClick = function(ctl, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            local charID, itemType, item, gameTime = unpack(event:GetLastAutomaticUpdate() or {});
            if (charID) then
                local charSettings = self.window.settings.characters[charID];
                if (charSettings) then
                    local settings = charSettings.autoReminders[itemType];
                    local control1, control2 = self.window.optionsPanel:ShowHighlightArea(charID, itemType);
                    if (itemType == "quests") then
                        settings = settings.questInfo[item];
                        if (settings) then
                            control2 = QuestRepeatedDialog.GetInstance(self.window, item, settings, charSettings, charID);
                        end
                    elseif (itemType == "raidlocks") then
                        settings = settings.lockInfo[item];
                        if (settings) then
                            control2 = RaidLockDialog.GetInstance(self.window, item, settings, charSettings, charID);
                        end
                    end
                    self.zoomer1 = Thurallor.UI.Zoomer(self.settings_icon, control1);
                    control1:SetVisible(false);
                    self.zoomer1 = Thurallor.UI.Zoomer(self.settings_icon, control1);
                    AddCallback(self.zoomer1, "ZoomComplete", function()
                        control1:SetVisible(true);
                    end);
                    if (control2) then
                        control2:SetVisible(false);
                        self.zoomer2 = Thurallor.UI.Zoomer(self.settings_icon, control2);
                        AddCallback(self.zoomer2, "ZoomComplete", function()
                            control2:SetVisible(true);
                            control2:Activate();
                        end);
                    end
                end
            end
        end
    end
    return self.settings_icon;
end

function Tab:SizeChanged()
    self.table:SetSize(self:GetWidth() - 10, self:GetHeight() - 30);
end

function Tab:TabLeftChanged(tabLeft)
    self.settings.tabLeft = tabLeft;
    if (tabLeft == 0) then
        -- Ensure that this tab appears to the left of any other
        self:SetTabLeft(-1);
    end
    self:GetParent():RedistributeTabs(); -- includes save
end

-- Finds the matching event with the oldest expiration time that is not "never".
-- Search criteria can be disabled by setting the corresponding argument to nil.
function Tab:FindOldestMatchingEvent(desc, charID, category, isExpired, location, checked)
    local oldestEvent = nil;
    local oldestExpTime = 10000000000000;
    for event, settings in pairs(self.events) do
        if ((desc == nil) or (desc == event:GetDescription())) then
            if ((charID == nil) or (charID == event:GetCharacterID())) then
                if ((category == nil) or (category == event:GetCategory())) then
--                    if ((isExpired == nil) or (isExpired == event:IsExpired())) then
--                        if ((location == nil) or (location == event:GetLocation())) then
--                            if ((checked == nil) or (checked == event:IsChecked())) then
                                local expTime = event:GetExpirationTime();
                                if ((expTime >= 0) and (expTime < oldestExpTime)) then
                                    oldestEvent = event;
                                end
--                            end
--                        end
--                    end
                end
            end
        end
    end
    return oldestEvent;
end

function Tab:CloneEvent(oldEvent)
    local settings = DeepTableCopy(oldEvent.settings);
    local newEvent = self:CreateEvent(settings, false);
    if (newEvent) then
        table.insert(self.settings.events, settings);
        self.events[newEvent] = settings;
        return newEvent;
    end
end

-- To do: Get rid of this wrapper
function Tab:CreateNewEvent(desc, charID, expTime, resetTimes, category, location, checked)
    local settings = {
        desc = desc;
        charID = charID;
        expTime = expTime;
        resetTimes = resetTimes;
        rotation = nil;
        category = category;
        location = location;
        checked = checked;
    };
    return self:CreateNewEvent2(settings);
end

function Tab:CreateNewEvent2(settings)
    settings = settings or {};
    local event = self:CreateEvent(settings, false);
    if (event) then
        table.insert(self.settings.events, settings);
        self.events[event] = settings;
        return event;
    end
end

function Tab:CreateSavedEvents()
    self.charID = self.window.charID;
    self.serverRegexp = "^" .. self.window.serverID .. "%.";
    local scope = self.window.settings.viewingScope;
    if (scope == "account") then
        self.eventInScope = function()
            return true;
        end;
    elseif (scope == "server") then
        self.eventInScope = function(charID)
            return charID:match(self.serverRegexp);
        end;
    else -- (scope == "character")
        self.eventInScope = function(charID)
            return (charID == self.charID);
        end;
    end
    for _, s in pairs(self.settings.events) do
        local event = self:CreateEvent(s, true);
        if (event) then
            self.events[event] = s;
        end
    end
    self.table:ReSort();
end

function Tab:CreateEvent(settings, moreEvents)
    if (not self.eventInScope(settings.charID)) then
        return;
    end

    local event = Event(self, settings);
    if (event:IsExpired()) then
        self.window:AddAlert(event, true);
    end    
    AddCallback(event, "ExpiredChanged", function(e, args)
        self:ExpiredChanged(e, args);
    end);

    local row, cells = self.table:AddRow(event, moreEvents);
    event:SetCells(cells);
    
    -- Display various clicky icons, when mouse is present
    AddCallback(row, "MouseEnter", function(ctl)
        self:ShowXIcon(ctl, 1, 1, event);
        if ((self.table:GetColumnWeight("desc") > 0) and event:GetLastAutomaticUpdate()) then
            local cell = cells.desc;
            self:ShowSettingsIcon(ctl, cell:GetLeft() + cell:GetWidth() - 23, 1, event);
        end
        if ((self.table:GetColumnWeight("remaining") > 0) and (not self.table:IsColumnLocked("remaining"))) then
            local cell = cells.remaining;
            self:ShowResetIcon(ctl, cell:GetLeft() + cell:GetWidth() - 23, 1, event);
        end
        if (self.table:GetColumnWeight("location") > 0) then
            local cell = cells.location;
            if (not self.table:IsColumnLocked("location")) then
                self:ShowTargetIcon(ctl, cell:GetLeft() + cell:GetWidth() - 23, 1, event);
            end
            self:ShowWaypointIcon(ctl, cell:GetLeft() + 1, 1, event);
        end

        -- Turn off shimmering
        if (ctl.shimmer) then
            ctl.shimmer = nil;
            for c = 1, #ctl.cells do
                self.window.shimmering:Remove(ctl.cells[c]);
            end
        end
    end);
    AddCallback(row, "MouseLeave", function(ctl)
        if (not (self.x_icon:IsMouseOver() or self.settings_icon:IsMouseOver() or self.reset_icon:IsMouseOver() or self.target_icon:IsMouseOver() or self.waypoint_icon:IsMouseOver())) then
            self.x_icon:SetVisible(false);
            self.settings_icon:SetVisible(false);
            self.reset_icon:SetVisible(false);
            self.waypoint_icon:SetVisible(false);
            self.target_icon:SetVisible(false);
        end
    end);
    row.ContextMenu = function()
        self:ShowEventContextMenu(event);
    end
    
    if (not moreEvents) then
        self:ReapplySort(nil, true);
    end
    return event;
end

function Tab:EnsureEventVisible(event)
    self.table:EnsureVisible(event);
    self.table:GetRow(event):Focus();
end

function Tab:SelectEvent(event)
    if (event) then
        self:EnsureEventVisible(event);
    end
    self.table:SelectRow(event);
end

-- Called once after settings are loaded, to change the time of any of the
-- current character's "at next login" events to "now"
function Tab:Login()
    local gameTime = Turbine.Engine.GetGameTime();
    for event, _ in pairs(self.events) do
        if ((event:GetExpirationTime() == 0) and event:IsMine()) then
            event:SetExpirationTime(gameTime);
            self:SaveSettings();
        end
    end
    self:ReapplySort("remaining");
end

function Tab:DeleteEvent(event)
    self.window:RemoveAlert(event);
    self.table:DeleteRow(event);
    local settings = self.events[event];
    self.events[event] = nil;
    for n, s in pairs(self.settings.events) do
        if (s == settings) then
            self.settings.events[n] = nil;
            break;
        end
    end
    event:Destroy();
    self:SaveSettings();
end

function Tab:Close()
    for event, _ in pairs(self.events) do
        event:Destroy();
    end
    Turbine.UI.Window.Close(self);
end

function Tab:SaveSettings(now)
    self.window:SaveSettings(now);
end

-- Function must accept a single 'event' argument.
-- Returning nil will continue the loop.
-- Returning 'true' aborts the loop and returns the event object.
function Tab:ForEachEventDo(func)
    for event, _ in pairs(self.events) do
        if (func(event)) then
            return event;
        end
    end
end

function Tab:UpdateDistanceColumn(location)
    local x1, y1 = Event.GetCoords(location or "");
    local unknown = "―";
    self:ForEachEventDo(function(event)
        local distCell = event.cells["distance"];
        if (x1 and y1) then
            local x2, y2 = event.cells["location"].x, event.cells["location"].y;
            if (x2 and y2) then
                distCell.sortValue = ((x1 - x2)^2 + (y1 - y2)^2)^0.5 * 202.2171; -- ratio from Lunarwater
                distCell:SetText(string.format("%.1d", math.ceil(distCell.sortValue)) .. "m");
            else
                distCell.sortValue = math.huge;
                distCell:SetText(unknown);
            end
        else
            distCell.sortValue = math.huge;
            distCell:SetText(unknown);
        end
    end);
    self:ReapplySort("distance");
end

function Tab:ExpiredChanged(event, expired)
    if (expired) then
        local controls = {};

        -- Make the event shimmer in the table
        local cells = event:GetCells();
        cells["desc"]:GetParent().shimmer = true;
        for colName, cell in pairs(cells) do
            table.insert(controls, cell);
        end
        
        -- If the tab is not in front, make the tab shimmer as well
        if (not self:IsInFront()) then
            table.insert(controls, self.tabText);
        end

        self.window:AddShimmer(controls);
        self.window:AddAlert(event);
    else
        self.window:RemoveAlert(event);
    end
end

function Tab:CleanupDropDowns()
    if (self.dropDownCtl) then
        self.dropDownCtl.dropDown:SetParent(nil);  -- Could trigger the mouse wheel bug, since it's a descendent of a ListBox.  But currently it seems to work OK.
        self.dropDownCtl.dropDown = nil;
        self.dropDownCtl:SetWantsKeyEvents(false);
        self.dropDownCtl = nil;
    end
end

function Tab:Deselect()
    self.table:Deselect()
end

function Tab:SelectionChanged(args)
    self:CleanupDropDowns();
    if (args.Old) then
        args.Old:SelectionLost();
    end
    if (args.New) then
        args.New:SelectionGained();
    end
    self.selectedEvent = args.New;
end

function Tab:GetSelectedEvent()
    return self.selectedEvent;
end

-- Resorts the table if and only if it's sorted on the specified column
function Tab:ReapplySort(columnName, now)
    if ((columnName == nil) or self.table:IsSorted(columnName)) then
        self.table:ReSort(now);
    end
end

function Tab:IsColumnShowing(columnName)
    return (self.table:GetColumnWeight(columnName) > 0);
end

-- Returns true if the tab is currently displaying any events (according to current scope)
function Tab:IsEmpty()
    return not next(self.events);
end

Compare with Previous | Blame


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


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