Quantcast

Might as well bring in histograms as well.

Scott Sibley [09-10-10 - 20:12]
Might as well bring in histograms as well.
Filename
Modules/Histograms.lua
modules.xml
diff --git a/Modules/Histograms.lua b/Modules/Histograms.lua
new file mode 100644
index 0000000..b379f34
--- /dev/null
+++ b/Modules/Histograms.lua
@@ -0,0 +1,589 @@
+local mod = StarTip:NewModule("Histograms", "AceTimer-3.0")
+mod.name = "Histograms"
+mod.toggled = true
+local _G = _G
+local StarTip = _G.StarTip
+local GameTooltip = _G.GameTooltip
+local GameTooltipStatusBar = _G.GameTooltipStatusBar
+local UnitIsPlayer = _G.UnitIsPlayer
+local RAID_CLASS_COLORS = _G.RAID_CLASS_COLORS
+local UnitSelectionColor = _G.UnitSelectionColor
+local UnitClass = _G.UnitClass
+local self = mod
+local timer
+local LSM = LibStub("LibSharedMedia-3.0")
+local WidgetHistogram = LibStub("StarLibWidgetHistogram-1.0")
+local LibCore = LibStub("StarLibCore-1.0")
+
+local createHistograms
+local widgets = {}
+
+local function copy(tbl)
+	local newTbl = {}
+	for k, v in pairs(tbl) do
+		if type(v) == "table" then
+			v = copy(v)
+		end
+		newTbl[k] = v
+	end
+	return newTbl
+end
+
+local defaultWidgets = {
+	["Health Histogram"] = {
+		type = "histogram",
+		expression = [[
+if not UnitExists("mouseover") then return random(100) end
+return UnitHealth("mouseover")
+]],
+		min = "return 0",
+		max = "return UnitHealthMax('mouseover')",
+		color1 = [[
+if not UnitExists("mouseover") or not self then return 100 end
+if self.visitor and self.visitor.visitor and self.visitor.visitor.db and self.visitor.visitor.db.profile.classColors then
+    return ClassColor("mouseover")
+else
+    local min, max = UnitHealth("mouseover"), UnitHealthMax("mouseover")
+    return HPColor(min, max)
+end
+]],
+		height = 20,
+		width = 10,
+		layer = 1,
+		point = {"BOTTOMLEFT", "GameTooltip", "TOPLEFT", 0, -12},
+		texture1 = LSM:GetDefault("statushistogram"),
+	},
+	["widget_random_histogram"] = {
+		type = "histogram",
+		expression = [[
+do return random(100) end
+mem, percent, memdiff, totalMem, totaldiff = GetMemUsage("StarTip")
+
+if mem then
+    if totaldiff == 0 then totaldiff = 1 end
+    return memdiff / totaldiff * 100
+end
+]],
+		min = "return 0",
+		max = "return 100",
+		reversed = true,
+		char = "0",
+		width = 5,
+		height = 50,
+		point = {"TOPLEFT", "GameTooltip", "BOTTOMLEFT", 0, -12},
+		layer = 1
+	},
+}
+
+local defaults = {
+	profile = {
+		classColors = true,
+	}
+}
+
+local options = {
+	add = {
+		name = "Add Histogram",
+		desc = "Add a histogram",
+		type = "input",
+		set = function(info, v)
+			mod.db.profile.histograms[v] = {
+				type = "histogram",
+				min = "return 0",
+				max = "return 100",
+				height = 6,
+				point = {"BOTTOMLEFT", "GameTooltip", "TOPLEFT"},
+				texture = LSM:GetDefault("statushistogram"),
+				expression = ""
+			}
+			StarTip:RebuildOpts()
+			createHistograms()
+		end,
+		order = 5
+	},
+	defaults = {
+		name = "Restore Defaults",
+		desc = "Restore Defaults",
+		type = "execute",
+		func = function()
+			mod.db.profile.histograms = copy(defaultWidgets);
+			StarTip:RebuildOpts()
+			StarTip:Print("Bug: You'll have to reload your UI to see the change in the histograms list. I'm not sure why.")
+		end,
+		order = 6
+	},
+	histograms = {
+		name = "Histograms",
+		type = "group",
+		args = {}
+	},
+}
+
+function updateHistogram(widget, hist)
+	hist:SetValue(widget.val * 100)
+
+	if not widget.color then return end
+
+	local r, g, b = 0, 0, 1
+
+	if widget.color.is_valid then
+		r, g, b = widget.color2.res1, widget.color2.res2, widget.color2.res3
+	end
+
+	if type(r) == "number" then
+		hist:SetStatusBarColor(r, g, b)
+	else
+		--histogram:Hide()
+	end
+end
+
+local textureDict = {}
+
+function mod:CreateHistograms()
+	createHistograms()
+end
+
+local new, del
+do
+	local pool = {}
+	function new()
+		local histogram = next(pool)
+
+		if histogram then
+			pool[histogram] = nil
+		else
+			histogram = CreateFrame("StatusBar", nil, GameTooltip)
+		end
+
+		return histogram
+	end
+	function del(histogram)
+		pool[histogram] = true
+	end
+end
+
+function createHistograms()
+	if type(mod.histograms) ~= "table" then mod.histograms = {} end
+	for k, v in pairs(mod.histograms) do
+		v[1]:Del()
+		v[2]:Hide()
+		del(v[2])
+	end
+	wipe(mod.histograms)
+	local appearance = StarTip:GetModule("Appearance")
+	for k, v in pairs(self.db.profile.histograms) do
+		for i = 0, v.width - 1 do
+			local histogram = new()
+			local widget = WidgetHistogram:New(mod.core, k, copy(v), v.row or 0, v.col or 0, 0, StarTip.db.profile.errorLevel, updateHistogram, histogram)
+			histogram:SetStatusBarTexture(LSM:Fetch("statusbar", v.texture1))
+			histogram:ClearAllPoints()
+			local arg1, arg2, arg3, arg4, arg5 = unpack(v.point or {"BOTTOMLEFT", "GameTooltip", "TOPLEFT"})
+			if v.width > 100 then
+				arg4 = (arg4 or 0) + i * (v.width / 100)
+			else
+				arg4 = (arg4 or 0) + i * (v.width or 6)
+			end
+			arg5 = (arg5 or 0)
+			histogram:SetPoint(arg1, arg2, arg3, arg4, arg5)
+			if v.width then
+				if (v.width > 100) then
+					histogram:SetWidth(v.width / 100)
+				else
+					histogram:SetWidth(v.width or 6)
+				end
+			else
+				histogram:SetPoint("TOPLEFT", GameTooltip, "TOPLEFT")
+				histogram:SetPoint("BOTTOMLEFT", GameTooltip, "BOTTOMLEFT")
+			end
+			histogram:SetHeight(v.height)
+			histogram:SetMinMaxValues(0, 100)
+			histogram:SetOrientation("VERTICAL")
+			histogram:Show()
+			tinsert(mod.histograms, {widget, histogram})
+		end
+	end
+
+end
+
+function mod:OnInitialize()
+	self.db = StarTip.db:RegisterNamespace(self:GetName(), defaults)
+
+	if not self.db.profile.histograms then
+		self.db.profile.histograms = {}
+	end
+
+	for k, v in ipairs(defaultWidgets) do
+		for kk, vv in ipairs(self.db.profile.histograms) do
+			if k == kk then
+				for k, val in pairs(v) do
+					if v[k] ~= vv[k] and not vv[k.."Dirty"] then
+						vv[k] = v[k]
+					end
+				end
+				v.tagged = true
+			end
+		end
+	end
+
+	for k, v in pairs(defaultWidgets) do
+		if not v.tagged and not v.deleted then
+			self.db.profile.histograms[k] = v
+		end
+	end
+
+	self.core = LibCore:New(mod, StarTip.environment, "StarTip.Histograms", {["StarTip.Histograms"] = {}}, nil, StarTip.db.profile.errorLevel)
+
+	self.offset = 0
+
+	StarTip:SetOptionsDisabled(options, true)
+
+end
+
+function mod:OnEnable()
+	if not self.histograms then self.histograms = {} end
+
+	for k, histogram in pairs(self.histograms) do
+		histogram[2]:Hide()
+	end
+	createHistograms()
+	GameTooltip:SetClampRectInsets(0, 0, 10, 10)
+	StarTip:SetOptionsDisabled(options, false)
+end
+
+function mod:OnDisable()
+	for k, histogram in pairs(self.histograms) do
+		histogram[1]:Del()
+		histogram[2]:Hide()
+	end
+	GameTooltip:SetClampRectInsets(0, 0, 0, 0)
+	StarTip:SetOptionsDisabled(options, true)
+end
+
+--[[function mod:RebuildOpts()
+	for k, v in ipairs(self.db.profile.histograms) do
+		options.histograms.args[k] = WidgetHistogram:GetOptions(v)
+	end
+end]]
+
+function mod:GetOptions()
+	return options
+end
+
+function mod:SetUnit()
+	GameTooltipStatusBar:Hide()
+	self.offset = 0
+	createHistograms()
+	for i, histogram in pairs(self.histograms) do
+		histogram[1]:Start()
+		histogram[2]:Show()
+	end
+end
+
+function mod:SetItem()
+	for i, histogram in pairs(self.histograms) do
+		histogram[1]:Stop()
+		histogram[2]:Hide()
+	end
+end
+
+function mod:SetSpell()
+	for i, histogram in pairs(self.histograms) do
+		histogram[1]:Stop()
+		histogram[2]:Hide()
+	end
+end
+
+function mod:OnHide()
+	if timer then
+		self:CancelTimer(timer)
+		timer = nil
+	end
+	for i, histogram in pairs(self.histograms) do
+		histogram[1]:Stop()
+		histogram[2]:Hide()
+	end
+end
+
+local function colorGradient(perc)
+    if perc <= 0.5 then
+        return 1, perc*2, 0
+    else
+        return 2 - perc*2, 1, 0
+    end
+end
+
+function mod:RebuildOpts()
+	local defaults = WidgetHistogram.defaults
+
+	for k, db in pairs(self.db.profile.histograms) do
+		options.histograms.args[k:gsub(" ", "_")] = {
+			name = k,
+			type="group",
+			order = 6,
+			args={
+				height = {
+					name = "Histogram height",
+					desc = "Enter the histogram's height",
+					type = "input",
+					pattern = "%d",
+					get = function() return tostring(db.height or defaults.height) end,
+					set = function(info, v)
+						db.height = tonumber(v);
+						db[k.."Dirty"] = true
+						createHistograms();
+					end,
+					order = 2
+				},
+				update = {
+					name = "Histogram update rate",
+					desc = "Enter the histogram's refresh rate",
+					type = "input",
+					pattern = "%d",
+					get = function() return tostring(db.update or defaults.update) end,
+					set = function(info, v)
+						db.update = tonumber(v);
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 3
+				},
+				--[[direction = {
+					name = "Histogram direction",
+					type = "select",
+					values = WidgetHistogram.directionList,
+					get = function() return db.direction or defaults.direction end,
+					set = function(info, v) db.direction = v; createHistograms() end,
+					order = 4
+				},
+				style = {
+					name = "Histogram Style",
+					type = "select",
+					values = WidgetHistogram.styleList,
+					get = function() return db.style or defaults.style end,
+					set = function(info, v) db.style = v; createHistograms() end,
+					order = 5
+				},]]
+				texture1 = {
+					name = "Texture #1",
+					desc = "The histogram's first texture",
+					type = "select",
+					values = LSM:List("statushistogram"),
+					get = function()
+						return StarTip:GetLSMIndexByName("statushistogram", db.texture1 or "Blizzard")
+					end,
+					set = function(info, v)
+						db.texture1 = LSM:List("statushistogram")[v]
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 4
+				},
+				texture2 = {
+					name = "Texture #2",
+					desc = "The histogram's second texture",
+					type = "select",
+					values = LSM:List("statushistogram"),
+					get = function()
+						return db.texture2 or db.texture1 or "Blizzard"
+					end,
+					set = function(info, v)
+						db.texture2 = LSM:List("statushistogram")[v]
+						db[k.."Dirty"] = true
+						createHistograms() end,
+					order = 5
+				},
+				point = {
+					name = "Anchor Points",
+					desc = "This histogram's anchor point. These arguments are passed to histogram:SetPoint()",
+					type = "input",
+					get = function() return db.point end,
+					set = function(info, v)
+						db.point = v;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 6
+				},
+				top = {
+					name = "First is Top",
+					desc = "Toggle whether to place the first histogram on top",
+					type = "toggle",
+					get = function() return db.top end,
+					set = function(info, v)
+						db.top = v;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 7
+				},
+				expression = {
+					name = "Histogram expression",
+					desc = "Enter the histogram's first expression",
+					type = "input",
+					multiline = true,
+					width = "full",
+					get = function() return db.expression end,
+					set = function(info, v)
+						db.expression = v;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 8
+				},
+				expression2 = {
+					name = "Histogram second expression",
+					desc = "Enter the histogram's second expression",
+					type = "input",
+					multiline = true,
+					width = "full",
+					get = function() return db.expression2 end,
+					set = function(info, v)
+						db.expression2 = v ;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 9
+				},
+				min = {
+					name = "Histogram min expression",
+					desc = "Enter the histogram's minimum expression",
+					type = "input",
+					multiline = true,
+					width = "full",
+					get = function() return db.min end,
+					set = function(info, v)
+						db.min = v;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 10
+
+				},
+				max = {
+					name = "Histogram max expression",
+					desc = "Enter the histogram's maximum expression",
+					type = "input",
+					multiline = true,
+					width = "full",
+					get = function() return db.max end,
+					set = function(info, v)
+						db.max = v;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 11
+				},
+				color1 = {
+					name = "First histogram color script",
+					desc = "Enter the histogram's first color script",
+					type = "input",
+					multiline = true,
+					width = "full",
+					get = function() return db.color1 end,
+					set = function(info, v)
+						db.color1 = v;
+						db[k.."Dirty"] = true
+					createHistograms() end,
+					order = 12
+				},
+				color2 = {
+					name = "Second histogram color script",
+					desc = "Enter the histogram's second color script",
+					type = "input",
+					multiline = true,
+					width = "full",
+					get = function() return db.color2 end,
+					set = function(info, v)
+						db.color2 = v;
+						db[k.."Dirty"] = true
+						createHistograms()
+					end,
+					order = 13
+				}
+			}
+		}
+	end
+end
+
+-- Colors, snagged from oUF
+local power = {
+	[0] = { r = 48/255, g = 113/255, b = 191/255}, -- Mana
+	[1] = { r = 226/255, g = 45/255, b = 75/255}, -- Rage
+	[2] = { r = 255/255, g = 178/255, b = 0}, -- Focus
+	[3] = { r = 1, g = 1, b = 34/255}, -- Energy
+	[4] = { r = 0, g = 1, b = 1}, -- Happiness
+	[5] = {}, --Unknown
+	[6] = { r = 0.23, g = 0.12, b = 0.77 } -- Runic Power
+}
+local health = {
+	[0] = {r = 49/255, g = 207/255, b = 37/255}, -- Health
+	[1] = {r = .6, g = .6, b = .6} -- Tapped targets
+}
+local happiness = {
+	[1] = {r = 1, g = 0, b = 0}, -- need.... | unhappy
+	[2] = {r = 1 ,g = 1, b = 0}, -- new..... | content
+	[3] = {r = 0, g = 1, b = 0}, -- colors.. | happy
+}
+
+--[[
+function mod:UpdateHistogram()
+	local unit = "mouseover"
+	if not UnitExists(unit) then return end
+	local min, max = UnitHealth(unit), UnitHealthMax(unit)
+	self.hpHistogram:SetMinMaxValues(0, max)
+	self.hpHistogram:SetValue(min)
+
+	local color
+	if self.db.profile.useGradient then
+		color = StarTip.new()
+		color.r, color.g, color.b = colorGradient(min/max)
+	elseif(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) or not UnitIsConnected(unit)) then
+		color = health[1]
+	elseif UnitIsPlayer(unit) then
+		color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
+	else
+		color = StarTip.new()
+		color.r, color.g, color.b = UnitSelectionColor(unit)
+	end
+	if not color then color = health[0] end
+	self.hpHistogram:SetStatusBarColor(color.r, color.g, color.b)
+	StarTip.del(color)
+end
+]]
+-- Logic snagged from oUF
+--[[
+function mod:UpdateHealth()
+	local unit = "mouseover"
+	if not UnitExists(unit) then return end
+	local min, max = UnitHealth(unit), UnitHealthMax(unit)
+	self.hpHistogram:SetMinMaxValues(0, max)
+	self.hpHistogram:SetValue(min)
+
+	local color
+	if self.db.profile.useGradient then
+		color = StarTip.new()
+		color.r, color.g, color.b = colorGradient(min/max)
+	elseif(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) or not UnitIsConnected(unit)) then
+		color = health[1]
+	elseif UnitIsPlayer(unit) then
+		color = RAID_CLASS_COLORS[select(2, UnitClass(unit))]
+	else
+		color = StarTip.new()
+		color.r, color.g, color.b = UnitSelectionColor(unit)
+	end
+	if not color then color = health[0] end
+	self.hpHistogram:SetStatusBarColor(color.r, color.g, color.b)
+	StarTip.del(color)
+end
+
+function mod:UpdateMana()
+	local unit = "mouseover"
+	if not UnitExists(unit) then return end
+	local min, max = UnitMana(unit), UnitManaMax(unit)
+	self.mpHistogram:SetMinMaxValues(0, max)
+	self.mpHistogram:SetValue(min)
+
+	local color = power[UnitPowerType(unit)]
+	self.mpHistogram:SetStatusBarColor(color.r, color.g, color.b)
+end
+]]
\ No newline at end of file
diff --git a/modules.xml b/modules.xml
index 625a07e..1738194 100644
--- a/modules.xml
+++ b/modules.xml
@@ -10,6 +10,7 @@
 <Script file = "Modules\DeadlyAnnounce.lua"/>
 <Script file = "Modules\Text.lua"/>
 <Script file = "Modules\Bars.lua"/>
+<Script file = "Modules\Histograms.lua"/>
 <Script file = "Modules\Talents.lua"/>

 <!--<Script file = "Modules\LCDDisplay.lua"/>-->