--[[
--
--	Fire Tree
--
--		An easy way of rendering structured data.
--
--		by Alexander Brazie, reviewed by Karl Isenberg (aka AnduinLothar)
--
--]]
 
FIRETREE_MAXTITLE_COUNT = 20;
FIRETREE_TITLE_HEIGHT = 16;
FIRETREE_EXPAND_INDENT = 16;
FIRETREE_COLOR_NUMBER = NORMAL_FONT_COLOR;
FIRETREE_COLOR_STRING = HIGHLIGHT_FONT_COLOR;
FIRETREE_COLOR_BOOLEAN = GRAY_FONT_COLOR;
FIRETREE_COLOR_NIL = RED_FONT_COLOR;
FIRETREE_COLOR_TABLE = RED_FONT_COLOR;
FIRETREE_COLOR_FUNCTION = GREEN_FONT_COLOR;
FIRETREE_COLOR_UNKNOWN = GRAY_FONT_COLOR;
FIRETREE_DEFAULT_FONT = ChatFontNormal;
FIRETREE_DEFAULT_HIGHLIGHT_COLOR = HIGHLIGHT_FONT_COLOR;

-- Debug Toggles
FIRETREE_DEBUG = false;

--[[
--
--	Using FireTree
--
--	Create a Frame which uses FireTreeTemplate. 
--
--	Usage:
--		Call either FireTree_LoadTable or FireTree_LoadEnhanced, 
--		Then call FireTree_UpdateFrame to draw to the screen.
--
--
--	Load a normal Lua table using
--	
--	FireTree_LoadTable(
--		getglobal("YourFrameName"), 
--		tableOfData,
--		functionTable,
--		keyOrder
--		);
--
--	functionTable may contain:
--		onClick - function called when the text is clicked
--			arguments to onClick are:
--				arg1 - table showing the parent hierarchy of the clicked item
--		onCheck - function called when the checkbox is checked or unchecked
--			arguments to onCheck are:
--				arg1 - check state (value or nil)
--				arg2 - table showing the parent hierarchy of the clicked item
--
--			returns:
--				true - the checkbox will be set
--				false - the checkbox will be unset
--				nil - set to whatever state was sent to it.
--
--	Load an enhanced (customized) table using:
--
--	FireTree_LoadEnhanced(
--		getglobal("YourFrameName"),
--		enhancedTable
--		);
--
--	enhancedTable is a table of numerically indexed elements. 
--		Each enhanced table entry may contain the following:
--
--		{
--			prefix - Extra field in front of title
--			prefixColor - Colour of field in front of title
--			title - the title text
--			titleColor - the color of the title 
--			right - the text bound to the right side
--			rightColor - the color of the right text
--
--			disabled - true if the text cannot be clicked.
--			
--			check - true if a checkbox exists, false if not
--			checked - true if the checkbox is checked, false if not
--			checkDisabled - true if the checkbox is disable, false if not
--
--			radio - uses radio artwork instead of checkbox artwork
--			radioSelected - true if the radio is active, false if not
--			radioDisabled - true if the radio button is disabled
--
--			onClick - function called when the text is clicked
--			onCheck - function called when the checkbox is checked or unchecked
--			onRadio - function called when the radio button is clicked
--
--			tooltip - tooltip text when the text is moused-over
--			checkTooltip - tooltip text when the checkbox is moused-over
--			radioTooltip - tooltip text when the radiobox is moused-over
--			expandTooltip - tooltip text when the expandbox is moused-over
--			
--			noTextIndent - the item will not indent children an extra amount 
--
--			children - a table of enhanced entrys
--			childrenOverride - true if the + should show up even if there are 0 children
--			collapsed - true if the child elements are collapsed(hidden)
--		}
--
--	Each FireTreeFrame has the following modifiable properties:
--		titleCount - the number of title(rows) shown in the tree
--		highlight - true if the frame will highlight the last clicked item
--		highlightSize - "long" or "short" (short is buggy)
--		
--		tooltip - a string which represents the name of the tooltip used
--		tooltipPlacement - "cursor","button" or "frame"
--		tooltipAnchor - a string which is any valid tooltip anchor
--
--		activeTable - the frame's activeTable
--		
--		collapseAllButton - true if the collapseAll button is shown
--
--		keyOrder is a list of keys to use, in the order you want to use them.
--]]

--[[ Load a generic table for the Frame ]]--
function FireTree_LoadTable(frame, data, funcTable, keyOrder, maxDepth)
	local newEnhancedTable = {};

	if ( not data ) then Sea.io.error("Attempt to send nil data to ", frame:GetName(), " from ", this:GetName()); end
	if ( not funcTable ) then funcTable = {}; end
	
	-- Since we can only load 2 levels of depth
	-- We simply parse the first set of keys/values
	if ( type(keyOrder) ~= "table" ) then 
		for k,v in pairs(data) do 
			local entry = FireTree_CreateEntry(k,v,funcTable);

			-- Set the tooltip
			entry.tooltip = nil; -- No tooltip!

			table.insert(newEnhancedTable, entry);
		end
	else
		for k,v in pairs(keyOrder) do 
			local entry = FireTree_CreateEntry(v,data[v],funcTable,nil,{data},maxDepth);

			-- Set the tooltip
			entry.tooltip = nil; -- No tooltip!

			table.insert(newEnhancedTable, entry);
		end
	end

	--[[ Load it ]]--
	FireTree_LoadEnhanced(frame, newEnhancedTable);
end

--[[ Loads an Enhanced (Complex) Table for the Frame ]]--
function FireTree_LoadEnhanced(frame, earthTable)
	if ( FireTree_CheckFrame(frame) and FireTree_CheckTable(earthTable) ) then
		frame.activeTable = earthTable;
		return true;
	else
		Sea.io.error("Invalid data in LoadEnhanced");
		return nil;
	end
	
end

--[[ Retrieves an Enhanced (Complex) Table from the Frame ]]--
function FireTree_GetEnhanced(frame)
	if (frame.activeTable) then 
		return frame.activeTable;
	end	
end


--[[ Updates the frame with values from the frame.activeTable object ]]--
function FireTree_UpdateFrame(frame)
	local flat = {};
	if ( not frame ) then 
		return;
	end

	-- Hide the highlight frame
	if ( getglobal(frame:GetName().."HighlightFrame") ) then
		getglobal(frame:GetName().."HighlightFrame"):Hide();
	end

	-- Check if there's a table
	if ( frame.activeTable ) then
		flat = FireTree_MakeFlatTable(frame.activeTable);
		local index = 0;
		
		if (frame.titleCount > FIRETREE_MAXTITLE_COUNT) then
			Sea.io.dprint(FIRETREE_DEBUG,frame.titleCount, " exceeds FIRETREE_MAXTITLE_COUNT (",FIRETREE_MAXTITLE_COUNT,")");
			frame.titleCount = FIRETREE_MAXTITLE_COUNT;
		end
		
		for id=1, frame.titleCount do 
			index = FauxScrollFrame_GetOffset(getglobal(frame:GetName().."ListScrollFrame")) + id;
			local value = flat[index];

			if ( value ) then 
				FireTree_AddItem(frame,value,id);
			else
				FireTree_ClearItem(frame,id);
			end

		end
		for id=frame.titleCount+1, FIRETREE_MAXTITLE_COUNT do 
			FireTree_ClearItem(frame,id);
		end
		Sea.io.dprint(FIRETREE_DEBUG,index,",",frame.titleCount);
		
	end
	
	local expandButton = getglobal(frame:GetName().."Expand");
	-- Toggles the collapseAllButton
	if ( frame.collapseAllButton ) then
		if ( expandButton ) then
			expandButton:Show();
		end		

		-- Shows or hides the artwork
		if ( frame.collapseAllArtwork ) then
			--getglobal(frame:GetName().."ExpandCollapseAllTabLeft"):SetTexture("Interface\\QuestFrame\\UI-QuestLogSortTab-Left");
			--getglobal(frame:GetName().."ExpandCollapseAllTabMiddle"):SetTexture("Interface\\QuestFrame\\UI-QuestLogSortTab-Middle");
			--getglobal(frame:GetName().."ExpandCollapseAllTabRight"):SetTexture("Interface\\QuestFrame\\UI-QuestLogSortTab-Right");
		else
			--getglobal(frame:GetName().."ExpandCollapseAllTabLeft"):SetTexture();
			--getglobal(frame:GetName().."ExpandCollapseAllTabMiddle"):SetTexture();
			--getglobal(frame:GetName().."ExpandCollapseAllTabRight"):SetTexture();
		end
	else
		if ( expandButton ) then
			expandButton:Hide();
		end
	end

	-- ScrollFrame update
	FauxScrollFrame_Update(getglobal(frame:GetName().."ListScrollFrame"), table.getn(flat), frame.titleCount, FIRETREE_TITLE_HEIGHT, nil, nil, nil, getglobal(frame:GetName().."HighlightFrame"), getglobal(frame:GetName().."HighlightFrame"):GetWidth(), getglobal(frame:GetName().."HighlightFrame"):GetHeight() );

end

--[[ Obtains an item from a GUI index ]]--
function FireTree_GetItemByID( frame, id ) 
	local nth = id + FauxScrollFrame_GetOffset(getglobal(frame:GetName().."ListScrollFrame"));
	local tableD = FireTree_MakeFlatTable(frame.activeTable);

	return tableD[nth];
end

--[[
--	Obtains a tooltip for a specific frame/id
--
--]]
function FireTree_GetTooltipText(frame, id, ttype)
	local item = FireTree_GetItemByID(frame,id);
	if ( item ) then
		local tooltip = "";
		if ( type(item.tooltip) == "function" ) then 
			tooltip = item.tooltip(item.value, ttype);
		else
			tooltip = item.tooltip;
		end

		if ( ttype == "CHECK" ) then 
			if ( type(item.checkTooltip) == "function" ) then 
				tooltip = item.checkTooltip(item.value, ttype);
			elseif ( type (item.checkTooltip) ~= "nil" ) then
				tooltip = item.checkTooltip;
			end
		elseif ( ttype == "RADIO" ) then 
			if ( type(item.radioTooltip) == "function" ) then 
				tooltip = item.radioTooltip(item.value, ttype);
			elseif ( type (item.radioTooltip) ~= "nil" ) then
				tooltip = item.radioTooltip;
			end
		end
		
		return tooltip;
	else
		return nil;
	end
end


--[[
--
--	Functions beyond this point are tool function and not meant for general use.
--
--	-Alex
--
--]]



--[[
--
--	FireTree_AddItem(
--		frame - the frame to add the item
--		item - the table containing the item values
--		i - the current index to be updated
--		depth - the number of recursions performed
--		)
--
--	Returns: 
--		i, total
--		i - the new i
--		total - the new total of non-collapsed tree items
--
--]]
function FireTree_AddItem(frame, item, i, depth) 
	if ( not i ) then i = 1; end
	if ( not depth ) then depth = 0; end

	if ( i > frame.titleCount ) then 
		-- Do nothing
		-- and FireTree_CheckItem(item)
	elseif ( FireTree_CheckFrame(frame) ) then
	
		-- If a item exits
		if ( item ) then
			local ldepth = item.depth-1;
			local pdepth = 0;
			local title = item.title; 

			local titleColor = nil;
			if ( type ( title ) == "function" ) then 
				title, titleColor = title();
			end
			if ( not titleColor ) then titleColor = item.titleColor; end
						
			Sea.io.dprint(FIRETREE_DEBUG,frame:GetName(),": ",i," ",title);

			if ( item.disabled ) then 
				getglobal(frame:GetName().."Title"..i.."Button"):Disable();
				getglobal(frame:GetName().."Title"..i.."Button"):SetDisabledTextColor(titleColor.r, titleColor.g, titleColor.b);
			else
				getglobal(frame:GetName().."Title"..i.."Button"):Enable();
			end
			
			-- Title
			if ( title ) then 
				getglobal(frame:GetName().."Title"..i):Show();
				if ( titleColor ) then 
					getglobal(frame:GetName().."Title"..i.."Button"):SetText(title);
					-- Inset																	
					getglobal(frame:GetName().."Title"..i.."Button"):SetTextColor(titleColor.r, titleColor.g, titleColor.b);
					
					getglobal(frame:GetName().."Title"..i.."Button").r = titleColor.r;
					getglobal(frame:GetName().."Title"..i.."Button").g = titleColor.g;
					getglobal(frame:GetName().."Title"..i.."Button").b = titleColor.b;
				else							
					getglobal(frame:GetName().."Title"..i.."Button"):SetText(title);
					getglobal(frame:GetName().."Title"..i.."Button"):SetTextColor(FIRETREE_COLOR_NUMBER.r,FIRETREE_COLOR_NUMBER.g,FIRETREE_COLOR_NUMBER.b);

					getglobal(frame:GetName().."Title"..i.."Button").r = FIRETREE_COLOR_NUMBER.r;
					getglobal(frame:GetName().."Title"..i.."Button").g = FIRETREE_COLOR_NUMBER.g;
					getglobal(frame:GetName().."Title"..i.."Button").b = FIRETREE_COLOR_NUMBER.b;
				end
				getglobal(frame:GetName().."Title"..i):SetWidth(getglobal(frame:GetName().."Title"..i):GetParent():GetWidth()-20);

				
			else
				getglobal(frame:GetName().."Title"..i.."Button"):Hide();	
			end

			-- Tag
			local rightText = item.right;
			local rightColor = nil;
			
			if ( type ( rightText ) == "function" ) then 
				rightText, rightColor = rightText();
			end			
			if ( not rightColor ) then rightColor = item.rightColor; end
			
			Sea.io.dprint(FIRETREE_DEBUG,frame:GetName(),": ",i," ",rightText);
			
			if ( rightText ) then 				
				getglobal(frame:GetName().."Title"..i.."Tag"):Show();
				if ( rightColor ) then 
					getglobal(frame:GetName().."Title"..i.."Tag"):SetText(rightText);
					getglobal(frame:GetName().."Title"..i.."Tag"):SetTextColor(rightColor.r, rightColor.g, rightColor.b);
					
					getglobal(frame:GetName().."Title"..i.."Tag").r = rightColor.r;
					getglobal(frame:GetName().."Title"..i.."Tag").g = rightColor.g;
					getglobal(frame:GetName().."Title"..i.."Tag").b = rightColor.b;
				else			
					getglobal(frame:GetName().."Title"..i.."Tag"):SetText(rightText);
					getglobal(frame:GetName().."Title"..i.."Tag"):SetTextColor(FIRETREE_COLOR_STRING.r,FIRETREE_COLOR_STRING.g,FIRETREE_COLOR_STRING.b);
					
					getglobal(frame:GetName().."Title"..i.."Tag").r = FIRETREE_COLOR_STRING.r;
					getglobal(frame:GetName().."Title"..i.."Tag").g = FIRETREE_COLOR_STRING.g;
					getglobal(frame:GetName().."Title"..i.."Tag").b = FIRETREE_COLOR_STRING.b;
				end

			else
				getglobal(frame:GetName().."Title"..i.."Tag"):Hide();
			end

			-- Title Prefix
			local prefix = item.prefix;
			local prefixColor = nil;

			if ( type ( prefix ) == "function" ) then 
				prefix, prefixColor = prefix();
			else
				prefixColor = item.prefixColor; 
			end

			if ( prefix ) then
				getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):Show();

				if ( prefixColor ) then
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):SetText(prefix);
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):SetTextColor(prefixColor.r, prefixColor.g, prefixColor.b);
					
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix").r = prefixColor.r;
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix").g = prefixColor.g;
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix").b = prefixColor.b;
				else			
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):SetText(prefix);
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):SetTextColor(FIRETREE_COLOR_STRING.r,FIRETREE_COLOR_STRING.g,FIRETREE_COLOR_STRING.b);
					
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix").r = FIRETREE_COLOR_STRING.r;
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix").g = FIRETREE_COLOR_STRING.g;
					getglobal(frame:GetName().."Title"..i.."ButtonPrefix").b = FIRETREE_COLOR_STRING.b;
				end
				-- use a FontString object to get the size of our prefix text in pixel.
				getglobal(frame:GetName().."Title"..i.."PrefixSize"):SetText( prefix )
				getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):SetWidth(getglobal(frame:GetName().."Title"..i.."PrefixSize"):GetStringWidth());
				getglobal(frame:GetName().."Title"..i.."PrefixSize"):SetText("")
			else
				getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):Hide();
			end

			-- Checkbox Text?
			if ( item.check ) then 
				-- Indent the check symbol
				getglobal(frame:GetName().."Title"..i.."Check"):SetPoint("LEFT",frame:GetName().."Title"..i,"LEFT",FIRETREE_EXPAND_INDENT*(ldepth)-2, 2 );

				getglobal(frame:GetName().."Title"..i.."Check"):Show();

				-- If might be checked...
				if ( item.checked ) then 
					getglobal(frame:GetName().."Title"..i.."Check"):SetChecked(1);
				else
					getglobal(frame:GetName().."Title"..i.."Check"):SetChecked(nil);
				end

				-- If its disabled...
				if ( item.checkDisabled ) then
					getglobal(frame:GetName().."Title"..i.."Check"):Disable();
				else
					getglobal(frame:GetName().."Title"..i.."Check"):Enable();
				end

				-- Indent
				ldepth = ldepth + 1;

			else
				getglobal(frame:GetName().."Title"..i.."Check"):Hide();
			end

			-- Radio Box?
			if ( item.radio ) then 
				-- Indent the check symbol
				getglobal(frame:GetName().."Title"..i.."Radio"):SetPoint("LEFT",frame:GetName().."Title"..i,"LEFT",FIRETREE_EXPAND_INDENT*(ldepth)-2, 2 );

				getglobal(frame:GetName().."Title"..i.."Radio"):Show();

				-- If might be checked...
				if ( item.radioSelected ) then 
					getglobal(frame:GetName().."Title"..i.."Radio"):SetChecked(1);
				else
					getglobal(frame:GetName().."Title"..i.."Radio"):SetChecked(nil);
				end

				-- If its disabled...
				if ( item.radioDisabled ) then
					getglobal(frame:GetName().."Title"..i.."Radio"):Disable();
				else
					getglobal(frame:GetName().."Title"..i.."Radio"):Enable();
				end

				-- Indent
				ldepth = ldepth + 1;

			else
				getglobal(frame:GetName().."Title"..i.."Radio"):Hide();
			end

			-- display the highlight
			if ( frame.highlight ) then
				-- Check if its the selected item
				if ( FireTree_GetSelected(frame) == item ) then 
					--- Highlight Sizes
					if ( frame.highlightSize == "short" ) then 						
						getglobal(frame:GetName().."HighlightFrame"):ClearAllPoints();
						getglobal(frame:GetName().."HighlightFrame"):SetPoint("TOPLEFT", frame:GetName().."Title"..i, "TOPLEFT", FIRETREE_EXPAND_INDENT*(ldepth), -1);
					else
						getglobal(frame:GetName().."HighlightFrame"):SetAllPoints(frame:GetName().."Title"..i);
					end
					
					-- If there's a highlight color
					if ( frame.highlightColor ) then
						getglobal(frame:GetName().."HighlightFrameHighlight"):SetVertexColor(frame.highlightColor.r,frame.highlightColor.g,frame.highlightColor.b);
					else
						getglobal(frame:GetName().."HighlightFrameHighlight"):SetVertexColor(FIRETREE_DEFAULT_HIGHLIGHT_COLOR.r,FIRETREE_DEFAULT_HIGHLIGHT_COLOR.g,FIRETREE_DEFAULT_HIGHLIGHT_COLOR.b);
					end

					-- Render the highlight
					getglobal(frame:GetName().."HighlightFrame"):Show();
				end					
			end

			-- all children items
			if ( item.children and (table.getn(item.children) > 0 or item.childrenOverride) ) then
				-- Indent the + symbol
				getglobal(frame:GetName().."Title"..i.."Expand"):SetPoint("TOPLEFT",frame:GetName().."Title"..i,"TOPLEFT",FIRETREE_EXPAND_INDENT*(ldepth) -2, 2 );
				getglobal(frame:GetName().."Title"..i.."Expand"):Enable(); 
				getglobal(frame:GetName().."Title"..i.."Expand"):Show(); 
				
				-- Ignore collapsed items
				if ( item.collapsed ) then 
					getglobal(frame:GetName().."Title"..i.."Expand"):SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
				else
					getglobal(frame:GetName().."Title"..i.."Expand"):SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up"); 
					getglobal(frame:GetName().."Title"..i.."Expand".."Highlight"):SetTexture("Interface\\Buttons\\UI-PlusButton-Hilight");
					
				end
			else
				getglobal(frame:GetName().."Title"..i.."Expand"):Hide(); 
				getglobal(frame:GetName().."Title"..i.."Expand"):Disable(); 
				getglobal(frame:GetName().."Title"..i.."Expand"):SetNormalTexture(""); 
				getglobal(frame:GetName().."Title"..i.."Expand".."Highlight"):SetTexture("");		
			end

			-- Indent the text further if its marked as indented
			if ( not item.noTextIndent ) then 
				ldepth = ldepth + 1;
			end

			-- Indent Prefix
			if ( item.prefix ) then
				getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):SetPoint("TOPLEFT",frame:GetName().."Title"..i,"TOPLEFT",( 8 + FIRETREE_EXPAND_INDENT * ldepth ), 0 );
				pdepth = 8 + getglobal(frame:GetName().."Title"..i.."ButtonPrefix"):GetWidth();
			end

			-- Indent the text
			local titleIndent = (ldepth * FIRETREE_EXPAND_INDENT) + pdepth;
			getglobal(frame:GetName().."Title"..i.."Button"):SetPoint("TOPLEFT",frame:GetName().."Title"..i,"TOPLEFT", titleIndent, 0 );
			getglobal(frame:GetName().."Title"..i.."Button"):SetWidth( getglobal(frame:GetName().."Title"..i):GetWidth() - titleIndent );
			
			-- Set the text width
			if ( item.right ) then
				local newWidth =  getglobal(frame:GetName().."Title"..i):GetWidth() - getglobal(frame:GetName().."Title"..i.."Tag"):GetStringWidth() - ldepth * FIRETREE_EXPAND_INDENT - 2;
				-- Ideally this should be changed so frame scrolls left/right, needs looking at.
				if (newWidth < 1) then
					newWidth = 1;
				end
				getglobal(frame:GetName().."Title"..i.."ButtonText"):SetWidth( newWidth );
			else
				local newWidth = getglobal(frame:GetName().."Title"..i):GetWidth() - ldepth * FIRETREE_EXPAND_INDENT - 2;
				-- Ideally this should be changed so frame scrolls left/right, needs looking at.
				if (newWidth < 1) then
					newWidth = 1;
				end
				getglobal(frame:GetName().."Title"..i.."ButtonText"):SetWidth( newWidth );
			end
		end
	end
	
	return i;
end

--[[ Clear's a Tree's Item ]]--
function FireTree_ClearItem(frame, i ) 
	if ( i > 0  and i <= FIRETREE_MAXTITLE_COUNT ) then
		getglobal(frame:GetName().."Title"..i):Hide();
		getglobal(frame:GetName().."Title"..i.."Tag"):Hide();
		getglobal(frame:GetName().."Title"..i.."Check"):Hide();
		getglobal(frame:GetName().."Title"..i.."Expand"):Disable(); 
		getglobal(frame:GetName().."Title"..i.."Expand"):SetNormalTexture(""); 
		getglobal(frame:GetName().."Title"..i.."Expand".."Highlight"):SetTexture("");		
	end
end


--[[ Makes a flat tree from the activeTable, skipping collapsed trees according to setting ]]--

function FireTree_MakeFlatTable(theTable, depth, ignoreCollapsed)
	if ( not depth ) then depth = 0; end
	if ( ignoreCollapsed == nil ) then ignoreCollapsed = true; end
	local flatTable = {};
	local myTable = theTable;
	local i = 0;

	-- If the table doesnt exist, then the flat table is empty
	if ( myTable == nil ) then 
		return {};
	end

	for k,v in pairs(myTable) do
		v.depth = depth;
		table.insert(flatTable, v);

		if ( v.children and (not v.collapsed or ignoreCollapsed == false ) ) then 
			local flatChildren = FireTree_MakeFlatTable(v.children, depth + 1, ignoreCollapsed);

			for k2,v2 in pairs(flatChildren) do
				table.insert(flatTable,v2);
			end		
		end
	end

	return flatTable;
end

--[[ Collapses a Tree ]]--
function FireTree_SetItemCollapsed( frame, id, state ) 
	local count = 0;
	local nth = id+FauxScrollFrame_GetOffset(getglobal(frame:GetName().."ListScrollFrame"));
	local myTable = FireTree_MakeFlatTable(frame.activeTable);

	if ( myTable[nth] ) then
		myTable[nth].collapsed = state;
	end

	FireTree_UpdateFrame(frame);
end

--[[ Set the selected ID ]]--
function FireTree_SetSelectedByID(frame,id)
	local nth = id+FauxScrollFrame_GetOffset(getglobal(frame:GetName().."ListScrollFrame"));
	local flat = FireTree_MakeFlatTable(frame.activeTable, nil, true);

	if ( flat[nth] ) then 
		frame.selected = flat[nth];
	else
		frame.selected = nil;
	end
end

--[[ Get the selected object or nil ]]--
function FireTree_GetSelected(frame)
	if ( frame.selected ) then 
		return frame.selected;
	end
	return nil;
end

--[[
--	Returns the number of nodes in a table counting .children tables
--]]
function FireTree_GetNodeCount( tableD, ignoreCollapsed )
	local count = 0;

	if ( tableD.children ) then 
		if ( ignoreCollapsed and tableD.collapsed ) then 
		else
			count = count + table.getn(tableD.children);
			for k,v in pairs(tableD.children) do 
				if ( v.children ) then 
					count = count + FireTree_GetNodeCount(v, ignoreCollapsed);
				end
			end
		end
	end

	return count;
end


--[[
--	Returns the number of nodes in a table counting .children tables
--]]
function FireTree_GetFullCount( tableD, ignoreCollapsed )
	local count = table.getn( tableD );

	for k,v in pairs(tableD) do 
		if ( v.children ) then 
			if ( v.collapsed and ignoreCollapsed ) then 
			else
				count = count + table.getn(v.children);
				for k2,v2 in pairs(v.children) do 
					if ( v2.children ) then 
						count = count + FireTree_GetNodeCount(v2, ignoreCollapsed);
					end
				end
			end
		end
	end

	return count;
end


--[[ Validates a Frame ]]--
function FireTree_CheckFrame(frame)
	if ( frame ) then 
		return true;	
	else
		Sea.io.error("Invalid frame passed to FireTree_CheckFrame");
		return nil;
	end
end

--[[ Validates a Table ]]--
function FireTree_CheckTable(data)
	if ( not data ) then 
		Sea.io.error("Data sent to FireTree is nil! Name:", this:GetName() );
		return false;
	end

	if ( type(data) ~= "table" ) then 
		Sea.io.error("Data sent to FireTree is not a table! Name:", this:GetName() );
		return false;
	end

	for k,v in pairs(data) do 
		--Something
		if ( type(k) ~= "number" ) then 
			Sea.io.error("Invalid index in data: ",this:GetName() );
			return false;
		end
	
		if ( FireTree_CheckItem(v) == false ) then
			Sea.io.error("Invalid item: ",k);
			return false;
		end
	end

	return true;
end

--[[ Validates a Table Item ]]--
function FireTree_CheckItem(item)
	if ( not item.title and not item.right ) then 
		Sea.io.error("No title or subtext provided: ",this:GetName() );
		return false;
	end

	-- Now subfunctioned, this may never be used.
	if ( not item.titleColor ) then 
		item.titleColor = FIRETREE_COLOR_STRING;
	end
		
	if ( not item.rightColor ) then 
		item.rightColor = FIRETREE_COLOR_STRING;
	end

	if ( item.children ) then 
		return FireTree_CheckTable(item.children);
	end
end	

--[[ Creates an Entry out of a Standard Table ]]--
function FireTree_CreateEntry(k,v,funcTable,parents,parentValues,maxDepth)
	local entry = {};

	-- Create the parent chain
	if ( not parents ) then
		parents = {};
	end

	-- Set the title portion
	if ( type(k) == "table" ) then 
		entry.title = FIRETREE_KEYWORD_TABLE;
		entry.titleColor = FIRETREE_COLOR_STRING;
	elseif ( type(k) == "function" ) then
		entry.title = FIRETREE_KEYWORD_FUNCTION;
		entry.titleColor = FIRETREE_COLOR_STRING;
	elseif ( type(k) == "nil" ) then 
		entry.title = FIRETREE_KEYWORD_NIL;
		entry.titleColor = FIRETREE_COLOR_NUMBER;
	elseif ( type(k) == "number" ) then 
		entry.title = "["..k.."]";
		entry.titleColor = FIRETREE_COLOR_NUMBER;
	elseif ( type(k) == "boolean" ) then 
		if ( k ) then 
			entry.title = "|".."true".."|";
		else
			entry.title = "|".."false".."|";
		end
		entry.titleColor = FIRETREE_COLOR_BOOLEAN;		
		
	elseif ( type(k) == "string" ) then 
		entry.title = k;
		entry.titleColor = FIRETREE_COLOR_STRING;
	else
		entry.title = FIRETREE_KEYWORD_UNKNOWN;
		entry.titleColor = FIRETREE_COLOR_UNKNOWN;
	end

	-- Set the secondary value
	if ( type(v) == "table" ) then
		--Check to make sure this isn't a recursively embedded table of one of its parents
		local recursiveTable;
		if ( not parentValues ) then
			parentValues = {};
		else
			for k2,v2 in pairs(parentValues) do 
				if (v2 == v) then
					recursiveTable = k2;
				end
			end
		end
		if (recursiveTable) then --or (table.getn(parents) >= 4) then
			-- Recursively embedded table, print the table trace from the top most table
			local parentString = FIRETREE_KEYWORD_RECURSIVE_TABLE;
			for k2,v2 in pairs(parents) do
				if k2 >= recursiveTable then
					break;
				end
				parentString = parentString.."."..v2;
			end
			--entry.right = FIRETREE_KEYWORD_RECURSIVE_TABLE;
			entry.right = parentString;
			entry.rightColor = FIRETREE_COLOR_TABLE;
		elseif (type(maxDepth) == "number") and (table.getn(parents) >= maxDepth) then
			-- Reached max tree depth, 
			entry.right = FIRETREE_KEYWORD_DEEP_TABLE;
			entry.rightColor = FIRETREE_COLOR_TABLE;
		else
			-- Normal table, evaluate its children
			entry.right = FIRETREE_KEYWORD_TABLE;
			entry.rightColor = FIRETREE_COLOR_TABLE;
			
			entry.children = {};
			-- Ooh, its a table! Parse its children.
			for k2,v2 in pairs(v) do 
				-- Create the parent hierarchy!
				local newParent = {};
				for k3,v3 in pairs(parents) do 
					table.insert(newParent, v3);
				end
				
				-- Add the current parent
				table.insert(newParent, k);
				table.insert(parentValues, v);
				
				-- Add kids
				local kid = FireTree_CreateEntry(k2,v2,funcTable,newParent,parentValues,maxDepth);
				table.insert(entry.children, kid);
			end
	
			entry.expandTooltip = FIRETREE_EXPAND_INFO..FireTree_GetNodeCount( entry );
		end
		
	elseif ( type(v) == "function" ) then
		entry.right = FIRETREE_KEYWORD_FUNCTION;
		entry.rightColor = FIRETREE_COLOR_FUNCTION;
	elseif ( type(v) == "nil" ) then 
		entry.right = FIRETREE_KEYWORD_NIL;
		entry.rightColor = FIRETREE_COLOR_NIL;
	elseif ( type(v) == "number" ) then 
		entry.right = v;
		entry.rightColor = FIRETREE_COLOR_NUMBER;
	elseif ( type(v) == "string" ) then 
		entry.right = '"'..v..'"';
		entry.rightColor = FIRETREE_COLOR_STRING;
	elseif ( type(v) == "boolean" ) then 
		if ( v ) then 
			entry.right = "true";
		else
			entry.right = "false";
		end
		entry.rightColor = FIRETREE_COLOR_BOOLEAN;
	else
		entry.right = FIRETREE_KEYWORD_UNKNOWN;
		entry.rightColor = FIRETREE_COLOR_UNKNOWN;
	end

	-- Set the functions
	if ( funcTable.onClick ) then
		entry.onClick = funcTable.onClick;
	end
	if ( funcTable.onCollapseClick ) then
		entry.onCollapseClick = funcTable.onCollapseClick;
	end
	if ( funcTable.onDoubleClick ) then
		entry.onDoubleClick = funcTable.onDoubleClick;
	end
	if ( funcTable.onCheck ) then
		entry.onCheck = funcTable.onCheck;
	end


	-- Set the value passed back to the function
	entry.value = {key=k,value=v,parent=parents};

	return entry;
end

--[[
--	HandleAction
--
--	Delegates particular actions to events
--
--]]
function FireTree_HandleAction(frame, id, action, data)
	Sea.io.dprint(FIRETREE_DEBUG, frame:GetName(),": ",id," [",action,"]");
	
	local update = true;
	if ( action == "CLICK_EXPAND" or action == "CLICK_COLLAPSE") then 
		if ( id > 0 ) then 
			local item = FireTree_GetItemByID(frame,id);
			local collapse = false;
			if ( not item.collapsed ) then 
				collapse = true;
			end		
			if ( item ) then 
				if ( item.onCollapseClick ) then
					local newCollapse = nil;
					newCollapse = item.onCollapseClick(collapse, item.value);
					
					if ( newCollapse ~= nil ) then 
						collapse = newCollapse;
					end
				end
			end

			FireTree_SetItemCollapsed(frame,id, collapse);
		else
			FireTree_CollapseAllToggle(frame);
		end
	elseif ( action == "CLICK_TEXT" ) then 
		if ( id > 0 ) then 
			local item = FireTree_GetItemByID(frame,id);
			if ( item ) then 
				if ( item.onClick ) then 
					item.onClick(item.value);
				end
			end
			
			-- Set the selection
			FireTree_SetSelectedByID(frame,id);
		end	
	elseif ( action == "DOUBLECLICK_TEXT" ) then 
		if ( id > 0 ) then 
			local item = FireTree_GetItemByID(frame,id);
			if ( item ) then 
				if ( item.onDoubleClick ) then 
					item.onDoubleClick(item.value);
				end
			end
			
			-- Set the selection
			FireTree_SetSelectedByID(frame,id);
		end	
	elseif ( action == "CLICK_CHECK" ) then 
		if ( id > 0 ) then 
			local item = FireTree_GetItemByID(frame,id);
			if ( item ) then
				local checked = nil;
				if ( item.onCheck ) then 
					checked = item.onCheck(data, item.value);
				end

				if ( checked == nil ) then 
					-- Set the checkbox state.
					item.checked = data;
				else
					item.checked = checked;
				end
			end
		end
	elseif ( action == "CLICK_RADIO" ) then 
		if ( id > 0 ) then 
			local item = FireTree_GetItemByID(frame,id);
			if ( item ) then 
				if ( item.onRadio ) then 
					item.onRadio(data, item.value);
				end

				-- Set the checkbox state.
				item.radioSelected = data;
			end
		end
	elseif ( action == "ENTER_TEXT" ) then 
		local tooltipText = FireTree_GetTooltipText(frame,id);
		FireTree_SetTooltip(frame, tooltipText);	
		update = false;
	elseif ( action == "ENTER_CHECK" ) then
		local tooltipText = FireTree_GetTooltipText(frame,id, "CHECK");
		FireTree_SetTooltip(frame, tooltipText);
		update = false;
	elseif ( action == "ENTER_RADIO" ) then
		local tooltipText = FireTree_GetTooltipText(frame,id, "RADIO");
		FireTree_SetTooltip(frame, tooltipText);
		update = false;
	elseif ( action == "ENTER_EXPAND" ) then 
		local tooltipText = FireTree_GetTooltipText(frame,id, "EXPAND");
		FireTree_SetTooltip(frame, tooltipText);
		update = false;
	elseif ( action == "LEAVE_TEXT" or action == "LEAVE_CHECK" or action == "LEAVE_EXPAND" ) then
		FireTree_HideTooltip(frame);
		update = false;
	end

	-- Prevent unnessecary re-draws
	if ( update ) then
		-- Update the gui
		FireTree_UpdateFrame( frame );
	end
end


--
--	Sets the location of the Tooltip
--
function FireTree_SetTooltip(frame, tooltipText) 
	if ( frame.tooltip ) then 
		local tooltip = getglobal(frame.tooltip);
		if ( tooltipText ) then 	
			-- Set the location of the tooltip
			if ( frame.tooltipPlacement == "cursor" ) then
				tooltip:SetOwner(UIParent,"ANCHOR_CURSOR");	
			elseif ( frame.tooltipPlacement == "button" ) then
				tooltip:SetOwner(this,frame.tooltipAnchor);	
			else
				tooltip:SetOwner(frame,frame.tooltipAnchor);				
			end

			tooltip:SetText(tooltipText, 0.8, 0.8, 1.0);
			tooltip:Show();	
		end
	end
end

--
--	Hides the location of the Tooltip
--
function FireTree_HideTooltip(frame)
	if ( frame.tooltip ) then 		
		getglobal(frame.tooltip):Hide();
		getglobal(frame.tooltip):SetOwner(UIParent, "ANCHOR_RIGHT");
	end
end

--[[
--	All Object Event Handlers are Below
--
--]]

--[[ MouseWheel Events ]]
function FireTree_OnMouseWheel(frameName, delta)
	local offset = FauxScrollFrame_GetOffset(getglobal(frameName.."ListScrollFrame"));
	local maxOffset = FireTree_GetFullCount( getglobal(frameName).activeTable, true) - getglobal(frameName).titleCount;
	local scrollbar = getglobal(frameName.."ListScrollFrameScrollBar")
	local min,max = scrollbar:GetMinMaxValues();

	if ( type(offset) == "number" ) then 
		local newVal = offset - delta;
		if ( newVal >= 0 and newVal <= maxOffset ) then
			scrollbar:SetValue(newVal/maxOffset*max);
			FauxScrollFrame_SetOffset(getglobal(frameName.."ListScrollFrame"), newVal );
			FireTree_UpdateFrame(getglobal(frameName));
		elseif ( newVal > maxOffset ) then 
			if ( maxOffset < 0 ) then 
				offset = 0;
				maxOffset = 1;
			else
				offset = maxOffset;
			end
			scrollbar:SetValue(offset/maxOffset*max);
			
			FauxScrollFrame_SetOffset(getglobal(frameName.."ListScrollFrame"), offset);
			FireTree_UpdateFrame(getglobal(frameName));
		end
	end
end

--[[ CheckButton Events ]]--
function FireTree_CheckButton_OnLoad()
	--this:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonDown", "RightButtonUp");
	this:RegisterForClicks("LeftButtonDown", "RightButtonDown");
end	
function FireTree_CheckButton_OnEnter()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"ENTER_CHECK", this:GetChecked());
end
function FireTree_CheckButton_OnLeave()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"LEAVE_CHECK", this:GetChecked());
end
function FireTree_CheckButton_OnClick()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"CLICK_CHECK", this:GetChecked());
end


--[[ CheckButton Events ]]--
function FireTree_RadioButton_OnLoad()
	--this:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonDown", "RightButtonUp");
	this:RegisterForClicks("LeftButtonDown", "RightButtonDown");
end	
function FireTree_RadioButton_OnEnter()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"ENTER_RADIO", this:GetChecked());
end
function FireTree_RadioButton_OnLeave()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"LEAVE_RADIO", this:GetChecked());
end
function FireTree_RadioButton_OnClick()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"CLICK_RADIO", this:GetChecked());
end

--[[ Expand Button Event Handlers ]]--
function FireTree_ExpandButton_OnLoad()
	--this:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonDown", "RightButtonUp");
	this:RegisterForClicks("LeftButtonDown", "RightButtonDown");
end

function FireTree_ExpandButton_OnEnter()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"ENTER_EXPAND");
end

function FireTree_ExpandButton_OnClick()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"CLICK_EXPAND");
end

function FireTree_ExpandButton_OnLeave()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"LEAVE_EXPAND");
end
function FireTree_ExpandButton_OnMouseWheel(delta)
	local frameName = this:GetParent():GetParent():GetName();
	FireTree_OnMouseWheel(frameName, delta);
end

--[[ Clicking on Text Event Handlers ]]--

function FireTree_Text_OnLoad()
	--this:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonDown", "RightButtonUp");
	this:RegisterForClicks("LeftButtonDown", "RightButtonDown");
end

function FireTree_Text_OnEnter()
	-- Highlights the 2ndary text on mouseover
	getglobal(this:GetParent():GetName().."Tag"):SetTextColor(HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b);

	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"ENTER_TEXT");	
end

function FireTree_Text_OnClick()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"CLICK_TEXT");
end

function FireTree_Text_OnDoubleClick()
	FireTree_HandleAction(this:GetParent():GetParent(),this:GetParent():GetID(),"DOUBLECLICK_TEXT");
end

function FireTree_ButtonFrame_OnMouseWheel(delta)
	local frameName = this:GetParent():GetName();
	FireTree_OnMouseWheel(frameName, delta);
end

function FireTree_Text_OnMouseWheel(delta)
	local frameName = this:GetParent():GetParent():GetName();
	FireTree_OnMouseWheel(frameName, delta);
end
function FireTree_Text_OnLeave()
	if (this:GetParent():GetID() ~= this:GetParent():GetParent().selectedId) then
		local button = getglobal(this:GetName());
		button:SetTextColor(button.r, button.g,button.b);
		local check = getglobal(this:GetParent():GetName().."Check");
		check:SetTextColor(check.r, check.g, check.b);
		local tag = getglobal(this:GetParent():GetName().."Tag");
		tag:SetTextColor(tag.r, tag.g,tag.b);
	end
	
	-- Hides the parent tooltip
	FireTree_HideTooltip(this:GetParent():GetParent());
end

--[[ Collapse All Button Event Handlers ]]--
function FireTree_CollapseAllButton_OnLoad()
	--this:RegisterForClicks("LeftButtonDown", "LeftButtonUp", "RightButtonDown", "RightButtonUp");
	local button = getglobal(this:GetName().."Button");
	local expand = getglobal(this:GetName().."Expand");
	
	button:RegisterForClicks("LeftButtonDown", "RightButtonDown");
	button:SetText(ALL);
	button:SetWidth(this:GetWidth());
	button:SetPoint("TOPLEFT", this:GetName(), "TOPLEFT", FIRETREE_EXPAND_INDENT, -2);

	button:SetScript("OnClick", FireTree_CollapseAllButton_OnClick);
	expand:SetScript("OnClick", FireTree_CollapseAllButton_Icon_OnClick);
	button:SetScript("OnEnter", FireTree_CollapseAllButton_OnEnter);
	expand:SetScript("OnEnter", FireTree_CollapseAllButton_Icon_OnEnter);
	button:SetScript("OnLeave", FireTree_CollapseAllButton_OnLeave);
	expand:SetScript("OnLeave", FireTree_CollapseAllButton_Icon_OnLeave);
end


function FireTree_CollapseAllButton_Icon_OnClick()
	FireTree_HandleAction(this:GetParent():GetParent():GetParent(),0,"CLICK_COLLAPSE");

end
function FireTree_CollapseAllButton_OnClick()
	FireTree_HandleAction(this:GetParent():GetParent():GetParent(),0,"CLICK_COLLAPSE");

end
function FireTree_CollapseAllButton_OnEnter()
end
function FireTree_CollapseAllButton_Icon_OnEnter()
end
function FireTree_CollapseAllButton_OnLeave()
end
function FireTree_CollapseAllButton_Icon_OnLeave()
end

--[[
--	Toggles the collapsed state of all trees.
--]]
function FireTree_CollapseAllToggle(frame)
	local count = 0;
	local myTable = FireTree_MakeFlatTable(frame.activeTable, nil, false);

	-- Check if they are all collapsed
	for k,v in pairs(myTable) do 
	   -- Count collapsed and entries. assume nil collapsed states are expanded.
		if ( v.collapsed ) then 
			count = count + 1;
		end
	end
	
	-- If they are all collapsed
	if ( count == table.getn(myTable) ) then 
		-- Expand them all
		for k,v in pairs(myTable) do 
			myTable[k].collapsed = false;
			if ( myTable[k].onCollapseClick ~= nil ) then
			   myTable[k].onCollapseClick( false, myTable[k].value );
			end
		end
		
		getglobal(frame:GetName().."Expand".."CollapseAllExpand"):SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up"); 		
	else
		-- Collapse them all
		for k,v in pairs(myTable) do
			myTable[k].collapsed = true;
			if ( myTable[k].onCollapseClick ~= nil ) then
			   myTable[k].onCollapseClick( true, myTable[k].value );
			end
		end

		getglobal(frame:GetName().."Expand".."CollapseAllExpand"):SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up");
	end

	FireTree_UpdateFrame(frame);
end


--[[ Frame Event handlers ]]--
function FireTree_Frame_OnLoad()
	--
	-- Sets the default object values
	-- 
	this.titleCount = FIRETREE_MAXTITLE_COUNT;
	this.highlight = true;
	this.highlightSize = "long"; 	-- Can also be "short" [Buggy]
	this.extraIndent = true; -- Indents child nodes once all the of the time

	-- Use any tooltip you'd like. I use my own
	this.tooltip = "GameTooltip";
	
	--
	-- Can be "button", "frame", "cursor"
	-- 
	this.tooltipPlacement = "cursor"; 	
	this.tooltipAnchor = "ANCHOR_RIGHT"; -- Can be any valid tooltip anchor
	this.activeTable = {};

	--
	-- Shows or hides the expand all button
	--
	this.collapseAllButton = true;
	this.collapseAllArtwork = false;

	-- Hide all buttons once
	for i=1,this.titleCount do
		getglobal(this:GetName().."Title"..i):Show();
	end
	for i=this.titleCount+1, FIRETREE_MAXTITLE_COUNT do
		getglobal(this:GetName().."Title"..i):Hide();
	end
end

function FireTree_Frame_OnShow()
	FireTree_UpdateFrame(this);
end

function FireTree_Frame_OnMouseWheel(delta)
	local frameName = this:GetName();
	FireTree_OnMouseWheel(frameName, delta);
end


--[[
--
--	Fire Tree Demo Code
--
--
--
--
function dt()
	local tree = {
		a = "a";
		b = "b";
		c = "c";
		d = "d";
		e = "e";
		f = {
			1,2,3,4,5,6,7,8;
			a={
				11,22,33,44,55;
			};
			b={
				66,77,88,99,110;
			};
		};

	};
	local eTree = { 
		{
			title="a";
			right="b";
			tooltip="Hail!";
			onClick = function(a) Sea.io.print(a); end;
			children = {
				{
					title="a's child";
					right="(some thing)";
					onClick = function(a) Sea.io.error(a); end;
					children = {
						{
							title="a's first grandkid";
							check=true;
							checked=true;
							onCheck = function(check) Sea.io.print(check) end;
							onClick = function( a ) Sea.io.print(a); end;
							children = {
								{
									check=true;
									checked=1;
									title="great grandkid";
									onClick = function( a ) Sea.io.error(a,"!") end;
								}
							};
						};
						{
							title="a's second grandkid";
							check=true;
							checked=true;
							checkDisabled=true;
							onCheck = function(check) Sea.io.print(check) end;
							onClick = function( a ) Sea.io.print(a); end;
							children = {
								{
									check=true;
									checked=1;
									title="great grandkid";
									onClick = function( a ) Sea.io.error(a,"!") end;
								}
							};
						};
					};
				};
				{
					title="a's child 2";
					right="(some other thing)";
					tooltip="Simon";
					onClick = function(a) Sea.io.error(a); end;
				};
				{
					title="a's child 3";
					right="(some other2 thing)";
					tooltip="Alvin";
					onClick = function(a) Sea.io.error(a); end;
				}
			};
		};
		{
			title="two";
			right="5";
			onClick = function(a) Sea.io.print(a); end;
			children = {
				{
					title="two's child";
					tooltip="Theodore";
					right="(some OTHER)";
					rightColor={r=1.0,g=.24,b=0};
					onClick = function(a) Sea.io.print(a); end;
				}
			};
		};
		
		{
			title="three";
			right="99 Bottles";
			onClick = function(a) Sea.io.print(a); end;
			children = {
				{
					title="three's child";
					right="(some third thing)";
					rightColor={r=1.0,g=.24,b=0};
					onClick = function(a) Sea.io.print(a); end;
				}
			};
		};
		
	};
	FireTree_LoadTable(
		getglobal("FireTree"), 
		tree,
		{
			onClick = function(a) Sea.io.printTable(a); end;
		},
		);
	FireTree_LoadEnhanced(
		getglobal("FireTree"), 
		eTree
		);
	FireTree_UpdateFrame(
		getglobal("FireTree")
		); 
end
]]
