v1, reasonably clean and usable.

His Dad [03-16-15 - 06:15]
v1, reasonably clean and usable.
Filename
GRID.lua
RTOffline.lua
ResearchTimer.lua
ResearchTimer.txt
Screenshots/InGame1.jpg
Screenshots/OnDesktop1.jpg
doc/offline_use.txt
lua/GRID.lua
lua/RTOffline.lua
lua/ResearchTimer.lua
diff --git a/GRID.lua b/GRID.lua
new file mode 100644
index 0000000..bf6a896
--- /dev/null
+++ b/GRID.lua
@@ -0,0 +1,241 @@
+
+local num_char   --track character number drawing for, for positioning
+
+function RT.GRID_Remove_Expired()					--- Prevent display for completely expired crafting chars.
+		for k, _ in pairs(RT.SV.data.Craft) do
+
+			if ((RT.SV.data.Craft[k][0].Simu_craft == 0 and
+				RT.SV.data.Craft[k][1].Simu_craft == 0 and
+				RT.SV.data.Craft[k][2].Simu_craft == 0))
+			then
+				RT.SV.data.Craft[k] = nil
+			end
+		end
+end
+
+function RT.GRID_Create()
+
+		RT.UI.GRID_TLW= WINDOW_MANAGER:CreateTopLevelWindow("RT_GRID_TLW")
+		RT.UI.GRID_TLW:SetClampedToScreen(false)
+		RT.UI.GRID_TLW:SetMouseEnabled(true)
+		RT.UI.GRID_TLW:SetDrawLayer(1)
+		RT.UI.GRID_TLW:SetHidden(true)
+
+
+		--/background
+		RT.UI.GRID_BD = WINDOW_MANAGER:CreateControlFromVirtual("RT_GRID_BD",RT.UI.GRID_TLW, "ZO_DefaultBackdrop")
+
+		-- Close Button
+		RT.UI.GRID_BTN = WINDOW_MANAGER:CreateControl("RT_GRID_BTN" , RT.UI.GRID_TLW, CT_BUTTON)
+		RT.UI.GRID_BTN:SetDimensions( 30 , 30 )
+		RT.UI.GRID_BTN:SetAnchor(TOPRIGHT,RT.UI.GRID_TLW,TOPRIGHT,5,-10)
+		RT.UI.GRID_BTN:SetState( BSTATE_NORMAL )
+--		RT.UI.GRID_BTN:SetMouseOverBlendMode(0)
+		RT.UI.GRID_BTN:SetNormalTexture("/esoui/art/buttons/decline_down.dds")
+		RT.UI.GRID_BTN:SetMouseOverTexture("/esoui/art/buttons/decline_up.dds")
+		RT.UI.GRID_BTN:SetHandler( "OnClicked" , function(self) RT.UI.GRID_TLW:SetHidden(true); end )
+
+		for k, _ in pairs(RT.SV.data.Craft) do
+			RT.GRID_Create_Character(k)
+		end
+end
+
+function RT.GRID_Create_Character(k)
+
+	local width = 360
+	local panelheight = 130  -- per character  at 100%
+	local prevcontrol, ctl_headers
+		ctl_headers = {}		-- controls at top of craft, indexed on craft
+		if (num_char == nil) then
+			num_char = 0
+		end
+
+				RT.UI.GRID_WD[k] = {}
+				-- Containing window for character data. We can then move it as a group
+				RT.UI.GRID_WD[k].panel = WINDOW_MANAGER:CreateTopLevelWindow("RT_GRID_"..k.."_panel")
+				RT.UI.GRID_WD[k].panel:SetParent(RT.UI.GRID_TLW)
+				RT.UI.GRID_WD[k].panel:SetAnchor(TOPRIGHT,RT.UI.GRID_TLW,TOPRIGHT,0,panelheight*num_char)
+				RT.UI.GRID_WD[k].panel:SetDimensions(width,panelheight)
+
+				-- label for character name
+				RT.UI.GRID_WD[k].label = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_label",RT.UI.GRID_WD[k].panel,CT_LABEL)
+				RT.UI.GRID_WD[k].label:SetFont(RT.font)
+				RT.UI.GRID_WD[k].label:SetDimensions(width,20)
+				RT.UI.GRID_WD[k].label:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k].panel,TOPLEFT,0,0)
+				RT.UI.GRID_WD[k].label:SetHorizontalAlignment(1)
+				RT.UI.GRID_WD[k].label:SetText(string.upper(k))
+
+				prevcontrol = RT.UI.GRID_WD[k].label	-- use this to anchor the next control, in this case the row of skill headers
+
+
+        -- Create section headers with dummy text for each skill
+				--blacksmithing
+				RT.UI.GRID_WD[k][0] = {}
+				RT.UI.GRID_WD[k][0][0]	= {}
+				RT.UI.GRID_WD[k][0][0]["BS_Icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_0_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
+				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetHidden(false)
+				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetDimensions(20,20)
+				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,0,5)  -- below
+				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetTexture("/esoui/art/icons/ability_smith_007.dds")
+
+				RT.UI.GRID_WD[k][0][0]["BS_Text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_0_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
+				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetHidden(false)
+				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetFont(RT.font)
+				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetDimensions(width/3,20)
+				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k][0][0]["BS_Icon"],TOPRIGHT,0,0)   -- Side by the previous
+				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetText(RT.L["Loading"])
+				ctl_headers[0] = RT.UI.GRID_WD[k][0][0]["BS_Icon"]
+
+				--Clothing
+				RT.UI.GRID_WD[k][1] = {}
+				RT.UI.GRID_WD[k][1][0] = {}
+				RT.UI.GRID_WD[k][1][0]["CL_Icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_1_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
+				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetHidden(false)
+				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetDimensions(20,20)
+				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,width/3,5)
+				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetTexture("/esoui/art/icons/ability_tradecraft_008.dds")
+
+				RT.UI.GRID_WD[k][1][0]["CL_Text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_1_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
+				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetHidden(false)
+				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetFont(RT.font)
+				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetDimensions(width/3,20)
+				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k][1][0]["CL_Icon"],TOPRIGHT,0,0)
+				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetText(RT.L["Loading"])
+				ctl_headers[1] = RT.UI.GRID_WD[k][1][0]["CL_Icon"]
+
+				--Woodworking
+				RT.UI.GRID_WD[k][2] = {}
+				RT.UI.GRID_WD[k][2][0] = {}
+				RT.UI.GRID_WD[k][2][0]["WO_Icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_2_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
+				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetHidden(false)
+				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetDimensions(20,20)
+				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,(width*2/3),5)
+				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetTexture("/esoui/art/icons/ability_tradecraft_009.dds")
+
+				RT.UI.GRID_WD[k][2][0]["WO_Text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_2_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
+				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetHidden(false)
+				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetFont(RT.font)
+				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetDimensions(width,20)
+				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k][2][0]["WO_Icon"],TOPRIGHT,0,0)
+				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetText(RT.L["Loading"])
+				ctl_headers[2] = RT.UI.GRID_WD[k][2][0]["WO_Icon"]
+
+				for craft_id = 0, 2,1 do    -- column
+					prevcontrol=ctl_headers[craft_id]   -- line up under this column
+
+					for simcraft = 1, 3,1 do
+
+						RT.UI.GRID_WD[k][craft_id][simcraft] = {}
+						-- item icon
+						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_"..craft_id.."_"..simcraft.."_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetHidden(true)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetDimensions(20,20)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,0,0)  --below
+						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetMouseEnabled(true)
+						prevcontrol= RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]
+
+
+						-- trait icon
+						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_"..craft_id.."_"..simcraft.."_trait",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetHidden(true)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetDimensions(20,20)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetAnchor(TOPLEFT,prevcontrol,TOPRIGHT,0,0)  --to right
+						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetMouseEnabled(true)
+
+
+						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetHandler("OnMouseExit", function (self)
+																					ZO_Tooltips_HideTextTooltip()
+																		end)
+						prevcontrol=RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]
+
+						-- text
+						RT.UI.GRID_WD[k][craft_id][simcraft]["text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_"..craft_id.."_"..simcraft.."_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetHidden(true)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetFont(RT.font)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetDimensions(360,20)
+						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetAnchor(TOPLEFT,prevcontrol,TOPRIGHT,0,0)   --to right
+
+						prevcontrol=RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]		-- set back to beginning of line
+					end
+				end
+				num_char = num_char+1
+				RT.UI.GRID_TLW:SetDimensions(width,RT.UI.GRID_WD[k].panel:GetHeight()*num_char)
+end
+
+function RT.GRID_Update(timestamp)
+        local  emp_start, em_finish
+		for k, _ in pairs(RT.SV.data.Craft) do
+			if ( (RT.SV.data.Craft[k][0].Simu_craft ~= 0 or RT.SV.data.Craft[k][1].Simu_craft ~= 0 or RT.SV.data.Craft[k][2].Simu_craft ~= 0)) then
+				for craft_id = 0, 2,1 do
+					if (RT.SV.data.Craft[k][craft_id].MaxResearch ~= nil ) then
+						local MaxResearch = RT.SV.data.Craft[k][craft_id].MaxResearch
+						local Simu_craft = RT.SV.data.Craft[k][craft_id].Simu_craft
+						if Simu_craft == MaxResearch then
+							emp_start = ""		--no highlighting
+							em_finish = ""
+						else
+							emp_start = "|cFF0000"
+							em_finish = "|r"
+						end
+						if (craft_id == 0) then
+						RT.UI.GRID_WD[k][craft_id][0]["BS_Text"]:SetText(" "..emp_start .. Simu_craft.." / "..MaxResearch .. em_finish)
+
+						elseif(craft_id == 1) then
+
+						RT.UI.GRID_WD[k][craft_id][0]["CL_Text"]:SetText(" "..emp_start .. Simu_craft.." / "..MaxResearch .. em_finish)
+						elseif(craft_id == 2) then
+						RT.UI.GRID_WD[k][craft_id][0]["WO_Text"]:SetText(" "..emp_start .. Simu_craft.." / "..MaxResearch .. em_finish)
+						end
+
+					end
+
+
+					for simcraft = 1, 3,1 do
+
+						if (RT.SV.data.Craft[k][craft_id].doing[simcraft] ~= nil)then
+
+
+							RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetHidden(false)
+							RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetTexture(RT.SV.data.Craft[k][craft_id].doing[simcraft]["Item_icon"])
+
+							RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetHidden(false)
+							RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetTexture(RT.SV.data.Craft[k][craft_id].doing[simcraft]["Trait_icon"])
+
+							local currenttimer = RT.SV.data.Craft[k][craft_id].doing[simcraft]["EndTimeStamp"] - timestamp - 1
+							RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetHidden(false)
+							if (currenttimer > 0) then
+							local tFormatted = FormatTimeSeconds(currenttimer, TIME_FORMAT_STYLE_COLONS, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
+							-- chop seconds
+								RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetText(string.sub(tFormatted, 1,string.len(tFormatted)-3))
+							else
+								RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetText(RT.L["Finished"])
+								RT.UI.GRID_WD[k].label:SetText("|cFF0000" .. string.upper(k) .."|r" )
+							end
+						end
+					end
+				end
+			end
+		end
+		RT.Set_Shortest()
+end
+function RT.Char_sort()    -- Produce a sorted list for display
+  RT.CharsInOrder = {}
+  for k, _ in pairs(RT.SV.data.Craft) do
+			table.insert(RT.CharsInOrder,k)
+  end
+
+  table.sort(RT.CharsInOrder, function (a,b) return RT.SV.data.Craft[a].shortest < RT.SV.data.Craft[b].shortest end)
+end
+
+-- move characters in grid
+function RT.GRID_Sort()
+    local panelheight
+	RT.Char_sort()
+    panelheight = RT.UI.GRID_WD[RT.CharsInOrder[1]].panel:GetHeight()  -- after scaling
+	for k, v  in ipairs(RT.CharsInOrder) do
+		RT.UI.GRID_WD[v].panel:SetAnchor(TOPLEFT,RT.UI.GRID_TLW,TOPLEFT,0,panelheight*(k-1))
+	end
+
+	RT.UI.GRID_TLW:SetHeight(table.getn(RT.CharsInOrder) * panelheight)
+ end
+EVENT_MANAGER:RegisterForEvent(RT.name, EVENT_ADD_ON_LOADED, RT.Init)
diff --git a/RTOffline.lua b/RTOffline.lua
new file mode 100644
index 0000000..6d31553
--- /dev/null
+++ b/RTOffline.lua
@@ -0,0 +1,86 @@
+--Licence: No restriction and no responsibility
+-- Version 1
+local dateformat = "%d/%m, %H:%M"
+
+require( "iuplua" )
+require( "iupluacontrols" )
+
+dofile "../../SavedVariables/ResearchTimer.lua"
+
+function dump(o)
+   if type(o) == 'table' then
+      local s = '{ '
+      for k,v in pairs(o) do
+         if type(k) ~= 'number' then k = '"'..k..'"' end
+         s = s .. '['..k..'] = ' .. dump(v) .. ','
+      end
+      return s .. '} '
+   else
+      return tostring(o)
+   end
+end
+
+
+for i,_ in pairs(ResearchTimer["Default"]) do -- Only one entry
+	myaccount = i
+end
+
+local allcraft = ResearchTimer["Default"][myaccount]["$AccountWide"]["Craft"]
+local donetimestr = ""
+
+-- print (dump (allcraft))
+
+--get all character names into an array
+local names = {}
+ for char, _ in pairs(allcraft) do
+    if allcraft[char]["shortest"] ~= nil  -- Some chars may have incorrect data. Just Skip.
+		then
+      table.insert (names, char)
+		end
+	end
+--Sort by soonest occuring. This is stored by the addon.
+table.sort(names, function (a,b) return allcraft[a].shortest < allcraft[b].shortest end)
+
+
+mat = iup.matrix {numcol=3, numlin= #names, numlin_visible = #names, numcol_visible=3, widthdef=200,heightdef=40}
+mat.resizematrix = "YES"
+mat.hidefocus = "YES"
+mat.multiline = "YES"
+mat.readonly = "YES"
+
+mat:setcell(0,0,"Character")
+mat:setcell(0,1,"Blacksmithing")
+mat:setcell(0,2,"Clothing")
+mat:setcell(0,3,"Woodworking")
+
+for k, char in ipairs(names) do
+mat:setcell(k,0,char)
+
+  for  thiscraft = 0,2  do  -- can't use ipairs as it starts from 0. can't use pairs, has "shortest" as key
+	  local itemstr = ""
+	  for _, thisitem in pairs(allcraft[char][thiscraft].doing) do
+
+		local itempadded = thisitem.Item_name .. "\\" .. thisitem.Trait_name .. string.rep("-", 40)
+		itempadded = string.sub(itempadded,1,26)
+		if (thisitem.EndTimeStamp <os.time())
+			then
+			donetimestr = "Finished"
+			else donetimestr = os.date(dateformat,thisitem.EndTimeStamp)
+		end
+		itemstr = itemstr .. itempadded    .. "  " .. donetimestr .. "\n"
+	  end
+
+	  mat:setcell(k,thiscraft+1, string.sub(itemstr, 1, string.len(itemstr)-1))  -- cut trailing newline
+  end
+end
+
+
+dlg = iup.dialog{iup.vbox{mat; margin="10x10"}}
+
+dlg:showxy(iup.CENTER, iup.CENTER)
+dlg.title="Research"
+
+if (iup.MainLoopLevel()==0) then
+  iup.MainLoop()
+end
+
diff --git a/ResearchTimer.lua b/ResearchTimer.lua
new file mode 100644
index 0000000..a8287e3
--- /dev/null
+++ b/ResearchTimer.lua
@@ -0,0 +1,156 @@
+-- Research Timer by hisdad; Based on CRT by Ato
+-- v1
+
+RT = {
+	name = "ResearchTimer",
+	font = "ZoFontGame",
+	cmdsetup = "/rt",
+	version = "v1",
+	playername = "",
+	Init_done = false,
+	UI = {},
+	SV={}
+}
+
+
+RT.UI.GRID_TLW = {}
+RT.UI.GRID_BD = {}
+RT.UI.GRID_WD = {}
+RT.UI.GRID_BTN = {}
+RT.SV.data = {}
+
+function RT.Collect_Data()
+	RT.Info_Research(CRAFTING_TYPE_BLACKSMITHING, 0)
+	RT.Info_Research(CRAFTING_TYPE_CLOTHIER, 1)
+	RT.Info_Research(CRAFTING_TYPE_WOODWORKING, 2)
+end
+
+
+function RT.Info_Research(craft_type,craft_id)
+	local Simu_craft = 0
+	local ResearchLines, ResearchTrait
+	local MaxResearch = GetMaxSimultaneousSmithingResearch(craft_type)
+	local nbtype = GetNumSmithingResearchLines(craft_type)
+
+	RT.SV.data.Craft[RT.playername][craft_id] = {}
+	RT.SV.data.Craft[RT.playername][craft_id].doing = {}
+	for ResearchLines = 1, nbtype, 1 do
+		local item_name, item_icon, numTraits, timeRequiredForNextResearchSecs = GetSmithingResearchLineInfo(craft_type, ResearchLines)
+		for ResearchTrait = 1, numTraits, 1 do
+			local duration, timeRemaining = GetSmithingResearchLineTraitTimes(craft_type, ResearchLines, ResearchTrait)
+
+			if (duration ~= nil and timeRemaining ~= nil) then
+				Simu_craft = Simu_craft + 1
+
+
+			local traitType, trait_description, _ = GetSmithingResearchLineTraitInfo(craft_type,ResearchLines,ResearchTrait)
+			local _, trait_name, trait_icon, _, _, _, _ = GetSmithingTraitItemInfo(traitType+1)
+
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft] = {}
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["EndTimeStamp"] = GetTimeStamp() + timeRemaining
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Item_name"] = string.sub(item_name, 1, 18)
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Item_icon"] = item_icon
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_stone"] = trait_name
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_icon"] = trait_icon
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_description"] = trait_description
+			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_name"]= GetString("SI_ITEMTRAITTYPE",traitType)
+			end
+		end
+	end
+	RT.SV.data.Craft[RT.playername][craft_id].MaxResearch = MaxResearch
+	RT.SV.data.Craft[RT.playername][craft_id].Simu_craft = Simu_craft
+end
+
+
+
+-- for each character, find the research completing soonest and set RT.SV.data.Craft[Char].shortest
+function RT.Set_Shortest()
+	local char,craft,shortest, remaining,v
+	for char,_ in pairs (RT.SV.data.Craft) do
+
+		shortest = 9999999999
+		for craft =0,2, 1 do
+			for _,v in pairs (RT.SV.data.Craft[char][craft].doing) do
+				remaining = v["EndTimeStamp"] - GetTimeStamp()
+				if shortest > remaining
+				then shortest = remaining
+				end
+			end
+		end
+		RT.SV.data.Craft[char].shortest = shortest
+	end
+end
+
+function RT.Research_started()  -- Triggered by Event
+		-- erase all data for this character
+		RT.SV.data.Craft[RT.playername] = {}
+		-- Collect new data
+		RT.Collect_Data()
+
+		if (RT.UI.GRID_WD[RT.playername] == nil) then
+			RT.GRID_Create_Character(RT.playername)
+		end
+		RT.Set_Shortest()
+		RT.UI.GRID_WD[RT.playername].label:SetText(string.upper(RT.playername)) -- remove highlighting
+end
+
+
+function RT.Init(eventCode, addOnName)
+
+	if(addOnName == RT.name) then
+	  RT.playername = GetUnitName("player")
+
+	    -- SavedVariables
+	  RT.SV.data = ZO_SavedVars:NewAccountWide(RT.name, 1, nil, nil )
+	  if RT.SV.data.Craft == nil
+		then RT.SV.data.Craft = {}
+			 RT.SV.data.Craft[RT.playername]= {}
+		else RT.GRID_Remove_Expired()
+	  end
+		RT.InitialiseLanguage()
+
+	    -- Slash commands
+	  SLASH_COMMANDS[RT.cmdsetup] = RT.CommandText_setup
+
+
+	    -- Create Keybinds
+	  ZO_CreateStringId("SI_BINDING_NAME_RT_toggleGRID", "Toggle Display")
+
+		local timestamp = GetTimeStamp()
+
+		RT.SV.data.Craft[RT.playername] = {}
+
+		RT.Collect_Data()
+		RT.GRID_Create()
+		RT.GRID_Update(timestamp)	--Manual Update
+		RT.GRID_Sort()
+		RT.Init_done = true
+
+		-- Only after initialised do we hook any other events.
+		EVENT_MANAGER:RegisterForEvent(RT.name, EVENT_SMITHING_TRAIT_RESEARCH_STARTED, RT.Research_started)
+		EVENT_MANAGER:RegisterForUpdate(RT.name, 1000, RT.Update)
+	end
+end
+function RT.Update()
+	if (RT.UI.GRID_TLW:IsHidden()) then return; end		-- Don't waste effort while its hidden.
+	local timestamp = GetTimeStamp()
+	RT.GRID_Update(timestamp)
+	RT.GRID_Sort()
+end
+
+
+function RT.toggleGRID()
+	if (RT.UI.GRID_TLW:IsHidden()) then
+	RT.GRID_Sort()
+	RT.UI.GRID_TLW:SetHidden(false)
+	else
+	RT.UI.GRID_TLW:SetHidden(true)
+	end
+end
+
+function RT.CommandText_setup()
+		RT.toggleGRID()
+end
+
+
+
diff --git a/ResearchTimer.txt b/ResearchTimer.txt
index d2be921..98c35f7 100644
--- a/ResearchTimer.txt
+++ b/ResearchTimer.txt
@@ -6,8 +6,8 @@



-lua\ResearchTimer.lua
-lua\grid.lua
+ResearchTimer.lua
+grid.lua

 xml\Bindings.xml

diff --git a/Screenshots/InGame1.jpg b/Screenshots/InGame1.jpg
new file mode 100644
index 0000000..3ba6bab
Binary files /dev/null and b/Screenshots/InGame1.jpg differ
diff --git a/Screenshots/OnDesktop1.jpg b/Screenshots/OnDesktop1.jpg
new file mode 100644
index 0000000..18be470
Binary files /dev/null and b/Screenshots/OnDesktop1.jpg differ
diff --git a/doc/offline_use.txt b/doc/offline_use.txt
index 778ce4e..d4ebb40 100644
--- a/doc/offline_use.txt
+++ b/doc/offline_use.txt
@@ -1,4 +1,4 @@
-The program "RTOffline.lua" will read the saved variables files and presents a grid on your windows desktop.
+The program "RTOffline.lua" will read the saved variables file and presents a grid on your windows desktop.
 To use it you need a copy of IUP for lua which you can download from here.

 The site page:  http://webserver2.tecgraf.puc-rio.br/iup/
@@ -6,37 +6,35 @@ download http://sourceforge.net/projects/iup/files/3.13/



-
-
 This is a zip archive which contains 2 versions of Lua with the IUP Dlls.
 It also contains some exe programs that we don't need.
 Unzip it and move stuff around if you want.
-The basic is in directory \IUP\Lua52  All else can be discarded.
+The necessary files are in  \IUP\Lua52  All else can be discarded.

 Lua52 contains a command line exe (lua52.exe) that has a console--good for debugging and a windows exe, wlua52.exe


-
+===Optional===
 Open RTOffline.lua in a text editor.
-
 Review this line.

 dateformat = "%d/%m, %H:%M"

-This formats the date display.
+This formats the date display. That's for day/month format.
+==============

-Edit this line
-local allcraft = ResearchTimer["Default"]["@MYACCOUNTNAME"]["$AccountWide"]["Craft"]
+Create a shortcut on your desktop for the lua52.exe.
+Edit its properties, change the "Start in" to the Addons/ResearchTimer Folder. You will probably need quotes around it.

-the part MYACCOUNTNAME  must be changed to your account name.
+Run it and you will get a lua console
+Type dofile "RTOffline.lua"

-Create a shortcut on your desktop for the lua52.exe.
-Edit its properties, change the "Start in" to the Addons/SavedVariables Folder.
+It should work fine. Otherwise it should give  something helpful as an error.

-Run. When it works ok, you can edit the shortcut to use wlua52.exe
+When it works ok, you can edit the shortcut to use wlua52.exe and put RTOffline.lua in the "target" field after wlua52.exe


+Feel free to edit. It's not rocket science.

-tada. Feel free to edit

 -Dad
diff --git a/lua/GRID.lua b/lua/GRID.lua
deleted file mode 100644
index 97c1e9b..0000000
--- a/lua/GRID.lua
+++ /dev/null
@@ -1,240 +0,0 @@
-
-local num_char   --track character number drawing for, for positioning
-local k,v
-
-function RT.GRID_Remove_Expired()					--- Prevent display for completely expired crafting chars.
-		for k, _ in pairs(RT.SV.data.Craft) do
-
-			if ((RT.SV.data.Craft[k][0].Simu_craft == 0 and
-				RT.SV.data.Craft[k][1].Simu_craft == 0 and
-				RT.SV.data.Craft[k][2].Simu_craft == 0))
-			then
-				RT.SV.data.Craft[k] = nil
-			end
-		end
-end
-
-function RT.GRID_Create()
-
-		RT.UI.GRID_TLW= WINDOW_MANAGER:CreateTopLevelWindow("RT_GRID_TLW")
-		RT.UI.GRID_TLW:SetClampedToScreen(false)
-		RT.UI.GRID_TLW:SetMouseEnabled(true)
-		RT.UI.GRID_TLW:SetDrawLayer(1)
-		RT.UI.GRID_TLW:SetHidden(true)
-
-
-		--/background
-		RT.UI.GRID_BD = WINDOW_MANAGER:CreateControlFromVirtual("RT_GRID_BD",RT.UI.GRID_TLW, "ZO_DefaultBackdrop")
-
-		-- Close Button
-		RT.UI.GRID_BTN = WINDOW_MANAGER:CreateControl("RT_GRID_BTN" , RT.UI.GRID_TLW, CT_BUTTON)
-		RT.UI.GRID_BTN:SetDimensions( 30 , 30 )
-		RT.UI.GRID_BTN:SetAnchor(TOPRIGHT,RT.UI.GRID_TLW,TOPRIGHT,5,-10)
-		RT.UI.GRID_BTN:SetState( BSTATE_NORMAL )
---		RT.UI.GRID_BTN:SetMouseOverBlendMode(0)
-		RT.UI.GRID_BTN:SetNormalTexture("/esoui/art/buttons/decline_down.dds")
-		RT.UI.GRID_BTN:SetMouseOverTexture("/esoui/art/buttons/decline_up.dds")
-		RT.UI.GRID_BTN:SetHandler( "OnClicked" , function(self) RT.UI.GRID_TLW:SetHidden(true); end )
-
-		for k, _ in pairs(RT.SV.data.Craft) do
-			RT.GRID_Create_Character(k)
-		end
-end
-
-function RT.GRID_Create_Character(k)
-  local x, y
-	local width = 360
-	local panelheight = 130  -- per character  at 100%
-	local prevcontrol, ctl_headers
-		ctl_headers = {}		-- controls at top of craft, indexed on craft
-		if (num_char == nil) then
-			num_char = 0
-		end
-
-				RT.UI.GRID_WD[k] = {}
-				-- Containing window for character data. We can then move it as a group
-				RT.UI.GRID_WD[k].panel = WINDOW_MANAGER:CreateTopLevelWindow("RT_GRID_"..k.."_panel")
-				RT.UI.GRID_WD[k].panel:SetParent(RT.UI.GRID_TLW)
-				RT.UI.GRID_WD[k].panel:SetAnchor(TOPRIGHT,RT.UI.GRID_TLW,TOPRIGHT,0,panelheight*num_char)
-				RT.UI.GRID_WD[k].panel:SetDimensions(width,panelheight)
-
-				-- label for character name
-				RT.UI.GRID_WD[k].label = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_label",RT.UI.GRID_WD[k].panel,CT_LABEL)
-				RT.UI.GRID_WD[k].label:SetFont(RT.font)
-				RT.UI.GRID_WD[k].label:SetDimensions(width,20)
-				RT.UI.GRID_WD[k].label:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k].panel,TOPLEFT,0,0)
-				RT.UI.GRID_WD[k].label:SetHorizontalAlignment(1)
-				RT.UI.GRID_WD[k].label:SetText(string.upper(k))
-
-				prevcontrol = RT.UI.GRID_WD[k].label	-- use this to anchor the next control, in this case the row of skill headers
-
-
-        -- Create section headers with dummy text for each skill
-				--blacksmithing
-				RT.UI.GRID_WD[k][0] = {}
-				RT.UI.GRID_WD[k][0][0]	= {}
-				RT.UI.GRID_WD[k][0][0]["BS_Icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_0_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
-				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetHidden(false)
-				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetDimensions(20,20)
-				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,0,5)  -- below
-				RT.UI.GRID_WD[k][0][0]["BS_Icon"]:SetTexture("/esoui/art/icons/ability_smith_007.dds")
-
-				RT.UI.GRID_WD[k][0][0]["BS_Text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_0_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
-				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetHidden(false)
-				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetFont(RT.font)
-				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetDimensions(width/3,20)
-				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k][0][0]["BS_Icon"],TOPRIGHT,0,0)   -- Side by the previous
-				RT.UI.GRID_WD[k][0][0]["BS_Text"]:SetText(RT.L["Loading"])
-				ctl_headers[0] = RT.UI.GRID_WD[k][0][0]["BS_Icon"]
-
-				--Clothing
-				RT.UI.GRID_WD[k][1] = {}
-				RT.UI.GRID_WD[k][1][0] = {}
-				RT.UI.GRID_WD[k][1][0]["CL_Icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_1_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
-				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetHidden(false)
-				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetDimensions(20,20)
-				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,width/3,5)
-				RT.UI.GRID_WD[k][1][0]["CL_Icon"]:SetTexture("/esoui/art/icons/ability_tradecraft_008.dds")
-
-				RT.UI.GRID_WD[k][1][0]["CL_Text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_1_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
-				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetHidden(false)
-				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetFont(RT.font)
-				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetDimensions(width/3,20)
-				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k][1][0]["CL_Icon"],TOPRIGHT,0,0)
-				RT.UI.GRID_WD[k][1][0]["CL_Text"]:SetText(RT.L["Loading"])
-				ctl_headers[1] = RT.UI.GRID_WD[k][1][0]["CL_Icon"]
-
-				--Woodworking
-				RT.UI.GRID_WD[k][2] = {}
-				RT.UI.GRID_WD[k][2][0] = {}
-				RT.UI.GRID_WD[k][2][0]["WO_Icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_2_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
-				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetHidden(false)
-				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetDimensions(20,20)
-				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,(width*2/3),5)
-				RT.UI.GRID_WD[k][2][0]["WO_Icon"]:SetTexture("/esoui/art/icons/ability_tradecraft_009.dds")
-
-				RT.UI.GRID_WD[k][2][0]["WO_Text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_2_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
-				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetHidden(false)
-				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetFont(RT.font)
-				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetDimensions(width,20)
-				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetAnchor(TOPLEFT,RT.UI.GRID_WD[k][2][0]["WO_Icon"],TOPRIGHT,0,0)
-				RT.UI.GRID_WD[k][2][0]["WO_Text"]:SetText(RT.L["Loading"])
-				ctl_headers[2] = RT.UI.GRID_WD[k][2][0]["WO_Icon"]
-
-				for craft_id = 0, 2,1 do    -- column
-					prevcontrol=ctl_headers[craft_id]   -- line up under this column
-
-					for simcraft = 1, 3,1 do
-
-						RT.UI.GRID_WD[k][craft_id][simcraft] = {}
-						-- item icon
-						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_"..craft_id.."_"..simcraft.."_icon",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetHidden(true)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetDimensions(20,20)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetAnchor(TOPLEFT,prevcontrol,BOTTOMLEFT,0,0)  --below
-						RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetMouseEnabled(true)
-						prevcontrol= RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]
-
-
-						-- trait icon
-						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_"..craft_id.."_"..simcraft.."_trait",RT.UI.GRID_WD[k].panel,CT_TEXTURE)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetHidden(true)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetDimensions(20,20)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetAnchor(TOPLEFT,prevcontrol,TOPRIGHT,0,0)  --to right
-						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetMouseEnabled(true)
-
-
-						RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetHandler("OnMouseExit", function (self)
-																					ZO_Tooltips_HideTextTooltip()
-																		end)
-						prevcontrol=RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]
-
-						-- text
-						RT.UI.GRID_WD[k][craft_id][simcraft]["text"] = WINDOW_MANAGER:CreateControl("RT_GRID_"..k.."_"..craft_id.."_"..simcraft.."_text",RT.UI.GRID_WD[k].panel,CT_LABEL)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetHidden(true)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetFont(RT.font)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetDimensions(360,20)
-						RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetAnchor(TOPLEFT,prevcontrol,TOPRIGHT,0,0)   --to right
-
-						prevcontrol=RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]		-- set back to beginning of line
-					end
-				end
-				num_char = num_char+1
-				RT.UI.GRID_TLW:SetDimensions(width,RT.UI.GRID_WD[k].panel:GetHeight()*num_char)
-end
-
-function RT.GRID_Update(timestamp)
-        local  emp_start, em_finish
-		for k, _ in pairs(RT.SV.data.Craft) do
-			if ( (RT.SV.data.Craft[k][0].Simu_craft ~= 0 or RT.SV.data.Craft[k][1].Simu_craft ~= 0 or RT.SV.data.Craft[k][2].Simu_craft ~= 0)) then
-				for craft_id = 0, 2,1 do
-					if (RT.SV.data.Craft[k][craft_id].MaxResearch ~= nil ) then
-						local MaxResearch = RT.SV.data.Craft[k][craft_id].MaxResearch
-						local Simu_craft = RT.SV.data.Craft[k][craft_id].Simu_craft
-						if Simu_craft == MaxResearch then
-							emp_start = ""		--no highlighting
-							em_finish = ""
-						else
-							emp_start = "|cFF0000"
-							em_finish = "|r"
-						end
-						if (craft_id == 0) then
-						RT.UI.GRID_WD[k][craft_id][0]["BS_Text"]:SetText(" "..emp_start .. Simu_craft.." / "..MaxResearch .. em_finish)
-
-						elseif(craft_id == 1) then
-
-						RT.UI.GRID_WD[k][craft_id][0]["CL_Text"]:SetText(" "..emp_start .. Simu_craft.." / "..MaxResearch .. em_finish)
-						elseif(craft_id == 2) then
-						RT.UI.GRID_WD[k][craft_id][0]["WO_Text"]:SetText(" "..emp_start .. Simu_craft.." / "..MaxResearch .. em_finish)
-						end
-
-					end
-
-
-					for simcraft = 1, 3,1 do
-
-						if (RT.SV.data.Craft[k][craft_id].doing[simcraft] ~= nil)then
-
-
-							RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetHidden(false)
-							RT.UI.GRID_WD[k][craft_id][simcraft]["item_icon"]:SetTexture(RT.SV.data.Craft[k][craft_id].doing[simcraft]["Item_icon"])
-
-							RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetHidden(false)
-							RT.UI.GRID_WD[k][craft_id][simcraft]["trait_icon"]:SetTexture(RT.SV.data.Craft[k][craft_id].doing[simcraft]["Trait_icon"])
-
-							local currenttimer = RT.SV.data.Craft[k][craft_id].doing[simcraft]["EndTimeStamp"] - timestamp - 1
-							RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetHidden(false)
-							if (currenttimer > 0) then
-								RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetText(RT.Converthms(currenttimer))
-							else
-								RT.UI.GRID_WD[k][craft_id][simcraft]["text"]:SetText(RT.L["Finished"])
-								RT.UI.GRID_WD[k].label:SetText("|cFF0000" .. string.upper(k) .."|r" )
-							end
-						end
-					end
-				end
-			end
-		end
-		RT.Set_Shortest()
-end
-function RT.Char_sort()    -- Produce a sorted list for display
-  RT.CharsInOrder = {}
-  for k, _ in pairs(RT.SV.data.Craft) do
-			table.insert(RT.CharsInOrder,k)
-  end
-
-  table.sort(RT.CharsInOrder, function (a,b) return RT.SV.data.Craft[a].shortest < RT.SV.data.Craft[b].shortest end)
-end
-
--- move characters in grid
-function RT.GRID_Sort()
-    local panelheight
-	RT.Char_sort()
-    panelheight = RT.UI.GRID_WD[RT.CharsInOrder[1]].panel:GetHeight()  -- after scaling
-	for k, v  in ipairs(RT.CharsInOrder) do
-		RT.UI.GRID_WD[v].panel:SetAnchor(TOPLEFT,RT.UI.GRID_TLW,TOPLEFT,0,panelheight*(k-1))
-	end
-
-	RT.UI.GRID_TLW:SetHeight(table.getn(RT.CharsInOrder) * panelheight)
- end
-EVENT_MANAGER:RegisterForEvent(RT.name, EVENT_ADD_ON_LOADED, RT.Init)
diff --git a/lua/RTOffline.lua b/lua/RTOffline.lua
deleted file mode 100644
index ab2e8f0..0000000
--- a/lua/RTOffline.lua
+++ /dev/null
@@ -1,85 +0,0 @@
---Licence: No restriction and no responsibility
-dateformat = "%d/%m, %H:%M"
-
-require( "iuplua" )
-require( "iupluacontrols" )
-
-dofile "C:/iup/prog/ResearchTimer.lua"
-
-function dump(o)
-   if type(o) == 'table' then
-      local s = '{ '
-      for k,v in pairs(o) do
-         if type(k) ~= 'number' then k = '"'..k..'"' end
-         s = s .. '['..k..'] = ' .. dump(v) .. ','
-      end
-      return s .. '} '
-   else
-      return tostring(o)
-   end
-end
-
-local i =0 k =0
-
-for i,_ in pairs(ResearchTimer["Default"]) do -- Only one entry
-	myaccount = i
-end
-
-local allcraft = ResearchTimer["Default"][myaccount]["$AccountWide"]["Craft"]
-
--- print (dump (allcraft))
-local summary = {} names = {}
- for char, _ in pairs(allcraft) do
-        if allcraft[char]["shortest"] ~= nil  -- Some chars may have incorrect data. Just Skip.
-		then
---		print (allcraft[char]["shortest"]);
-			summary[char] = {}
-			for craft, _ in pairs (allcraft[char]) do
-				summary[char][craft] = {}
-				summary[char][craft]["Finished"] = 0
-			end
-		table.insert (names, char)
-		end
-	end
-lines=  #names
-
-table.sort(names, function (a,b) return allcraft[a].shortest < allcraft[b].shortest end)
-
-
-mat = iup.matrix {numcol=3, numlin=lines, numlin_visible = lines, numcol_visible=3, widthdef=150,heightdef=40}
-mat.resizematrix = "YES"
-mat.hidefocus = "YES"
-mat.multiline = "YES"
-mat.readonly = "YES"
-
-mat:setcell(0,0,"Character")
-mat:setcell(0,1,"Blacksmithing")
-mat:setcell(0,2,"Clothing")
-mat:setcell(0,3,"Woodworking")
-
-for k, char in ipairs(names) do
-mat:setcell(k,0,char)
-
-  for  thiscraft = 0,2  do  -- cant use ipairs as it starts from 0. can't use pairs, has "shortest" as key
-	  local itemstr = "" itempadded = ""
-	  for thisdoing, thisitem in pairs(allcraft[char][thiscraft].doing) do
-		--print (thisitem.Item_name)
-		itempadded = thisitem.Item_name .. "\\" .. thisitem.Trait_name .. string.rep("-", 40)
-		itempadded = string.sub(itempadded,1,26)
-		itemstr = itemstr .. itempadded    .. "  " .. os.date(dateformat,thisitem.EndTimeStamp) .. "\n"
-	  end
-
-	  mat:setcell(k,thiscraft+1, string.sub(itemstr, 1, string.len(itemstr)-1))  -- cut trailing newline
-  end
-end
-
-
-dlg = iup.dialog{iup.vbox{mat; margin="10x10"}}
-
-dlg:showxy(iup.CENTER, iup.CENTER)
-dlg.title="Research"
-
-if (iup.MainLoopLevel()==0) then
-  iup.MainLoop()
-end
-
diff --git a/lua/ResearchTimer.lua b/lua/ResearchTimer.lua
deleted file mode 100644
index 1c713ce..0000000
--- a/lua/ResearchTimer.lua
+++ /dev/null
@@ -1,190 +0,0 @@
--- Research Timer by hisdad
--- v1
-
-RT = {
-	name = "ResearchTimer",
-	font = "ZoFontGame",
-	cmdsetup = "/rt",
-	version = "v1",
-	playername = "",
-	width = 100,
-	height = 80,
-	Init_done = false,
-	UI = {},
-	SV={}
-}
-
-
-RT.UI.GRID_TLW = {}
-RT.UI.GRID_BD = {}
-RT.UI.GRID_WD = {}
-RT.UI.GRID_BTN = {}
-RT.SV.data = {}
-
-function RT.Collect_Data()
-	RT.Info_Research(CRAFTING_TYPE_BLACKSMITHING, 0)
-	RT.Info_Research(CRAFTING_TYPE_CLOTHIER, 1)
-	RT.Info_Research(CRAFTING_TYPE_WOODWORKING, 2)
-end
-
-
-function RT.Info_Research(craft_type,craft_id)
-	local Simu_craft = 0
-	local ResearchLines, ResearchTrait
-	local MaxResearch = GetMaxSimultaneousSmithingResearch(craft_type)
-	local nbtype = GetNumSmithingResearchLines(craft_type)
-
-	RT.SV.data.Craft[RT.playername][craft_id] = {}
-	RT.SV.data.Craft[RT.playername][craft_id].doing = {}
-	for ResearchLines = 1, nbtype, 1 do
-		local item_name, item_icon, numTraits, timeRequiredForNextResearchSecs = GetSmithingResearchLineInfo(craft_type, ResearchLines)
-		for ResearchTrait = 1, numTraits, 1 do
-			local duration, timeRemaining = GetSmithingResearchLineTraitTimes(craft_type, ResearchLines, ResearchTrait)
-
-			if (duration ~= nil and timeRemaining ~= nil) then
-				Simu_craft = Simu_craft + 1
-
-
-			local traitType, trait_description, _ = GetSmithingResearchLineTraitInfo(craft_type,ResearchLines,ResearchTrait)
-			local _, trait_name, trait_icon, _, _, _, _ = GetSmithingTraitItemInfo(traitType+1)
-
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft] = {}
-	--		RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["PlayerName"] = RT.playername
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["EndTimeStamp"] = GetTimeStamp() + timeRemaining
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Item_name"] = string.sub(item_name, 1, 18)
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Item_icon"] = item_icon
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_stone"] = trait_name
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_icon"] = trait_icon
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_description"] = trait_description
-			RT.SV.data.Craft[RT.playername][craft_id].doing[Simu_craft]["Trait_name"]= GetString("SI_ITEMTRAITTYPE",traitType)
-			end
-		end
-	end
-	RT.SV.data.Craft[RT.playername][craft_id].MaxResearch = MaxResearch
-	RT.SV.data.Craft[RT.playername][craft_id].Simu_craft = Simu_craft
-end
-
-
-
--- for each character, find the research completing soonest and set RT.SV.data.Craft[Char].shortest
-function RT.Set_Shortest()
-	local char,craft,shortest, remaining,v
-	for char,_ in pairs (RT.SV.data.Craft) do
-
-		shortest = 9999999999
-		for craft =0,2, 1 do
-			for _,v in pairs (RT.SV.data.Craft[char][craft].doing) do
-				remaining = v["EndTimeStamp"] - GetTimeStamp()
-				if shortest > remaining
-				then shortest = remaining
-				end
-			end
-		end
-		RT.SV.data.Craft[char].shortest = shortest
-	end
-end
-
-function RT.Research_started()  -- Triggered by Event
-		-- erase all data for this character
-		RT.SV.data.Craft[RT.playername] = {}
-		-- Collect new data
-		RT.Collect_Data()
-
-		if (RT.UI.GRID_WD[RT.playername] == nil) then
-			RT.GRID_Create_Character(RT.playername)
-		end
-		RT.Set_Shortest()
-		RT.UI.GRID_WD[RT.playername].label:SetText(string.upper(RT.playername)) -- remove highlighting
-end
-
-
-function RT.Init(eventCode, addOnName)
-
-	if(addOnName == RT.name) then
-	  RT.playername = GetUnitName("player")
-
-	    -- SavedVariables
-	  RT.SV.data = ZO_SavedVars:NewAccountWide(RT.name, 1, nil, nil )
-	  if RT.SV.data.Craft == nil
-		then RT.SV.data.Craft = {}
-			 RT.SV.data.Craft[RT.playername]= {}
-		else RT.GRID_Remove_Expired()
-	  end
-		RT.InitialiseLanguage()
-
-	    -- Slash commands
-	  SLASH_COMMANDS[RT.cmdsetup] = RT.CommandText_setup
-
-      -- Default sort
-		RT.SortFunction = SortTimeA
-
-	    -- Create Keybinds
-	  ZO_CreateStringId("SI_BINDING_NAME_RT_toggleGRID", "|c96FF00Toggle GRID|r")
-
-		local timestamp = GetTimeStamp()
-
-		RT.SV.data.Craft[RT.playername] = {}
-
-		RT.Collect_Data()
-		RT.GRID_Create()
-		RT.GRID_Update(timestamp)	--Manual Update
-		RT.GRID_Sort()
-		RT.Init_done = true
-
-		-- Only after initialised do we hook any other events.
-		EVENT_MANAGER:RegisterForEvent(RT.name, EVENT_SMITHING_TRAIT_RESEARCH_STARTED, RT.Research_started)
-		EVENT_MANAGER:RegisterForUpdate(RT.name, 1000, RT.Update)
-	end
-end
-function RT.Update()
-	if (RT.UI.GRID_TLW:IsHidden()) then return; end		-- Don't waste effort while its hidden.
-	local timestamp = GetTimeStamp()
-	RT.GRID_Update(timestamp)
-	RT.GRID_Sort()
-end
-
-
-function RT.toggleGRID()
-	if (RT.UI.GRID_TLW:IsHidden()) then
-	RT.GRID_Sort()
-	RT.UI.GRID_TLW:SetHidden(false)
-	else
-	RT.UI.GRID_TLW:SetHidden(true)
-	end
-end
-
-function RT.Converthms(timesec)
-
-    local days = 0
-    local hours = 0
-    local minutes = 0
-    local seconds = 0
-    local humanDuration
-
-    local function extractIntegerUnits(sec, unitduration)
-        local units = math.floor(sec / unitduration)
-        return units, sec - (units * unitduration)
-    end
-
-
-    days, timesec = extractIntegerUnits(timesec, 60*60*24)
-    hours, timesec = extractIntegerUnits(timesec, 60*60)
-    minutes, seconds = extractIntegerUnits(timesec, 60)
-
-
-
-    humanDuration = string.format("%d:%02d", hours, minutes)
-        if (days > 0) then
-            humanDuration = string.format("%dd ", days)..humanDuration
-        end
-
-  return humanDuration
-end
--- local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
-
-function RT.CommandText_setup()
-		RT.toggleGRID()
-end
-
-
-