diff Libs/LibWindow-1.1/LibWindow-1.1.lua @ 9:f2a55f2d45c8

- added LibWindow to handle the window position.
author Tercioo
date Fri, 12 Feb 2016 14:11:13 -0200
parents
children fedcd7c21db9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libs/LibWindow-1.1/LibWindow-1.1.lua	Fri Feb 12 14:11:13 2016 -0200
@@ -0,0 +1,317 @@
+--[[
+Name: LibWindow-1.1
+Revision: $Rev: 8 $
+Author(s): Mikk (dpsgnome@mail.com)
+Website: http://old.wowace.com/wiki/LibWindow-1.1
+Documentation: http://old.wowace.com/wiki/LibWindow-1.1
+SVN: http://svn.wowace.com/root/trunk/WindowLib/Window-1.0
+Description: A library that handles the basics of "window" style frames: scaling, smart position saving, dragging..
+Dependencies: none
+License: Public Domain
+]]
+
+local MAJOR = "LibWindow-1.1"
+local MINOR = tonumber(("$Revision: 8 $"):match("(%d+)"))
+
+local lib = LibStub:NewLibrary(MAJOR,MINOR)
+if not lib then return end
+
+local min,max,abs = min,max,abs
+local pairs = pairs
+local tostring = tostring
+local UIParent,GetScreenWidth,GetScreenHeight,IsAltKeyDown = UIParent,GetScreenWidth,GetScreenHeight,IsAltKeyDown
+-- GLOBALS: error, ChatFrame1, assert
+
+local function print(msg) ChatFrame1:AddMessage(MAJOR..": "..tostring(msg)) end
+
+lib.utilFrame = lib.utilFrame or CreateFrame("Frame")
+lib.delayedSavePosition = lib.delayedSavePosition or {}
+lib.windowData = lib.windowData or {} 
+  --[frameref]={ 
+  --  names={optional names data from .RegisterConfig()}
+  --  storage= -- tableref where config data is read/written
+  --  altEnable=true/false
+  --}
+
+
+lib.embeds = lib.embeds or {}
+
+local mixins = {} -- "FuncName"=true
+
+
+
+---------------------------------------------------------
+-- UTILITIES
+---------------------------------------------------------
+
+
+local function getStorageName(frame, name)
+  local names = lib.windowData[frame].names
+  if names then
+		if names[name] then
+			return names[name]
+		end
+		if names.prefix then
+			return names.prefix .. name;
+		end
+	end
+	return name;
+end
+
+local function setStorage(frame, name, value)
+	lib.windowData[frame].storage[getStorageName(frame, name)] = value
+end
+
+local function getStorage(frame, name)
+	return lib.windowData[frame].storage[getStorageName(frame, name)]
+end
+
+
+lib.utilFrame:SetScript("OnUpdate", function(this)
+	this:Hide()
+	for frame,_ in pairs(lib.delayedSavePosition) do
+		lib.delayedSavePosition[frame] = nil
+		lib.SavePosition(frame)
+	end
+end)
+
+local function queueSavePosition(frame)
+	lib.delayedSavePosition[frame] = true
+	lib.utilFrame:Show()
+end
+
+
+---------------------------------------------------------
+-- IMPORTANT APIS
+---------------------------------------------------------
+
+mixins["RegisterConfig"]=true
+function lib.RegisterConfig(frame, storage, names)
+	if not lib.windowData[frame] then
+		lib.windowData[frame] = {}
+	end
+	lib.windowData[frame].names = names
+	lib.windowData[frame].storage = storage
+	
+	--[[ debug
+	frame.tx = frame:CreateTexture()
+	frame.tx:SetTexture(0,0,0, 0.4)
+	frame.tx:SetAllPoints(frame)
+	frame.tx:Show()
+	]]
+end
+
+
+
+
+---------------------------------------------------------
+-- POSITIONING AND SCALING
+---------------------------------------------------------
+
+local nilParent = {
+	GetWidth = function()
+		return GetScreenWidth() * UIParent:GetScale()
+	end,
+	GetHeight = function()
+		return GetScreenHeight() * UIParent:GetScale()
+	end,
+	GetScale = function() 
+		return 1
+	end,
+}
+
+mixins["SavePosition"]=true
+function lib.SavePosition(frame)
+	local parent = frame:GetParent() or nilParent
+	-- No, this won't work very well with frames that aren't parented to nil or UIParent
+	local s = frame:GetScale()
+	local left,top = frame:GetLeft()*s, frame:GetTop()*s
+	local right,bottom = frame:GetRight()*s, frame:GetBottom()*s
+	local pwidth, pheight = parent:GetWidth(), parent:GetHeight()
+
+	local x,y,point;
+	if left < (pwidth-right) and left < abs((left+right)/2 - pwidth/2) then
+		x = left;
+		point="LEFT";
+	elseif (pwidth-right) < abs((left+right)/2 - pwidth/2) then
+		x = right-pwidth;
+		point="RIGHT";
+	else
+		x = (left+right)/2 - pwidth/2;
+		point="";
+	end
+	
+	if bottom < (pheight-top) and bottom < abs((bottom+top)/2 - pheight/2) then
+		y = bottom;
+		point="BOTTOM"..point;
+	elseif (pheight-top) < abs((bottom+top)/2 - pheight/2) then
+		y = top-pheight;
+		point="TOP"..point;
+	else
+		y = (bottom+top)/2 - pheight/2;
+		-- point=""..point;
+	end
+	
+	if point=="" then
+		point = "CENTER"
+	end
+	
+	setStorage(frame, "x", x)
+	setStorage(frame, "y", y)
+	setStorage(frame, "point", point)
+	setStorage(frame, "scale", s)
+	
+	frame:ClearAllPoints()
+	frame:SetPoint(point, frame:GetParent(), point, x/s, y/s);
+end
+
+
+mixins["RestorePosition"]=true
+function lib.RestorePosition(frame)
+	local x = getStorage(frame, "x")
+	local y = getStorage(frame, "y")
+	local point = getStorage(frame, "point")
+	
+	local s = getStorage(frame, "scale")
+	if s then
+		(frame.lw11origSetScale or frame.SetScale)(frame,s)
+	else
+		s = frame:GetScale()
+	end
+	
+	if not x or not y then		-- nothing stored in config yet, smack it in the center
+		x=0; y=0; point="CENTER"
+	end
+
+	x = x/s
+	y = y/s
+	
+	frame:ClearAllPoints()
+	if not point and y==0 then	-- errr why did i do this check again? must have been a reason, but i can't remember it =/
+		point="CENTER"
+	end
+		
+	if not point then	-- we have position, but no point, which probably means we're going from data stored by the addon itself before LibWindow was added to it. It was PROBABLY topleft->bottomleft anchored. Most do it that way.
+		frame:SetPoint("TOPLEFT", frame:GetParent(), "BOTTOMLEFT", x, y)
+		-- make it compute a better attachpoint (on next update)
+		queueSavePosition(frame)
+		return
+	end
+	
+	frame:SetPoint(point, frame:GetParent(), point, x, y)
+end
+
+
+mixins["SetScale"]=true
+function lib.SetScale(frame, scale)
+	setStorage(frame, "scale", scale);
+	(frame.lw11origSetScale or frame.SetScale)(frame,scale)
+	lib.RestorePosition(frame)
+end
+
+
+
+---------------------------------------------------------
+-- DRAG SUPPORT
+---------------------------------------------------------
+
+
+function lib.OnDragStart(frame)
+	lib.windowData[frame].isDragging = true
+	frame:StartMoving()
+end
+
+
+function lib.OnDragStop(frame)
+	frame:StopMovingOrSizing()
+	lib.SavePosition(frame)
+	lib.windowData[frame].isDragging = false
+	if lib.windowData[frame].altEnable and not IsAltKeyDown() then
+		frame:EnableMouse(false)
+	end
+end
+
+local function onDragStart(...) return lib.OnDragStart(...) end  -- upgradable
+local function onDragStop(...) return lib.OnDragStop(...) end  -- upgradable
+
+mixins["MakeDraggable"]=true
+function lib.MakeDraggable(frame)
+	assert(lib.windowData[frame])
+	frame:SetMovable(true)
+	frame:SetScript("OnDragStart", onDragStart)
+	frame:SetScript("OnDragStop", onDragStop)
+	frame:RegisterForDrag("LeftButton")
+end
+
+
+---------------------------------------------------------
+-- MOUSEWHEEL
+---------------------------------------------------------
+
+function lib.OnMouseWheel(frame, dir)
+	local scale = getStorage(frame, "scale")
+	if dir<0 then
+		scale=max(scale*0.9, 0.1)
+	else
+		scale=min(scale/0.9, 3)
+	end
+	lib.SetScale(frame, scale)
+end
+
+local function onMouseWheel(...) return lib.OnMouseWheel(...) end  -- upgradable
+
+mixins["EnableMouseWheelScaling"]=true
+function lib.EnableMouseWheelScaling(frame)
+	frame:SetScript("OnMouseWheel", onMouseWheel)
+end
+
+
+---------------------------------------------------------
+-- ENABLEMOUSE-ON-ALT
+---------------------------------------------------------
+
+lib.utilFrame:SetScript("OnEvent", function(this, event, key, state)
+	if event=="MODIFIER_STATE_CHANGED" then
+		if key == "LALT" or key == "RALT" then
+			for frame,_ in pairs(lib.altEnabledFrames) do
+				if not lib.windowData[frame].isDragging then		-- if it's already dragging, it'll disable mouse on DragStop instead
+					frame:EnableMouse(state == 1)
+				end
+			end
+		end
+	end
+end)
+
+mixins["EnableMouseOnAlt"]=true
+function lib.EnableMouseOnAlt(frame)
+	assert(lib.windowData[frame])
+	lib.windowData[frame].altEnable = true
+	frame:EnableMouse(not not IsAltKeyDown())
+	if not lib.altEnabledFrames then
+		lib.altEnabledFrames = {}
+		lib.utilFrame:RegisterEvent("MODIFIER_STATE_CHANGED")
+	end
+	lib.altEnabledFrames[frame] = true
+end
+
+
+
+---------------------------------------------------------
+-- Embed support (into FRAMES, not addons!)
+---------------------------------------------------------
+
+function lib:Embed(target)
+	if not target or not target[0] or not target.GetObjectType then
+		error("Usage: LibWindow:Embed(frame)", 1)
+	end
+	target.lw11origSetScale = target.SetScale
+	for name, _ in pairs(mixins) do
+		target[name] = self[name]
+	end
+	lib.embeds[target] = true
+	return target
+end
+
+for target, _ in pairs(lib.embeds) do
+	lib:Embed(target)
+end