Quantcast

Added items to filter menu and made them work.

Paul Schifferer [12-11-10 - 18:15]
Added items to filter menu and made them work.
Tweaks to the layout of skill items.
Made the filter status bar work.
Major performance improvement in window drawing (Cauldron is much smarter about when it needs to scan the skill list and draw the items).
Filename
CauldronMain.lua
CauldronMain.xml
CauldronMainUI.lua
CauldronTradeskill.lua
CauldronUtil.lua
diff --git a/CauldronMain.lua b/CauldronMain.lua
index 3a3957d..b99141b 100644
--- a/CauldronMain.lua
+++ b/CauldronMain.lua
@@ -24,6 +24,7 @@ Cauldron.vars = {
 	enabled = true,
 	showQueue = true,
 	inventory = {},
+	filterVersion = 300, -- TODO: @project-revision@,
 };

 Cauldron.libs = {};
@@ -601,7 +602,7 @@ function Cauldron:OnAchievementEarned()

 	-- update the achievement skill map
 	Cauldron:CreateAchievementSkillMap();
-	Cauldron:UpdateSkillList();
+-- TODO	Cauldron:UpdateSkillList();

 end

diff --git a/CauldronMain.xml b/CauldronMain.xml
index d1462be..f55da0f 100755
--- a/CauldronMain.xml
+++ b/CauldronMain.xml
@@ -116,7 +116,7 @@
 	</Frame>

     <!-- Template: Skill item (normal, collapsed) -->
-    <Button name="CauldronSkillItemNormalCollapsedFrameTemplate" inherits="CauldronSkillItemBaseFrameTemplate" virtual="true">
+    <Button name="CauldronSkillItemFrameTemplate" inherits="CauldronSkillItemBaseFrameTemplate" virtual="true">
 		<Layers>
 			<Layer level="OVERLAY">
 				<FontString name="$parentSkillName" inherits="GameFontNormal"
@@ -129,7 +129,7 @@
 					</Anchors>
 				</FontString>
 				<FontString name="$parentSkillInfo" inherits="GameFontNormalSmall"
-							text="(skill info)" justifyH="LEFT" justifyV="CENTER">
+							text="" justifyH="LEFT" justifyV="CENTER">
 					<Size x="250" y="12"/>
 					<Anchors>
 						<Anchor point="TOPLEFT">
@@ -218,6 +218,7 @@
 					<OnClick>
 						PlaySound("igMainMenuOptionCheckBoxOn");
 						Cauldron:FavoriteItemButton_OnClick(self);
+						Cauldron:info("updating skill list from favorites selection");
 						Cauldron:UpdateSkillList();
 					</OnClick>
 				</Scripts>
@@ -317,7 +318,7 @@
     			<Size x="110" y="37" />
     			<Anchors>
     				<Anchor point="TOPRIGHT">
-    					<Offset x="-140" y="0" />
+    					<Offset x="-90" y="0" />
     				</Anchor>
     			</Anchors>
     			<Layers>
@@ -330,21 +331,23 @@
 									<Offset x="20" y="0"/>
 								</Anchor>
 							</Anchors>
+							<Color r="1.0" g="1.0" b="0.0" />
 						</FontString>
 						<FontString name="$parentNumSkillUps" inherits="GameFontNormal"
-									justifyH="CENTER" justifyV="CENTER" text="0">
+									justifyH="CENTER" justifyV="CENTER" text="">
 							<Size x="16" y="18"/>
 							<Anchors>
 								<Anchor point="LEFT" relativeTo="$parentMiscInfo" relativePoint="LEFT">
 									<Offset x="50" y="-18"/>
 								</Anchor>
 							</Anchors>
+							<Color r="1.0" g="0.5" b="0.25" />
 						</FontString>
 						<FontString name="$parentCount" inherits="GameFontNormalLarge"
 									justifyH="CENTER" justifyV="CENTER">
 							<Size x="40" y="37"/>
 							<Anchors>
-								<Anchor point="RIGHT" relativeTo="$parentMiscInfo" relativePoint="RIGHT">
+								<Anchor point="LEFT" relativeTo="$parentNumSkillUps" relativePoint="RIGHT">
 									<Offset x="0" y="0"/>
 								</Anchor>
 							</Anchors>
@@ -369,12 +372,14 @@
     				<Frame>
     					<Size x="16" y="16" />
     					<Anchors>
-							<Anchor point="LEFT" relativeTo="$parentMiscInfo" relativePoint="LEFT">
+							<Anchor point="RIGHT" relativeTo="$parentNumSkillUps" relativePoint="LEFT">
 								<Offset x="34" y="0"/>
 							</Anchor>
     					</Anchors>
     					<Layers level="OVERLAY">
 							<Texture name="$parentNumSkillUpsIcon" file="Interface\TradeSkillFrame\UI-TradeSkill-Multiskill">
+								<Size x="16" y="16" />
+								<Color r="1.0" g="0.5" b="0.25" />
 							</Texture>
     					</Layers>
     				</Frame>
@@ -397,281 +402,6 @@
 		</Scripts>
     </Button>

-    <!-- Template: Skill item (normal, expanded) -->
-    <Button name="CauldronSkillItemNormalExpandedFrameTemplate" virtual="true">
-    	<Layers>
-			<Layer level="OVERLAY">
-				<FontString name="$parentSkillName" inherits="GameFontNormal"
-							text="(name)" justifyH="LEFT" justifyV="CENTER">
-					<Size x="250" y="12"/>
-					<Anchors>
-						<Anchor point="TOPLEFT">
-							<Offset x="62" y="-4"/>
-						</Anchor>
-					</Anchors>
-				</FontString>
-				<FontString name="$parentSkillCategory" inherits="GameFontNormalSmall"
-							text="(category)" justifyH="LEFT" justifyV="CENTER">
-					<Size x="250" y="12"/>
-					<Anchors>
-						<Anchor point="TOPLEFT">
-							<Offset x="62" y="-20"/>
-						</Anchor>
-					</Anchors>
-				</FontString>
-				<FontString name="$parentSkillCooldown" inherits="GameFontRedSmall"
-							text="(cooldown)" justifyH="RIGHT" nonSpaceWrap="true" maxLines="3"
-							hidden="true">
-					<Size x="75" y="50"/>
-					<Anchors>
-						<Anchor point="TOPRIGHT">
-							<Offset x="0" y="0"/>
-						</Anchor>
-					</Anchors>
-				</FontString>
-			</Layer>
-			<Layer level="HIGHLIGHT" setAllPoints="true">
-				<Texture file="Interface\QuestFrame\UI-QuestLogTitleHighlight" alphaMode="ADD">
-					<Color r="0.7" g="0.7" b="0.7" a="0.5" />
-				</Texture>
-			</Layer>
-    	</Layers>
-    	<Frames>
-    		<!--
-    		<Frame name="$parentSkillNameTooltipFrame">
-				<Size x="250" y="12"/>
-				<Anchors>
-					<Anchor point="TOPLEFT">
-						<Offset x="62" y="-4"/>
-					</Anchor>
-				</Anchors>
-				<Scripts>
-					<OnClick>
-						HandleModifiedItemClick(GetTradeSkillItemLink(self.skillIndex));
-						Cauldron:SkillItem_OnClick(self, button, down);
-					</OnClick>
-					<OnEnter>
-						GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
-						GameTooltip:SetTradeSkillItem(self.skillIndex);
-						CursorUpdate(self);
-					</OnEnter>
-					<OnLeave>
-						GameTooltip:Hide();
-						ResetCursor();
-					</OnLeave>
-					<OnUpdate>
-						if GameTooltip:IsOwned(self) then
-							GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
-							GameTooltip:SetTradeSkillItem(self.skillIndex);
-							CursorUpdate(self);
-						end
-						CursorOnUpdate(self);
-					</OnUpdate>
-				</Scripts>
-    		</Frame>
-    		-->
-			<Button name="$parentSkillIcon">
-				<Size x="37" y="37"/>
-				<Anchors>
-					<Anchor point="TOPLEFT">
-						<Offset x="24" y="-3"/>
-					</Anchor>
-				</Anchors>
-				<Layers>
-					<Layer level="ARTWORK">
-						<FontString name="$parentCount" inherits="NumberFontNormal" justifyH="RIGHT" hidden="false">
-							<Anchors>
-								<Anchor point="BOTTOMRIGHT">
-									<Offset x="-2" y="2"/>
-								</Anchor>
-							</Anchors>
-						</FontString>
-					</Layer>
-				</Layers>
-				<Scripts>
-					<OnLoad>
-                        self.isCompact = false;
-						-- self.hasItem = 1;
-					</OnLoad>
-					<OnClick>
-						HandleModifiedItemClick(GetTradeSkillItemLink(self.skillIndex));
-						Cauldron:SkillItem_OnClick(self, button, down);
-					</OnClick>
-					<OnEnter>
-						GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
-						GameTooltip:SetTradeSkillItem(self.skillIndex);
-						-- Cauldron:AppendToTooltip(GameTooltip, self.skillIndex);
-						CursorUpdate(self);
-					</OnEnter>
-					<OnLeave>
-						GameTooltip:Hide();
-						ResetCursor();
-					</OnLeave>
-					<OnUpdate>
-						if GameTooltip:IsOwned(self) then
-							GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
-							GameTooltip:SetTradeSkillItem(self.skillIndex);
-							CursorUpdate(self);
-						end
-						CursorOnUpdate(self);
-					</OnUpdate>
-				</Scripts>
-			</Button>
-			<Button name="$parentDiscloseButton" hidden="false" inherits="ClassTrainerSkillButtonTemplate">
-				<Size x="20" y="22"/>
-				<Anchors>
-					<Anchor point="RIGHT" relativeTo="$parentSkillIcon" relativePoint="LEFT">
-						<Offset x="0" y="0"/>
-					</Anchor>
-				</Anchors>
-				<Scripts>
-					<OnLoad>
-						self:SetText("");
-					</OnLoad>
-					<OnClick>
-						Cauldron:CollapseItemButton_OnClick(self);
-					</OnClick>
-				</Scripts>
-			</Button>
-			<CheckButton name="$parentFavoriteButton" hidden="false" inherits="UICheckButtonTemplate" text="">
-				<Size x="20" y="22"/>
-				<Anchors>
-					<Anchor point="TOPRIGHT">
-						<Offset x="0" y="0"/>
-					</Anchor>
-				</Anchors>
-				<Scripts>
-					<OnLoad>
-						self:SetScale(0.625);
-						self:SetText(Cauldron:LocaleString("Favorite?"));
-					</OnLoad>
-                	<OnEnter>
-						GameTooltip:SetOwner(self, "ANCHOR_RIGHT");
-						GameTooltip:ClearLines();
-						GameTooltip:AddLine(Cauldron:LocaleString("Mark this skill as a favorite"));
-						GameTooltip:Show();
-						CursorUpdate(self);
-                	</OnEnter>
-                	<OnLeave>
-                		GameTooltip:Hide();
-                		ResetCursor();
-                	</OnLeave>
-					<OnClick>
-						PlaySound("igMainMenuOptionCheckBoxOn");
-						Cauldron:FavoriteItemButton_OnClick(self);
-						Cauldron:UpdateSkillList();
-					</OnClick>
-				</Scripts>
-			</CheckButton>
-    		<Frame name="$parentReagents">
-    			<Size x="40" y="100" />
-				<Anchors>
-					<Anchor point="TOPLEFT" relativeTo="$parentSkillIcon" relativePoint="BOTTOMLEFT">
-						<Offset x="10" y="-3"/>
-					</Anchor>
-				</Anchors>
-    			<Layers>
-    				<Layer level="OVERLAY">
-    					<FontString name="$parentToolsInfo" inherits="GameFontNormal"
-    								text="(tools info)" justifyH="LEFT">
-    						<Size x="250" y="12" />
-							<Anchors>
-								<Anchor point="TOPLEFT">
-									<Offset x="0" y="0"/>
-								</Anchor>
-							</Anchors>
-							<Color r="1.0" g="1.0" b="1.0" />
-    					</FontString>
-    				</Layer>
-    			</Layers>
-    			<Frames>
-					<Button name="$parentItemDetail1" inherits="CauldronReagentDetailTemplate" id="1">
-						<Anchors>
-							<Anchor point="TOPLEFT" relativeTo="$parentToolsInfo" relativePoint="BOTTOMLEFT">
-								<Offset x="0" y="-2"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail2" inherits="CauldronReagentDetailTemplate" id="2">
-						<Anchors>
-							<Anchor point="LEFT" relativeTo="$parentItemDetail1" relativePoint="RIGHT">
-								<Offset x="5" y="0"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail3" inherits="CauldronReagentDetailTemplate" id="3">
-						<Anchors>
-							<Anchor point="TOP" relativeTo="$parentItemDetail1" relativePoint="BOTTOM">
-								<Offset x="0" y="-3"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail4" inherits="CauldronReagentDetailTemplate" id="4">
-						<Anchors>
-							<Anchor point="LEFT" relativeTo="$parentItemDetail3" relativePoint="RIGHT">
-								<Offset x="5" y="0"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail5" inherits="CauldronReagentDetailTemplate" id="5">
-						<Anchors>
-							<Anchor point="TOP" relativeTo="$parentItemDetail3" relativePoint="BOTTOM">
-								<Offset x="0" y="-3"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail6" inherits="CauldronReagentDetailTemplate" id="6">
-						<Anchors>
-							<Anchor point="LEFT" relativeTo="$parentItemDetail5" relativePoint="RIGHT">
-								<Offset x="5" y="0"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail7" inherits="CauldronReagentDetailTemplate" id="7">
-						<Anchors>
-							<Anchor point="TOP" relativeTo="$parentItemDetail7" relativePoint="BOTTOM">
-								<Offset x="0" y="-3"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-					<Button name="$parentItemDetail8" inherits="CauldronReagentDetailTemplate" id="8">
-						<Anchors>
-							<Anchor point="LEFT" relativeTo="$parentItemDetail7" relativePoint="RIGHT">
-								<Offset x="5" y="0"/>
-							</Anchor>
-						</Anchors>
-					</Button>
-    			</Frames>
-    		</Frame>
-    		<Frame name="$parentSelection" setAllPoints="true" enableMouse="true" hidden="true" frameStrata="LOW" frameLevel="1">
-    			<Layers>
-					<Layer level="OVERLAY">
-						<Texture name="$parentSelection" file="Interface\QuestFrame\UI-QuestLogTitleHighlight" alphaMode="ADD">
-							<Color r="0.5" g="0.5" b="0.5" a="0.5" />
-						</Texture>
-					</Layer>
-				</Layers>
-			</Frame>
-    	</Frames>
-    	<Scripts>
-    		<OnEnter>
-    			Cauldron:SkillItem_OnEnter(self);
-    		</OnEnter>
-    		<OnLeave>
-    			Cauldron:SkillItem_OnLeave(self);
-    		</OnLeave>
-    		<OnClick>
-                PlaySound("igMainMenuOptionCheckBoxOn");
-				HandleModifiedItemClick(GetTradeSkillRecipeLink(self.skillIndex));
-    			Cauldron:SkillItem_OnClick(self, button, down);
-    		</OnClick>
-    	</Scripts>
-    </Button>
-
-    <!-- Template: Skill item (compact, collapsed) -->
-
-    <!-- Template: Skill item (compact, expanded) -->
-
     <!-- Main UI frame -->
     <Frame name="CauldronFrame" inherits="ButtonFrameTemplate"
     	   toplevel="true" parent="UIParent"
@@ -908,6 +638,8 @@
 								TradeSkillUpdateFilterBar();
 								CloseDropDownMenus();
 								--]]
+								Cauldron:FilterDropDown_Reset();
+								Cauldron:UpdateStatus();
 							</OnClick>
 						</Scripts>
 					</Button>
diff --git a/CauldronMainUI.lua b/CauldronMainUI.lua
index f705669..d103610 100644
--- a/CauldronMainUI.lua
+++ b/CauldronMainUI.lua
@@ -1,6 +1,11 @@
 -- $Revision: 213 $
 -- Cauldron main user interface logic

+CAULDRON_SKILLITEM_COLLAPSED_HEIGHT = 37;
+CAULDRON_SKILLITEM_EXPANDED_HEIGHT = 100;
+
+CAULDRON_TRADESKILL_NAME = CURRENT_TRADESKILL;
+
 local L = LibStub("AceLocale-3.0"):GetLocale("Cauldron")

 -- CauldronUI = LibStub("AceAddon-3.0"):NewAddon("CauldronUI", "AceEvent-3.0", "AceConsole-3.0", "LibDebugLog-1.0")
@@ -52,36 +57,42 @@ function CauldronFilterDropDown_Initialize(self, level)

 	if level == 1 then

-		if not IsTradeSkillLinked() then
+		if not IsTradeSkillLinked() and not IsTradeSkillGuild() then
 			-- favorites
-			info.text = L["Favorites"];
-			info.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites or false;
-			info.isNotRadio = true;
-			info.keepShownOnClick = true;
+			local favorites = UIDropDownMenu_CreateInfo();
+			favorites.text = L["Favorites"];
+			favorites.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites or false;
+			favorites.isNotRadio = true;
+			favorites.keepShownOnClick = true;
 			-- tooltipTitle = L["Favorites"],
 			-- tooltipText = L["Display only favorite skills"],
-			info.func = function()
+			favorites.func = function()
 				Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites;
+						Cauldron:info("updating skill list from favorites filter");
 				Cauldron:UpdateSkillList();
+				Cauldron:UpdateStatus();
 			end;
 			-- arg1 = "favorite",
 			-- arg2 = "",
-			UIDropDownMenu_AddButton(info);
+			UIDropDownMenu_AddButton(favorites, level);

 			-- achievements
-			info.text = L["Achievements"];
-			info.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements or false;
-			info.isNotRadio = true;
-			info.keepShownOnClick = true;
+			local achievements = UIDropDownMenu_CreateInfo();
+			achievements.text = L["Achievements"];
+			achievements.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements or false;
+			achievements.isNotRadio = true;
+			achievements.keepShownOnClick = true;
 			-- tooltipTitle = L["Achievements"],
 			-- tooltipText = L["Display only skills for achievements"],
-			info.func = function()
+			achievements.func = function()
 				Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements;
+						Cauldron:info("updating skill list from achievements filter");
 				Cauldron:UpdateSkillList();
+				Cauldron:UpdateStatus();
 			end;
 			-- arg1 = "achievement",
 			-- arg2 = "",
-			UIDropDownMenu_AddButton(info);
+			UIDropDownMenu_AddButton(achievements, level);
 		end

 	--[==[
@@ -128,6 +139,211 @@ function CauldronFilterDropDown_Initialize(self, level)
 		info.hasArrow = true;
 		info.value = 2;
 		UIDropDownMenu_AddButton(info, level)
+
+		-- spacer
+		UIDropDownMenu_AddButton({
+			text = "",
+			notClickable = true,
+			isNotRadio = nil,
+			notCheckable = true,
+		}, level);
+
+		-- skill difficulty
+
+		local difficultyTitle = UIDropDownMenu_CreateInfo();
+		difficultyTitle.text = L["Difficulty"];
+		difficultyTitle.isTitle = true;
+		difficultyTitle.isNotRadio = nil;
+		difficultyTitle.notCheckable = true;
+		difficultyTitle.tooltipTitle = "";
+		difficultyTitle.tooltipText = "";
+		UIDropDownMenu_AddButton(difficultyTitle, level);
+
+		local difficultyOptimal = UIDropDownMenu_CreateInfo();
+		difficultyOptimal.text = L["Optimal"];
+--		textR = 1.0,
+--		textG = 1.0,
+--		textB = 1.0,
+		difficultyOptimal.isNotRadio = true;
+		difficultyOptimal.notCheckable = false;
+		difficultyOptimal.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.optimal;
+		difficultyOptimal.keepShownOnClick = false;
+		difficultyOptimal.tooltipTitle = L["Optimal"];
+		difficultyOptimal.tooltipText = L["Set whether items of this difficulty level should be shown"];
+		difficultyOptimal.func = function(arg1, arg2)
+			Cauldron:FilterDropDown_ToggleDifficulty(arg1);
+			Cauldron:UpdateStatus();
+		end;
+		difficultyOptimal.arg1 = "optimal";
+		difficultyOptimal.arg2 = "";
+		UIDropDownMenu_AddButton(difficultyOptimal, level);
+
+		local difficultyMedium = UIDropDownMenu_CreateInfo();
+		difficultyMedium.text = L["Medium"];
+--		textR = 1.0,
+--		textG = 1.0,
+--		textB = 1.0,
+		difficultyMedium.isNotRadio = true;
+		difficultyMedium.notCheckable = false;
+		difficultyMedium.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.medium;
+		difficultyMedium.keepShownOnClick = false;
+		difficultyMedium.tooltipTitle = L["Medium"];
+		difficultyMedium.tooltipText = L["Set whether items of this difficulty level should be shown"];
+		difficultyMedium.func = function(arg1, arg2)
+			Cauldron:FilterDropDown_ToggleDifficulty(arg1);
+			Cauldron:UpdateStatus();
+		end;
+		difficultyMedium.arg1 = "medium";
+		difficultyMedium.arg2 = "";
+		UIDropDownMenu_AddButton(difficultyMedium, level);
+
+		local difficultyEasy = UIDropDownMenu_CreateInfo();
+		difficultyEasy.text = L["Easy"];
+--		textR = 1.0,
+--		textG = 1.0,
+--		textB = 1.0,
+		difficultyEasy.isNotRadio = true;
+		difficultyEasy.notCheckable = false;
+		difficultyEasy.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.easy;
+		difficultyEasy.keepShownOnClick = false;
+		difficultyEasy.tooltipTitle = L["Easy"];
+		difficultyEasy.tooltipText = L["Set whether items of this difficulty level should be shown"];
+		difficultyEasy.func = function(arg1, arg2)
+			Cauldron:FilterDropDown_ToggleDifficulty(arg1);
+			Cauldron:UpdateStatus();
+		end;
+		difficultyEasy.arg1 = "easy";
+		difficultyEasy.arg2 = "";
+		UIDropDownMenu_AddButton(difficultyEasy, level);
+
+		local difficultyTrivial = UIDropDownMenu_CreateInfo();
+		difficultyTrivial.text = L["Trivial"];
+--		textR = 1.0,
+--		textG = 1.0,
+--		textB = 1.0,
+		difficultyTrivial.isNotRadio = true;
+		difficultyTrivial.notCheckable = false;
+		difficultyTrivial.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.trivial;
+		difficultyTrivial.keepShownOnClick = false;
+		difficultyTrivial.tooltipTitle = L["Trivial"];
+		difficultyTrivial.tooltipText = L["Set whether items of this difficulty level should be shown"];
+		difficultyTrivial.func = function(arg1, arg2)
+			Cauldron:FilterDropDown_ToggleDifficulty(arg1);
+			Cauldron:UpdateStatus();
+		end;
+		difficultyTrivial.arg1 = "trivial";
+		difficultyTrivial.arg2 = "";
+		UIDropDownMenu_AddButton(difficultyTrivial, level);
+
+		-- spacer
+		UIDropDownMenu_AddButton({
+			text = "",
+			notClickable = true,
+			isNotRadio = nil,
+			notCheckable = true,
+		}, level);
+
+		-- reagents availability
+
+		local reagentsTitle = UIDropDownMenu_CreateInfo();
+		reagentsTitle.text = L["Reagents"];
+		reagentsTitle.isTitle = true;
+		reagentsTitle.isNotRadio = nil;
+		reagentsTitle.notCheckable = true;
+		reagentsTitle.tooltipTitle = "";
+		reagentsTitle.tooltipText = "";
+		UIDropDownMenu_AddButton(reagentsTitle, level);
+
+		-- force check "normal" if the list is linked
+		if IsTradeSkillLinked() then
+			Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveAllReagents = false;
+			Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveKeyReagents = false;
+			Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveAnyReagents = false;
+		end
+
+		local normal = UIDropDownMenu_CreateInfo();
+		normal.text = L["Normal"];
+		normal.checked = Cauldron:ReagentsFilterNormalCheck();
+		normal.tooltipTitle = L["Reagents"];
+		normal.tooltipText = L["Display the normal list of skills"];
+		normal.func = function(arg1, arg2)
+			Cauldron:FilterDropDown_SetReagentFilter(arg1)
+			Cauldron:UpdateStatus();
+		end;
+		normal.arg1 = "normal";
+		normal.arg2 = "";
+		UIDropDownMenu_AddButton(normal, level);
+
+		if not IsTradeSkillLinked() then
+
+			local haveAllReagents = UIDropDownMenu_CreateInfo();
+			haveAllReagents.text = L["Have all"];
+			haveAllReagents.isNotRadio = nil;
+			haveAllReagents.notCheckable = false;
+			haveAllReagents.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveAllReagents;
+			haveAllReagents.tooltipTitle = L["Reagents"];
+			haveAllReagents.tooltipText = L["Set whether skills for which you have all the required reagents are shown in the list"];
+			haveAllReagents.func = function(arg1, arg2)
+				Cauldron:FilterDropDown_SetReagentFilter(arg1);
+				Cauldron:UpdateStatus();
+			end;
+			haveAllReagents.arg1 = "all";
+			haveAllReagents.arg2 = "";
+			UIDropDownMenu_AddButton(haveAllReagents, level);
+
+			local haveKeyReagents = UIDropDownMenu_CreateInfo();
+			haveKeyReagents.text = L["Have key"];
+			haveKeyReagents.isNotRadio = nil;
+			haveKeyReagents.notCheckable = false;
+			haveKeyReagents.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveKeyReagents;
+			haveKeyReagents.tooltipTitle = L["Reagents"];
+			haveKeyReagents.tooltipText = L["Set whether skills for which you have all key reagents (non-vendor available) are shown in the list"];
+			haveKeyReagents.func = function(arg1, arg2)
+				Cauldron:FilterDropDown_SetReagentFilter(arg1);
+				Cauldron:UpdateStatus();
+			end;
+			haveKeyReagents.arg1 = "key";
+			haveKeyReagents.arg2 = "";
+			UIDropDownMenu_AddButton(haveKeyReagents, level);
+
+			local haveAnyReagents = UIDropDownMenu_CreateInfo();
+			haveAnyReagents.text = L["Have any"];
+			haveAnyReagents.isNotRadio = nil;
+			haveAnyReagents.notCheckable = false;
+			haveAnyReagents.checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveAnyReagents;
+			haveAnyReagents.tooltipTitle = L["Reagents"];
+			haveAnyReagents.tooltipText = L["Set whether skills for which you have any reagents are shown in the list"];
+			haveAnyReagents.func = function(arg1, arg2)
+				Cauldron:FilterDropDown_SetReagentFilter(arg1);
+				Cauldron:UpdateStatus();
+			end;
+			haveAnyReagents.arg1 = "any";
+			haveAnyReagents.arg2 = "";
+			UIDropDownMenu_AddButton(haveAnyReagents, level);
+
+		end
+
+		-- spacer
+		UIDropDownMenu_AddButton({
+			text = "",
+			notClickable = true,
+			isNotRadio = nil,
+			notCheckable = true,
+		}, level);
+
+		-- reset item
+		local resetFilters = UIDropDownMenu_CreateInfo();
+		resetFilters.text = L["Reset filters"];
+		resetFilters.checked = false;
+		resetFilters.isNotRadio = nil;
+		resetFilters.notCheckable = true;
+		resetFilters.tooltipTitle = L["Reset filters"];
+		resetFilters.tooltipText = L["Reset all filters on the skills list"];
+		resetFilters.func = function(arg1, arg2)
+			Cauldron:FilterDropDown_Reset();
+			Cauldron:UpdateStatus();
+		end;
+		UIDropDownMenu_AddButton(resetFilters, level);

 	elseif level == 2 then
 		if UIDROPDOWNMENU_MENU_VALUE == 1 then
@@ -135,7 +351,9 @@ function CauldronFilterDropDown_Initialize(self, level)
 			local subslots = {};
 			for i,slot in pairs(slots) do
 				info.text = slot;
-				info.func =  function() --[[ TradeSkillSetFilter(0, i, "", slots[i]); --]] end;
+				info.func =  function()
+					-- TradeSkillSetFilter(0, i, "", slots[i]);
+				end;
 				info.notCheckable = true;
 				info.hasArrow = false;
 				UIDropDownMenu_AddButton(info, level);
@@ -145,7 +363,9 @@ function CauldronFilterDropDown_Initialize(self, level)
 			local subslots = {};
 			for i,subClass in pairs(subClasses) do
 				info.text = subClass;
-				info.func =  function() --[[ TradeSkillSetFilter(i, 0, subClasses[i], ""); --]] end
+				info.func =  function()
+					-- TradeSkillSetFilter(i, 0, subClasses[i], "");
+				end
 				info.notCheckable = true;
 				subslots  = { GetTradeSkillSubClassFilteredSlots(i) };
 				info.hasArrow = #subslots > 1;
@@ -158,7 +378,11 @@ function CauldronFilterDropDown_Initialize(self, level)
 		local subslots  = { GetTradeSkillSubClassFilteredSlots(UIDROPDOWNMENU_MENU_VALUE) };
 		for i,slot in pairs(subslots) do
 			info.text = slot;
-			info.func =  function() --[[ TradeSkillSetFilter(UIDROPDOWNMENU_MENU_VALUE, i, subClasses[UIDROPDOWNMENU_MENU_VALUE], subslots[i]); --]] end
+			info.func =  function()
+				--[[
+				TradeSkillSetFilter(UIDROPDOWNMENU_MENU_VALUE, i, subClasses[UIDROPDOWNMENU_MENU_VALUE], subslots[i]);
+				--]]
+			end;
 			info.notCheckable = true;
 			info.value = {UIDROPDOWNMENU_MENU_VALUE, i};
 			UIDropDownMenu_AddButton(info, level);
@@ -244,6 +468,7 @@ self:debug("frame show: "..tostring(CauldronQueueWindowFrame));
 		-- show main UI
 		ShowUIPanel(CauldronFrame);
 		SetPortraitToTexture(CauldronFramePortrait, GetTradeSkillTexture());
+		CauldronInputBox:SetNumber(1);
 		CauldronFrameTitleText:SetText(L["Cauldron"].." "..Cauldron.version);

 		-- show queue UI
@@ -252,6 +477,35 @@ self:debug("frame show: "..tostring(CauldronQueueWindowFrame));
 			SetPortraitToTexture(CauldronQueueWindowFramePortrait, GetTradeSkillTexture());
 			CauldronQueueWindowFrameTitleText:SetText(L["Queue"]);
 		end
+
+		-- check if the filter structure is out of date
+		--[[
+		if not Cauldron.db.global.version or (tonumber(Cauldron.db.global.version) < tonumber(Cauldron.vars.filterVersion)) then
+			Cauldron.db.global.version = tonumber(Cauldron.vars.filterVersion);
+			Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter = {
+				-- sorting
+				sortDefault = true,
+				sortAlpha = false,
+				sortDifficulty = false,
+				sortBenefit = false,
+
+				-- difficulty
+				optimal = true,
+				medium = true,
+				easy = true,
+				trivial = true,
+
+				-- favorites
+				favorites = false,
+				favoritesAtTop = false,
+
+				-- availability
+				haveAllReagents = false,
+				haveKeyReagents = false,
+				haveAnyReagents = false,
+			};
+		end
+		--]]

 	 	self:RegisterMessage("Cauldron_Update", "OnCauldronUpdate");

@@ -322,14 +576,18 @@ function Cauldron:Frame_Update()
 	-- update search text box
 	self:UpdateSearchText();

---[==[
-	-- TODO: update filter information
+	-- update filter information
 	self:UpdateStatus();
+--[==[
 	self:UpdateFilterDropDowns();
 --]==]

 	-- display list of matching skills
-	self:UpdateSkillList();
+--						Cauldron:info("updating skill list from frame update");
+	if CAULDRON_TRADESKILL_NAME ~= CURRENT_TRADESKILL then
+		CAULDRON_TRADESKILL_NAME = CURRENT_TRADESKILL;
+		self:UpdateSkillList();
+	end

 	-- display queue
 	self:UpdateQueue();
@@ -389,8 +647,12 @@ end

 function Cauldron:UpdateStatus()

-	local filters = {};
+	local skillName = CURRENT_TRADESKILL;
+	if IsTradeSkillLinked() then
+		skillName = "Linked-"..skillName;
+	end

+	local filters = {};
 	local filterTable = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter;
 	--[[
 							["sortAlpha"] = false, -- should the list be sorted alphabetically (mutually-exclusive to "sortDifficulty" and "sortBenefit")
@@ -406,40 +668,43 @@ function Cauldron:UpdateStatus()
 							["favorites"] = false, -- should only favorite skills be shown?
 	--]]
 	if filterTable.haveAllReagents then
-		table.insert(filters, "All reagents");
+		table.insert(filters, L["Have all"]);
 	elseif filterTable.haveKeyReagents then
-		table.insert(filters, "Key reagents");
+		table.insert(filters, L["Have key"]);
 	elseif filterTable.haveAnyReagents then
-		table.insert(filters, "Any reagents");
+		table.insert(filters, L["Have any"]);
 	end

 	local difficulties = {};
-	if filterTable.optimal then
-		table.insert(difficulties, "optimal");
+	if not filterTable.optimal then
+		table.insert(difficulties, "!"..L["Optimal"]);
 	end
-	if filterTable.medium then
-		table.insert(difficulties, "medium");
+	if not filterTable.medium then
+		table.insert(difficulties, "!"..L["Medium"]);
 	end
-	if filterTable.easy then
-		table.insert(difficulties, "easy");
+	if not filterTable.easy then
+		table.insert(difficulties, "!"..L["Easy"]);
 	end
-	if filterTable.trivial then
-		table.insert(difficulties, "trivial");
+	if not filterTable.trivial then
+		table.insert(difficulties, "!"..L["Trivial"]);
 	end
 	if #difficulties > 0 then
-		table.insert(filters, Cauldron:JoinStrings(difficulties, ","));
+		table.insert(filters, L["Difficulty"]..": "..Cauldron:JoinStrings(difficulties, ","));
 	end

 	if filterTable.favorites then
-		table.insert(filters, "Favorites");
+		table.insert(filters, L["Favorites"]);
+	end
+	if filterTable.achievements then
+		table.insert(filters, L["Achievements"]);
 	end

 	if #filters > 0 then
 		local statusText = Cauldron:JoinStrings(filters, "; ");
-		CauldronStatusText:SetText(statusText);
-		CauldronStatusText:Show();
+		CauldronStatusText:SetText(L["Filters"]..": "..statusText);
+		CauldronStatusFrame:Show();
 	else
-		CauldronStatusText:Hide();
+		CauldronStatusFrame:Hide();
 	end
 end

@@ -451,6 +716,11 @@ end

 function Cauldron:UpdateSkillList()

+	if Cauldron.updatingSkillList then
+		Cauldron:info("already updating skill list");
+		return;
+	end
+
 	local skillName = CURRENT_TRADESKILL;
 	if IsTradeSkillLinked() then
 		skillName = "Linked-"..skillName;
@@ -463,10 +733,14 @@ function Cauldron:UpdateSkillList()

 	local height = 0;

+	Cauldron.updatingSkillList = true;
+
 	-- iterate over the list of skills
+--	Cauldron:info("iterate over skill list of "..#skillList.." items");
 	for i, skillInfo in ipairs(skillList) do

 		local skillFrame = _G["CauldronSkillItem"..i];
+--		Cauldron:info("asked for skill item frame "..i.."; frame: "..tostring(skillFrame));

 		-- check if we have a frame for this position
 		if not skillFrame then
@@ -479,7 +753,8 @@ function Cauldron:UpdateSkillList()
 			skillFrame = CreateFrame("Button",
 									 "CauldronSkillItem"..i,
 									 CauldronSkillListScrollFrameScrollChild,
-									 "CauldronSkillItemNormalCollapsedFrameTemplate");
+									 "CauldronSkillItemFrameTemplate");
+--			Cauldron:info("created new skill item frame for "..i.."; frame: "..tostring(skillFrame));
 		end

 		--[[
@@ -498,8 +773,11 @@ function Cauldron:UpdateSkillList()
 		    -- hide the category info
 		    _G["CauldronSkillItem"..i.."SkillCategory"]:Hide();
 		else
+		--]]
 		    -- set the height of frame
-		    skillFrame:SetHeight(50);
+		    skillFrame:SetHeight(CAULDRON_SKILLITEM_COLLAPSED_HEIGHT);
+		    -- TODO: set height if expanded
+		--[[
 		    _G["CauldronSkillItem"..i.."SkillCooldown"]:SetHeight(50);

 		    -- rescale the icon frame
@@ -723,8 +1001,16 @@ function Cauldron:UpdateSkillList()

 		-- special skill-ups
 		frame = _G["CauldronSkillItem"..i.."MiscInfoNumSkillUpsIcon"];
+		Cauldron:info("skill ups icon frame: "..tostring(frame));
 		if frame then
-			-- TODO
+			if IsTradeSkillGuild() or (skillInfo.difficulty ~= "optimal") or (not skillInfo.numSkillUps or (skillInfo.numSkillUps < 1)) then
+				frame:Hide();
+				_G["CauldronSkillItem"..i.."MiscInfoNumSkillUps"]:Hide();
+			else
+				frame:Show();
+				_G["CauldronSkillItem"..i.."MiscInfoNumSkillUps"]:Show();
+				_G["CauldronSkillItem"..i.."MiscInfoNumSkillUps"]:SetText(skillInfo.numSkillUps);
+			end
 		end

 		-- achievement indicator
@@ -757,9 +1043,12 @@ function Cauldron:UpdateSkillList()

 	-- hide any remaining frames
 	local j = #skillList + 1;
+--	Cauldron:info("looking to hide remaining skill item frames: starting at "..j);
 	while true do
 		local frame = _G["CauldronSkillItem"..j];
+--		Cauldron:info("hiding skill item frame "..j.."; frame: "..tostring(frame));
 		if not frame then
+--			Cauldron:info("no frames left");
 			break;
 		end

@@ -769,6 +1058,8 @@ function Cauldron:UpdateSkillList()
 		j = j + 1;
 	end

+	Cauldron.updatingSkillList = false;
+
 end

 function Cauldron:UpdateButtons()
@@ -947,7 +1238,11 @@ function Cauldron:FilterDropDown_Initialize(level)
 		checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].options.compactView,
 		tooltipTitle = L["Compact"],
 		tooltipText = L["Display a compacted view of the skill list"],
-		func = function(arg1, arg2) Cauldron.db.realm.userdata[Cauldron.vars.playername].options.compactView = not Cauldron.db.realm.userdata[Cauldron.vars.playername].options.compactView; Cauldron:UpdateSkillList(); end,
+		func = function(arg1, arg2)
+			Cauldron.db.realm.userdata[Cauldron.vars.playername].options.compactView = not Cauldron.db.realm.userdata[Cauldron.vars.playername].options.compactView;
+						Cauldron:info("updating skill list from compact view filter (old)");
+			Cauldron:UpdateSkillList();
+		end,
 		arg1 = "compact",
 		arg2 = "",
 	};
@@ -960,7 +1255,11 @@ function Cauldron:FilterDropDown_Initialize(level)
 			checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites,
 			tooltipTitle = L["Favorites"],
 			tooltipText = L["Display only favorite skills"],
-			func = function(arg1, arg2) Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites; Cauldron:UpdateSkillList(); end,
+			func = function(arg1, arg2)
+				Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.favorites;
+						Cauldron:info("updating skill list from favorites filter (old)");
+				Cauldron:UpdateSkillList();
+			end,
 			arg1 = "favorite",
 			arg2 = "",
 		};
@@ -972,7 +1271,11 @@ function Cauldron:FilterDropDown_Initialize(level)
 			checked = Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements,
 			tooltipTitle = L["Achievements"],
 			tooltipText = L["Display only skills for achievements"],
-			func = function(arg1, arg2) Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements; Cauldron:UpdateSkillList(); end,
+			func = function(arg1, arg2)
+				Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.achievements;
+						Cauldron:info("updating skill list from achievements filter (old)");
+				Cauldron:UpdateSkillList();
+			end,
 			arg1 = "achievement",
 			arg2 = "",
 		};
@@ -1254,6 +1557,7 @@ function Cauldron:FilterDropDown_Reset()
 	Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter.haveAnyReagents = false;

 	-- update the UI
+						Cauldron:info("updating skill list from filter dropdown reset");
 	Cauldron:UpdateSkillList();

 end
@@ -1326,6 +1630,7 @@ function Cauldron:FilterDropDown_SetSort(info)
 	end

 	-- update the UI
+						Cauldron:info("updating skill list from sort change");
 	Cauldron:UpdateSkillList();

 end
@@ -1376,6 +1681,7 @@ function Cauldron:FilterDropDown_SetReagentFilter(info)
 	end

 	-- update the UI
+						Cauldron:info("updating skill list from reagent filter change");
 	Cauldron:UpdateSkillList();

 end
@@ -1390,6 +1696,7 @@ function Cauldron:FilterDropDown_ToggleDifficulty(info)
 	Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.filter[info.arg1] = not Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[CURRENT_TRADESKILL].window.filter[info.arg1];

 	-- update the UI
+						Cauldron:info("updating skill list from difficulty filter change");
 	Cauldron:UpdateSkillList();

 end
@@ -1507,6 +1814,7 @@ function Cauldron:InvSlotDropDown_SetSlot(info)
 --		end
 	end

+						Cauldron:info("updating skill list from slot filter change");
 	Cauldron:UpdateSkillList();

 	Cauldron:debug("InvSlotDropDown_SetSlot exit");
@@ -1622,6 +1930,7 @@ function Cauldron:CategoryDropDown_SetCategory(info)
 	end

 	-- update the UI
+						Cauldron:info("updating skill list from category filter change");
 	Cauldron:UpdateSkillList();

 end
@@ -1663,6 +1972,7 @@ function Cauldron:CollapseAllButton_OnClick(button)
 	-- Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.selected = 0;

 	-- update the UI
+						Cauldron:info("updating skill list from collapse all button click");
 	Cauldron:UpdateSkillList();

 end
@@ -1680,6 +1990,7 @@ function Cauldron:CollapseItemButton_OnClick(button)
 	Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.selected = skillInfo.index;

 	-- update the UI
+						Cauldron:info("updating skill list from collapse item button click");
 	Cauldron:UpdateSkillList();

 end
@@ -1717,6 +2028,7 @@ function Cauldron:SkillItem_OnClick(frame, button, down)
     end

 	-- update the UI
+						Cauldron:info("updating skill list from skill item selection");
 	Cauldron:UpdateSkillList();
 	Cauldron:UpdateButtons();

@@ -1744,6 +2056,7 @@ function Cauldron:TradeSkillFilter_OnTextChanged(frame)
 	Cauldron.db.realm.userdata[Cauldron.vars.playername].skills[skillName].window.search = text;

 	-- update the UI
+						Cauldron:info("updating skill list from tradeskill filter text change");
 	Cauldron:UpdateSkillList();

 end
diff --git a/CauldronTradeskill.lua b/CauldronTradeskill.lua
index a73beec..0569b25 100644
--- a/CauldronTradeskill.lua
+++ b/CauldronTradeskill.lua
@@ -76,6 +76,7 @@ function Cauldron:UpdateSkills()
 	if not Cauldron.scanningSkills then

 		Cauldron.scanningSkills = true;
+		Cauldron:Print("Scanning recipes...");

 		if IsTradeSkillLinked() then
 			skillName = "Linked-"..skillName;
@@ -150,10 +151,11 @@ function Cauldron:UpdateSkills()
 		--]]

 		local category = "";
+		local rescanCount = 0;

 		for i=1,GetNumTradeSkills() do
 	--		self:info("i="..tostring(i));
-			local name, difficulty, avail, expanded, verb = GetTradeSkillInfo(i);
+			local name, difficulty, avail, expanded, verb, numSkillUps = GetTradeSkillInfo(i);
 	--		self:debug("UpdateSkills: name="..name.."; difficulty="..difficulty.."; avail="..avail);

 			if name and difficulty ~= "header" then
@@ -178,6 +180,7 @@ function Cauldron:UpdateSkills()
 					skillDB.recipes[name].available = avail;
 					skillDB.recipes[name].minMade = minMade;
 					skillDB.recipes[name].maxMade = maxMade;
+					skillDB.recipes[name].numSkillUps = numSkillUps;

 					-- update reagent skill index
 					for _,r in ipairs(skillDB.recipes[name].reagents) do
@@ -211,6 +214,7 @@ function Cauldron:UpdateSkills()
 						['available'] = avail,
 						['minMade'] = minMade,
 						['maxMade'] = maxMade,
+						['numSkillUps'] = numSkillUps,

 						-- filter information
 						['slot'] = slot,
@@ -268,6 +272,7 @@ function Cauldron:UpdateSkills()
 							if not rescan then
 								-- Cauldron:error("Failed to retrieve reagent info; marking recipe for rescan: "..name);
 								Cauldron:MarkRecipeForRescan(skillDB, name);
+								rescanCount = rescanCount + 1;
 							end

 							--[[
@@ -326,6 +331,10 @@ function Cauldron:UpdateSkills()
 		end

 		Cauldron.scanningSkills = false;
+
+		if rescanCount > 0 then
+			Cauldron:Print(rescanCount.." recipes marked for rescan.");
+		end
 	end

 	--[[
diff --git a/CauldronUtil.lua b/CauldronUtil.lua
index d953fc0..b1cfe0b 100644
--- a/CauldronUtil.lua
+++ b/CauldronUtil.lua
@@ -334,7 +334,7 @@ function Cauldron:JoinStrings(strings, sep)
 	local joinedStr = "";

 	for i,str in ipairs(strings) do
-		if i > 0 then
+		if i > 1 then
 			joinedStr = joinedStr..sep;
 		end