Quantcast
local addonName, Butterfly = ...;
--[[============

--============]]
local FauxFrame = Butterfly.FauxFrame

local GALLERY_PADDING = 2

local GalleryFrame = CreateFrame("Frame", "ButterflyGalleryFrame", FauxFrame, "BasicFrameTemplateWithInset")
local ButterflyGalleryScrollFrame = CreateFrame("ScrollFrame", "ButterflyGalleryScrollFrame", GalleryFrame)
GalleryFrame.ScrollFrame = ButterflyGalleryScrollFrame

--[[============
Boring verbose layout building code inside.
--============]]
do
	-- We don't want the title bar and such, but rather than play with textures...
	-- Since we're doing such sketchy stuff to attach the frame anyways, just sweep it under the rug
	-- Hide the CloseButton though, just in case?
	GalleryFrame:SetPoint("TOP", FauxFrame, "BOTTOM", 0, 26)
	GalleryFrame.CloseButton:Hide()
	-- Bump up the size of the inset a bit
	GalleryFrame.InsetBg:ClearAllPoints()
	GalleryFrame.InsetBg:SetPoint("TOPLEFT", 6, -24) -- (4, -24)
	GalleryFrame.InsetBg:SetPoint("BOTTOMRIGHT", -8, 6) -- (-6, 4)


	ButterflyGalleryScrollFrame:SetPoint("TOPLEFT", 10, -30)
	ButterflyGalleryScrollFrame:SetPoint("BOTTOMRIGHT", -12, 36)

	-- The bar itself.
	local scrollBar = CreateFrame("Slider", "ButterflyGalleryScrollFrameScrollBar", ButterflyGalleryScrollFrame)
	local scrollThumb = scrollBar:CreateTexture("ButterflyGalleryScrollFrameScrollBarThumbTexture", "ARTWORK", "UIPanelScrollBarButton")
	scrollThumb:SetSize(18, 24)
	scrollThumb:SetTexCoord(0.20, 0.80, 0.125, 0.875)
	scrollThumb:SetTexture([[Interface\Buttons\UI-ScrollBar-Knob]])
	scrollThumb:SetPoint("LEFT", 0, 2)
	scrollBar:SetThumbTexture(scrollThumb)
	scrollBar:SetOrientation("HORIZONTAL")
	scrollBar:SetPoint("BOTTOMLEFT", GalleryFrame, "BOTTOMLEFT", 30, 14)
	scrollBar:SetPoint("BOTTOMRIGHT", GalleryFrame, "BOTTOMRIGHT", -31, 14)
	scrollBar:SetHeight(16)
	scrollBar:SetScript("OnValueChanged", function(self, value)
		self:GetParent():SetHorizontalScroll(value);
	end)
	local scrollBarLeftTexture = scrollBar:CreateTexture("BST")
	scrollBarLeftTexture:SetTexture([[Interface\ClassTrainerFrame\UI-ClassTrainer-ScrollBar]])
	scrollBarLeftTexture:SetTexCoord(0.53125, 1.0,   1.0, 1.0,   0.53125, 0.03125,   1.0, 0.03125)
	scrollBarLeftTexture:SetSize(123, 29)
	scrollBarLeftTexture:SetPoint("BOTTOMLEFT", -21, -5)

	local scrollBarRightTexture = scrollBar:CreateTexture("BSR")
	scrollBarRightTexture:SetTexture([[Interface\ClassTrainerFrame\UI-ClassTrainer-ScrollBar]])
	scrollBarRightTexture:SetTexCoord(0.0, 0.9609375,   0.46875, 0.9609375,   0.0, 0.0234375,   0.46875, 0.0234375)
	scrollBarRightTexture:SetSize(120, 29)
	scrollBarRightTexture:SetPoint("BOTTOMRIGHT", 19, -5)

	local scrollBarMiddleTexture = scrollBar:CreateTexture("BSM")
	scrollBarMiddleTexture:SetTexture([[Interface\ClassTrainerFrame\UI-ClassTrainer-ScrollBar]])
	scrollBarMiddleTexture:SetTexCoord(0.0, 0.9609375,   0.46875, 0.9609375,   0.0, 0.4,   0.46875, 0.4)
	scrollBarMiddleTexture:SetHeight(29)
	scrollBarMiddleTexture:SetPoint("LEFT", scrollBarLeftTexture, "RIGHT")
	scrollBarMiddleTexture:SetPoint("RIGHT", scrollBarRightTexture, "LEFT")

	-- The right née Down button
	local scrollBarRightButton = CreateFrame("Button", "ButterflyGalleryScrollFrameScrollBarScrollDownButton", scrollBar, "UIPanelScrollDownButtonTemplate")
	scrollBarRightButton:SetScript("OnClick", function(self)
		local parent = self:GetParent();
		local scrollStep = self:GetParent().scrollStep or (parent:GetHeight() / 2);
		parent:SetValue(parent:GetValue() + scrollStep);
		PlaySound("UChatScrollButton");
	end)
	scrollBarRightButton:SetPoint("LEFT", scrollBar, "RIGHT", 1, 0)
	local rightAnim = scrollBarRightButton:CreateAnimationGroup()
	local rightAnimRot = rightAnim:CreateAnimation("Rotation")
	rightAnimRot:SetDegrees(90)
	rightAnimRot:SetEndDelay(math.huge)
	rightAnim:Play()

	-- The left née Up button
	local scrollBarLeftButton = CreateFrame("Button", "ButterflyGalleryScrollFrameScrollBarScrollUpButton", scrollBar, "UIPanelScrollUpButtonTemplate")
	scrollBarLeftButton:SetScript("OnClick", function(self)
		local parent = self:GetParent();
		local scrollStep = self:GetParent().scrollStep or (parent:GetHeight() / 2);
		parent:SetValue(parent:GetValue() - scrollStep);
		PlaySound("UChatScrollButton");
	end)
	scrollBarLeftButton:SetPoint("RIGHT", scrollBar, "LEFT", -1, 0)
	local leftAnim = scrollBarLeftButton:CreateAnimationGroup()
	local leftAnimRot = leftAnim:CreateAnimation("Rotation")
	leftAnimRot:SetDegrees(90)
	leftAnimRot:SetEndDelay(math.huge)
	leftAnim:Play()

	-- The actual "content" of the scroll frame.
	local scrollChild = CreateFrame("Frame", "ButterflyGalleryScrollFrameContent", ButterflyGalleryScrollFrame)
	ButterflyGalleryScrollFrame:SetScrollChild(scrollChild)
	GalleryFrame.ScrollFrame.Content = scrollChild

	--[[============
		The rest of this is scripts lifted from Blizz's normal ScrollFrame stuff, just modified for horizontal scrolling.
	--============]]
	ScrollFrame_OnLoad(ButterflyGalleryScrollFrame)
	ButterflyGalleryScrollFrame:SetScript("OnScrollRangeChanged", function(self, xrange, yrange)
		local scrollbar = self.ScrollBar or _G[self:GetName().."ScrollBar"];
		if ( not xrange ) then
			xrange = self:GetHorizontalScrollRange();
		end
		local value = scrollbar:GetValue();
		if ( value > xrange ) then
			value = xrange;
		end
		scrollbar:SetMinMaxValues(0, xrange);
		scrollbar:SetValue(value);
		if ( floor(xrange) == 0 ) then
			if ( self.scrollBarHideable ) then
				_G[self:GetName().."ScrollBar"]:Hide();
				_G[scrollbar:GetName().."ScrollDownButton"]:Hide();
				_G[scrollbar:GetName().."ScrollUpButton"]:Hide();
				_G[scrollbar:GetName().."ThumbTexture"]:Hide();
			else
				_G[scrollbar:GetName().."ScrollDownButton"]:Disable();
				_G[scrollbar:GetName().."ScrollUpButton"]:Disable();
				_G[scrollbar:GetName().."ScrollDownButton"]:Show();
				_G[scrollbar:GetName().."ScrollUpButton"]:Show();
				if ( not self.noScrollThumb ) then
					_G[scrollbar:GetName().."ThumbTexture"]:Show();
				end
			end
		else
			_G[scrollbar:GetName().."ScrollDownButton"]:Show();
			_G[scrollbar:GetName().."ScrollUpButton"]:Show();
			_G[self:GetName().."ScrollBar"]:Show();
			if ( not self.noScrollThumb ) then
				_G[scrollbar:GetName().."ThumbTexture"]:Show();
			end
			-- The 0.005 is to account for precision errors
			if ( xrange - value > 0.005 ) then
				_G[scrollbar:GetName().."ScrollDownButton"]:Enable();
			else
				_G[scrollbar:GetName().."ScrollDownButton"]:Disable();
			end
		end

		-- Hide/show ButterflyGalleryScrollFrame borders
		local top = _G[self:GetName().."Top"];
		local bottom = _G[self:GetName().."Bottom"];
		local middle = _G[self:GetName().."Middle"];
		if ( top and bottom and self.scrollBarHideable ) then
			if ( self:GetHorizontalScrollRange() == 0 ) then
				top:Hide();
				bottom:Hide();
			else
				top:Show();
				bottom:Show();
			end
		end
		if ( middle and self.scrollBarHideable ) then
			if ( self:GetHorizontalScrollRange() == 0 ) then
				middle:Hide();
			else
				middle:Show();
			end
		end
	end)
	ButterflyGalleryScrollFrame:SetScript("OnHorizontalScroll", function(self, offset)
		local scrollbar = _G[self:GetName().."ScrollBar"];
		scrollbar:SetValue(offset);
		local min;
		local max;
		min, max = scrollbar:GetMinMaxValues();
		if ( offset == 0 ) then
			_G[scrollbar:GetName().."ScrollUpButton"]:Disable();
		else
			_G[scrollbar:GetName().."ScrollUpButton"]:Enable();
		end
		if ((scrollbar:GetValue() - max) == 0) then
			_G[scrollbar:GetName().."ScrollDownButton"]:Disable();
		else
			_G[scrollbar:GetName().."ScrollDownButton"]:Enable();
		end
	end)
	ButterflyGalleryScrollFrame:SetScript("OnMouseWheel", function(self, value, scrollBar)
		scrollBar = scrollBar or _G[self:GetName() .. "ScrollBar"];
		local scrollStep = scrollBar.scrollStep or scrollBar:GetWidth() / 2
		if ( value > 0 ) then
			scrollBar:SetValue(scrollBar:GetValue() - scrollStep);
		else
			scrollBar:SetValue(scrollBar:GetValue() + scrollStep);
		end
	end)
end

function GalleryFrame:GetChromeHeight()
	local yOffsets = 0
	for i = 1, self.ScrollFrame:GetNumPoints() do
		-- Technically, it really SHOULDN'T be a simple absolute value, it should be directional
		-- But y'know what? The points aren't "backwards" and they never should be, bite me
		-- (I fully expect to come back months from now, bitten)
		yOffsets = yOffsets + math.abs(select(5, self.ScrollFrame:GetPoint(i)))
	end
	return yOffsets
end

--[[============
	Note that AddGalleryButton does *not* set the size on anything.
--============]]
function GalleryFrame:AddGalleryButton()
	local ScrollContent = GalleryFrame.ScrollFrame.Content
	local lastIndex = #self.galleryButtons

	local valid, width, height = C_Social.GetScreenshotByIndex(lastIndex+1)
	assert(valid, "Failed to load screenshot")

	local f = CreateFrame("Button", "ButterflyGalleryContentButton" .. lastIndex+1, ScrollContent, "HelpPlateBox")
	f:SetScript("OnClick", function(self)
		SocialPostFrame:SetAttribute("screenshotview", self.id)
	end)
	-- I don't have a good reason but I need to show the buttons or they don't come up. Parenting issue?
	f:Show()
	f.id = lastIndex+1
	C_Social.SetTextureToScreenshot(f.BG, f.id)
	-- This line feels hackish but the texture doesn't return valid sizes until it's sized > 0 somewhere
	f.BG.width, f.BG.height = width, height

	hooksecurefunc(f.BG, "SetDesaturated", function() assert(false, "Desaturated texture!\nPlease forward this crash log to corveroth@gmail.com") end)

	f.Plus = f:CreateTexture()
	f.Plus:SetDrawLayer("HIGHLIGHT")
	f.Plus:SetAtlas("WoWShare-Plus", true)
	f.Plus:SetPoint("TOPLEFT")

	-- Create the highlight glow
	do
		local bottom = f:CreateTexture()
		bottom:SetDrawLayer("HIGHLIGHT")
		bottom:SetTexture([[Interface\Common\talent-blue-glow]])
		bottom:SetPoint("BOTTOMLEFT")
		bottom:SetPoint("BOTTOMRIGHT")

		local top = f:CreateTexture()
		top:SetDrawLayer("HIGHLIGHT")
		top:SetTexture([[Interface\Common\talent-blue-glow]])
		top:SetTexCoord(1.0, 1.0,    1.0, 0.0,   0.0, 1.0,   0.0, 0.0)
		top:SetPoint("TOPLEFT")
		top:SetPoint("TOPRIGHT")

		local left = f:CreateTexture()
		left:SetDrawLayer("HIGHLIGHT")
		left:SetTexture([[Interface\Common\talent-blue-glow]])
		left:SetTexCoord(0.0, 1.0,   1.0, 1.0,   0.0, 0.0,   1.0, 0.0)
		left:SetPoint("TOPLEFT")
		left:SetPoint("BOTTOMLEFT")

		local right = f:CreateTexture()
		right:SetDrawLayer("HIGHLIGHT")
		right:SetTexture([[Interface\Common\talent-blue-glow]])
		right:SetTexCoord(1.0, 0.0,   0.0, 0.0,   1.0, 1.0,   0.0, 1.0)
		right:SetPoint("TOPRIGHT")
		right:SetPoint("BOTTOMRIGHT")
	end

	if lastIndex == 0 then
		f:SetPoint("RIGHT", ScrollContent, "RIGHT", -GALLERY_PADDING, 0)
	else
		f:SetPoint("RIGHT", self.galleryButtons[lastIndex], "LEFT", -GALLERY_PADDING, 0)
	end
	tinsert(self.galleryButtons, f)
end

function GalleryFrame:ResizeGalleryButtons()
	local gbWidth, gbHeight
	local sumWidths, maxHeight = 0, 0
	for i, button in pairs (self.galleryButtons) do
		gbWidth, gbHeight = CalculateScreenshotSize(button.BG.width, button.BG.height, SOCIAL_SCREENSHOT_TOOLTIP_MAX_WIDTH, SOCIAL_SCREENSHOT_TOOLTIP_MAX_HEIGHT)
		button:SetSize(gbWidth, gbHeight)
		if gbHeight > maxHeight then
			maxHeight = gbHeight
		end
		sumWidths = sumWidths + gbWidth
	end

	return sumWidths, maxHeight
end

function GalleryFrame:ResizeContents()
	local buttonWidths, maxButtonHeight = self:ResizeGalleryButtons()
	local contentHeight = maxButtonHeight + 2*GALLERY_PADDING
	local galleryHeight = contentHeight + self:GetChromeHeight()

	local contentWidth = buttonWidths + (#self.galleryButtons+1)*GALLERY_PADDING
	self.ScrollFrame.Content:SetSize(contentWidth, contentHeight)
	self:SetHeight(galleryHeight)
end


--[[============
	C_Social.SetTextureToScreenshot is a fucking expensive function.
	There's not much way around that, though. In order to prevent a total lockup when the Social UI opens,
	at least stagger it on a timer. Each iteration will still cause stutter on lower-end hardware, but it's something.

	(Yes, STTS is the killer here. Don't try to get clever unless you can work around that)
--============]]
function GalleryFrame:RebuildFromReload()
	local ticker = C_Timer.NewTicker(0.2, function(self)
		if #GalleryFrame.galleryButtons < C_Social.GetLastScreenshot() then
			GalleryFrame:AddGalleryButton()
			GalleryFrame:ResizeContents()
			if not GalleryFrame:IsShown() then
				GalleryFrame:Show()
			end
		else
			self:Cancel()
		end
	end)
end

function Butterfly:InitializeGalleryFrame()
	GalleryFrame.galleryButtons = {}
	if C_Social.GetLastScreenshot() > 0 then
		GalleryFrame:RebuildFromReload()
	end

	GalleryFrame:RegisterEvent("SCREENSHOT_SUCCEEDED")
	GalleryFrame:SetScript("OnEvent", function(self, event)
		if event == "SCREENSHOT_SUCCEEDED" then
			self:AddGalleryButton()
			self:ResizeContents()
			if not self:IsShown() then
				self:Show()
			end
		end
	end)
	GalleryFrame:SetScript("OnShow", function(self)
		if #self.galleryButtons < 1 then
			self:Hide()
		end
	end)
	hooksecurefunc(FauxFrame, "Resize", function(frame, width, height)
		GalleryFrame:SetWidth(width - GALLERY_PADDING*4)
	end)
end