lotrointerface.com
Search Downloads

LoTROInterface SVN Reminders

[/] [trunk/] [Thurallor/] [Common/] [UI/] [Tabs_5/] [TabCardStack.lua] - Rev 2

Compare with Previous | Blame | View Log

TabCardStack = class(Turbine.UI.Control);

function TabCardStack:Constructor()
    Turbine.UI.Control.Constructor(self);
    self:SetMouseVisible(false);
    self.tabCards = {};
    self.autoHidden = {};
end

function TabCardStack:AddTabCard(tabCard)
    table.insert(self.tabCards, tabCard);
    tabCard:SetParent(self);
    self:BringToFront(tabCard);
    self:_UpdateButtonPositions();

    -- Default behavior when the tab is clicked is to bring the card to the front.
    AddCallback(tabCard, "Click", function(ctl, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            self:BringToFront(ctl);
        end
    end);
end

function TabCardStack:SetAddTabButtonEnabled(enable, tooltip)
    local button = self.addTabButton;
    if (enable) then
        if (not button) then
            button = self:_CreateButton("+", tooltip);
            button.MouseClick = function(_, args)
                DoCallbacks(self, "AddTabButtonClicked", args);
            end
            self.addTabButton = button;
        end
        button:SetParent(self);
        self:_UpdateButtonPositions();
        self:_UpdateButtonColors(button);
    else
        if (button) then
            button:SetParent(nil);
        end
        self.addTabButton = nil;
    end
end

function TabCardStack:_MoreTabsButtonClicked(args)
    local menu = Turbine.UI.ContextMenu();
    local items = menu:GetItems();
    local hiddenTabs = {};
    for _, tabCard in pairs(self.tabCards) do
        if (tabCard.hidden or tabCard.autoHidden) then
            table.insert(hiddenTabs, tabCard);
        end
    end
    table.sort(hiddenTabs, function(a, b)
        return (a:GetTabText() < b:GetTabText());
    end);
    for _, tabCard in ipairs(hiddenTabs) do
        local item = Turbine.UI.MenuItem(tabCard:GetTabText(), true, false);
        item.tabCard = tabCard;
        item.Click = function(ctl)
            ctl.tabCard:SetHidden(false);
            ctl.tabCard:_SetAutoHidden(false);
            self:BringToFront(ctl.tabCard);
            self:RedistributeTabs();
        end
        items:Add(item);
    end
    menu:ShowMenu();
end

function TabCardStack:SetMoreTabsButtonEnabled(enable, tooltip)
    local button = self.moreTabsButton;
    if (enable) then
        if (not button) then
            button = self:_CreateButton("...", tooltip);
            button.MouseClick = function(_, args)
                DoCallbacks(self, "MoreTabsButtonClicked", args);
                if (not args.Cancel) then
                    self:_MoreTabsButtonClicked(args);
                end
            end
            self.moreTabsButton = button;
        end
        button:SetParent(self);
        self:_UpdateButtonPositions();
        self:_UpdateButtonColors(button);
    else
        if (button) then
            button:SetParent(nil);
        end
        self.moreTabsButton = nil;
    end
end

function TabCardStack:_CreateButton(text, tooltip)
    button = Turbine.UI.Label();
    button:SetMultiline(false);
    button:SetFont(Turbine.UI.Lotro.Font.Verdana16);
    button:SetTextAlignment(Turbine.UI.ContentAlignment.MiddleCenter);
    button:SetFontStyle(Turbine.UI.FontStyle.Outline);
    button:SetOutlineColor(Turbine.UI.Color.Black);
    button:SetText(text);
    button:AutoSize();
    button:SetWidth(button:GetWidth() + 4);
    button:SetZOrder(2); -- in front of all tabs
    button.MouseEnter = function(ctl)
        ctl.mouseInside = true;
        self:_UpdateButtonColors(ctl);
    end
    button.MouseLeave = function(ctl)
        ctl.mouseInside = false;
        self:_UpdateButtonColors(ctl);
    end
    button.MouseDown = function(ctl, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            ctl.mouseDown = true;
            self:_UpdateButtonColors(ctl);
        end
    end
    button.MouseUp = function(ctl, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            ctl.mouseDown = false;
            self:_UpdateButtonColors(ctl);
        end
    end
    if (tooltip) then
        Thurallor.UI.Tooltip(tooltip):Attach(button);
    end
    button:SetParent(self);
    return button;
end

function TabCardStack:HasHiddenTabs()
    for _, tabCard in pairs(self.tabCards) do
        if (tabCard.hidden or tabCard.autoHidden) then
            return true;
        end
    end
end

function TabCardStack:_GetRightmostVisibleTab()
    for n = #self.tabCards, 1, -1 do
        local tabCard = self.tabCards[n];
        if (not (tabCard.hidden or tabCard.autoHidden)) then
            return tabCard;
        end
    end
end

function TabCardStack:_UpdateButtonPositions()
    local left = 0;
    local rightTab = self:_GetRightmostVisibleTab();
    if (rightTab) then
        left = rightTab:GetTabRight();
    end
    if (self.moreTabsButton) then
        if (self:HasHiddenTabs()) then
            self.moreTabsButton:SetParent(self);
            self.moreTabsButton:SetPosition(left, 2);
            left = left + self.moreTabsButton:GetWidth();
        else
            self.moreTabsButton:SetParent(nil);
        end
    end
    if (self.addTabButton) then
        self.addTabButton:SetPosition(left, 2);
        --left = left + self.addTabButton:GetWidth();
    end
end

function TabCardStack:_UpdateButtonColors(button)
    if (button.mouseDown) then
        button:SetForeColor(Turbine.UI.Color.Black);
        button:SetOutlineColor(Turbine.UI.Color.PaleGoldenrod);
    elseif (button.mouseInside) then
        --button:SetForeColor(Turbine.UI.Color(0.75, 1, 1, 1));
        button:SetForeColor(Turbine.UI.Color.White);
        button:SetOutlineColor(Turbine.UI.Color.DarkGoldenrod);
    else
        --button:SetForeColor(Turbine.UI.Color(0.5, 1, 1, 1));
        button:SetForeColor(Turbine.UI.Color.PaleGoldenrod);
        button:SetOutlineColor(Turbine.UI.Color.Black);
    end
end

function TabCardStack:BringToFront(tabCard)
    for t = 1, #self.tabCards do
        local otherTabCard = self.tabCards[t];
        if (otherTabCard == tabCard) then
            tabCard:BringToFront(true);
            tabCard:SetSize(self:GetSize());
            self.frontTabCard = tabCard;
        else
            otherTabCard:SendToBack(true);
        end
    end
    DoCallbacks(self, "FrontTabChanged", tabCard);
end

function TabCardStack:GetFrontTabCard()
    return self.frontTabCard;
end

function TabCardStack:RedistributeTabs()
    local width = self:GetWidth();
    if (self.addTabButton) then
        width = width - self.addTabButton:GetWidth();
    end
    if (self.moreTabsButton) then
        width = width - self.moreTabsButton:GetWidth();
    end

    -- Sort the tabCards by left edge
    local function compare(a, b)
        return (a:GetTabLeft() < b:GetTabLeft());
    end
    table.sort(self.tabCards, compare);

    -- Unhide auto-hidden tabs
    for _, tabCard in pairs(self.tabCards) do
        tabCard:_SetAutoHidden(false);
    end

    -- Spread out the tabCards to eliminate overlap
    local left, rightTab = 0, nil;
    for t = 1, #self.tabCards do
        local tabCard = self.tabCards[t];
        tabCard:SetTabLeft(left);
        left = left + tabCard:GetTabWidth();
        if (not (tabCard.hidden or tabCard.autoHidden)) then
            rightTab = tabCard;
        end
    end
    if (left <= width) then
        -- All the tabs fit without overlapping.  Done.
        self:_UpdateButtonPositions(width);
        return;
    end

    -- Too many tabs to display without overlapping
    local frontTab = self.frontTabCard;
    if (self.moreTabsButton) then
        -- Auto-hide excess tabs
        for _, tabCard in ipairs(self.tabCards) do
            local left, right = tabCard:GetTabLeft(), tabCard:GetTabRight();
            local hidden = tabCard:IsHidden();
            if (not hidden) then
                if ((right <= width) or (left == 0)) then
                    rightTab = tabCard;
                else
                    tabCard:_SetAutoHidden(true);
                end
            end
        end

        -- If we auto-hid the front-tab, hide the rightmost non-hidden tab instead
        if (frontTab:_IsAutoHidden()) then
            frontTab:_SetAutoHidden(false);
            frontTab:SetTabLeft(rightTab:GetTabLeft());
            rightTab:_SetAutoHidden(true);
            rightTab = frontTab;
        end
    else

        -- Minimize overlapping.  Distribute the left edges evenly.
        local rightTabWidth = rightTab:GetTabWidth();
        local newRightTabLeft = math.max(#self.tabCards, (width - rightTabWidth)); -- need at least as many pixels as tabs
        local squeezeRatio = newRightTabLeft / rightTab:GetTabLeft();
        for t = 1, #self.tabCards do
            local tabCard = self.tabCards[t];
            local left = math.floor(0.5 + tabCard:GetTabLeft() * squeezeRatio);
            tabCard:SetTabLeft(left);
        end

        -- Bring front tabCard to the front again so its tab isn't concealed if there's overlap
        self.frontTabCard:SetZOrder(1);
        self.frontTabCard:SetZOrder(0);
    end

    self:_UpdateButtonPositions(width);
end

function TabCardStack:SetSize(width, height)
    Turbine.UI.Control.SetSize(self, width, height);
    for t = 1, #self.tabCards do
        local tabCard = self.tabCards[t];
        tabCard:SetSize(width, height);
    end
    self:_UpdateButtonPositions();
end

function TabCardStack:SetWidth(width)
    self:SetSize(width, self:GetHeight());
end

function TabCardStack:SetHeight(height)
    self:SetSize(self:GetWidth(), height);
end

Compare with Previous | Blame


All times are GMT -5. The time now is 12:43 PM.


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