Quantcast

Nearing Ace3 Conversation Completion

Xruptor [08-31-16 - 15:44]
Nearing Ace3 Conversation Completion
-Added custom AceGUI Widget to handle a few things for certain BagSync windows.
-Finish Professions and Recipes window.
-Removed tekKonfigScroll, it was nice while lasted :) Thanks again Tekkub!
Filename
BagSync.lua
BagSync.toc
libs/tekKonfigScroll.lua
locale/enUS.lua
modules/currency.lua
modules/minimap.lua
modules/professions.lua
modules/recipes.lua
modules/test.lua
widgets/BagSyncInteractiveLabel.lua
diff --git a/BagSync.lua b/BagSync.lua
index 51dc7c4..aa2f0e2 100644
--- a/BagSync.lua
+++ b/BagSync.lua
@@ -41,7 +41,7 @@ local dataobj = ldb:NewDataObject("BagSyncLDB", {
 	OnClick = function(self, button)
 		if button == "LeftButton" then
 			BSYC:GetModule("Search").frame:Show()
-		elseif button == "RightButton" and BagSync_TokensFrame then
+		elseif button == "RightButton" then
 			if bgsMinimapDD then
 				ToggleDropDownMenu(1, nil, bgsMinimapDD, "cursor", 0, 0)
 			end
@@ -341,6 +341,9 @@ function BSYC:FilterDB(dbSelect)
 	if dbSelect and dbSelect == 1 then
 		--use BagSyncPROFESSION_DB
 		dbObj = self.db.profession
+	elseif dbSelect and dbSelect == 2 then
+		--use BagSyncCURRENCY_DB
+		dbObj = self.db.currency
 	end

 	--add more realm names if necessary based on BNet or Cross Realms
@@ -1173,11 +1176,7 @@ function BSYC:ChatCommand(input)
 			self:ShowMoneyTooltip()
 			return true
 		elseif cmd == L.SlashCurrency then
-			if BagSync_TokensFrame:IsVisible() then
-				BagSync_TokensFrame:Hide()
-			else
-				BagSync_TokensFrame:Show()
-			end
+			BSYC:GetModule("Currency").frame:Show()
 			return true
 		elseif cmd == L.SlashProfiles then
 			self:GetModule("Profiles").frame:Show()
diff --git a/BagSync.toc b/BagSync.toc
index 3183eff..2e45b4e 100644
--- a/BagSync.toc
+++ b/BagSync.toc
@@ -18,7 +18,8 @@ libs\Unfit-1.0\Unfit-1.0.lua
 libs\CustomSearch-1.0\CustomSearch-1.0.lua
 libs\LibItemSearch-1.2\LibItemSearch-1.2.lua
 libs\LibDataBroker-1.1\LibDataBroker-1.1.lua
-libs\tekKonfigScroll.lua
+
+widgets\BagSyncInteractiveLabel.lua

 locale\enUS.lua
 locale\deDE.lua
@@ -39,5 +40,4 @@ modules\professions.lua
 modules\recipes.lua
 modules\blacklist.lua
 modules\profiles.lua
-modules\config.lua
-modules\test.lua
\ No newline at end of file
+modules\config.lua
\ No newline at end of file
diff --git a/libs/tekKonfigScroll.lua b/libs/tekKonfigScroll.lua
deleted file mode 100644
index ff69b13..0000000
--- a/libs/tekKonfigScroll.lua
+++ /dev/null
@@ -1,80 +0,0 @@
-
-local lib, oldminor = LibStub:NewLibrary("tekKonfig-Scroll", 2)
-if not lib then return end
-
-lib.bg = {
-	edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
-	tile = true,
-	tileSize = 16,
-	edgeSize = 12,
-	insets = { left = 0, right = 0, top = 5, bottom = 5 }
-}
-
--- Creates a scrollbar
--- Parent is required, offset and step are optional
-function lib.new(parent, offset, step)
-	local f = CreateFrame("Slider", nil, parent)
-	f:SetWidth(16)
-
-	f:SetPoint("TOPRIGHT", 0 - (offset or 0), -16 - (offset or 0))
-	f:SetPoint("BOTTOMRIGHT", 0 - (offset or 0), 16 + (offset or 0))
-
-	local up = CreateFrame("Button", nil, f)
-	up:SetPoint("BOTTOM", f, "TOP")
-	up:SetWidth(16) up:SetHeight(16)
-	up:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Up")
-	up:SetPushedTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Down")
-	up:SetDisabledTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Disabled")
-	up:SetHighlightTexture("Interface\\Buttons\\UI-ScrollBar-ScrollUpButton-Highlight")
-
-	up:GetNormalTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	up:GetPushedTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	up:GetDisabledTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	up:GetHighlightTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	up:GetHighlightTexture():SetBlendMode("ADD")
-
-	up:SetScript("OnClick", function(self)
-		local parent = self:GetParent()
-		parent:SetValue(parent:GetValue() - (step or parent:GetHeight()/2))
-		PlaySound("UChatScrollButton")
-	end)
-
-	local down = CreateFrame("Button", nil, f)
-	down:SetPoint("TOP", f, "BOTTOM")
-	down:SetWidth(16) down:SetHeight(16)
-	down:SetNormalTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
-	down:SetPushedTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Down")
-	down:SetDisabledTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Disabled")
-	down:SetHighlightTexture("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Highlight")
-
-	down:GetNormalTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	down:GetPushedTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	down:GetDisabledTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	down:GetHighlightTexture():SetTexCoord(1/4, 3/4, 1/4, 3/4)
-	down:GetHighlightTexture():SetBlendMode("ADD")
-
-	down:SetScript("OnClick", function(self)
-		local parent = self:GetParent()
-		parent:SetValue(parent:GetValue() + (step or parent:GetHeight()/2))
-		PlaySound("UChatScrollButton")
-	end)
-
-	f:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
-	local thumb = f:GetThumbTexture()
-	thumb:SetWidth(16) thumb:SetHeight(24)
-	thumb:SetTexCoord(1/4, 3/4, 1/8, 7/8)
-
-	f:SetScript("OnValueChanged", function(self, value)
-		local min, max = self:GetMinMaxValues()
-		if value == min then up:Disable() else up:Enable() end
-		if value == max then down:Disable() else down:Enable() end
-	end)
-
-	local border = CreateFrame("Frame", nil, f)
-	border:SetPoint("TOPLEFT", up, -5, 5)
-	border:SetPoint("BOTTOMRIGHT", down, 5, -3)
-	border:SetBackdrop(lib.bg)
-	border:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b, 0.5)
-
-	return f, up, down, border
-end
diff --git a/locale/enUS.lua b/locale/enUS.lua
index 61d437d..d118927 100644
--- a/locale/enUS.lua
+++ b/locale/enUS.lua
@@ -36,7 +36,7 @@ L.ON = "ON"
 L.OFF = "OFF"
 L.LeftClickSearch = "Left Click = Search Window"
 L.RightClickBagSyncMenu = "Right Click = BagSync Menu"
-L.ProfessionLeftClick = "Left Click = Open Profession Recipe List"
+L.ProfessionInformation = "Left Click a Profession to view Recipes."
 L.ClickViewProfession = "Click to view profession: "
 L.ClickHere = "Click Here"
 L.ErrorUserNotFound = "BagSync: Error user not found!"
@@ -49,6 +49,8 @@ L.ItemIDRemoved = "[%d] ItemID Removed"
 L.ItemIDAdded = "[%d] ItemID Added"
 L.ItemIDExist = "[%d] ItemID already in database."
 L.ProfessionsFailedRequest = "[%d] Server Request Failed."
+L.ProfessionHasRecipes = "Left click to view recipes."
+L.ProfessionHasNoRecipes = "Has no recipes to view."
 -- ----THESE ARE FOR SLASH COMMANDS
 L.SlashItemName = "[itemname]"
 L.SlashSearch = "search"
diff --git a/modules/currency.lua b/modules/currency.lua
index 92b47f4..1e7d13c 100644
--- a/modules/currency.lua
+++ b/modules/currency.lua
@@ -1,238 +1,147 @@
+
+local BSYC = select(2, ...) --grab the addon namespace
+local Currency = BSYC:NewModule("Currency")
+
 local L = LibStub("AceLocale-3.0"):GetLocale("BagSync", true)
-local tokensTable = {}
-local tRows, tAnchor = {}
-local currentPlayer = UnitName("player")
-local currentRealm = select(2, UnitFullName("player"))
-local GetItemInfo = _G["GetItemInfo"]
+local AceGUI = LibStub("AceGUI-3.0")

-local bgTokens = CreateFrame("Frame","BagSync_TokensFrame", UIParent)
+function Currency:OnEnable()

-local function tooltipColor(color, str)
-  return string.format("|cff%02x%02x%02x%s|r", (color.r or 1) * 255, (color.g or 1) * 255, (color.b or 1) * 255, str)
-end
+	--lets create our widgets
+	local CurrencyFrame = AceGUI:Create("Window")
+	Currency.frame = CurrencyFrame
+	Currency.parentFrame = CurrencyFrame.frame

-local function LoadSlider()
+	CurrencyFrame:SetTitle("BagSync - "..L.Currency)
+	CurrencyFrame:SetHeight(500)
+	CurrencyFrame:SetWidth(380)
+	CurrencyFrame:EnableResize(false)

-	local function OnEnter(self)
-		if self.name and self.tooltip then
-			GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
-			GameTooltip:AddLine(self.name)
-			GameTooltip:AddLine(" ")
-			for i=1, #self.tooltip do
-				GameTooltip:AddDoubleLine(tooltipColor(BagSyncOpt.colors.first, self.tooltip[i].name), tooltipColor(BagSyncOpt.colors.second, self.tooltip[i].count))
-			end
-			GameTooltip:Show()
-		end
-	end
+	local information = AceGUI:Create("Label")
+	information:SetText(L.ProfessionInformation)
+	information:SetFont("Fonts\\FRIZQT__.TTF", 12, THICKOUTLINE)
+	information:SetColor(1, 165/255, 0)
+	information:SetFullWidth(true)
+	CurrencyFrame:AddChild(information)

-	local function OnLeave() GameTooltip:Hide() end
+	local scrollframe = AceGUI:Create("ScrollFrame");
+	scrollframe:SetFullWidth(true)
+	scrollframe:SetLayout("Flow")

-	local EDGEGAP, ROWHEIGHT, ROWGAP, GAP = 40, 20, 2, 4
-	local FRAME_HEIGHT = bgTokens:GetHeight() - 50
-	local SCROLL_TOP_POSITION = -80
-	local totaltRows = math.floor((FRAME_HEIGHT-22)/(ROWHEIGHT + ROWGAP))
+	Currency.scrollframe = scrollframe
+	CurrencyFrame:AddChild(scrollframe)
+
+	hooksecurefunc(CurrencyFrame, "Show" ,function()
+		self:DisplayList()
+	end)

-	for i=1, totaltRows do
-		if not tRows[i] then
-			local row = CreateFrame("Button", nil, bgTokens)
-			if not tAnchor then row:SetPoint("BOTTOMLEFT", bgTokens, "TOPLEFT", 0, SCROLL_TOP_POSITION)
-			else row:SetPoint("TOP", tAnchor, "BOTTOM", 0, -ROWGAP) end
-			row:SetPoint("LEFT", EDGEGAP, 0)
-			row:SetPoint("RIGHT", -EDGEGAP*1-8, 0)
-			row:SetHeight(ROWHEIGHT)
-			row:SetHighlightTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
-			tAnchor = row
-			tRows[i] = row
-
-			local title = row:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
-			title:SetPoint("LEFT")
-			title:SetJustifyH("LEFT")
-			title:SetWidth(row:GetWidth())
-			title:SetHeight(ROWHEIGHT)
-			row.title = title
-
-			local icon = row:CreateTexture(nil,"OVERLAY")
-			icon:SetPoint("LEFT", (ROWHEIGHT * -1) -3, 0)
-			icon:SetWidth(ROWHEIGHT)
-			icon:SetHeight(ROWHEIGHT)
-			icon:SetTexture("Interface\\Icons\\Spell_Shadow_Shadowbolt")
-			icon:Hide()
-			row.icon = icon
+	CurrencyFrame:Hide()

-			row:SetScript("OnEnter", OnEnter)
-			row:SetScript("OnLeave", OnLeave)
-		end
-	end
+end

-	local offset = 0
-	local RefreshTokens = function()
-		if not BagSync_TokensFrame:IsVisible() then return end
-
-		for i,row in ipairs(tRows) do
-			if (i + offset) <= #tokensTable then
-				if tokensTable[i + offset] then
-
-					if tokensTable[i + offset].isHeader then
-						row.title:SetText("|cFFFFFFFF"..tokensTable[i + offset].name.."|r")
-					else
-						row.title:SetText(tokensTable[i + offset].name)
-					end
-
-					--header texture and parameters
-					if tokensTable[i + offset].isHeader then
-						row:LockHighlight()
-						row.title:SetJustifyH("CENTER")
-						row.tooltip = nil
-					else
-						row:UnlockHighlight()
-						row.title:SetJustifyH("LEFT")
-						row.name = row.title:GetText()
-						row.tooltip = tokensTable[i + offset].tooltip
-					end
-
-					row.icon:SetTexture(tokensTable[i + offset].icon or nil)
-					row.icon:Show()
-					row:Show()
-				end
-			else
-				row.icon:SetTexture(nil)
-				row.icon:Hide()
-				row:Hide()
-			end
-		end
-	end
+function Currency:AddEntry(entry, isHeader)

-	RefreshTokens()
+	local highlightColor = {1, 0, 0}
+	local label = AceGUI:Create("BagSyncInteractiveLabel")

-	if not bgTokens.scrollbar then
-		bgTokens.scrollbar = LibStub("tekKonfig-Scroll").new(bgTokens, nil, #tRows/2)
-		bgTokens.scrollbar:ClearAllPoints()
-		bgTokens.scrollbar:SetPoint("TOP", tRows[1], 0, -16)
-		bgTokens.scrollbar:SetPoint("BOTTOM", tRows[#tRows], 0, 16)
-		bgTokens.scrollbar:SetPoint("RIGHT", -16, 0)
-	end
-
-	if #tokensTable > 0 then
-		bgTokens.scrollbar:SetMinMaxValues(0, math.max(0, #tokensTable - #tRows))
-		bgTokens.scrollbar:SetValue(0)
-		bgTokens.scrollbar:Show()
+	label.userdata.color = {1, 1, 1}
+	label:SetHeaderHighlight("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+	label:ToggleHeaderHighlight(false)
+
+	if isHeader then
+		label:SetText(entry.player)
+		label:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
+		label:SetFullWidth(true)
+		label:SetColor(unpack(label.userdata.color))
+		label:ApplyJustifyH("CENTER")
+		label.userdata.isHeader = true
+		label.userdata.hasRecipes = false
+		label:ToggleHeaderHighlight(true)
 	else
-		bgTokens.scrollbar:Hide()
+		local labelText = entry.name..format(" |cFFFFFFFF(%s)|r", entry.level)
+		label:SetText(labelText)
+		label:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
+		label:SetFullWidth(true)
+		if entry.recipes then
+			label.userdata.color = {153/255,204/255,51/255} --primary profession color it green
+			label.userdata.hasRecipes = true
+		else
+			label.userdata.color = {102/255,153/255,1} --gathering profession color it blue
+			label.userdata.hasRecipes = false
+		end
+		label:SetColor(unpack(label.userdata.color))
+		label:ApplyJustifyH("LEFT")
+		label.userdata.isHeader = false
 	end

-	local f = bgTokens.scrollbar:GetScript("OnValueChanged")
-	bgTokens.scrollbar:SetScript("OnValueChanged", function(self, value, ...)
-		offset = math.floor(value)
-		RefreshTokens()
-		return f(self, value, ...)
-	end)
-
-	bgTokens:EnableMouseWheel()
-	bgTokens:SetScript("OnMouseWheel", function(self, val)
-		bgTokens.scrollbar:SetValue(bgTokens.scrollbar:GetValue() - val*#tRows/2)
-	end)
+	label:SetCallback(
+		"OnClick",
+		function (widget, sometable, button)
+			if "LeftButton" == button and label.userdata.hasRecipes then
+				BSYC:GetModule("Recipes"):ViewRecipes(entry.name, entry.level, entry.recipes)
+			end
+		end)
+	label:SetCallback(
+		"OnEnter",
+		function (widget, sometable)
+			label:SetColor(unpack(highlightColor))
+			GameTooltip:SetOwner(label.frame, "ANCHOR_BOTTOMRIGHT")
+			if label.userdata.hasRecipes then
+				GameTooltip:AddLine(L.ProfessionHasRecipes)
+			else
+				GameTooltip:AddLine(L.ProfessionHasNoRecipes)
+			end
+			GameTooltip:Show()
+		end)
+	label:SetCallback(
+		"OnLeave",
+		function (widget, sometable)
+			label:SetColor(unpack(label.userdata.color))
+			GameTooltip:Hide()
+		end)
+
+	self.scrollframe:AddChild(label)
 end

-local function DoTokens()
-	if not BagSync or not BagSyncTOKEN_DB then return end
-	if not BagSyncTOKEN_DB[currentRealm] then return end
+function Currency:DisplayList()
+
+	local CurrencyTable = {}
+	local tempList = {}
+	local count = 0
+
+	self.scrollframe:ReleaseChildren() --clear out the scrollframe

-	tokensTable = {} --reset
-	local tmp = {}
+	local xDB = BSYC:FilterDB(1) --dbSelect 1

 	--loop through our characters
-	-----------------------------------
-	if BagSyncTOKEN_DB[currentRealm] then
-		for k, v in pairs(BagSyncTOKEN_DB[currentRealm]) do
-
-			tmp = {}
-			--this will loop and store all characters whom have counts greater then zero,
-			--ignoring the icon and header table entry, then it sorts it by character name
-			for q, r in pairs(v) do
-				if q ~= "icon" and q ~= "header" and r > 0 then
-					--only show counts that are greater then zero
-					table.insert(tmp, { name=q, count=r} )
-				end
-			end
-			table.sort(tmp, function(a,b) return (a.name < b.name) end)
-
-			--now add it to master table to sort later
-			table.insert(tokensTable, {name=k, icon=v.icon, header=v.header, tooltip=tmp})
-		end
-	end
-	-----------------------------------
-
-	--sort it
-	table.sort(tokensTable, function(a,b)
-		if a.header < b.header then
-			return true;
-		elseif a.header == b.header then
-			return (a.name < b.name);
-		end
-	end)
-
-	--add headers
-	local lastHeader = ""
-	tmp = {} --reset
-
-	for i=1, #tokensTable do
-		if tokensTable[i].header ~= lastHeader then
-			lastHeader = tokensTable[i].header
-			table.insert(tmp, { name=lastHeader, header=lastHeader, isHeader=true } )
-			table.insert(tmp, tokensTable[i])
-		else
-			table.insert(tmp, tokensTable[i])
-		end
-	end
-	tokensTable = tmp
+	--k = player, v = stored data for player
+	for k, v in pairs(xDB) do

-	LoadSlider()
-end
+		local tmp = {}
+		local yName, yRealm  = strsplit("^", k)
+		local playerName = BSYC:GetCharacterRealmInfo(yName, yRealm)

-bgTokens:SetFrameStrata("HIGH")
-bgTokens:SetToplevel(true)
-bgTokens:EnableMouse(true)
-bgTokens:SetMovable(true)
-bgTokens:SetClampedToScreen(true)
-bgTokens:SetWidth(380)
-bgTokens:SetHeight(500)
-
-bgTokens:SetBackdrop({
-		bgFile = "Interface/Tooltips/UI-Tooltip-Background",
-		edgeFile = "Interface/Tooltips/UI-Tooltip-Border",
-		tile = true,
-		tileSize = 16,
-		edgeSize = 32,
-		insets = { left = 5, right = 5, top = 5, bottom = 5 }
-})
-
-bgTokens:SetBackdropColor(0,0,0,1)
-bgTokens:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
-
-local addonTitle = bgTokens:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
-addonTitle:SetPoint("CENTER", bgTokens, "TOP", 0, -20)
-addonTitle:SetText("|cFF99CC33BagSync|r |cFFFFFFFF("..L.Currency..")|r")
-
-local closeButton = CreateFrame("Button", nil, bgTokens, "UIPanelCloseButton");
-closeButton:SetPoint("TOPRIGHT", bgTokens, -15, -8);
-
-bgTokens:SetScript("OnShow", function(self) DoTokens(); LoadSlider(); end)
-bgTokens:SetScript("OnHide", function(self)
-	tokensTable = {}
-end)
-
-bgTokens:SetScript("OnMouseDown", function(frame, button)
-	if frame:IsMovable() then
-		frame.isMoving = true
-		frame:StartMoving()
+		for q, r in pairs(v) do
+			table.insert(tmp, { player=playerName, name=r.name, level=r.level, recipes=r.recipes } )
+			count = count + 1
+		end
+
+		--add to master table
+		table.insert(CurrencyTable, { player=playerName, info=tmp } )
 	end
-end)
-
-bgTokens:SetScript("OnMouseUp", function(frame, button)
-	if( frame.isMoving ) then
-		frame.isMoving = nil
-		frame:StopMovingOrSizing()
+
+	--show or hide the scrolling frame depending on count
+	if count > 0 then
+		table.sort(CurrencyTable, function(a,b) return (a.player < b.player) end)
+		for i=1, #CurrencyTable do
+			self:AddEntry(CurrencyTable[i], true) --add header
+			for z=1, #CurrencyTable[i].info do
+				self:AddEntry(CurrencyTable[i].info[z], false)
+			end
+		end
+		self.scrollframe.frame:Show()
+	else
+		self.scrollframe.frame:Hide()
 	end
-end)
-
-bgTokens:Hide()
\ No newline at end of file
+
+end
\ No newline at end of file
diff --git a/modules/minimap.lua b/modules/minimap.lua
index d05f746..8fa21c6 100644
--- a/modules/minimap.lua
+++ b/modules/minimap.lua
@@ -44,7 +44,7 @@ bgsMinimapDD.initialize = function(self, level)
 			BSYC:GetModule("Search").frame:Show()
 		end)
 		addButton(level, L.Currency, nil, 1, nil, 'currency', function(frame, ...)
-			if BagSync_TokensFrame then BagSync_TokensFrame:Show() end
+			BSYC:GetModule("Currency").frame:Show()
 		end)
 		addButton(level, L.Profiles, nil, 1, nil, 'profiles', function(frame, ...)
 			BSYC:GetModule("Profiles").frame:Show()
@@ -72,13 +72,9 @@ bgsMinimapDD.initialize = function(self, level)
 end

 bgMinimapButton:SetScript('OnMouseUp', function(self, button)
-	if button == 'LeftButton' and BagSync_SearchFrame then
-		if BagSync_SearchFrame:IsVisible() then
-			BagSync_SearchFrame:Hide()
-		else
-			BagSync_SearchFrame:Show()
-		end
-	elseif button == 'RightButton' and BagSync_TokensFrame then
+	if button == 'LeftButton' then
+		BSYC:GetModule("Search").frame:Show()
+	elseif button == 'RightButton' then
 		ToggleDropDownMenu(1, nil, bgsMinimapDD, 'cursor', 0, 0)
 	end
 end)
diff --git a/modules/professions.lua b/modules/professions.lua
index 46505c1..1aea08a 100644
--- a/modules/professions.lua
+++ b/modules/professions.lua
@@ -18,7 +18,7 @@ function Professions:OnEnable()
 	ProfessionsFrame:EnableResize(false)

 	local information = AceGUI:Create("Label")
-	information:SetText(L.ProfessionLeftClick)
+	information:SetText(L.ProfessionInformation)
 	information:SetFont("Fonts\\FRIZQT__.TTF", 12, THICKOUTLINE)
 	information:SetColor(1, 165/255, 0)
 	information:SetFullWidth(true)
@@ -42,40 +42,21 @@ end
 function Professions:AddEntry(entry, isHeader)

 	local highlightColor = {1, 0, 0}
-	local label = AceGUI:Create("InteractiveLabel")
-
-	--I know you aren't supposed to but I'm going to have to put it on the label object.  Only because when using userdata the texture sticks around even with release.
-	--So I'm forced to have to add it to label and do a custom OnRelease to get rid of it for other addons.
-	if not label.headerhighlight then
-		label.headerhighlight = label.frame:CreateTexture(nil, "BACKGROUND") --userdata gets deleted when widget is recycled
-		label.headerhighlight:SetAllPoints()
-		label.headerhighlight:SetBlendMode("ADD")
-		label.headerhighlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") --userdata gets deleted when widget is recycled
-	end
-	--remove the highlight texture on widget release for other addons
-	local oldOnRelease = label.OnRelease
-	label.OnRelease = function(self)
-		if self.headerhighlight then
-			self.headerhighlight:SetTexture(nil)
-			self.headerhighlight = nil
-		end
-		if oldOnRelease then
-			oldOnRelease(self)
-		end
-	end
+	local label = AceGUI:Create("BagSyncInteractiveLabel")

 	label.userdata.color = {1, 1, 1}
-	label.headerhighlight:Hide() --hide on default
+	label:SetHeaderHighlight("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+	label:ToggleHeaderHighlight(false)

 	if isHeader then
 		label:SetText(entry.player)
 		label:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
 		label:SetFullWidth(true)
 		label:SetColor(unpack(label.userdata.color))
-		label.label:SetJustifyH("CENTER") --don't like doing this until they update Ace3GUI
+		label:ApplyJustifyH("CENTER")
 		label.userdata.isHeader = true
 		label.userdata.hasRecipes = false
-		label.headerhighlight:Show()
+		label:ToggleHeaderHighlight(true)
 	else
 		local labelText = entry.name..format(" |cFFFFFFFF(%s)|r", entry.level)
 		label:SetText(labelText)
@@ -89,7 +70,7 @@ function Professions:AddEntry(entry, isHeader)
 			label.userdata.hasRecipes = false
 		end
 		label:SetColor(unpack(label.userdata.color))
-		label.label:SetJustifyH("LEFT")--don't like doing this until they update Ace3GUI
+		label:ApplyJustifyH("LEFT")
 		label.userdata.isHeader = false
 	end

@@ -104,11 +85,19 @@ function Professions:AddEntry(entry, isHeader)
 		"OnEnter",
 		function (widget, sometable)
 			label:SetColor(unpack(highlightColor))
+			GameTooltip:SetOwner(label.frame, "ANCHOR_BOTTOMRIGHT")
+			if label.userdata.hasRecipes then
+				GameTooltip:AddLine(L.ProfessionHasRecipes)
+			else
+				GameTooltip:AddLine(L.ProfessionHasNoRecipes)
+			end
+			GameTooltip:Show()
 		end)
 	label:SetCallback(
 		"OnLeave",
 		function (widget, sometable)
 			label:SetColor(unpack(label.userdata.color))
+			GameTooltip:Hide()
 		end)

 	self.scrollframe:AddChild(label)
diff --git a/modules/recipes.lua b/modules/recipes.lua
index 56da92a..989a56c 100644
--- a/modules/recipes.lua
+++ b/modules/recipes.lua
@@ -13,43 +13,24 @@ function Recipes:OnEnable()

 	RecipesFrame:SetTitle("BagSync - "..L.Recipes)
 	RecipesFrame:SetHeight(500)
-	RecipesFrame:SetWidth(380)
+	RecipesFrame:SetWidth(570)
 	RecipesFrame:EnableResize(false)

-	local information = AceGUI:Create("Label")
-	information:SetText(L.ProfessionLeftClick)
+	local information = AceGUI:Create("BagSyncInteractiveLabel")
 	information:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
 	information:SetColor(153/255,204/255,51/255)
 	information:SetFullWidth(true)
+	information:ApplyJustifyH("CENTER")
 	RecipesFrame:AddChild(information)

 	Recipes.information = information

-	local label = AceGUI:Create("InteractiveLabel")
+	local label = AceGUI:Create("BagSyncInteractiveLabel")
 	label:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
 	label:SetFullWidth(true)
 	label:SetText(" ") --add an empty space just to show the label
-
-	--I know you aren't supposed to but I'm going to have to put it on the label object.  Only because when using userdata the texture sticks around even with release.
-	--So I'm forced to have to add it to label and do a custom OnRelease to get rid of it for other addons.
-	if not label.headerhighlight then
-		label.headerhighlight = label.frame:CreateTexture(nil, "BACKGROUND") --userdata gets deleted when widget is recycled
-		label.headerhighlight:SetAllPoints()
-		label.headerhighlight:SetBlendMode("ADD")
-		label.headerhighlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight") --userdata gets deleted when widget is recycled
-		label.headerhighlight:Show()
-	end
-	--remove the highlight texture on widget release for other addons
-	local oldOnRelease = label.OnRelease
-	label.OnRelease = function(self)
-		if self.headerhighlight then
-			self.headerhighlight:SetTexture(nil)
-			self.headerhighlight = nil
-		end
-		if oldOnRelease then
-			oldOnRelease(self)
-		end
-	end
+	label:SetHeaderHighlight("Interface\\QuestFrame\\UI-QuestTitleHighlight")
+	label:ToggleHeaderHighlight(true)
 	RecipesFrame:AddChild(label)

 	local scrollframe = AceGUI:Create("ScrollFrame");
@@ -69,7 +50,7 @@ end

 function Recipes:AddEntry(entry)

-	local name, recipeID = entry.name, entry.recipeID
+	local name, recipeID, icon = entry.name, entry.recipeID, entry.icon

 	local highlightColor = {1, 0, 0}
 	local label = AceGUI:Create("InteractiveLabel")
@@ -78,6 +59,7 @@ function Recipes:AddEntry(entry)
 	label:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
 	label:SetFullWidth(true)
 	label:SetColor( 1,1,1)
+	label:SetImage(icon)
 	label:SetCallback(
 		"OnClick",
 		function (widget, sometable, button)
@@ -121,17 +103,22 @@ function Recipes:DisplayList(tradeRecipes)

 		local recipe_info = _G.C_TradeSkillUI.GetRecipeInfo(valuesList[idx])
 		local craftName = valuesList[idx]
+		local iconTexture = "Interface\\Icons\\INV_Misc_QuestionMark"
+
+		local gName, gRank, gIcon = GetSpellInfo(valuesList[idx])

 		if recipe_info and recipe_info.name then
 			craftName = recipe_info.name
-		elseif GetSpellInfo(valuesList[idx]) then
-			craftName = GetSpellInfo(valuesList[idx])
+			iconTexture = recipe_info.icon
+		elseif gName then
+			craftName = gName
+			iconTexture = gIcon
 		else
 			craftName = L.ProfessionsFailedRequest:format(valuesList[idx])
 		end

 		count = count + 1
-		table.insert(searchTable, {name=craftName, recipeID=valuesList[idx]})
+		table.insert(searchTable, {name=craftName, recipeID=valuesList[idx], icon=iconTexture})
 	end

 	--show or hide the scrolling frame depending on count
diff --git a/modules/test.lua b/modules/test.lua
deleted file mode 100644
index 2a81ca1..0000000
--- a/modules/test.lua
+++ /dev/null
@@ -1,118 +0,0 @@
-
-local BSYC = select(2, ...) --grab the addon namespace
-local Testing = BSYC:NewModule("Testing")
-
-local L = LibStub("AceLocale-3.0"):GetLocale("BagSync", true)
-local AceGUI = LibStub("AceGUI-3.0")
-
-function Testing:OnEnable()
-
-	--lets create our widgets
-	local TestingFrame = AceGUI:Create("Window")
-	Testing.frame = TestingFrame
-
-	TestingFrame:SetTitle("Testing")
-	TestingFrame:SetHeight(500)
-	TestingFrame:SetWidth(380)
-	TestingFrame:EnableResize(false)
-
-	local refreshbutton = AceGUI:Create("Button")
-	refreshbutton:SetText(L.Refresh)
-	refreshbutton:SetWidth(100)
-	refreshbutton:SetHeight(20)
-	refreshbutton:SetCallback("OnClick", function()
-		self:DisplayList()
-	end)
-	TestingFrame:AddChild(refreshbutton)
-
-	local scrollframe = AceGUI:Create("ScrollFrame");
-	scrollframe:SetFullWidth(true)
-	scrollframe:SetLayout("Flow")
-
-	Testing.scrollframe = scrollframe
-	TestingFrame:AddChild(scrollframe)
-
-	TestingFrame:Hide()
-end
-
-
-function Testing:AddEntry(entry)
-
-	local name, recipeID = entry.name, entry.recipeID
-
-	local highlightColor = {1, 0, 0}
-	local label = AceGUI:Create("InteractiveLabel")
-
-	label:SetText(name)
-	label:SetFont("Fonts\\FRIZQT__.TTF", 14, THICKOUTLINE)
-	label:SetFullWidth(true)
-	label:SetColor( 1,1,1)
-	label:SetCallback(
-		"OnClick",
-		function (widget, sometable, button)
-			ChatEdit_InsertLink(GetSpellLink(recipeID))
-		end)
-	label:SetCallback(
-		"OnEnter",
-		function (widget, sometable)
-			label:SetColor(unpack(highlightColor))
-			GameTooltip:SetOwner(label.frame, "ANCHOR_BOTTOMRIGHT")
-			GameTooltip:SetSpellByID(recipeID)
-			GameTooltip:Show()
-		end)
-	label:SetCallback(
-		"OnLeave",
-		function (widget, sometable)
-			label:SetColor(1,1,1)
-			GameTooltip:Hide()
-		end)
-
-	self.scrollframe:AddChild(label)
-end
-
-function Testing:DisplayList()
-
-	self.scrollframe:ReleaseChildren() --clear out the scrollframe
-
-	local searchTable = {}
-	local count = 0
-
-	--loop through our Testing
-	for k, v in pairs(BSYC.db.profession[BSYC.currentRealm]) do
-		if k == "test1" then
-			local tName, tlevel, tValues = strsplit(",", v)
-			local valuesList = {strsplit("|", tValues)}
-
-			for idx = 1, #valuesList do
-
-				local recipe_info = _G.C_TradeSkillUI.GetRecipeInfo(valuesList[idx])
-				local craftName = valuesList[idx]
-
-				if recipe_info and recipe_info.name then
-					craftName = recipe_info.name
-				elseif GetSpellInfo(valuesList[idx]) then
-					craftName = GetSpellInfo(valuesList[idx])
-				else
-					craftName = L.ProfessionsFailedRequest:format(valuesList[idx])
-				end
-
-				table.insert(searchTable, {name=craftName, recipeID=valuesList[idx]})
-			end
-			count = count + 1
-		end
-	end
-
-	--show or hide the scrolling frame depending on count
-	if count > 0 then
-		table.sort(searchTable, function(a,b) return (a.name < b.name) end)
-		for i=1, #searchTable do
-			self:AddEntry(searchTable[i])
-		end
-		self.scrollframe.frame:Show()
-	else
-		self.scrollframe.frame:Hide()
-	end
-
-	--169080
-	--GetSpellInfo(169080)
-end
\ No newline at end of file
diff --git a/widgets/BagSyncInteractiveLabel.lua b/widgets/BagSyncInteractiveLabel.lua
new file mode 100644
index 0000000..c828d6e
--- /dev/null
+++ b/widgets/BagSyncInteractiveLabel.lua
@@ -0,0 +1,162 @@
+--[[-----------------------------------------------------------------------------
+BagSyncInteractiveLabel Widget
+-------------------------------------------------------------------------------]]
+local Type, Version = "BagSyncInteractiveLabel", 1
+local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
+if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
+
+-- Lua APIs
+local select, pairs = select, pairs
+
+-- WoW APIs
+local CreateFrame, UIParent = CreateFrame, UIParent
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GameFontHighlightSmall
+
+--[[-----------------------------------------------------------------------------
+Scripts
+-------------------------------------------------------------------------------]]
+local function Control_OnEnter(frame)
+	frame.obj:Fire("OnEnter")
+end
+
+local function Control_OnLeave(frame)
+	frame.obj:Fire("OnLeave")
+end
+
+local function Label_OnClick(frame, button)
+	frame.obj:Fire("OnClick", button)
+	AceGUI:ClearFocus()
+end
+
+--[[-----------------------------------------------------------------------------
+Methods
+-------------------------------------------------------------------------------]]
+local methods = {
+	["OnAcquire"] = function(self)
+		self:LabelOnAcquire()
+		self:ApplyJustifyH()
+		self:ApplyJustifyV()
+		self:SetHighlight()
+		self:SetHeaderHighlight()
+		self:SetHighlightTexCoord()
+		self:SetHeaderHighlightTexCoord()
+		self:ToggleHeaderHighlight()
+		self:SetDisabled(false)
+	end,
+
+	["ApplyJustifyH"] = function(self,position)
+		if position then
+			self.label:SetJustifyH(position)
+		else
+			self.label:SetJustifyH("LEFT")
+		end
+	end,
+
+	["ApplyJustifyV"] = function(self,position)
+		if position then
+			self.label:SetJustifyV(position)
+		else
+			self.label:SetJustifyV("TOP")
+		end
+	end,
+
+	["SetDisabled"] = function(self,disabled)
+		self.disabled = disabled
+		if disabled then
+			self.frame:EnableMouse(false)
+			self.label:SetTextColor(0.5, 0.5, 0.5)
+		else
+			self.frame:EnableMouse(true)
+			self.label:SetTextColor(1, 1, 1)
+		end
+	end,
+
+
+	["SetHighlight"] = function(self, ...)
+		self.highlight:SetTexture(...)
+		self.headerhighlight:SetTexture(nil) --only one active highlight at a time
+	end,
+
+	["SetHighlightTexCoord"] = function(self, ...)
+		local c = select("#", ...)
+		if c == 4 or c == 8 then
+			self.highlight:SetTexCoord(...)
+		else
+			self.highlight:SetTexCoord(0, 1, 0, 1)
+		end
+	end,
+
+	["SetHeaderHighlight"] = function(self, ...)
+		self.headerhighlight:SetTexture(...)
+		self.highlight:SetTexture(nil) --only one active highlight at a time
+	end,
+
+	["SetHeaderHighlightTexCoord"] = function(self, ...)
+		local c = select("#", ...)
+		if c == 4 or c == 8 then
+			self.headerhighlight:SetTexCoord(...)
+		else
+			self.headerhighlight:SetTexCoord(0, 1, 0, 1)
+		end
+	end,
+
+	["ToggleHeaderHighlight"] = function(self,toggle)
+		if toggle then
+			self.headerhighlight:Show()
+		else
+			self.headerhighlight:Hide()
+		end
+	end,
+
+	["SetDisabled"] = function(self,disabled)
+		self.disabled = disabled
+		if disabled then
+			self.frame:EnableMouse(false)
+			self.label:SetTextColor(0.5, 0.5, 0.5)
+		else
+			self.frame:EnableMouse(true)
+			self.label:SetTextColor(1, 1, 1)
+		end
+	end,
+}
+
+--[[-----------------------------------------------------------------------------
+Constructor
+-------------------------------------------------------------------------------]]
+local function Constructor()
+	-- create a Label type that we will hijack
+	local label = AceGUI:Create("Label")
+
+	local frame = label.frame
+	frame:EnableMouse(true)
+	frame:SetScript("OnEnter", Control_OnEnter)
+	frame:SetScript("OnLeave", Control_OnLeave)
+	frame:SetScript("OnMouseDown", Label_OnClick)
+
+	local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
+	highlight:SetTexture(nil)
+	highlight:SetAllPoints()
+	highlight:SetBlendMode("ADD")
+
+	local headerhighlight = frame:CreateTexture(nil, "BACKGROUND")
+	headerhighlight:SetTexture(nil)
+	headerhighlight:SetAllPoints()
+	headerhighlight:SetBlendMode("ADD")
+	headerhighlight:Hide()
+
+	label.highlight = highlight
+	label.headerhighlight = headerhighlight
+	label.type = Type
+	label.LabelOnAcquire = label.OnAcquire
+	for method, func in pairs(methods) do
+		label[method] = func
+	end
+
+	return label
+end
+
+AceGUI:RegisterWidgetType(Type, Constructor, Version)
+