| contrebasse@0 | 1 local addonName, A = ... | 
| contrebasse@0 | 2 | 
| contrebasse@111 | 3 -- GLOBALS: UIErrorsFrame, UIErrorsFrame_OnEvent | 
| contrebasse@111 | 4 | 
| contrebasse@16 | 5 -- Lua functions | 
| contrebasse@16 | 6 local tonumber = tonumber | 
| contrebasse@16 | 7 local select = select | 
| contrebasse@16 | 8 local sfind = string.find | 
| contrebasse@111 | 9 local min = math.min | 
| contrebasse@111 | 10 local floor = math.floor | 
| contrebasse@111 | 11 local pairs = pairs | 
| contrebasse@111 | 12 local ipairs = ipairs | 
| contrebasse@111 | 13 local wipe = wipe | 
| contrebasse@111 | 14 local tinsert = tinsert | 
| contrebasse@111 | 15 local tremove = tremove | 
| contrebasse@16 | 16 | 
| contrebasse@16 | 17 -- Wow functions | 
| contrebasse@111 | 18 local GetItemCount = GetItemCount | 
| contrebasse@0 | 19 | 
| contrebasse@38 | 20 -- Messages to the user | 
| contrebasse@38 | 21 function A.Warn(msg) | 
| contrebasse@38 | 22 	if not msg then return end | 
| contrebasse@38 | 23 	local event = "UI_INFO_MESSAGE" | 
| contrebasse@38 | 24 	UIErrorsFrame_OnEvent(UIErrorsFrame, event, msg) | 
| contrebasse@38 | 25 end -- function | 
| contrebasse@38 | 26 function A.Error(msg) | 
| contrebasse@38 | 27 	if not msg then return end | 
| contrebasse@38 | 28 	local event = "UI_ERROR_MESSAGE" | 
| contrebasse@38 | 29 	UIErrorsFrame_OnEvent(UIErrorsFrame, event, msg) | 
| contrebasse@38 | 30 end -- function | 
| contrebasse@38 | 31 | 
| contrebasse@3 | 32 -- Returns the item ID from its link | 
| contrebasse@3 | 33 function A.link2ID(link) | 
| contrebasse@16 | 34 	return tonumber(select(3,sfind(link or "", "-*:(%d+)[:|].*")) or "") | 
| contrebasse@3 | 35 end -- function | 
| contrebasse@3 | 36 | 
| contrebasse@3 | 37 -- Returns the button number for the reagents buttons | 
| contrebasse@3 | 38 function A.buttonNumber(btn) | 
| contrebasse@3 | 39 	-- "TradeSkillReagentN" | 
| contrebasse@3 | 40 	return tonumber(btn:GetName():sub(-1)) | 
| contrebasse@0 | 41 end | 
| contrebasse@0 | 42 | 
| contrebasse@16 | 43 do | 
| contrebasse@16 | 44 	-- Wow functions | 
| contrebasse@16 | 45 	local GetTradeSkillInfo = GetTradeSkillInfo | 
| contrebasse@16 | 46 	local GetNumTradeSkills = GetNumTradeSkills | 
| contrebasse@16 | 47 	local GetTradeSkillItemLink = GetTradeSkillItemLink | 
| contrebasse@111 | 48 	local GetTradeSkillRecipeLink = GetTradeSkillRecipeLink | 
| contrebasse@0 | 49 | 
| contrebasse@110 | 50 	function A.numRecipeMakable(reagentIDIfUnique,reagents) | 
| contrebasse@111 | 51 		local itemCount | 
| contrebasse@110 | 52 		if reagentIDIfUnique then -- only one reagent | 
| contrebasse@110 | 53 			itemCount = GetItemCount(reagentIDIfUnique) | 
| contrebasse@110 | 54 			if not itemCount then return end | 
| contrebasse@111 | 55 			return floor(itemCount/reagents) | 
| contrebasse@110 | 56 		else -- many reagents | 
| contrebasse@110 | 57 			local m | 
| contrebasse@110 | 58 			for _,reagent in pairs(reagents) do | 
| contrebasse@110 | 59 				itemCount = GetItemCount(reagent[1]) | 
| contrebasse@110 | 60 				if not itemCount then return end | 
| contrebasse@110 | 61 				if not m then | 
| contrebasse@111 | 62 					m = floor(itemCount/reagent[2]) | 
| contrebasse@110 | 63 				else | 
| contrebasse@111 | 64 					m = min(m,floor(itemCount/reagent[2])) | 
| contrebasse@110 | 65 				end | 
| contrebasse@110 | 66 				if m==0 then break end | 
| contrebasse@110 | 67 			end | 
| contrebasse@110 | 68 			return m | 
| contrebasse@110 | 69 		end -- if | 
| contrebasse@110 | 70 	end | 
| contrebasse@110 | 71 | 
| contrebasse@116 | 72 	-- Gives the total number of craftable items | 
| contrebasse@108 | 73 	function A.numMakable(reagentID) | 
| contrebasse@108 | 74 		-- No recipe | 
| contrebasse@108 | 75 		if not A.data[reagentID] then return 0 end | 
| contrebasse@108 | 76 | 
| contrebasse@108 | 77 		-- Many recipes | 
| contrebasse@116 | 78 		local n1 = 0 | 
| contrebasse@116 | 79 		local n2 = 0 | 
| contrebasse@116 | 80 		local m | 
| contrebasse@116 | 81 		local approx = nil | 
| contrebasse@108 | 82 		for _,recipe in pairs(A.data[reagentID]) do | 
| contrebasse@116 | 83 			-- number of times the recipe is makable | 
| contrebasse@116 | 84 			m = A.numRecipeMakable(recipe[1],recipe[2]) | 
| contrebasse@116 | 85 			if not m then return end | 
| contrebasse@116 | 86 | 
| contrebasse@116 | 87 			-- number of items it gives | 
| contrebasse@116 | 88 			if not recipe[3] or recipe[3]==1 then | 
| contrebasse@116 | 89 				n1 = n1 + m | 
| contrebasse@116 | 90 				n2 = n2 + m | 
| contrebasse@116 | 91 			elseif recipe[3]<1 then | 
| contrebasse@116 | 92 				approx = approx or m>0 -- 0 is not approx | 
| contrebasse@116 | 93 				n1 = n1 + m*recipe[3] | 
| contrebasse@116 | 94 				n2 = n2 + m*recipe[3] | 
| contrebasse@116 | 95 			elseif recipe[4] then | 
| contrebasse@116 | 96 				n1 = n1 + m*recipe[3] | 
| contrebasse@116 | 97 				n2 = n2 + m*recipe[4] | 
| contrebasse@116 | 98 			else | 
| contrebasse@116 | 99 				n1 = n1 + m*recipe[3] | 
| contrebasse@116 | 100 				n2 = n2 + m*recipe[3] | 
| contrebasse@116 | 101 			end | 
| contrebasse@108 | 102 		end -- for | 
| contrebasse@116 | 103 		return n1,n2,approx | 
| contrebasse@108 | 104 	end -- function | 
| contrebasse@16 | 105 | 
| contrebasse@16 | 106 	-- Find the first tradeskill index of the recipe to make an item | 
| contrebasse@16 | 107 	function A.findSkillIndex(itemID) | 
| contrebasse@110 | 108 		if not itemID then return end | 
| contrebasse@16 | 109 		for i = 1,GetNumTradeSkills() do | 
| contrebasse@110 | 110 			if select(2,GetTradeSkillInfo(i)) ~= "header" and A.link2ID(GetTradeSkillItemLink(i)) == itemID then | 
| contrebasse@110 | 111 				return i | 
| contrebasse@110 | 112 			end -- if | 
| contrebasse@110 | 113 		end -- for | 
| contrebasse@110 | 114 	end -- function | 
| contrebasse@110 | 115 | 
| contrebasse@110 | 116 	-- Find the exact tradeskill index of the recipe to make an item | 
| contrebasse@111 | 117 	function A.findExactSkillIndex(itemID,recipeLink) | 
| contrebasse@111 | 118 		if not itemID or not recipeLink then return end | 
| contrebasse@110 | 119 		for i = 1,GetNumTradeSkills() do | 
| contrebasse@111 | 120 			if select(2,GetTradeSkillInfo(i)) ~= "header" and GetTradeSkillRecipeLink(i)==recipeLink and A.link2ID(GetTradeSkillItemLink(i)) == itemID then | 
| contrebasse@110 | 121 				return i | 
| contrebasse@3 | 122 			end -- if | 
| contrebasse@16 | 123 		end -- for | 
| contrebasse@16 | 124 	end -- function | 
| contrebasse@16 | 125 end -- do | 
| contrebasse@24 | 126 | 
| contrebasse@24 | 127 | 
| contrebasse@110 | 128 -- Bypass filters and collpsed headers | 
| contrebasse@24 | 129 do | 
| contrebasse@24 | 130 	local selectedTradeSkillIndex | 
| contrebasse@107 | 131 	local stateSaved | 
| contrebasse@107 | 132 	local filtersState = {} | 
| contrebasse@24 | 133 	local headersState = {} | 
| contrebasse@24 | 134 | 
| contrebasse@107 | 135 	local function ApplyFilters() | 
| contrebasse@107 | 136 		TradeSkillOnlyShowSkillUps(TradeSkillFrame.filterTbl.hasSkillUp); | 
| contrebasse@107 | 137 		TradeSkillOnlyShowMakeable(TradeSkillFrame.filterTbl.hasMaterials); | 
| contrebasse@107 | 138 		SetTradeSkillSubClassFilter(TradeSkillFrame.filterTbl.subClassValue, 1, 1); | 
| contrebasse@107 | 139 		SetTradeSkillInvSlotFilter(TradeSkillFrame.filterTbl.slotValue, 1, 1); | 
| contrebasse@107 | 140 		TradeSkillUpdateFilterBar(); | 
| contrebasse@107 | 141 		CloseDropDownMenus(); | 
| contrebasse@107 | 142 	end | 
| contrebasse@107 | 143 | 
| contrebasse@82 | 144 	function A.SaveActiveFilters(headerName) | 
| contrebasse@82 | 145 		A.blockScan = true | 
| contrebasse@82 | 146 | 
| contrebasse@111 | 147 		-- Save position | 
| contrebasse@111 | 148 		filtersState.positionOffset = FauxScrollFrame_GetOffset(TradeSkillListScrollFrame) | 
| contrebasse@111 | 149 		filtersState.positionValue = TradeSkillListScrollFrameScrollBar:GetValue() | 
| contrebasse@111 | 150 | 
| contrebasse@107 | 151 		-- Save filters | 
| contrebasse@108 | 152 		filtersState.text = GetTradeSkillItemNameFilter() | 
| contrebasse@108 | 153 		filtersState.minLevel, filtersState.maxLevel = GetTradeSkillItemLevelFilter() | 
| contrebasse@107 | 154 		filtersState.hasMaterials = TradeSkillFrame.filterTbl.hasMaterials | 
| contrebasse@107 | 155 		filtersState.hasSkillUp = TradeSkillFrame.filterTbl.hasSkillUp | 
| contrebasse@107 | 156 		filtersState.subClassValue = TradeSkillFrame.filterTbl.subClassValue | 
| contrebasse@107 | 157 		filtersState.slotValue = TradeSkillFrame.filterTbl.slotValue | 
| contrebasse@24 | 158 | 
| contrebasse@107 | 159 		-- Remove all filters | 
| contrebasse@108 | 160 		SetTradeSkillItemNameFilter(nil) | 
| contrebasse@108 | 161 		SetTradeSkillItemLevelFilter(0, 0) | 
| contrebasse@107 | 162 		TradeSkillFrame.filterTbl.hasMaterials = false | 
| contrebasse@107 | 163 		TradeSkillFrame.filterTbl.hasSkillUp = false | 
| contrebasse@107 | 164 		TradeSkillFrame.filterTbl.subClassValue = -1 | 
| contrebasse@107 | 165 		TradeSkillFrame.filterTbl.slotValue = -1 | 
| contrebasse@107 | 166 		ApplyFilters() | 
| contrebasse@24 | 167 | 
| contrebasse@24 | 168 		-- Headers | 
| contrebasse@107 | 169 		headersState.headerName = headerName | 
| contrebasse@24 | 170 		for i = GetNumTradeSkills(), 1, -1 do		-- 1st pass, expand all categories | 
| contrebasse@82 | 171 			local skillName, skillType, _, isExpanded  = GetTradeSkillInfo(i) | 
| contrebasse@108 | 172 			if (skillType == "header") and skillName==headerName then | 
| contrebasse@108 | 173 				if not isExpanded then | 
| contrebasse@108 | 174 					ExpandTradeSkillSubClass(i) | 
| contrebasse@111 | 175 					tinsert(headersState,true) | 
| contrebasse@108 | 176 				else | 
| contrebasse@111 | 177 					tinsert(headersState,false) | 
| contrebasse@24 | 178 				end | 
| contrebasse@108 | 179 			end | 
| contrebasse@24 | 180 		end | 
| contrebasse@24 | 181 | 
| contrebasse@108 | 182 		stateSaved = true | 
| contrebasse@108 | 183 		A.blockScan = nil | 
| contrebasse@108 | 184 | 
| contrebasse@107 | 185 		--@todo Scroll down to the selected recipe | 
| contrebasse@107 | 186 		-- with TradeSkillSkillXX:Show() ? | 
| contrebasse@24 | 187 	end | 
| contrebasse@24 | 188 | 
| contrebasse@24 | 189 	function A.RestoreActiveFilters() | 
| contrebasse@107 | 190 		if not stateSaved then return end | 
| contrebasse@82 | 191 		A.blockScan = true | 
| contrebasse@82 | 192 | 
| contrebasse@107 | 193 		-- restore headers | 
| contrebasse@24 | 194 		for i = GetNumTradeSkills(), 1, -1 do | 
| contrebasse@107 | 195 			local skillName, skillType  = GetTradeSkillInfo(i) | 
| contrebasse@111 | 196 			if (skillType == "header") and skillName==headersState.headerName and tremove(headersState,1) then | 
| contrebasse@24 | 197 					CollapseTradeSkillSubClass(i) | 
| contrebasse@24 | 198 			end | 
| contrebasse@24 | 199 		end | 
| contrebasse@24 | 200 		wipe(headersState) | 
| contrebasse@107 | 201 | 
| contrebasse@107 | 202 		-- restore filters | 
| contrebasse@108 | 203 		SetTradeSkillItemNameFilter(filtersState.text) | 
| contrebasse@108 | 204 		SetTradeSkillItemLevelFilter(filtersState.minLevel, filtersState.maxLevel) | 
| contrebasse@107 | 205 		TradeSkillFrame.filterTbl.hasMaterials = filtersState.hasMaterials | 
| contrebasse@107 | 206 		TradeSkillFrame.filterTbl.hasSkillUp = filtersState.hasSkillUp | 
| contrebasse@107 | 207 		TradeSkillFrame.filterTbl.subClassValue = filtersState.subClassValue | 
| contrebasse@107 | 208 		TradeSkillFrame.filterTbl.slotValue = filtersState.slotValue | 
| contrebasse@107 | 209 		ApplyFilters() | 
| contrebasse@107 | 210 | 
| contrebasse@111 | 211 		-- Re set position | 
| contrebasse@111 | 212 		FauxScrollFrame_SetOffset(TradeSkillListScrollFrame,filtersState.positionOffset) | 
| contrebasse@111 | 213 		TradeSkillListScrollFrameScrollBar:SetValue(filtersState.positionValue) | 
| contrebasse@111 | 214 | 
| contrebasse@108 | 215 		stateSaved = nil | 
| contrebasse@108 | 216 		A.blockScan = nil | 
| contrebasse@107 | 217 | 
| contrebasse@108 | 218 		--@todo Scroll down to the selected recipe | 
| contrebasse@108 | 219 		-- with TradeSkillSkillXX:Show() ? | 
| contrebasse@24 | 220 	end | 
| contrebasse@24 | 221 end | 
| contrebasse@73 | 222 | 
| contrebasse@73 | 223 function A.isRecipeUnique(itemData) | 
| contrebasse@73 | 224 	local unique = true | 
| contrebasse@107 | 225 | 
| contrebasse@73 | 226 	-- Check if the item is made by only one recipe. If not, return | 
| contrebasse@73 | 227 	if #itemData>1 then | 
| contrebasse@73 | 228 		local spellLink | 
| contrebasse@73 | 229 		for _,v in ipairs(itemData) do | 
| contrebasse@73 | 230 			if not spellLink then | 
| contrebasse@73 | 231 				spellLink = v.spellLink | 
| contrebasse@73 | 232 			else | 
| contrebasse@73 | 233 				if v.spellLink ~= spellLink then | 
| contrebasse@73 | 234 					unique = nil | 
| contrebasse@73 | 235 					break | 
| contrebasse@73 | 236 				end | 
| contrebasse@73 | 237 			end | 
| contrebasse@73 | 238 		end | 
| contrebasse@73 | 239 	end | 
| contrebasse@107 | 240 | 
| contrebasse@73 | 241 	return unique | 
| contrebasse@73 | 242 end | 
| contrebasse@76 | 243 | 
| contrebasse@76 | 244 --[[ | 
| contrebasse@76 | 245 function A.isTradeskillUnique(itemData) | 
| contrebasse@110 | 246 	local tradeskillName = itemData[1].tradeskillName | 
| contrebasse@107 | 247 | 
| contrebasse@76 | 248 	-- Check if the item is made by only one recipe. If not, return | 
| contrebasse@76 | 249 	if #itemData>1 then | 
| contrebasse@76 | 250 		for _,v in ipairs(itemData) do | 
| contrebasse@110 | 251 			if v.tradeskillName ~= tradeskillName then | 
| contrebasse@110 | 252 				tradeskillName = nil | 
| contrebasse@76 | 253 				break | 
| contrebasse@76 | 254 			end | 
| contrebasse@76 | 255 		end | 
| contrebasse@76 | 256 	end | 
| contrebasse@89 | 257 | 
| contrebasse@110 | 258 	return tradeskillName | 
| contrebasse@76 | 259 end | 
| contrebasse@107 | 260 --]] |