lotrointerface.com
Search Downloads

LoTROInterface SVN SequenceBars

[/] [trunk/] [Thurallor/] [SequenceBars/] [Bar.lua] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

Bar = class(Turbine.UI.Window);

function Bar:Constructor(group, barID, settings)
    Turbine.UI.Window.Constructor(self);
    self.constructing = true;
    self:SetZOrder(2147483647 - 10);
    
    self.parent = group;
    self.manager = group.manager;
    self.objectID = barID;
    self.onLoad = onLoad;
    self.sequenceItems = { };
    self.cursorSlot = 3;
    self.cursorSequenceItem = 1;
    self.globals = self.manager.settings;
    self.eventGeneratorIDs = {};
    
    -- Default settings
    local defaults = {};
    defaults.type = "bar";
    defaults.locked = false;
    defaults.hidden = false;
    defaults.color = "7B68EE";
    defaults.cursorStyle = "SmallSquareGlow";
    defaults.caption = { };
    defaults.caption.hidden = false;
    defaults.caption.text = L:GetText("/Default/BarName");
    defaults.caption.position = "beginning";
    defaults.caption.width = 80;
    defaults.caption.height = 35;
    defaults.caption.font = Turbine.UI.Lotro.Font.TrajanPro15;
    defaults.slotSize = 35; -- must be an even number
    defaults.slotSpacing = 0;
    defaults.orientation = "Right";
    defaults.visibleSlots = 5;
    defaults.cursorHomePosition = 2;
    defaults.animation = { duration = 0.1 };
    defaults.sequenceItemInfo = { {}, {}, {}, {}, {} };
    defaults.position = { left = math.floor(Turbine.UI.Display:GetWidth() / 2); top = math.floor(Turbine.UI.Display:GetHeight() / 2 )};
    
    -- Previously-saved settings override the defaults
    DeepTableCopy(settings, defaults);
    DeepTableCopy(defaults, settings);
    self.settings = settings;

    self:ReapplySettings();
    self.constructing = nil;
end

function Bar:ReapplySettings()

    -- Make color object from hex string
    self.color = Thurallor.Utils.Color(1, 0, 0, 0);
    self.color:SetHex(self.settings.color);

    -- Derived from settings
    self:SetCursorStyle(self.settings.cursorStyle);
    
    self:GetQuickSlots();
    self:Redraw();
end

function Bar:CanHaveChildren()
    return false;
end

function Bar:Contains(object)
    return false;
end

function Bar:GetID()
    return self.objectID;
end

function Bar:GetColor()
    return self.color;
end

function Bar:SetColor(color)
    self.color = color;
    self.settings.color = color:GetHex();
    self:SaveSettings(true);
    self:Redraw();
    self:SetCursorStyle();
    if (self.sequenceEditor) then
        self.sequenceEditor:Redraw();
    end
end

function Bar:GetName()
    return self.settings.caption.text;
end

function Bar:SetName(caption)
    self.settings.caption.text = caption;
    self:SaveSettings(true);
    self:Redraw();
    if (self.sequenceEditor) then
        self.sequenceEditor:SetText(caption);
    end
    if (self.exportWindow) then
        self.exportWindow:SetText(caption);
    end
end

function Bar:SetCaptionSize(width, height)
    self.settings.caption.width = width;
    self.settings.caption.height = height;
    self:SaveSettings(false);
    self:Redraw();
end

function Bar:SetCaptionFont(font)
    self.settings.caption.font = font;
    self:SaveSettings(false);
    self:Redraw();
end

function Bar:IsHidden()
    return (self.settings.hidden or self:IsParentHidden());
end

function Bar:IsParentHidden()
    return self.parent:IsHidden();
end

function Bar:SetHidden(hide)
    self.settings.hidden = hide;
    self:ApplyHiddenness();
end

function Bar:SetCaptionHidden(hide)
    self.settings.caption.hidden = hide;
    self:SaveSettings(false);
    self:Redraw();
end

function Bar:ApplyHiddenness()
    local hidden = self:IsHidden();
    self:SetVisible(not hidden);
    self.caption:SetVisible(not self:IsHidden());
    if (self.cursor) then
        self.cursor:SetVisible(not hidden);
    end
    self:SaveSettings(true);
end

-- Updates the sequence item when a user drags a shortcut onto the sequence editor
function Bar:ShortcutChanged(i)

    -- Hide and destroy all objects in preparation for recreation (self:GetQuickSlots())
    for s = 1, #self.sequenceItems, 1 do
        self.sequenceItems[s]:SetVisible(false);
        self.sequenceItems[s] = nil;
    end
    
    self:SaveSettings(false);
    self:GetQuickSlots();
    self:Redraw();
end

-- Creates (or recreates) the array of objects (e.g. Quickslot) according to self.settings.sequenceItemInfo
function Bar:GetQuickSlots()
    -- Unregister event generator.  We will re-register for each generated event as we loop through the sequence below.
    for eventName, generatorID in pairs(self.eventGeneratorIDs) do
        self.manager:RemoveEventGenerator(generatorID, eventName);
    end
    self.eventGeneratorIDs = {};

    -- Iterate through the sequence creating clickable objects.
    self.sequenceItems = {};
    local s = 0;
    for i = 1, #self.settings.sequenceItemInfo, 1 do
        local info = self.settings.sequenceItemInfo[i];
        if ((type(info) == "table") and (info.class)) then
            if ((info.class == "Turbine.UI.Lotro.Quickslot") and info.Data) then
                s = s + 1;
--Puts("Adding quickslot item " .. i .. " in slot " .. s .. ": type = " .. tostring(info.type) .. ", data = " .. tostring(info.data));
                self.sequenceItems[s] = Turbine.UI.Lotro.Quickslot();
                local item = self.sequenceItems[s];
                item.class = info.class;
                item.s = s;
                item:SetZOrder(self:GetZOrder() + 2);    
                item:SetParent(self);
                item:SetVisible(true);
                item:SetSize(self.settings.slotSize, self.settings.slotSize);
                item:SetAllowDrop(false);
                item:SetShortcut(Turbine.UI.Lotro.Shortcut(info.type, info.Data));
                item:SetUseOnRightClick(false);
                item.MouseUp = function(sender, args)
--Puts("info.class = " .. tostring(info.class) .. "; info.type = " .. tostring(info.type) .. "; info.Data = " .. tostring(info.Data));
                    self:SequenceItemClick(sender.s);
                end
            elseif (info.class == "Turbine.UI.Control") then
                s = s + 1;
--Puts("Adding action item " .. i .. " in slot " .. s);
                self.sequenceItems[s] = Turbine.UI.Control();
                local item = self.sequenceItems[s];
                DeepTableCopy(info, item);
                if ((item.type == "GenerateEvent") and (not self.eventGeneratorIDs[item.eventName])) then
                    self.eventGeneratorIDs[item.eventName] = self.manager:AddEventGenerator(self, item.eventName);
                end
                item.bar = self;
                item.s = s;
                item:SetZOrder(self:GetZOrder() + 2);    
                item:SetParent(self);
                item:SetVisible(true);
                item:SetSize(self.settings.slotSize - 3, self.settings.slotSize - 3);
                item:SetBackground(info.background);
                item.actionFunc = loadstring(info.action);
                item.MouseUp = function(sender, args)
                    sender:actionFunc(args);
                    self:SequenceItemClick(sender.s);
                end;
            end
        end
    end
end

function Bar:SaveSettings(updateOptionsPanel)
    if (not self.constructing) then
        self.parent:SaveSettings(updateOptionsPanel);
    end
end

function Bar:Redraw()
    local displaySlots = self.settings.visibleSlots;
    local barLongDimension = (2 * self.cursorMargin) + displaySlots * self.settings.slotSize + (displaySlots - 1) * self.settings.slotSpacing;
    local barShortDimension = (2 * self.cursorMargin) + self.settings.slotSize;
    
    local barWidth, barHeight;
    if ((self.settings.orientation == "Up") or (self.settings.orientation == "Down")) then
        barWidth = barShortDimension;
        barHeight = barLongDimension;
    else
        barWidth = barLongDimension;
        barHeight = barShortDimension;
    end
    self:SetSize(barWidth, barHeight);
    self:SetPosition(self.settings.position.left, self.settings.position.top);

    -- Draw cursor icon.
    self:Reset();
 --self:SetBackColor(Turbine.UI.Color( 1, 1, 1 ));

    self:SetWantsUpdates(false);
    self:DrawCaption();
    self:ApplyHiddenness();
end

function Bar:Reset()
    self:SetCursorSlot(self.settings.cursorHomePosition);
    self:SetCursorSequenceItem(1);
    self.animationStopped = false;
end

-- Moves the cursor to the specified position on the bar
function Bar:SetCursorSlot(pos)
    local resource = resources.Cursor[self.settings.cursorStyle];
    local left, top = self:GetSlotCoords(pos);
    left = left - self.cursorMargin + resource.xOffset;
    top = top - self.cursorMargin + resource.yOffset;
    left, top = self:PointToScreen(left, top);
    self.cursor:SetPosition(left, top);
    self.cursor.left, self.cursor.top = left, top;
--Turbine.Shell.WriteLine("pos = " .. tostring(pos) .. ", left = " .. tostring(left) .. ", top = " .. tostring(top));
    self.cursorSlot = pos;
end

function Bar:DrawCaption()
    local barCenter = {
        x = math.floor(self:GetLeft() + self:GetWidth() / 2);
        y = math.floor(self:GetTop() + self:GetHeight() / 2);
    }
    if (not self.caption) then
        self.caption = Turbine.UI.Window();
    end
    local caption = self.caption;
    local captionSeparation = self.settings.slotSpacing + 3;
    local left, top, width, height, where;
    where = self.settings.orientation;
    if (self.settings.caption.position == "end") then
        local swap = {Up = "Down"; Down = "Up"; Left = "Right"; Right = "Left"};
        where = swap[where];
    end
    if (where == "Up") then
        top = self:GetTop() + self:GetHeight() - self.cursorMargin + captionSeparation;
        left = barCenter.x - math.floor(self.settings.caption.width / 2);
        alignment = Turbine.UI.ContentAlignment.TopCenter;
    elseif (where == "Down") then
        top = self:GetTop() - self.settings.caption.height + self.cursorMargin - captionSeparation;
        left = barCenter.x - math.floor(self.settings.caption.width / 2);
        alignment = Turbine.UI.ContentAlignment.BottomCenter;
    elseif (where == "Right") then
        top = barCenter.y - math.floor(self.settings.caption.height / 2);
        left = self:GetLeft() - self.settings.caption.width + self.cursorMargin - captionSeparation;
        alignment = Turbine.UI.ContentAlignment.MiddleRight;
    else -- "Left"
        top = barCenter.y - math.floor(self.settings.caption.height / 2);
        left = self:GetLeft() + self:GetWidth() - self.cursorMargin + captionSeparation;
        alignment = Turbine.UI.ContentAlignment.MiddleLeft;
    end

    caption:SetPosition(left, top);
    caption:SetWidth(self.settings.caption.width);
    caption:SetHeight(self.settings.caption.height);
    caption:SetZOrder(self:GetZOrder() + 3);
-- caption:SetBackColor(Turbine.UI.Color(0, 1, 1));
    
    if (not caption.label) then
        caption.label = Turbine.UI.Label();
        caption.label:SetParent(caption);
    end
    local label = caption.label;
    label:SetText(self.settings.caption.text);
    label:SetVisible(not self.settings.caption.hidden);
    label:SetMouseVisible(false);
    self:FormatCaptionLabel(label, alignment);
    if (self.captionEditor and self.captionEditor:WantsCaptionUpdates()) then
        local textBox = self.captionEditor:GetTextBox();
        self:FormatCaptionLabel(textBox, alignment);
        self.captionEditor:Redraw();
    end
    
    caption.MouseClick = function(sender, args)
        -- Left-click resets the sequence back to the beginning.
        if (args.Button == Turbine.UI.MouseButton.Left) then
            self:Reset();
        end
        
        -- Right-click displays the settings menu.
        if (args.Button == Turbine.UI.MouseButton.Right) then
            self:ShowSettingsMenu();
        end
    end

    caption.MouseDoubleClick = function(sender, args)
        -- Left-double-click opens the caption editor.
        if (args.Button == Turbine.UI.MouseButton.Left) then
            self:EditCaption();
        end
        
        -- Right-double-click would open the sequence editor, but
        -- since right-click opens the settings menu, right-double
        -- -click isn't possible.
    end
        
    -- While mouse is over label, turn it yellow to indicate that it can be clicked.
    caption.MouseEnter = function(sender, args)
        label:SetForeColor(Turbine.UI.Color(1, 1, 1, 0));
        label:SetVisible(true);
    end
    caption.MouseLeave = function(sender, args)
        label:SetForeColor(self.color);
        label:SetVisible(not self.settings.caption.hidden);
    end
    
    -- MouseDown, MouseUp, and MouseMove are used to move the window (if not locked)
    caption.MouseDown = function(sender, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            caption.mouseDown = true;
            caption.originalMouseX, caption.originalMouseY = Turbine.UI.Display.GetMouseX(), Turbine.UI.Display.GetMouseY();
        end
    end
    caption.MouseUp = function(sender, args)
        if (args.Button == Turbine.UI.MouseButton.Left) then
            caption.mouseDown = false;
            if (not self.settings.locked) then
                if (self.parent:GetBarsMoveTogether()) then
                    self.parent:SnapToGrid();
                else
                    self:SnapToGrid();
                end
                self:SaveSettings(false);
            end
        end
    end
    caption.MouseMove = function(sender, args)
        if (caption.mouseDown and not self.settings.locked) then
            local newMouseX, newMouseY = Turbine.UI.Display.GetMouseX(), Turbine.UI.Display.GetMouseY();
            local deltaX, deltaY = newMouseX - caption.originalMouseX, newMouseY - caption.originalMouseY;
            if (self.parent:GetBarsMoveTogether()) then
                self.parent:OffsetPosition(deltaX, deltaY, "up");
            else
                self:OffsetPosition(deltaX, deltaY);
            end
            caption.originalMouseX, caption.originalMouseY = newMouseX, newMouseY;
        end
    end
    caption:SetAllowDrop(true);
    caption.DragDrop = function(sender, args)
        self:EditSequence();
    end
end

function Bar:EditCaption()
    if (self.captionEditor == nil) then
        self.captionEditor = CaptionEditor("BarCaption", self, self.caption.label:GetWidth(), self.caption.label:GetHeight(), self.settings.caption.text);
        self.captionEditor.Closed = function(sender, args)
            self.captionEditor = nil;
        end
        self:Redraw();
    end
end

function Bar:EditColor()
    if (self.colorPicker == nil) then
        self.previousColor = self.color;
        self.colorPicker = Thurallor.UI.ColorPicker(self.color, "H");
        self.colorPicker:SetZOrder(self:GetZOrder() + 10);
        self.colorPicker.ColorChanged = function(picker)
            self:SetColor(picker:GetColor());
        end
        self.colorPicker.Accepted = function()
            self.colorPicker = nil;
            self:SaveSettings(true);
        end
        self.colorPicker.Canceled = function()
            self:SetColor(self.previousColor);
            self.colorPicker = nil;
        end
    end
end

function Bar:EditSequence()
    if (self.sequenceEditor == nil) then
        self.sequenceEditor = SequenceEditor(self, self.settings);
        self.sequenceEditor.Closed = function(sender, args)
            self.sequenceEditor = nil;
        end
    end
end

function Bar:FormatCaptionLabel(control, alignment)
    control:SetFont(self.settings.caption.font);
    control:SetForeColor(self.color);
    control:SetFontStyle(Turbine.UI.FontStyle.Outline);
    control:SetOutlineColor(Turbine.UI.Color(0.75, 0, 0, 0));
    control:SetTextAlignment(alignment);
    control:SetWidth(self.settings.caption.width);
    control:SetHeight(self.settings.caption.height);
end

function Bar:OffsetPosition(deltaX, deltaY)
    self:SetPosition(self:GetLeft() + deltaX, self:GetTop() + deltaY);
    self.caption:SetPosition(self.caption:GetLeft() + deltaX, self.caption:GetTop() + deltaY);
    self.cursor:SetPosition(self.cursor:GetLeft() + deltaX, self.cursor:GetTop() + deltaY);
    self.settings.position = { left = self:GetLeft(); top = self:GetTop() };
    self:SaveSettings(false);
end

function Bar:SnapToGrid()
    if (not self.globals.snapToGrid) then
        return;
    end
    local left, top = self:GetVisibleSizePos();
    local newLeft, newTop = self.parent.manager:GetNearestGridPos(left, top);
    self:SetVisibleLeft(newLeft);
    self:SetVisibleTop(newTop);
    self:SaveSettings(false);
end

function Bar:Export()
    if (self.exportWindow) then
        self.exportWindow:Close();
        self.exportWindow = nil;
        return self:Export();
    end

    -- Compile the data to be exported
    local exportObjects = {};
    Puts(L:GetText("/ExportWindow/Exporting"));
    exportObjects[self.objectID] = self.settings;
    
    -- Create the export window
    local title = L:GetText("/ExportWindow/Title");
    title = string.gsub(title, "<name>", self.settings.caption.text);
    self.exportWindow = ExportWindow(title, exportObjects);
    self.exportWindow.Closing = function()
        self.exportWindow = nil;
    end
end

function Bar:ShowSettingsMenu(fromOptionsPanel)
    -- Build the settings menu.
    if (not self.settingsMenu) then
        self.settingsMenu = Turbine.UI.ContextMenu();
    end
    self:AddSettingsMenuItem(self.settingsMenu, "Root", fromOptionsPanel);
    self.settingsMenu:ShowMenu();
end

function Bar:AddSettingsMenuItem(parent, itemName, amSubMenu)
    if (amSubMenu ~= nil) then
        self.amSubMenu = amSubMenu;
    end
    local item = Turbine.UI.MenuItem(L:GetText(itemName), true, false);
    parent:GetItems():Add(item);

    if (itemName == "Root") then
        local prevContext = L:SetContext("/BarMenu");
        parent:GetItems():Clear();
        if (not self:IsHidden()) then
            self:AddSettingsMenuItem(parent, "Find");
        end
        self:AddSettingsMenuItem(parent, "Hide");
        self:AddSettingsMenuItem(parent, "LockPosition");
        self:AddSettingsMenuItem(parent, "Clone");
        self:AddSettingsMenuItem(parent, "Delete");
        self:AddSettingsMenuItem(parent, "Export");
        self:AddSettingsMenuItem(parent, "EditSequence");
        self:AddSettingsMenuItem(parent, "Settings");
        if (not amSubMenu) then
            self:AddSettingsMenuItem(parent, "Group");
            Group.AddSettingsMenuItem(self.parent, parent, "Global", true);
            self:AddSettingsMenuItem(parent, "Directory");
        end
        L:SetContext(prevContext);
    elseif (itemName == "Directory") then
        item.Click = function(sender, args)
            self.manager.optionsPanel:Show();
        end
    elseif (itemName == "Export") then
        item.Click = function(sender, args)
            self:Export();
        end
    elseif (itemName == "Find") then
        item.Click = function(sender, args)
            self:Find();
        end
    elseif (itemName == "Hide") then
        item:SetChecked(self.settings.hidden);
        item.Click = function(sender, args)
            self:SetHidden(not self.settings.hidden);
        end
    elseif (itemName == "LockPosition") then
        item:SetChecked(self.settings.locked);
        item.Click = function(sender, args)
            self:SetLocked(not self.settings.locked);
        end
    elseif (itemName == "EditSequence") then
        item:SetEnabled(not self.sequenceEditor);
        item.Click = function(sender, args)
            self:EditSequence();
        end
    elseif (itemName == "Settings") then
        local prevContext = L:SetContext("SettingsMenu");
        self:AddSettingsMenuItem(item, "Orientation");
        if ((self.settings.orientation == "Up") or (self.settings.orientation == "Down")) then
            self:AddSettingsMenuItem(item, "Height");
        else
            self:AddSettingsMenuItem(item, "Width");
        end
        self:AddSettingsMenuItem(item, "Cursor");
        self:AddSettingsMenuItem(item, "Caption");
        self:AddSettingsMenuItem(item, "Color");
        self:AddSettingsMenuItem(item, "Animation");
        L:SetContext(prevContext);
    elseif (itemName == "Color") then
        item:SetEnabled(not self.colorPicker);
        item.Click = function(sender, args)
            self:EditColor();
        end
    elseif (itemName == "Animation") then
        local prevContext = L:SetContext("AnimationMenu");
        self:AddSettingsMenuItem(item, "Instantaneous");
        self:AddSettingsMenuItem(item, "Fast");
        self:AddSettingsMenuItem(item, "Slow");
        self:AddSettingsMenuItem(item, "VerySlow");
        self:AddSettingsMenuItem(item, "Disabled");
        L:SetContext(prevContext);
    elseif (string.find("Instantaneous|Fast|Slow|VerySlow|Disabled", itemName)) then
        local duration = { ["Instantaneous"] = 0; ["Fast"] = 0.05; ["Slow"] = 0.1; ["VerySlow"] = 0.5; ["Disabled"] = -1; };
        local checked = (self.settings.animation.duration == duration[itemName]);
        item:SetChecked(checked);
        item:SetEnabled(not checked);
        item.Click = function(sender, args)
            self:SetAnimationSpeed(duration[itemName]);
        end
    elseif (itemName == "Orientation") then
        local prevContext = L:SetContext("OrientationMenu");
        self:AddSettingsMenuItem(item, "Up");
        self:AddSettingsMenuItem(item, "Right");
        self:AddSettingsMenuItem(item, "Left");
        self:AddSettingsMenuItem(item, "Down");
        L:SetContext(prevContext);
    elseif ((itemName == "Up") or (itemName == "Down") or (itemName == "Left") or (itemName == "Right")) then
        local checked = (self.settings.orientation == itemName);
        item:SetChecked(checked);
        item:SetEnabled(not checked);
        item.Click = function(sender, args)
            self.settings.orientation = itemName;
            self:SaveSettings(false);
            self:Redraw();
            self:MoveOntoScreen();
        end
    elseif (string.find("Width|Height", itemName)) then
        local size = self.settings.visibleSlots;
        local displayWidth, displayHeight = Turbine.UI.Display.GetSize();
        local minSize = 1, maxSize;
        if ((self.settings.orientation == "Up") or (self.settings.orientation == "Down")) then
            maxSize = math.floor(displayHeight / self.settings.slotSize);
        else
            maxSize = math.floor(displayWidth / self.settings.slotSize);
        end
        local prevContext = L:SetContext("HeightWidthMenu");
        for i = maxSize, minSize, -1 do
            local subItemName = L:GetText("Slots");
            if (i == 1) then
                subItemName = L:GetText("Slot");
            end
            subItemName = string.gsub(subItemName, "<num>", tostring(i));
            local checked = (i == self.settings.visibleSlots)
            local subItem = Turbine.UI.MenuItem(subItemName, not checked, checked);
            item:GetItems():Add(subItem);
            subItem.Click = function(sender, args)
                self:ResizeBar(i);
                self:MoveOntoScreen();
            end
        end
        L:SetContext(prevContext);
    elseif (itemName == "Cursor") then
        local prevContext = L:SetContext("CursorMenu");
        self:AddSettingsMenuItem(item, "Style");
        self:AddSettingsMenuItem(item, "HomePosition");
        L:SetContext(prevContext);
    elseif (itemName == "HomePosition") then
        local prevContext = L:SetContext("HomePositionMenu");
        for i = 1, self.settings.visibleSlots, 1 do
            local subItemName = L:GetText("Slot");
            subItemName = string.gsub(subItemName, "<num>", tostring(i));
            local checked = (i == self.settings.cursorHomePosition);
            local subItem = Turbine.UI.MenuItem(subItemName, not checked, checked);
            item:GetItems():Add(subItem);
            subItem.Click = function(sender, args)
                self.settings.cursorHomePosition = i;
                self:SaveSettings(false);
                self:Redraw();
            end
        end
        L:SetContext(prevContext);
    elseif (itemName == "Style") then
        local prevContext = L:SetContext("StyleMenu");
        for name, info in pairs(resources.Cursor) do
            local checked = (name == self.settings.cursorStyle);
            local style = Turbine.UI.MenuItem(L:GetText(name), not checked, checked);
            item:GetItems():Add(style);
            style.Click = function(sender, args)
                self:SetCursorStyle(name);
                self:SaveSettings(false);
                self:Redraw();
            end
        end
        L:SetContext(prevContext);
    elseif (itemName == "Caption") then
        local prevContext = L:SetContext("CaptionMenu");
        self:AddSettingsMenuItem(item, "Edit");
        self:AddSettingsMenuItem(item, "HideCaption");
        self:AddSettingsMenuItem(item, "Position");
        L:SetContext(prevContext);
    elseif (itemName == "Edit") then
        item:SetEnabled(not self.captionEditor);
        item.Click = function(sender, args)
            self:EditCaption();
        end
    elseif (itemName == "HideCaption") then
        item:SetChecked(self.settings.caption.hidden);
        item.Click = function(sender, args)
            self:SetCaptionHidden(not self.settings.caption.hidden);
        end
    elseif (itemName == "Position") then
        local prevContext = L:SetContext("PositionMenu");
        if ((self.settings.orientation == "Up") or (self.settings.orientation == "Down")) then
            self:AddSettingsMenuItem(item, "Top");
            self:AddSettingsMenuItem(item, "Bottom");
        else -- "Left" or "Right"
            self:AddSettingsMenuItem(item, "LeftSide");
            self:AddSettingsMenuItem(item, "RightSide");
        end
        L:SetContext(prevContext);
    elseif (string.find("Top|Bottom|LeftSide|RightSide", itemName)) then
        local beginPosMap = { Left = "RightSide"; Right = "LeftSide"; Up = "Bottom"; Down = "Top" };
        local amBeginPos = (itemName == beginPosMap[self.settings.orientation]);
        local beginPosSelected = (self.settings.caption.position == "beginning");
        local checked = (amBeginPos and beginPosSelected) or (not amBeginPos and not beginPosSelected);
        local myOrientation = (amBeginPos and "beginning") or "end";
        item:SetChecked(checked);
        item:SetEnabled(not checked);
        item.Click = function(sender, args)
            self.settings.caption.position = myOrientation;
            self:SaveSettings(false);
            self:Redraw();
            self:MoveOntoScreen();
        end
    elseif (itemName == "Clone") then
        item.Click = function(sender, args)
            self.parent:CloneBar(self.objectID);
        end
    elseif (itemName == "Group") then
        self.parent.AddSettingsMenuItem(self.parent, item, "Root", true, self);
    elseif (itemName == "Delete") then
        item.Click = function(sender, args)
            self.parent:DeleteBar(self.objectID);
        end
    end
end

function Bar:ResizeBar(size)
    self.settings.visibleSlots = size;
    if (self.settings.cursorHomePosition > size) then
        self.settings.cursorHomePosition = size;
    end
    self:SaveSettings(false);
    self:Redraw();
end

function Bar:SetCursorStyle(style)
    local oldCursorMargin = self.cursorMargin;
    if (style == nil) then
        style = self.settings.cursorStyle;
    end
    self.settings.cursorStyle = style;
    local resource = resources.Cursor[style];
 
    if (self.cursor) then
        self.cursor:Close();
        self.cursor = nil;
    end
    self.cursor = Turbine.UI.Window();
    self.cursor:SetAllowDrop(false);
    self.cursor:SetMouseVisible(false);
    if (resource.ApplyColor) then
        self.cursor:SetBackColor(self.color);
    end
    local background = resources.Cursor[style].Background;
    if (background) then
        self.cursor:SetBackground(resource.Background);
        self.cursorWidth, self.cursorHeight = GetAssetSize(resource.Background);
        self.cursor:SetSize(self.cursorWidth, self.cursorHeight);
        -- for now, presume square shape
        self.cursorSize = math.ceil(self.cursorWidth / 2) * 2;
    else
        self.cursorSize = 36;
    end
    if (resource.BackColorBlendMode) then
        self.cursor:SetBackColorBlendMode(resource.BackColorBlendMode);
    end
    if (resource.BlendMode) then
        self.cursor:SetBlendMode(resource.BlendMode);
    end
    if (resource.ZOrder) then
        self.cursor:SetZOrder(self:GetZOrder() + resource.ZOrder);
    end
    self.cursor:SetVisible(not self:IsHidden());
    if (not resource.xOffset) then
        resource.xOffset = 0;
    end
    if (not resource.yOffset) then
        resource.yOffset = 0;
    end
    self.cursorMargin = (self.cursorSize - self.settings.slotSize) / 2;
    if (oldCursorMargin) then
        self:OffsetPosition(oldCursorMargin - self.cursorMargin, oldCursorMargin - self.cursorMargin);
    end
    self:SetCursorSlot(self.cursorSlot);
end

function Bar:SetLocked(state)
    self.settings.locked = state;
    self:SaveSettings(false);
end

function Bar:IsLocked()
    return self.settings.locked;
end

-- Scrolls the sequence such that the specified item appears under the cursor
function Bar:SetCursorSequenceItem(item)

    if (item > #self.sequenceItems) then
        item = 1;
    end
    
    local first = item - self.cursorSlot + 1;
    local last = first + self.settings.visibleSlots - 1;
--Turbine.Shell.WriteLine("visibleSlots = " .. tostring(self.settings.visibleSlots) .. "; first = " .. tostring(first) .. "; item = " .. tostring(item) .. "; last = " .. tostring(last) .. "; #sequenceItems = " .. tostring(#self.sequenceItems));

    for i = 1, #self.sequenceItems, 1 do
        local item = self.sequenceItems[i];
        
        if ((i < first) or (i > last)) then
            item:SetVisible(false);
        else
            local left, top = self:GetSlotCoords(i - first + 1);
            if (item.class == "Turbine.UI.Control") then
                left = left + 3;
                top = top + 3;
            end
            item:SetPosition(left - 1, top - 1);
--Puts("Positioning item " .. i .. " at " .. tostring(left - 1) .. ", " .. tostring(top - 1));
--            item:SetVisible(not self:IsHidden());
            item:SetVisible(true);
            item:SetAllowDrop(false);
        end
    end
    
    self.cursorSequenceItem = item;
end

function Bar:GetSlotCoords(slot)
    local offset = self.cursorMargin + (slot - 1) * (self.settings.slotSize + self.settings.slotSpacing);
    local left, top;
    if (self.settings.orientation == "Up") then
        left = self.cursorMargin;
        top = self:GetHeight() - self.settings.slotSize - offset;
    elseif (self.settings.orientation == "Down") then
        left = self.cursorMargin;
        top = offset;
    elseif (self.settings.orientation == "Left") then
        left = self:GetWidth() - self.settings.slotSize - offset;
        top = self.cursorMargin;
    else -- "Right"
        left = offset;
        top = self.cursorMargin;
    end
-- Turbine.Shell.WriteLine("returning (left, top) = (" .. tostring(left) .. ", " .. tostring(top) .. ") for " .. tostring(slot));
    return left, top
end

function Bar:SequenceItemClick(clickedItem)
    local clickedSlot = self.cursorSlot + clickedItem - self.cursorSequenceItem;
--Turbine.Shell.WriteLine("clickedItem = " .. tostring(clickedItem) .. "; clickedSlot = " .. tostring(clickedSlot));
--Turbine.Shell.WriteLine("before: cursorSlot = " .. tostring(self.cursorSlot) .. "; cursorSequenceItem = " .. tostring(self.cursorSequenceItem));
    if ((self.settings.animation.duration ~= -1) and (not self.animationStopped)) then
        if (clickedSlot == self.cursorSlot) then
--Puts("Clicked cursor slot (" .. tostring(self.cursorSlot) .. ". Setting item to " .. tostring(self.cursorSequenceItem + 1));
            self:SetCursorSequenceItem(self.cursorSequenceItem + 1);
            if (self.settings.animation.duration > 0) then
                self:Animate(0);
            end
        elseif (clickedSlot > self.cursorSlot) then
            local cursorOffset = clickedSlot - self.cursorSlot;
            self:SetCursorSlot(clickedSlot);
            self:SetCursorSequenceItem(self.cursorSequenceItem + cursorOffset + 1);
            if (self.settings.animation.duration > 0) then
                self:Animate(0);
            end
        end

        -- Execute automatic actions
        local nextItem = self.sequenceItems[clickedItem + 1];
        if (nextItem and nextItem.automatic) then
            nextItem:MouseUp();
        end
    end
--Turbine.Shell.WriteLine("after: cursorSlot = " .. tostring(self.cursorSlot) .. "; cursorSequenceItem = " .. tostring(self.cursorSequenceItem));
end

function Bar:Update()
    local timeDelta = Turbine.Engine.GetGameTime() - self.animationStartTime;
    if (timeDelta > 0) then
        self:Animate(timeDelta);
    end
end

function Bar:SetAnimationSpeed(duration)
    self.settings.animation.duration = duration;
    self:SaveSettings(false);
end

-- Achieves the scrolling effect.  Gets called by Bar:Update().
function Bar:Animate(timeDelta)
    local progress = timeDelta / self.settings.animation.duration;
    if (progress == 0) then
        self.animationStartTime = Turbine.Engine.GetGameTime();
        self.animationDistance = self.settings.slotSize + self.settings.slotSpacing;
        self:SetWantsUpdates(true);
    elseif (progress > 1) then
        progress = 1;
    end
    local displacement = math.floor(self.animationDistance * (1 - progress));
    if (self.settings.orientation == "Up") then
        self:SetTop(self.settings.position.top - displacement);
        self.cursor:SetTop(self.cursor.top - displacement);
    elseif (self.settings.orientation == "Down") then
        self:SetTop(self.settings.position.top + displacement);
        self.cursor:SetTop(self.cursor.top + displacement);
    elseif (self.settings.orientation == "Left") then
        self:SetLeft(self.settings.position.left - displacement);
        self.cursor:SetLeft(self.cursor.left - displacement);
    elseif (self.settings.orientation == "Right") then
        self:SetLeft(self.settings.position.left + displacement);
        self.cursor:SetLeft(self.cursor.left + displacement);
    end

    -- Make sure the item under the cursor is always clickable.  This hack is
    -- necessary because as the slot moves, no MouseEnter event occurs and
    -- hence no MouseClick events can be received.
    self.sequenceItems[self.cursorSequenceItem]:SetVisible(false);
    self.sequenceItems[self.cursorSequenceItem]:SetVisible(true);

    if (progress == 1) then
        self:SetWantsUpdates(false);
    end
end

function Bar:Destroy()
    if (self.cursor) then
        self.cursor:Close();
    end
    if (self.settingsMenu) then
        self.settingsMenu:Close();
    end
    if (self.caption) then
        self.caption:Close();
    end
    if (self.captionEditor) then
        self.captionEditor:Close();
    end
    if (self.sequenceEditor) then
        self.sequenceEditor:Close();
    end
    if (self.exportWindow) then
        self.exportWindow:Close();
    end
    if (self.colorPicker) then
        self.colorPicker:Close();
    end
    -- Unregister as event generator
    for eventName, generatorID in pairs(self.eventGeneratorIDs) do
        self.manager:RemoveEventGenerator(generatorID, eventName);
    end
    self.manager.objects[self.objectID] = nil;
    self:Close();
end

function Bar:GetVisibleLeft()
    local left, _, _, _ = self:GetVisibleSizePos();
    return left;
end

function Bar:SetVisibleLeft(left)
    self:OffsetPosition(left - self:GetVisibleLeft(), 0);
end

function Bar:GetVisibleTop()
    local _, top, _, _ = self:GetVisibleSizePos();
    return top;
end

function Bar:SetVisibleTop(top)
    self:OffsetPosition(0, top - self:GetVisibleTop());
end

function Bar:GetVisibleWidth()
    local _, _, width, _ = self:GetVisibleSizePos();
    return width;
end

function Bar:GetVisibleHeight()
    local _, _, _, height = self:GetVisibleSizePos();
    return height;
end

function Bar:GetVisibleSizePos()
    local left, top, width, height;
    local slotSize = self.settings.slotSize + self.settings.slotSpacing;
    local left_firstSlot, top_firstSlot = self:PointToScreen(self:GetSlotCoords(1));
    local left_lastSlot, top_lastSlot = self:PointToScreen(self:GetSlotCoords(self.settings.visibleSlots));
--Puts("[" .. self.settings.caption.text .. "] first (" .. left_firstSlot .. ", " .. top_firstSlot .. "); last (" .. left_lastSlot .. ", " .. top_lastSlot .. ")");
    if (self.settings.orientation == "Up") then
        left, top = left_lastSlot, top_lastSlot;
        width = slotSize;
        height = top_firstSlot - top_lastSlot + slotSize;
    elseif (self.settings.orientation == "Down") then
        left, top = left_firstSlot, top_firstSlot;
        width = slotSize;
        height = top_lastSlot - top_firstSlot + slotSize;
    elseif (self.settings.orientation == "Left") then
        left, top = left_lastSlot, top_lastSlot;
        width = left_firstSlot - left_lastSlot + slotSize;
        height = slotSize;
    else -- "Right"
        left, top = left_firstSlot, top_firstSlot;
        width = left_lastSlot - left_firstSlot + slotSize;
        height = slotSize;
    end
    return left, top, width, height;
end

function Bar:GetSlotCoords(slot)
    local slotSize = self.settings.slotSize + self.settings.slotSpacing;
    local offset = self.cursorMargin + (slot - 1) * slotSize;
    local left, top;
    if (self.settings.orientation == "Up") then
        left = self.cursorMargin;
        top = self:GetHeight() - slotSize - offset;
    elseif (self.settings.orientation == "Down") then
        left = self.cursorMargin;
        top = offset;
    elseif (self.settings.orientation == "Left") then
        left = self:GetWidth() - slotSize - offset;
        top = self.cursorMargin;
    else -- "Right"
        left = offset;
        top = self.cursorMargin;
    end
-- Turbine.Shell.WriteLine("returning (left, top) = (" .. tostring(left) .. ", " .. tostring(top) .. ") for " .. tostring(slot));
    return left, top
end

function Bar:Find()
    self:MoveOntoScreen();
    self:Flash();
end

function Bar:MoveOntoScreen()
    local screenWidth, screenHeight = Turbine.UI.Display:GetWidth(), Turbine.UI.Display:GetHeight();
    local left, top = self.caption:GetLeft(), self.caption:GetTop();
    local right, bottom = left + self.caption:GetWidth(), top + self.caption:GetHeight();
    local deltaX, deltaY = 0, 0;
    if (left < 0) then
        deltaX = -left;
    elseif (right > screenWidth) then
        deltaX = screenWidth - right;
    end
    if (top < 0) then
        deltaY = -top;
    elseif (bottom > screenHeight) then
        deltaY = screenHeight - bottom;
    end
    self:OffsetPosition(deltaX, deltaY);
    self:SnapToGrid();
end

function Bar:Flash()
    self.caption.startTime = Turbine.Engine.GetGameTime();
    self.caption.label:SetVisible(true);
    self.caption.Update = function(caption, args)
        local timeDelta = Turbine.Engine.GetGameTime() - caption.startTime;
        if (timeDelta > 3) then
            caption.label:SetForeColor(self.color);
            caption.label:SetVisible(not self.settings.caption.hidden);
            caption:SetWantsUpdates(false);
        else
            local progress = (math.sin(timeDelta * 15) + 1) / 2; --math.modf(timeDelta / 0.3);
            caption.label:SetForeColor(Turbine.UI.Color(progress, 1, 1, 0));
        end
    end
    self.caption:SetWantsUpdates(true);
end

Go to most recent revision | Compare with Previous | Blame


All times are GMT -5. The time now is 06:17 AM.


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