yellowfive@57: local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot") yellowfive@57: local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true) yellowfive@57: local AceGUI = LibStub("AceGUI-3.0") yellowfive@57: yellowfive@57: -- used to make some stuff layer correctly yellowfive@57: Amr.FrameLevels = { yellowfive@57: High = 100, yellowfive@57: Highest = 125 yellowfive@57: } yellowfive@57: yellowfive@57: -- standard colors used throughout the UI (in standard 0-255 RGB format, game uses 0-1 decimals, but we auto-convert it below) yellowfive@57: Amr.Colors = { yellowfive@57: White = { R = 255, G = 255, B = 255 }, yellowfive@57: Black = { R = 0, G = 0, B = 0 }, yellowfive@57: Gray = { R = 153, G = 153, B = 153 }, yellowfive@57: Orange = { R = 201, G = 87, B = 1 }, yellowfive@57: Green = { R = 77, G = 134, B = 45 }, yellowfive@57: Blue = { R = 54, G = 172, B = 204 }, yellowfive@57: Red = { R = 204, G = 38, B = 38 }, yellowfive@57: Gold = { R = 255, G = 215, B = 0 }, yellowfive@57: BrightGreen = { R = 0, G = 255, B = 0 }, yellowfive@57: Text = { R = 255, G = 255, B = 255 }, yellowfive@57: TextHover = { R = 255, G = 255, B = 0 }, yellowfive@57: TextGray = { R = 120, G = 120, B = 120 }, yellowfive@57: TextHeaderActive = { R = 223, G = 134, B = 61 }, yellowfive@57: TextHeaderDisabled = { R = 188, G = 188, B = 188 }, yellowfive@57: TextTan = { R = 223, G = 192, B = 159 }, yellowfive@57: BorderBlue = { R = 26, G = 83, B = 98 }, yellowfive@57: BorderGray = { R = 96, G = 96, B = 96 }, yellowfive@57: Bg = { R = 41, G = 41, B = 41 }, yellowfive@57: BgInput = { R = 17, G = 17, B = 17 }, yellowfive@57: BarHigh = { R = 114, G = 197, B = 66 }, yellowfive@57: BarMed = { R = 255, G = 196, B = 36 }, yellowfive@57: BarLow = { R = 201, G = 87, B = 1 } yellowfive@57: } yellowfive@57: yellowfive@57: -- convert from common RGB to 0-1 RGB values yellowfive@57: for k,v in pairs(Amr.Colors) do yellowfive@57: v.R = v.R / 255 yellowfive@57: v.G = v.G / 255 yellowfive@57: v.B = v.B / 255 yellowfive@57: end yellowfive@57: yellowfive@57: -- get colors for classes from WoW's constants yellowfive@57: Amr.Colors.Classes = {} yellowfive@57: for k,v in pairs(RAID_CLASS_COLORS) do yellowfive@57: Amr.Colors.Classes[k] = { R = v.r, G = v.g, B = v.b } yellowfive@57: end yellowfive@57: yellowfive@133: -- get colors for item qualities from WoW's constants yellowfive@133: Amr.Colors.Qualities = {} yellowfive@133: for k,v in pairs(ITEM_QUALITY_COLORS) do yellowfive@133: Amr.Colors.Qualities[k] = { R = v.r, G = v.g, B = v.b } yellowfive@133: end yellowfive@133: yellowfive@57: -- helper to take 0-1 value and turn into 2-digit hex value yellowfive@57: local function decToHex(num) yellowfive@57: num = math.ceil(num * 255) yellowfive@57: num = string.format("%X", num) yellowfive@57: if string.len(num) == 1 then num = "0" .. num end yellowfive@57: return num yellowfive@57: end yellowfive@57: yellowfive@57: function Amr.ColorToHex(color, alpha) yellowfive@57: return decToHex(alpha) .. decToHex(color.R) .. decToHex(color.G) .. decToHex(color.B) yellowfive@57: end yellowfive@57: yellowfive@57: local function getFontPath(style) yellowfive@73: local locale = GetLocale() yellowfive@73: if locale == "koKR" then yellowfive@73: return "Fonts\\2002.TTF" yellowfive@73: elseif locale == "zhCN" then yellowfive@73: return "Fonts\\ARKai_T.ttf" yellowfive@73: elseif locale == "zhTW" then yellowfive@73: return "Fonts\\bLEI00D.ttf" yellowfive@73: elseif locale == "ruRU" then yellowfive@73: return "Fonts\\FRIZQT___CYR.TTF" yellowfive@67: else yellowfive@67: return "Interface\\AddOns\\" .. Amr.ADDON_NAME .. "\\Media\\Ubuntu-" .. style .. ".ttf" yellowfive@67: end yellowfive@57: end yellowfive@57: yellowfive@57: -- create a font with the specified style (Regular, Bold, Italic), size (pixels, max of 32), color (object with R, G, B), and alpha (if not specified, defaults to 1) yellowfive@57: function Amr.CreateFont(style, size, color, a) yellowfive@57: local alpha = a or 1 yellowfive@57: local id = string.format("%s_%d_%f_%f_%f_%f", style, size, color.R, color.G, color.B, alpha) yellowfive@57: local font = CreateFont(id) yellowfive@57: font:SetFont(getFontPath(style), size) yellowfive@57: font:SetTextColor(color.R, color.G, color.B, alpha) yellowfive@57: return font yellowfive@57: end yellowfive@57: yellowfive@57: -- helper to create a solid texture from a color with R,G,B properties yellowfive@57: function Amr.CreateTexture(parent, color, alpha, layer) yellowfive@57: local t = parent:CreateTexture(nil, layer or "ARTWORK") yellowfive@81: t:SetColorTexture(color.R, color.G, color.B, alpha or 1) yellowfive@57: return t yellowfive@57: end yellowfive@57: yellowfive@57: -- helper to create a cheater shadow without having to create custom images yellowfive@57: function Amr.DropShadow(frame) yellowfive@57: local shadow = frame:CreateTexture(nil, "BACKGROUND") yellowfive@81: shadow:SetColorTexture(0, 0, 0, 0.4) yellowfive@57: shadow:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -2) yellowfive@57: shadow:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 1, -1) yellowfive@57: yellowfive@57: shadow = frame:CreateTexture(nil, "BACKGROUND") yellowfive@81: shadow:SetColorTexture(0, 0, 0, 0.3) yellowfive@57: shadow:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -2) yellowfive@57: shadow:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 2, -2) yellowfive@57: yellowfive@57: shadow = frame:CreateTexture(nil, "BACKGROUND") yellowfive@81: shadow:SetColorTexture(0, 0, 0, 0.1) yellowfive@57: shadow:SetPoint("TOPLEFT", frame, "TOPLEFT", 2, -2) yellowfive@57: shadow:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 3, -3) yellowfive@57: end yellowfive@57: yellowfive@57: yellowfive@57: -- a layout that does nothing, just lets the children position themselves how they prefer yellowfive@57: AceGUI:RegisterLayout("None", function(content, children) yellowfive@57: if content.obj.LayoutFinished then yellowfive@57: content.obj:LayoutFinished(nil, nil) yellowfive@57: end yellowfive@57: end) yellowfive@57: yellowfive@57: local _mainFrame = nil yellowfive@57: local _mainTabs = nil yellowfive@57: local _mainCover = nil yellowfive@57: local _activeTab = "Export" yellowfive@57: yellowfive@57: -- release everything when the UI is closed yellowfive@57: local function onMainFrameClose(widget) yellowfive@57: AceGUI:Release(widget) yellowfive@57: Amr["ReleaseTab" .. _activeTab](Amr) yellowfive@57: _mainFrame = nil yellowfive@57: _mainTabs = nil yellowfive@57: _mainCover = nil yellowfive@57: end yellowfive@57: yellowfive@57: local function onMainTabSelected(container, event, group) yellowfive@57: container:ReleaseChildren() yellowfive@57: Amr["ReleaseTab" .. _activeTab](Amr) yellowfive@57: yellowfive@57: _activeTab = group yellowfive@57: yellowfive@57: -- each section defines its own render method in a separate file (options tab is defined in Core.lua, uses standard Ace config stuff to auto-generate) yellowfive@57: Amr["RenderTab" .. group](Amr, container) yellowfive@57: end yellowfive@57: yellowfive@57: -- refresh the currently displayed tab yellowfive@57: function Amr:RefreshTab() yellowfive@57: if not _mainTabs then return end yellowfive@57: yellowfive@57: _mainTabs:ReleaseChildren() yellowfive@57: Amr["ReleaseTab" .. _activeTab](Amr) yellowfive@57: Amr["RenderTab" .. _activeTab](Amr, container) yellowfive@57: end yellowfive@57: yellowfive@57: local function createMainWindow() yellowfive@57: yellowfive@57: local f = AceGUI:Create("AmrUiFrame") yellowfive@57: f:SetStatusTable(Amr.db.profile.window) -- window position is remembered in db yellowfive@57: f:SetCallback("OnClose", onMainFrameClose) yellowfive@57: f:SetLayout("None") yellowfive@57: f:SetWidth(1000) yellowfive@57: f:SetHeight(700) yellowfive@57: f:SetBorderColor(Amr.Colors.BorderBlue) yellowfive@57: f:SetBackgroundColor(Amr.Colors.Bg) yellowfive@61: yellowfive@61: if Amr.db.profile.options.uiScale ~= 1 then yellowfive@61: local scale = tonumber(Amr.db.profile.options.uiScale) yellowfive@61: f:SetScale(scale) yellowfive@61: end yellowfive@57: yellowfive@57: -- some status text yellowfive@57: local lblStatus = AceGUI:Create("AmrUiLabel") yellowfive@124: f:AddChild(lblStatus) yellowfive@57: lblStatus:SetWidth(900) yellowfive@57: lblStatus:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.TextTan)) yellowfive@133: lblStatus:SetText("Ask Mr. Robot " .. L.MainStatusText("v" .. GetAddOnMetadata(Amr.ADDON_NAME, "Version"), "https://www.askmrrobot.com/addon")) yellowfive@57: lblStatus:SetJustifyH("CENTER") yellowfive@57: lblStatus:SetWordWrap(false) yellowfive@57: lblStatus:SetPoint("TOP", f.content, "BOTTOM") yellowfive@57: yellowfive@57: -- create the main UI container yellowfive@57: local c = AceGUI:Create("AmrUiPanel") yellowfive@57: c:SetLayout("Fill") yellowfive@57: c:SetBackgroundColor(Amr.Colors.Black, 0) yellowfive@124: f:AddChild(c) yellowfive@57: c:SetPoint("TOPLEFT", f.content, "TOPLEFT") yellowfive@57: c:SetPoint("BOTTOMRIGHT", f.content, "BOTTOMRIGHT") yellowfive@57: yellowfive@57: -- create the main tab strip yellowfive@57: local t = AceGUI:Create("AmrUiTabGroup") yellowfive@124: c:AddChild(t) yellowfive@57: t:SetLayout("None") yellowfive@57: t:SetTabs({ yellowfive@57: {text=L.TabExportText, value="Export"}, yellowfive@57: {text=L.TabGearText, value="Gear"}, yellowfive@93: {text=L.TabLogText, value="Log"}, yellowfive@122: --{text=L.TabTeamText, value="Team"}, yellowfive@57: {text=L.TabOptionsText, value="Options"} yellowfive@57: }) yellowfive@57: t:SetCallback("OnGroupSelected", onMainTabSelected) yellowfive@57: yellowfive@57: -- create the cover/overlay container yellowfive@57: c = AceGUI:Create("AmrUiPanel") yellowfive@57: c:SetLayout("None") yellowfive@57: c:EnableMouse(true) yellowfive@57: c:SetBackgroundColor(Amr.Colors.Black, 0.75) yellowfive@124: f:AddChild(c) yellowfive@57: c:SetPoint("TOPLEFT", f.frame, "TOPLEFT") yellowfive@57: c:SetPoint("BOTTOMRIGHT", f.frame, "BOTTOMRIGHT") yellowfive@57: yellowfive@57: -- after adding, set cover to sit on top of everything, then hide it yellowfive@57: c:SetStrata("FULLSCREEN_DIALOG") yellowfive@57: c:SetLevel(Amr.FrameLevels.High) yellowfive@57: c:SetVisible(false) yellowfive@57: yellowfive@57: -- put standard cover ui elements (label, cancel button) yellowfive@57: local coverMsg = AceGUI:Create("AmrUiLabel") yellowfive@124: c:AddChild(coverMsg) yellowfive@57: coverMsg:SetWidth(600) yellowfive@57: coverMsg:SetFont(Amr.CreateFont("Regular", 16, Amr.Colors.TextTan)) yellowfive@57: coverMsg:SetJustifyH("MIDDLE") yellowfive@57: coverMsg:SetJustifyV("MIDDLE") yellowfive@57: coverMsg:SetText("") yellowfive@57: coverMsg:SetPoint("CENTER", c.frame, "CENTER", 0, 20) yellowfive@57: yellowfive@57: local coverCancel = AceGUI:Create("AmrUiTextButton") yellowfive@57: coverCancel:SetWidth(200) yellowfive@57: coverCancel:SetHeight(20) yellowfive@57: coverCancel:SetText(L.CoverCancel) yellowfive@57: coverCancel:SetFont(Amr.CreateFont("Italic", 14, Amr.Colors.TextHeaderDisabled)) yellowfive@57: coverCancel:SetHoverFont(Amr.CreateFont("Italic", 14, Amr.Colors.TextHeaderActive)) yellowfive@124: c:AddChild(coverCancel) yellowfive@57: coverCancel:SetPoint("CENTER", c.frame, "CENTER", 0, -20) yellowfive@57: yellowfive@57: coverCancel:SetCallback("OnClick", function(widget) yellowfive@57: Amr:HideCover() yellowfive@57: end) yellowfive@57: yellowfive@57: -- create cover content area for custom cover ui (sort of like a modal dialog) yellowfive@57: local coverContent = AceGUI:Create("AmrUiPanel") yellowfive@57: coverContent:SetLayout("None") yellowfive@57: coverContent:SetBackgroundColor(Amr.Colors.Black, 0) yellowfive@124: c:AddChild(coverContent) yellowfive@57: coverContent:SetPoint("TOPLEFT", c.frame, "TOPLEFT") yellowfive@57: coverContent:SetPoint("BOTTOMRIGHT", c.frame, "BOTTOMRIGHT") yellowfive@57: yellowfive@57: _mainFrame = f yellowfive@57: _mainTabs = t yellowfive@57: _mainCover = { yellowfive@57: panel = c, yellowfive@57: content = coverContent, yellowfive@57: label = coverMsg, yellowfive@57: cancel = coverCancel yellowfive@57: } yellowfive@57: end yellowfive@57: yellowfive@57: function Amr:ShowCover(msgOrRenderFunc, disableCancel) yellowfive@57: if _mainCover then yellowfive@57: _mainCover.panel:SetVisible(true) yellowfive@57: yellowfive@57: if type(msgOrRenderFunc) == "function" then yellowfive@57: _mainCover.label:SetText("") yellowfive@57: _mainCover.cancel:SetVisible(false) yellowfive@57: yellowfive@57: -- render custom content into the cover yellowfive@57: msgOrRenderFunc(_mainCover.content) yellowfive@57: else yellowfive@57: -- standard loading/waiting message with optional cancel button yellowfive@57: _mainCover.label:SetText(msgOrRenderFunc or "") yellowfive@57: _mainCover.cancel:SetVisible(not disableCancel) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: function Amr:HideCover() yellowfive@57: if _mainCover then yellowfive@57: _mainCover.panel:SetVisible(false) yellowfive@57: yellowfive@57: -- release any custom content rendered into the cover yellowfive@57: _mainCover.content:ReleaseChildren() yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- shows a "modal" alert over the main UI yellowfive@57: function Amr:ShowAlert(message, btnText) yellowfive@57: yellowfive@57: Amr:ShowCover(function(container) yellowfive@57: local border = AceGUI:Create("AmrUiPanel") yellowfive@57: border:SetLayout("None") yellowfive@57: border:SetBackgroundColor(Amr.Colors.BorderBlue) yellowfive@57: border:SetWidth(400) yellowfive@57: border:SetHeight(150) yellowfive@124: container:AddChild(border) yellowfive@57: border:SetPoint("CENTER", container.frame, "CENTER") yellowfive@57: yellowfive@57: local bg = AceGUI:Create("AmrUiPanel") yellowfive@57: bg:SetLayout("None") yellowfive@57: bg:SetBackgroundColor(Amr.Colors.Bg) yellowfive@124: border:AddChild(bg) yellowfive@57: bg:SetPoint("TOPLEFT", border.frame, "TOPLEFT", 1, -1) yellowfive@57: bg:SetPoint("BOTTOMRIGHT", border.frame, "BOTTOMRIGHT", -1, 1) yellowfive@57: yellowfive@57: local lbl = AceGUI:Create("AmrUiLabel") yellowfive@124: bg:AddChild(lbl) yellowfive@57: lbl:SetWidth(360) yellowfive@57: lbl:SetFont(Amr.CreateFont("Regular", 16, Amr.Colors.Text)) yellowfive@57: lbl:SetJustifyH("CENTER") yellowfive@57: lbl:SetText(message) yellowfive@57: lbl:SetPoint("TOP", bg.content, "TOP", 0, -20) yellowfive@57: yellowfive@57: local btn = AceGUI:Create("AmrUiButton") yellowfive@57: btn:SetBackgroundColor(Amr.Colors.Orange) yellowfive@57: btn:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White)) yellowfive@57: btn:SetWidth(120) yellowfive@57: btn:SetHeight(26) yellowfive@57: btn:SetText(btnText) yellowfive@124: bg:AddChild(btn) yellowfive@57: btn:SetPoint("BOTTOM", bg.content, "BOTTOM", 0, 20) yellowfive@57: yellowfive@57: btn:SetCallback("OnClick", function(widget) yellowfive@57: Amr:HideCover() yellowfive@57: end) yellowfive@57: end) yellowfive@57: end yellowfive@57: yellowfive@57: -- toggle visibility of the UI yellowfive@57: function Amr:Toggle() yellowfive@57: if not self:IsEnabled() then return end yellowfive@57: yellowfive@57: if not _mainFrame then yellowfive@57: self:Show() yellowfive@57: else yellowfive@57: self:Hide() yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- hide the UI if not already hidden yellowfive@57: function Amr:Hide() yellowfive@57: if not self:IsEnabled() then return end yellowfive@57: if not _mainFrame then return end yellowfive@57: yellowfive@57: _mainFrame:Hide() yellowfive@57: end yellowfive@57: yellowfive@57: -- show the UI if not shown already, and display the last active tab yellowfive@57: function Amr:Show() yellowfive@57: if not self:IsEnabled() then return end yellowfive@57: yellowfive@57: if _mainFrame then yellowfive@57: _mainFrame:Show() yellowfive@57: else yellowfive@57: createMainWindow() yellowfive@57: end yellowfive@57: yellowfive@57: -- show the active tab yellowfive@57: _mainTabs:SelectTab(_activeTab) yellowfive@57: end yellowfive@57: yellowfive@61: function Amr:Reset() yellowfive@61: if not self:IsEnabled() then return end yellowfive@61: yellowfive@61: Amr:Hide() yellowfive@61: Amr:HideLootWindow() yellowfive@61: Amr:HideShopWindow() yellowfive@61: Amr.db.profile.options.uiScale = 1 yellowfive@61: Amr.db.profile.window = {} yellowfive@61: Amr.db.profile.lootWindow = {} yellowfive@61: Amr.db.profile.shopWindow = {} yellowfive@61: end yellowfive@61: yellowfive@57: -- show the UI if not shown already, and select the specified tab yellowfive@57: function Amr:ShowTab(tab) yellowfive@57: if not self:IsEnabled() then return end yellowfive@57: yellowfive@57: _activeTab = tab yellowfive@57: self:Show() yellowfive@57: end yellowfive@57: yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: -- Tooltips yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: yellowfive@57: -- set an item tooltip on any AceGUI widget with OnEnter and OnLeave events yellowfive@57: function Amr:SetItemTooltip(obj, itemLink, anchor, x, y) yellowfive@57: obj:SetUserData("ttItemLink", itemLink) yellowfive@57: obj:SetCallback("OnEnter", function(widget) yellowfive@57: local tooltipLink = widget:GetUserData("ttItemLink") yellowfive@57: GameTooltip:SetOwner(widget.frame, anchor and anchor or "ANCHOR_CURSOR", x, y) yellowfive@57: GameTooltip:SetHyperlink(tooltipLink) yellowfive@57: end) yellowfive@57: obj:SetCallback("OnLeave", function(widget) yellowfive@57: GameTooltip:Hide() yellowfive@57: end) yellowfive@57: end yellowfive@57: yellowfive@57: function Amr:SetSpellTooltip(obj, spellId, anchor, x, y) yellowfive@57: obj:SetUserData("ttSpellId", spellId) yellowfive@57: obj:SetCallback("OnEnter", function(widget) yellowfive@57: local ttSpellId = widget:GetUserData("ttSpellId") yellowfive@57: GameTooltip:SetOwner(widget.frame, anchor and anchor or "ANCHOR_CURSOR", x, y) yellowfive@57: GameTooltip:SetSpellByID(ttSpellId) yellowfive@57: end) yellowfive@57: obj:SetCallback("OnLeave", function(widget) yellowfive@57: GameTooltip:Hide() yellowfive@57: end) yellowfive@57: end yellowfive@57: yellowfive@57: function Amr:RenderCoverChrome(container, width, height) yellowfive@57: yellowfive@57: local border = AceGUI:Create("AmrUiPanel") yellowfive@57: border:SetLayout("None") yellowfive@57: border:SetBackgroundColor(Amr.Colors.BorderBlue) yellowfive@57: border:SetWidth(width + 2) yellowfive@57: border:SetHeight(height + 2) yellowfive@124: container:AddChild(border) yellowfive@57: border:SetPoint("CENTER", container.frame, "CENTER") yellowfive@57: yellowfive@57: local bg = AceGUI:Create("AmrUiPanel") yellowfive@57: bg:SetLayout("None") yellowfive@57: bg:SetBackgroundColor(Amr.Colors.Bg) yellowfive@124: border:AddChild(bg) yellowfive@57: bg:SetPoint("TOPLEFT", border.frame, "TOPLEFT", 1, -1) yellowfive@57: bg:SetPoint("BOTTOMRIGHT", border.frame, "BOTTOMRIGHT", -1, 1) yellowfive@57: yellowfive@57: return bg, border yellowfive@57: end