diff ui/Ui.lua @ 57:01b63b8ed811 v21

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