diff Libs/DF/fw.lua @ 58:0682d738499b v8.0.1.058

- 8.0.1 Update.
author Tercio
date Fri, 20 Jul 2018 19:04:12 -0300
parents 7c0f819a85c6
children
line wrap: on
line diff
--- a/Libs/DF/fw.lua	Sun Mar 11 10:50:42 2018 -0300
+++ b/Libs/DF/fw.lua	Fri Jul 20 19:04:12 2018 -0300
@@ -1,5 +1,5 @@
 
-local dversion = 68
+local dversion = 85
 local major, minor = "DetailsFramework-1.0", dversion
 local DF, oldminor = LibStub:NewLibrary (major, minor)
 
@@ -15,6 +15,10 @@
 local _type = type
 local _unpack = unpack
 local upper = string.upper
+local string_match = string.match
+
+SMALL_NUMBER = 0.000001
+ALPHA_BLEND_AMOUNT = 0.8400251
 
 --> will always give a very random name for our widgets
 local init_counter = math.random (1, 1000000)
@@ -117,6 +121,12 @@
 	"CreateBorder",
 	"FormatNumber",
 	"IntegerToTimer",
+	"QuickDispatch",
+	"CommaValue",
+	"RemoveRealmName",
+	"Trim",
+	"CreateGlowOverlay",
+	"CreateFrameShake",
 }
 
 DF.table = {}
@@ -181,6 +191,7 @@
 			t1 [key] = value
 		end
 	end
+	return t1
 end
 
 function DF.table.dump (t, s, deep)
@@ -258,6 +269,22 @@
 	end
 end
 
+function DF:CommaValue (value)
+	if (not value) then 
+		return "0" 
+	end
+	
+	value = floor (value)
+	
+	if (value == 0) then
+		return "0"
+	end
+	
+	--source http://richard.warburton.it
+	local left, num, right = string_match (value, '^([^%d]*%d)(%d*)(.-)$')
+	return left .. (num:reverse():gsub ('(%d%d%d)','%1,'):reverse()) .. right
+end
+
 function DF:IntegerToTimer (value)
 	return "" .. floor (value/60) .. ":" .. format ("%02.f", value%60)
 end
@@ -328,13 +355,17 @@
 	fontString:SetFont (fonte, size, outline)
 end
 
+function DF:Trim (s) --hello name conventions!
+	return DF:trim (s)
+end
+
 function DF:trim (s)
 	local from = s:match"^%s*()"
 	return from > #s and "" or s:match(".*%S", from)
 end
 
 function DF:Msg (msg)
-	print ("|cFFFFFFAA" .. self.__name .. "|r " .. msg)
+	print ("|cFFFFFFAA" .. (self.__name or "FW Msg:") .. "|r ", msg)
 end
 
 function DF:GetNpcIdFromGuid (guid)
@@ -345,6 +376,25 @@
 	return 0
 end
 
+function DF.SortOrder1 (t1, t2)
+	return t1[1] > t2[1]
+end
+function DF.SortOrder2 (t1, t2)
+	return t1[2] > t2[2]
+end
+function DF.SortOrder3 (t1, t2)
+	return t1[3] > t2[3]
+end
+function DF.SortOrder1R (t1, t2)
+	return t1[1] < t2[1]
+end
+function DF.SortOrder2R (t1, t2)
+	return t1[2] < t2[2]
+end
+function DF.SortOrder3R (t1, t2)
+	return t1[3] < t2[3]
+end
+
 local onFinish = function (self)
 	if (self.showWhenDone) then
 		self.frame:SetAlpha (1)
@@ -462,6 +512,77 @@
 		return v1 or "topleft", v2, v3 or "topleft", v4 or 0, v5 or 0
 	end
 	
+	local anchoring_functions = {
+		function (frame, anchorTo, offSetX, offSetY) --> 1 TOP LEFT
+			frame:ClearAllPoints()
+			frame:SetPoint ("bottomleft", anchorTo, "topleft", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 2 LEFT
+			frame:ClearAllPoints()
+			frame:SetPoint ("right", anchorTo, "left", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 3 BOTTOM LEFT
+			frame:ClearAllPoints()
+			frame:SetPoint ("topleft", anchorTo, "bottomleft", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 4 BOTTOM
+			frame:ClearAllPoints()
+			frame:SetPoint ("top", anchorTo, "bottom", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 5 BOTTOM RIGHT
+			frame:ClearAllPoints()
+			frame:SetPoint ("topright", anchorTo, "bottomright", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 6 RIGHT
+			frame:ClearAllPoints()
+			frame:SetPoint ("left", anchorTo, "right", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 7 TOP RIGHT
+			frame:ClearAllPoints()
+			frame:SetPoint ("bottomright", anchorTo, "topright", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 8 TOP
+			frame:ClearAllPoints()
+			frame:SetPoint ("bottom", anchorTo, "top", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 9 CENTER
+			frame:ClearAllPoints()
+			frame:SetPoint ("center", anchorTo, "center", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 10
+			frame:ClearAllPoints()
+			frame:SetPoint ("left", anchorTo, "left", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 11
+			frame:ClearAllPoints()
+			frame:SetPoint ("right", anchorTo, "right", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 12
+			frame:ClearAllPoints()
+			frame:SetPoint ("top", anchorTo, "top", offSetX, offSetY)
+		end,
+		
+		function (frame, anchorTo, offSetX, offSetY) --> 13
+			frame:ClearAllPoints()
+			frame:SetPoint ("bottom", anchorTo, "bottom", offSetX, offSetY)
+		end
+	}
+
+	function DF:SetAnchor (widget, config, anchorTo)
+		anchorTo = anchorTo or widget:GetParent()
+		anchoring_functions [config.side] (widget, anchorTo, config.x, config.y)
+	end	
 
 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 --> colors
@@ -550,6 +671,7 @@
 		local cur_x = x_offset
 		local cur_y = y_offset
 		local max_x = 0
+		local line_widgets_created = 0 --how many widgets has been created on this line loop pass
 		
 		height = abs ((height or parent:GetHeight()) - abs (y_offset) + 20)
 		height = height*-1
@@ -567,6 +689,7 @@
 				label.widget_type = "label"
 				label:SetPoint (cur_x, cur_y)
 				tinsert (parent.widget_list, label)
+				line_widgets_created = line_widgets_created + 1
 			
 			elseif (widget_table.type == "select" or widget_table.type == "dropdown") then
 				local dropdown = DF:NewDropDown (parent, nil, "$parentWidget" .. index, nil, 140, 18, widget_table.values, widget_table.get(), dropdown_template)
@@ -584,6 +707,7 @@
 				
 				tinsert (parent.widget_list, dropdown)
 				widget_created = dropdown
+				line_widgets_created = line_widgets_created + 1
 				
 			elseif (widget_table.type == "toggle" or widget_table.type == "switch") then
 				local switch = DF:NewSwitch (parent, nil, "$parentWidget" .. index, nil, 60, 20, nil, nil, widget_table.get(), nil, nil, nil, nil, switch_template)
@@ -607,6 +731,7 @@
 				
 				tinsert (parent.widget_list, switch)
 				widget_created = switch
+				line_widgets_created = line_widgets_created + 1
 				
 			elseif (widget_table.type == "range" or widget_table.type == "slider") then
 				local is_decimanls = widget_table.usedecimals
@@ -631,6 +756,7 @@
 				
 				tinsert (parent.widget_list, slider)
 				widget_created = slider
+				line_widgets_created = line_widgets_created + 1
 				
 			elseif (widget_table.type == "color" or widget_table.type == "color") then
 				local colorpick = DF:NewColorPickButton (parent, "$parentWidget" .. index, nil, widget_table.set, nil, button_template)
@@ -656,6 +782,7 @@
 				
 				tinsert (parent.widget_list, colorpick)
 				widget_created = colorpick
+				line_widgets_created = line_widgets_created + 1
 				
 			elseif (widget_table.type == "execute" or widget_table.type == "button") then
 			
@@ -675,7 +802,7 @@
 				
 				tinsert (parent.widget_list, button)
 				widget_created = button
-				
+				line_widgets_created = line_widgets_created + 1
 				
 			elseif (widget_table.type == "textentry") then
 				local textentry = DF:CreateTextEntry (parent, widget_table.func, 120, 18, nil, "$parentWidget" .. index, nil, button_template)
@@ -697,6 +824,7 @@
 				
 				tinsert (parent.widget_list, textentry)
 				widget_created = textentry
+				line_widgets_created = line_widgets_created + 1
 				
 			end
 			
@@ -713,6 +841,7 @@
 			if (widget_table.type == "breakline" or cur_y < height) then
 				cur_y = y_offset
 				cur_x = cur_x + max_x + 30
+				line_widgets_created = 0
 				max_x = 0
 			end
 		
@@ -1303,6 +1432,281 @@
 	return anim
 end
 
+local frameshake_shake_finished = function (parent, shakeObject)
+	if (shakeObject.IsPlaying) then
+		shakeObject.IsPlaying = false
+		
+		--> update the amount of shake running on this frame
+		parent.__frameshakes.enabled = parent.__frameshakes.enabled - 1
+		
+		--> restore the default anchors, in case where deltaTime was too small that didn't triggered an update
+		for i = 1, #shakeObject.Anchors do
+			local anchor = shakeObject.Anchors [i]
+			
+			if (#anchor == 3) then
+				local anchorTo, point1, point2 = unpack (anchor)
+				parent:SetPoint (anchorTo, point1, point2)
+				
+			elseif (#anchor == 5) then
+				local anchorName1, anchorTo, anchorName2, point1, point2 = unpack (anchor)
+				parent:SetPoint (anchorName1, anchorTo, anchorName2, point1, point2)
+			end
+		end
+	end
+end
+
+local frameshake_do_update = function (parent, shakeObject, deltaTime)
+
+	--> check delta time
+	deltaTime = deltaTime or 0
+	
+	--> update time left
+	shakeObject.TimeLeft = max (shakeObject.TimeLeft - deltaTime, 0)
+	
+	if (shakeObject.TimeLeft > 0) then
+	
+		--> update fade in and out
+		if (shakeObject.IsFadingIn) then
+			shakeObject.IsFadingInTime = shakeObject.IsFadingInTime + deltaTime
+		end
+		if (shakeObject.IsFadingOut) then
+			shakeObject.IsFadingOutTime = shakeObject.IsFadingOutTime + deltaTime
+		end
+
+		--> check if can disable fade in
+		if (shakeObject.IsFadingIn and shakeObject.IsFadingInTime > shakeObject.FadeInTime) then
+			shakeObject.IsFadingIn = false
+		end
+		
+		--> check if can enable fade out
+		if (not shakeObject.IsFadingOut and shakeObject.TimeLeft < shakeObject.FadeOutTime) then
+			shakeObject.IsFadingOut = true
+			shakeObject.IsFadingOutTime = shakeObject.FadeOutTime - shakeObject.TimeLeft
+		end
+		
+		--> update position
+		local scaleShake = min (shakeObject.IsFadingIn and (shakeObject.IsFadingInTime / shakeObject.FadeInTime) or 1, shakeObject.IsFadingOut and (1 - shakeObject.IsFadingOutTime / shakeObject.FadeOutTime) or 1)
+		
+		if (scaleShake > 0) then
+
+			--> delate the time by the frequency on both X and Y offsets
+			shakeObject.XSineOffset = shakeObject.XSineOffset + (deltaTime * shakeObject.Frequency)
+			shakeObject.YSineOffset = shakeObject.YSineOffset + (deltaTime * shakeObject.Frequency)
+			
+			--> calc the new position
+			local newX, newY
+			if (shakeObject.AbsoluteSineX) then
+				--absoluting only the sine wave, passing a negative scale will reverse the absolute direction
+				newX = shakeObject.Amplitude * abs (math.sin (shakeObject.XSineOffset)) * scaleShake * shakeObject.ScaleX
+			else
+				newX = shakeObject.Amplitude * math.sin (shakeObject.XSineOffset) * scaleShake * shakeObject.ScaleX
+			end
+			
+			if (shakeObject.AbsoluteSineY) then
+				newY = shakeObject.Amplitude * abs (math.sin (shakeObject.YSineOffset)) * scaleShake * shakeObject.ScaleY
+			else
+				newY = shakeObject.Amplitude * math.sin (shakeObject.YSineOffset) * scaleShake * shakeObject.ScaleY
+			end
+			
+			--> apply the offset to the frame anchors
+			for i = 1, #shakeObject.Anchors do
+				local anchor = shakeObject.Anchors [i]
+				
+				if (#anchor == 3) then
+					local anchorTo, point1, point2 = unpack (anchor)
+					parent:SetPoint (anchorTo, point1 + newX, point2 + newY)
+					
+				elseif (#anchor == 5) then
+					local anchorName1, anchorTo, anchorName2, point1, point2 = unpack (anchor)
+					parent:SetPoint (anchorName1, anchorTo, anchorName2, point1 + newX, point2 + newY)
+				end
+			end
+			
+		end
+	else
+		frameshake_shake_finished (parent, shakeObject)
+	end
+end
+
+local frameshake_update_all = function (parent, deltaTime)
+	--> check if there's a shake running
+	--print ("Shakes Enabled: ", parent.__frameshakes.enabled)
+	if (parent.__frameshakes.enabled > 0) then
+		--update all shakes
+		for i = 1, #parent.__frameshakes do
+			local shakeObject = parent.__frameshakes [i]
+			if (shakeObject.IsPlaying) then
+				frameshake_do_update (parent, shakeObject, deltaTime)
+			end
+		end
+	end
+end
+
+--> scale direction scales the X and Y coordinates, scale strength scales the amplitude and frequency
+local frameshake_play = function (parent, shakeObject, scaleDirection, scaleAmplitude, scaleFrequency, scaleDuration)
+
+	--> check if is already playing
+	if (shakeObject.TimeLeft > 0) then
+		--> reset the time left
+		shakeObject.TimeLeft = shakeObject.Duration
+		
+		if (shakeObject.IsFadingOut) then
+			if (shakeObject.FadeInTime > 0) then
+				shakeObject.IsFadingIn = true
+				--> scale the current fade out into fade in, so it starts the fade in at the point where it was fading out
+				shakeObject.IsFadingInTime = shakeObject.FadeInTime * (1 - shakeObject.IsFadingOutTime / shakeObject.FadeOutTime)
+			else
+				shakeObject.IsFadingIn = false
+				shakeObject.IsFadingInTime = 0
+			end
+			
+			--> disable fade out and enable fade in
+			shakeObject.IsFadingOut = false
+			shakeObject.IsFadingOutTime = 0
+		end
+		
+	else
+		--> create a new random offset
+		shakeObject.XSineOffset = math.pi * 2 * math.random()
+		shakeObject.YSineOffset = math.pi * 2 * math.random()
+		
+		--> store the initial position if case it needs a reset
+		shakeObject.StartedXSineOffset = shakeObject.XSineOffset
+		shakeObject.StartedYSineOffset = shakeObject.YSineOffset
+		
+		--> check if there's a fade in time
+		if (shakeObject.FadeInTime > 0) then
+			shakeObject.IsFadingIn = true
+		else
+			shakeObject.IsFadingIn = false
+		end
+		
+		shakeObject.IsFadingInTime = 0
+		shakeObject.IsFadingOut = false
+		shakeObject.IsFadingOutTime = 0
+		
+		--> apply custom scale
+		shakeObject.ScaleX = (scaleDirection or 1) * shakeObject.OriginalScaleX
+		shakeObject.ScaleY = (scaleDirection or 1) * shakeObject.OriginalScaleY
+		shakeObject.Frequency = (scaleFrequency or 1) * shakeObject.OriginalFrequency
+		shakeObject.Amplitude = (scaleAmplitude or 1) * shakeObject.OriginalAmplitude
+		shakeObject.Duration = (scaleDuration or 1) * shakeObject.OriginalDuration
+		
+		--> update the time left
+		shakeObject.TimeLeft = shakeObject.Duration
+		
+		--> check if is dynamic points
+		if (shakeObject.IsDynamicAnchor) then
+			wipe (shakeObject.Anchors)
+			for i = 1, parent:GetNumPoints() do
+				local p1, p2, p3, p4, p5 = parent:GetPoint (i)
+				shakeObject.Anchors [#shakeObject.Anchors+1] = {p1, p2, p3, p4, p5}
+			end
+		end
+		
+		--> update the amount of shake running on this frame
+		parent.__frameshakes.enabled = parent.__frameshakes.enabled + 1
+	end
+
+	shakeObject.IsPlaying = true
+	
+	frameshake_do_update (parent, shakeObject)
+end
+
+function DF:CreateFrameShake (parent, duration, amplitude, frequency, absoluteSineX, absoluteSineY, scaleX, scaleY, fadeInTime, fadeOutTime, anchorPoints)
+
+	--> create the shake table
+	local frameShake = {
+		Amplitude = amplitude or 2,
+		Frequency = frequency or 5,
+		Duration = duration or 0.3,
+		FadeInTime = fadeInTime or 0.01,
+		FadeOutTime = fadeOutTime or 0.01,
+		ScaleX  = scaleX or 0.2,
+		ScaleY = scaleY or 1,
+		AbsoluteSineX = absoluteSineX,
+		AbsoluteSineY = absoluteSineY,
+		--
+		IsPlaying = false,
+		TimeLeft = 0,
+	}
+	
+	frameShake.OriginalScaleX = frameShake.ScaleX
+	frameShake.OriginalScaleY = frameShake.ScaleY
+	frameShake.OriginalFrequency = frameShake.Frequency
+	frameShake.OriginalAmplitude = frameShake.Amplitude
+	frameShake.OriginalDuration = frameShake.Duration
+	
+	if (type (anchorPoints) ~= "table") then
+		frameShake.IsDynamicAnchor = true
+		frameShake.Anchors = {}
+	else 
+		frameShake.Anchors = anchorPoints
+	end
+	
+	--> inject frame shake table into the frame
+	if (not parent.__frameshakes) then
+		parent.__frameshakes = {
+			enabled = 0,
+		}
+		parent.PlayFrameShake = frameshake_play
+		parent.UpdateFrameShake = frameshake_do_update
+		parent.UpdateAllFrameShake = frameshake_update_all
+		parent:HookScript ("OnUpdate", frameshake_update_all)
+	end
+
+	tinsert (parent.__frameshakes, frameShake)
+	
+	return frameShake
+end
+
+
+-----------------------------
+--> glow overlay
+
+local play_glow_overlay = function (self)
+	self:Show()
+	if (self.animOut:IsPlaying()) then
+		self.animOut:Stop()
+	end
+	self.animIn:Play()
+end
+
+local stop_glow_overlay = function (self)
+	self.animOut:Stop()
+	self.animIn:Stop()
+	self:Hide()
+end
+
+local defaultColor = {1, 1, 1, 1}
+
+--this is most copied from the wow client code, few changes applied to customize it
+function DF:CreateGlowOverlay (parent, antsColor, glowColor)
+	local glowFrame = CreateFrame ("frame", parent:GetName() and "$parentGlow2" or "OverlayActionGlow" .. math.random (1, 10000000), parent, "ActionBarButtonSpellActivationAlert")
+	
+	glowFrame.Play = play_glow_overlay
+	glowFrame.Stop = stop_glow_overlay
+	
+	parent.overlay = glowFrame
+	local frameWidth, frameHeight = parent:GetSize()
+	
+	local scale = 1.4
+	
+	--Make the height/width available before the next frame:
+	parent.overlay:SetSize(frameWidth * scale, frameHeight * scale)
+	parent.overlay:SetPoint("TOPLEFT", parent, "TOPLEFT", -frameWidth * 0.2, frameHeight * 0.2)
+	parent.overlay:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", frameWidth * 0.2, -frameHeight * 0.2)
+	
+	local r, g, b, a = DF:ParseColors (antsColor or defaultColor)
+	glowFrame.ants:SetVertexColor (r, g, b, a)
+	
+	local r, g, b, a = DF:ParseColors (glowColor or defaultColor)
+	glowFrame.outerGlow:SetVertexColor (r, g, b, a)
+	
+	glowFrame.outerGlow:SetScale (1.2)
+	
+	return glowFrame
+end
 
 -----------------------------
 --> borders
@@ -1327,6 +1731,34 @@
 	end
 end
 
+local SetBorderColor = function (self, r, g, b)
+	for _, texture in ipairs (self.Borders.Layer1) do
+		texture:SetColorTexture (r, g, b)
+	end
+	for _, texture in ipairs (self.Borders.Layer2) do
+		texture:SetColorTexture (r, g, b)
+	end
+	for _, texture in ipairs (self.Borders.Layer3) do
+		texture:SetColorTexture (r, g, b)
+	end
+end
+
+local SetLayerVisibility = function (self, layer1Shown, layer2Shown, layer3Shown)
+
+	for _, texture in ipairs (self.Borders.Layer1) do
+		texture:SetShown (layer1Shown)
+	end
+	
+	for _, texture in ipairs (self.Borders.Layer2) do
+		texture:SetShown (layer2Shown)
+	end
+	
+	for _, texture in ipairs (self.Borders.Layer3) do
+		texture:SetShown (layer3Shown)
+	end
+
+end
+
 function DF:CreateBorder (parent, alpha1, alpha2, alpha3)
 	
 	parent.Borders = {
@@ -1339,6 +1771,8 @@
 	}
 	
 	parent.SetBorderAlpha = SetBorderAlpha
+	parent.SetBorderColor = SetBorderColor
+	parent.SetLayerVisibility = SetLayerVisibility
 	
 	local border1 = parent:CreateTexture (nil, "background")
 	border1:SetPoint ("topleft", parent, "topleft", -1, 1)
@@ -1410,6 +1844,115 @@
 	
 end
 
+
+function DF:CreateBorderWithSpread (parent, alpha1, alpha2, alpha3, size, spread)
+	
+	parent.Borders = {
+		Layer1 = {},
+		Layer2 = {},
+		Layer3 = {},
+		Alpha1 = alpha1 or default_border_color1,
+		Alpha2 = alpha2 or default_border_color2,
+		Alpha3 = alpha3 or default_border_color3,
+	}
+	
+	parent.SetBorderAlpha = SetBorderAlpha
+	parent.SetBorderColor = SetBorderColor
+	parent.SetLayerVisibility = SetLayerVisibility
+	
+	--left
+	local border1 = parent:CreateTexture (nil, "background")
+	border1:SetPoint ("topleft", parent, "topleft", -1 + spread, 1 + (-spread))
+	border1:SetPoint ("bottomleft", parent, "bottomleft", -1 + spread, -1 + spread)
+	border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1)
+	border1:SetWidth (size)
+	
+	local border2 = parent:CreateTexture (nil, "background")
+	border2:SetPoint ("topleft", parent, "topleft", -2 + spread, 2 + (-spread))
+	border2:SetPoint ("bottomleft", parent, "bottomleft", -2 + spread, -2 + spread)
+	border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2)
+	border2:SetWidth (size)
+	
+	local border3 = parent:CreateTexture (nil, "background")
+	border3:SetPoint ("topleft", parent, "topleft", -3 + spread, 3 + (-spread))
+	border3:SetPoint ("bottomleft", parent, "bottomleft", -3 + spread, -3 + spread)
+	border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3)
+	border3:SetWidth (size)
+	
+	tinsert (parent.Borders.Layer1, border1)
+	tinsert (parent.Borders.Layer2, border2)
+	tinsert (parent.Borders.Layer3, border3)
+	
+	--top
+	local border1 = parent:CreateTexture (nil, "background")
+	border1:SetPoint ("topleft", parent, "topleft", 0 + spread, 1 + (-spread))
+	border1:SetPoint ("topright", parent, "topright", 1 + (-spread), 1 + (-spread))
+	border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1)
+	border1:SetHeight (size)
+	
+	local border2 = parent:CreateTexture (nil, "background")
+	border2:SetPoint ("topleft", parent, "topleft", -1 + spread, 2 + (-spread))
+	border2:SetPoint ("topright", parent, "topright", 2 + (-spread), 2 + (-spread))
+	border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2)
+	border2:SetHeight (size)
+	
+	local border3 = parent:CreateTexture (nil, "background")
+	border3:SetPoint ("topleft", parent, "topleft", -2 + spread, 3 + (-spread))
+	border3:SetPoint ("topright", parent, "topright", 3 + (-spread), 3 + (-spread))
+	border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3)
+	border3:SetHeight (size)
+	
+	tinsert (parent.Borders.Layer1, border1)
+	tinsert (parent.Borders.Layer2, border2)
+	tinsert (parent.Borders.Layer3, border3)	
+	
+	--right
+	local border1 = parent:CreateTexture (nil, "background")
+	border1:SetPoint ("topright", parent, "topright", 1 + (-spread), 0 + (-spread))
+	border1:SetPoint ("bottomright", parent, "bottomright", 1 + (-spread), -1 + spread)
+	border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1)
+	border1:SetWidth (size)
+	
+	local border2 = parent:CreateTexture (nil, "background")
+	border2:SetPoint ("topright", parent, "topright", 2 + (-spread), 1 + (-spread))
+	border2:SetPoint ("bottomright", parent, "bottomright", 2 + (-spread), -2 + spread)
+	border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2)
+	border2:SetWidth (size)
+	
+	local border3 = parent:CreateTexture (nil, "background")
+	border3:SetPoint ("topright", parent, "topright", 3 + (-spread), 2 + (-spread))
+	border3:SetPoint ("bottomright", parent, "bottomright", 3 + (-spread), -3 + spread)
+	border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3)
+	border3:SetWidth (size)
+	
+	tinsert (parent.Borders.Layer1, border1)
+	tinsert (parent.Borders.Layer2, border2)
+	tinsert (parent.Borders.Layer3, border3)	
+	
+	local border1 = parent:CreateTexture (nil, "background")
+	border1:SetPoint ("bottomleft", parent, "bottomleft", 0 + spread, -1 + spread)
+	border1:SetPoint ("bottomright", parent, "bottomright", 0 + (-spread), -1 + spread)
+	border1:SetColorTexture (0, 0, 0, alpha1 or default_border_color1)
+	border1:SetHeight (size)
+	
+	local border2 = parent:CreateTexture (nil, "background")
+	border2:SetPoint ("bottomleft", parent, "bottomleft", -1 + spread, -2 + spread)
+	border2:SetPoint ("bottomright", parent, "bottomright", 1 + (-spread), -2 + spread)
+	border2:SetColorTexture (0, 0, 0, alpha2 or default_border_color2)
+	border2:SetHeight (size)
+	
+	local border3 = parent:CreateTexture (nil, "background")
+	border3:SetPoint ("bottomleft", parent, "bottomleft", -2 + spread, -3 + spread)
+	border3:SetPoint ("bottomright", parent, "bottomright", 2 + (-spread), -3 + spread)
+	border3:SetColorTexture (0, 0, 0, alpha3 or default_border_color3)
+	border3:SetHeight (size)
+	
+	tinsert (parent.Borders.Layer1, border1)
+	tinsert (parent.Borders.Layer2, border2)
+	tinsert (parent.Borders.Layer3, border3)
+	
+end
+
 function DF:ReskinSlider (slider, heightOffset)
 	if (slider.slider) then
 		slider.cima:SetNormalTexture ([[Interface\Buttons\Arrow-Up-Up]])
@@ -1451,49 +1994,76 @@
 		slider.slider.thumb:SetTexCoord (482/512, 492/512, 104/512, 120/512)
 		slider.slider.thumb:SetSize (12, 12)
 		slider.slider.thumb:SetVertexColor (0.6, 0.6, 0.6, 0.95)
+		
 	else
+		--up button
+		do
+			local normalTexture = slider.ScrollBar.ScrollUpButton.Normal
+			normalTexture:SetTexture ([[Interface\Buttons\Arrow-Up-Up]])
+			normalTexture:SetTexCoord (0, 1, .2, 1)
+			
+			normalTexture:SetPoint ("topleft", slider.ScrollBar.ScrollUpButton, "topleft", 1, 0)
+			normalTexture:SetPoint ("bottomright", slider.ScrollBar.ScrollUpButton, "bottomright", 1, 0)
+			
+			local pushedTexture = slider.ScrollBar.ScrollUpButton.Pushed
+			pushedTexture:SetTexture ([[Interface\Buttons\Arrow-Up-Down]])
+			pushedTexture:SetTexCoord (0, 1, .2, 1)
+			
+			pushedTexture:SetPoint ("topleft", slider.ScrollBar.ScrollUpButton, "topleft", 1, 0)
+			pushedTexture:SetPoint ("bottomright", slider.ScrollBar.ScrollUpButton, "bottomright", 1, 0)
 
-		slider.ScrollBar.ScrollUpButton:SetNormalTexture ([[Interface\Buttons\Arrow-Up-Up]])
-		slider.ScrollBar.ScrollUpButton:GetNormalTexture():SetTexCoord (0, 1, 0, 1)
-		slider.ScrollBar.ScrollUpButton:SetPushedTexture ([[Interface\Buttons\Arrow-Up-Down]])
-		slider.ScrollBar.ScrollUpButton:GetPushedTexture():SetTexCoord (0, 1, 0, 1)
-		slider.ScrollBar.ScrollUpButton:SetDisabledTexture ([[Interface\Buttons\Arrow-Up-Disabled]])
-		slider.ScrollBar.ScrollUpButton:GetDisabledTexture():SetTexCoord (0, 1, 0, 1)
+			local disabledTexture = slider.ScrollBar.ScrollUpButton.Disabled
+			disabledTexture:SetTexture ([[Interface\Buttons\Arrow-Up-Disabled]])
+			disabledTexture:SetTexCoord (0, 1, .2, 1)
+			disabledTexture:SetAlpha (.5)
+			
+			disabledTexture:SetPoint ("topleft", slider.ScrollBar.ScrollUpButton, "topleft", 1, 0)
+			disabledTexture:SetPoint ("bottomright", slider.ScrollBar.ScrollUpButton, "bottomright", 1, 0)
+			
+			slider.ScrollBar.ScrollUpButton:SetSize (16, 16)
+			slider.ScrollBar.ScrollUpButton:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = "Interface\\Tooltips\\UI-Tooltip-Background"})
+			slider.ScrollBar.ScrollUpButton:SetBackdropColor (0, 0, 0, 0.3)
+			slider.ScrollBar.ScrollUpButton:SetBackdropBorderColor (0, 0, 0, 1)
+			
+			--it was having problems with the texture anchor when calling ClearAllPoints() and setting new points different from the original
+			--now it is using the same points from the original with small offsets tp align correctly
+		end
+		
+		--down button
+		do
+			local normalTexture = slider.ScrollBar.ScrollDownButton.Normal
+			normalTexture:SetTexture ([[Interface\Buttons\Arrow-Down-Up]])
+			normalTexture:SetTexCoord (0, 1, 0, .8)
+			
+			normalTexture:SetPoint ("topleft", slider.ScrollBar.ScrollDownButton, "topleft", 1, -4)
+			normalTexture:SetPoint ("bottomright", slider.ScrollBar.ScrollDownButton, "bottomright", 1, -4)
+			
+			local pushedTexture = slider.ScrollBar.ScrollDownButton.Pushed
+			pushedTexture:SetTexture ([[Interface\Buttons\Arrow-Down-Down]])
+			pushedTexture:SetTexCoord (0, 1, 0, .8)
+			
+			pushedTexture:SetPoint ("topleft", slider.ScrollBar.ScrollDownButton, "topleft", 1, -4)
+			pushedTexture:SetPoint ("bottomright", slider.ScrollBar.ScrollDownButton, "bottomright", 1, -4)
+			
+			local disabledTexture = slider.ScrollBar.ScrollDownButton.Disabled
+			disabledTexture:SetTexture ([[Interface\Buttons\Arrow-Down-Disabled]])
+			disabledTexture:SetTexCoord (0, 1, 0, .8)
+			disabledTexture:SetAlpha (.5)
+			
+			disabledTexture:SetPoint ("topleft", slider.ScrollBar.ScrollDownButton, "topleft", 1, -4)
+			disabledTexture:SetPoint ("bottomright", slider.ScrollBar.ScrollDownButton, "bottomright", 1, -4)
+			
+			slider.ScrollBar.ScrollDownButton:SetSize (16, 16)
+			slider.ScrollBar.ScrollDownButton:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = "Interface\\Tooltips\\UI-Tooltip-Background"})
+			slider.ScrollBar.ScrollDownButton:SetBackdropColor (0, 0, 0, 0.3)
+			slider.ScrollBar.ScrollDownButton:SetBackdropBorderColor (0, 0, 0, 1)
 
-		slider.ScrollBar.ScrollUpButton:SetSize (16, 16)
-		slider.ScrollBar.ScrollUpButton:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = "Interface\\Tooltips\\UI-Tooltip-Background"})
-		slider.ScrollBar.ScrollUpButton:SetBackdropColor (0, 0, 0, 0.3)
-		slider.ScrollBar.ScrollUpButton:SetBackdropBorderColor (0, 0, 0, 1)
-
-		slider.ScrollBar.ScrollUpButton:GetNormalTexture():ClearAllPoints()
-		slider.ScrollBar.ScrollUpButton:GetPushedTexture():ClearAllPoints()
-		slider.ScrollBar.ScrollUpButton:GetDisabledTexture():ClearAllPoints()
-		slider.ScrollBar.ScrollUpButton:GetNormalTexture():SetPoint ("center", slider.ScrollBar.ScrollUpButton, "center", 1, 1)
-		slider.ScrollBar.ScrollUpButton:GetPushedTexture():SetPoint ("center", slider.ScrollBar.ScrollUpButton, "center", 1, 1)
-		slider.ScrollBar.ScrollUpButton:GetDisabledTexture():SetPoint ("center", slider.ScrollBar.ScrollUpButton, "center", 1, 1)
-	
+			--<Anchor point="TOP" relativePoint="BOTTOM"/>
+			--slider.ScrollBar.ScrollDownButton:SetPoint ("top", slider.ScrollBar, "bottom", 0, 0)
+		end
+		
 		--
 		
-		slider.ScrollBar.ScrollDownButton:SetNormalTexture ([[Interface\Buttons\Arrow-Down-Up]])
-		slider.ScrollBar.ScrollDownButton:GetNormalTexture():SetTexCoord (0, 1, 0, 1)
-		slider.ScrollBar.ScrollDownButton:SetPushedTexture ([[Interface\Buttons\Arrow-Down-Down]])
-		slider.ScrollBar.ScrollDownButton:GetPushedTexture():SetTexCoord (0, 1, 0, 1)
-		slider.ScrollBar.ScrollDownButton:SetDisabledTexture ([[Interface\Buttons\Arrow-Down-Disabled]])
-		slider.ScrollBar.ScrollDownButton:GetDisabledTexture():SetTexCoord (0, 1, 0, 1)
-		
-		slider.ScrollBar.ScrollDownButton:SetSize (16, 16)
-		slider.ScrollBar.ScrollDownButton:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = "Interface\\Tooltips\\UI-Tooltip-Background"})
-		slider.ScrollBar.ScrollDownButton:SetBackdropColor (0, 0, 0, 0.3)
-		slider.ScrollBar.ScrollDownButton:SetBackdropBorderColor (0, 0, 0, 1)
-	
-		slider.ScrollBar.ScrollDownButton:GetNormalTexture():ClearAllPoints()
-		slider.ScrollBar.ScrollDownButton:GetPushedTexture():ClearAllPoints()
-		slider.ScrollBar.ScrollDownButton:GetDisabledTexture():ClearAllPoints()
-		slider.ScrollBar.ScrollDownButton:GetNormalTexture():SetPoint ("center", slider.ScrollBar.ScrollDownButton, "center", 1, -5)
-		slider.ScrollBar.ScrollDownButton:GetPushedTexture():SetPoint ("center", slider.ScrollBar.ScrollDownButton, "center", 1, -5)
-		slider.ScrollBar.ScrollDownButton:GetDisabledTexture():SetPoint ("center", slider.ScrollBar.ScrollDownButton, "center", 1, -5)
-	
-		--
 		slider.ScrollBar:SetPoint ("TOPLEFT", slider, "TOPRIGHT", 6, -16)
 		slider.ScrollBar:SetPoint ("BOTTOMLEFT", slider, "BOTTOMRIGHT", 6, 16 + (heightOffset and heightOffset*-1 or 0))
 		
@@ -1508,4 +2078,57 @@
 	end
 end
 
---doo elsee 
\ No newline at end of file
+function DF:GetCurrentSpec()
+	local specIndex = GetSpecialization()
+	if (specIndex) then
+		local specID = GetSpecializationInfo (specIndex)
+		if (specID and specID ~= 0) then
+			return specID
+		end
+	end
+end
+
+local specs_per_class = {
+	["DEMONHUNTER"] = {577, 581},
+	["DEATHKNIGHT"] = {250, 251, 252},
+	["WARRIOR"] = {71, 72, 73},
+	["MAGE"] = {62, 63, 64},
+	["ROGUE"] = {259, 260, 261},
+	["DRUID"] = {102, 103, 104, 105},
+	["HUNTER"] = {253, 254, 255},
+	["SHAMAN"] = {262, 263, 254},
+	["PRIEST"] = {256, 257, 258},
+	["WARLOCK"] = {265, 266, 267},
+	["PALADIN"] = {65, 66, 70},
+	["MONK"] = {268, 269, 270},
+}
+
+function DF:GetClassSpecIDs (class)
+	return specs_per_class [class]
+end
+
+local dispatch_error = function (context, errortext)
+	DF:Msg ( (context or "<no context>") .. " |cFFFF9900error|r: " .. (errortext or "<no error given>"))
+end
+
+--> safe call an external func with payload and without telling who is calling
+function DF:QuickDispatch (func, ...)
+	if (type (func) ~= "function") then
+		return
+	end
+	
+	local okay, errortext = pcall (func, ...)
+	
+	if (not okay) then
+		--> trigger an error msg
+		dispatch_error (_, errortext)
+		return
+	end
+	
+	return true
+end
+
+
+
+--doo elsee 
+--was doing double loops due to not enought height