Fix Styles not highlighting on start.

His Dad [12-12-14 - 19:54]
Fix Styles not highlighting on start.
Add .gitattributes to keep text files CRLF
Filename
.gitattributes
AIResearchGrid.lua
doc/changelog.txt
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..767a616
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# This project is staying on windows, don't mess with the CRLF
+*.txt  -text
+*.lua  -text
+*.jpg  binary
+
diff --git a/AIResearchGrid.lua b/AIResearchGrid.lua
index e94653e..d1d0a04 100644
--- a/AIResearchGrid.lua
+++ b/AIResearchGrid.lua
@@ -1,822 +1,823 @@
--- AI Research Grid Addon for Elder Scrolls Online
--- Author: Stormknight/LCAmethyst
--- "All" and "Relative"  functionality by His Dad
--- Dwemer Motif by rkuhnjr
-
-local _
-AIRG = {}
-
-AIRG.name = "AIResearchGrid"
-AIRG.version = "3.1.5"
-AIRG.initialised = false
-AIRG.processing = false
-AIRG.all = " #ALL"  -- Default displayname for Virtual character, overrwritten by Localised version
-AIRG.ShowRelative = false  -- State of Button
-AIRG.relative= {}
-AIRG.L = {}   -- declare language strings
-
--- Set-up the defaults options for saved variables.
-AIRG.defaults = {
-    data        = {},
-    styles      = {},
-    showMotifs = true,
-}
-
-
-function AIRG.PlayerActivated()
-        -- somehow somewhere it sometimes happens that the data is not correct completely for whatever reason
-        -- so we force a reload of the current character data when we are actually loaded into the world.
-  AIRG.PopulateMatrix()
-  AIRG.PopulateStyleData()
-  AIRG.PopulateAll()  -- do last
-
-end
-
-function AIRG.ToggleMainWindow()
-    if (AIResearchGrid:IsHidden()) then
-        AIRG.OnCraftSelected()              -- Redisplay data for the current profession
-        SetGameCameraUIMode(true)	        -- Enable mouse pointer
-        AIResearchGrid:SetHidden(false)     -- Display the addon
-        AIRG.OnCharacterSelect()
-    else
-        SetGameCameraUIMode(false)	        -- Enable mouse pointer
-        AIResearchGrid:SetHidden(true)      -- Display the addon
-    end
-end -- AIRG.ToggleMainWindow
-
--- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_STARTED
--- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
-function AIRG.ResearchStarted(eventCode, craftingSkillType, researchLineIndex, traitIndex)
-    AIRG.PopulateMatrix()
-    AIRG.PopulateAll()
-    -- TO DO: If it's visible, invoke a redisplay
-    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
-end -- AIRG.ResearchStarted
-
--- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED
--- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
-function AIRG.ResearchCompleted()
-    AIRG.PopulateMatrix()
-    AIRG.PopulateAll()
-    -- TO DO: If it's visible, invoke a redisplay
-    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
-end -- AIRG.ResearchEnded
-
-function AIRG.StyleLearned(eventCode, styleIndex)
-    AIRG.PopulateStyleData()
-    AIRG.DisplayStyles()
-    AIRG.PopulateAll()
-end -- AIRG.StyleLearned
-
--- Invoked from AIRG.Initialise but lengthy so in it's own function to not clutter Initialise
-function AIRG.initUI()
-    -- Some local variable declaration
-    local i, j      -- used in for loops
-    local thisTrait, tType, tDesc, rowNum, charName
-    -- Initialise a table to hold all the lua generated components
-    AIRG.UI = {}
-    -- Set the main window title
-    AIRG.UI.WindowTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowTitle", AIResearchGrid, CT_LABEL)
-    AIRG.UI.WindowTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 0)
-    AIRG.UI.WindowTitle:SetFont("ZoFontAnnounceMedium")
-    AIRG.UI.WindowTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
-    AIRG.UI.WindowTitle:SetText("|c8080ffAI|r RESEARCH GRID")
-    -- Set the main window subtitle
-    AIRG.UI.WindowSubTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowSubTitle", AIResearchGrid, CT_LABEL)
-    AIRG.UI.WindowSubTitle:SetAnchor(LEFT, AIRG.UI.WindowTitle, RIGHT, 10, 0)
-    AIRG.UI.WindowSubTitle:SetFont("ZoFontAnnounceMedium")
-    AIRG.UI.WindowSubTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
-    AIRG.UI.WindowSubTitle:SetColor(0, 1, 0, 1);    -- green
-    AIRG.UI.WindowSubTitle:SetText("")
-    -- Nice little line under the main title
-    -- ## Check is htis showing right?
-    AIRG.UI.TopDivider = WINDOW_MANAGER:CreateControl("AIResearchGridTopDivider", AIResearchGrid, CT_TEXTURE)
-    AIRG.UI.TopDivider:SetDimensions(760, 5)
-    AIRG.UI.TopDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 32)
-    AIRG.UI.TopDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
-    -- Nice little line under the grid
-    AIRG.UI.BottomDivider = WINDOW_MANAGER:CreateControl("AIResearchGridBottomDivider", AIResearchGrid, CT_TEXTURE)
-    AIRG.UI.BottomDivider:SetDimensions(760, 5)
-    AIRG.UI.BottomDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 636)
-    AIRG.UI.BottomDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
-    AIRG.UI.BottomDivider:SetHidden(not AIRG.vars.showMotifs)
-    -- CREATE BUTTON FOR CLOSE ADDON AT TOP_RIGHT
-    AIRG.UI.btnCloseAddonFrame = WINDOW_MANAGER:CreateControl("AIResearchGridButtonCloseAddon", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnCloseAddonFrame:SetDimensions(28, 28)
-    AIRG.UI.btnCloseAddonFrame:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, 5 , 0)
-    AIRG.UI.btnCloseAddonFrame:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnCloseAddonFrame:SetMouseOverBlendMode(0)
---    AIRG.UI.btnCloseAddonFrame:SetHidden(false)
-    AIRG.UI.btnCloseAddonFrame:SetEnabled(true)
---    AIRG.UI.btnCloseAddonFrame:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
-    AIRG.UI.btnCloseAddonFrame:SetNormalTexture("/esoui/art/buttons/clearslot_down.dds")
-    AIRG.UI.btnCloseAddonFrame:SetMouseOverTexture("/esoui/art/buttons/clearslot_up.dds")
-    AIRG.UI.btnCloseAddonFrame:SetHandler("OnClicked", function(self) AIRG.ToggleMainWindow() end)
-
-    -- CREATE the DROPDOWN BOX for CHARACTER SELECT
-    -- Uses code based on example from Seerah
-    AIRG.UI.charDropdown = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridDropdownCharacter", AIResearchGrid, "ZO_StatsDropdownRow")
-    AIRG.UI.charDropdown:SetWidth(205) -- Defaults to 607!!!
-    AIRG.UI.charDropdown:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, -32, 0)
-    AIRG.UI.charDropdown:GetNamedChild("Dropdown"):SetWidth(200)
-    AIRG.UI.charDropdown.dropdown:SetSelectedItem(AIRG.curCharacter)  -- Set the current character as selected
-    local function OnItemSelect(_, choiceText, choice)  --this is the callback function for when an item gets selected in the dropdown
-        AIRG.OnCharacterSelect(choiceText)
-    end
-    for charName, _ in pairs(AIRG.vars.data) do
-        local entry = AIRG.UI.charDropdown.dropdown:CreateItemEntry(charName, OnItemSelect)
-        AIRG.UI.charDropdown.dropdown:AddItem(entry)
-    end
-    -- CREATE BUTTON FOR "Update Other" AT TOP_RIGHT
-    --AIRG.UI.btnUpdateOther = WINDOW_MANAGER:CreateControl("AIResearchGridButtonUpdateOther", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnUpdateOther = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridButtonUpdateOther", AIResearchGrid, "ZO_DefaultButton")
-	--Attempt to adjust button size to content, but units are different. May not be fixable. leave for meantime.
-    local textlen = 0
-    if string.len(AIRG.L["btnRelativeOn"]) > string.len(AIRG.L["btnRelativeOff"])
-    then textlen = string.len(AIRG.L["btnRelativeOn"])
-    else textlen = string.len(AIRG.L["btnRelativeOff"])
-    end
-
-    AIRG.UI.btnUpdateOther:SetDimensions(140+textlen, 30)
-    AIRG.UI.btnUpdateOther:SetAnchor(RIGHT, AIRG.UI.charDropdown, LEFT, 0, 0)
-    AIRG.UI.btnUpdateOther:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnUpdateOther:SetMouseOverBlendMode(0)
---    AIRG.UI.btnUpdateOther:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
-    AIRG.UI.btnUpdateOther:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnUpdateOther:SetClickSound("Click")
-    AIRG.UI.btnUpdateOther:SetDisabledFontColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
-    AIRG.UI.btnUpdateOther:SetFont("ZoFontGame")
-    AIRG.UI.btnUpdateOther:SetText(AIRG.L["btnRelativeOff"])
-    AIRG.UI.btnUpdateOther:SetEnabled(false)  -- starts pointing to current character, which can't use this
-    AIRG.UI.btnUpdateOther:SetHidden(false)
--- enabled at end of function
-    AIRG.UI.btnUpdateOther:SetHandler("OnClicked",
-      function(self)
-                       AIRG.ShowRelative = not AIRG.ShowRelative
-                       if AIRG.ShowRelative
-                       then  self:SetText(AIRG.L["btnRelativeOn"]) -- Lime green
-  --                     else  self:SetText(AIRG.btnUpdateOtherText1 )
-                        else  self:SetText(AIRG.L["btnRelativeOff"])
-                     end
-                     AIRG.OnCraftSelected() --redisplay
-         end)
-    AIRG.UI.btnUpdateOther:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
-    AIRG.UI.btnUpdateOther:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
-    AIRG.UI.btnUpdateOther:SetMouseEnabled(true)
-  --
-    -- PEOPLE ICON NEXT TO THE DROPDOWN BOX.
---    AIRG.UI.PeopleIcon = WINDOW_MANAGER:CreateControl("AIResearchGridPeopleIcon", AIResearchGrid, CT_TEXTURE)
---    AIRG.UI.PeopleIcon:SetDimensions(40, 32)
---    AIRG.UI.PeopleIcon:SetAnchor(TOPRIGHT, AIRG.UI.charDropdown, TOPLEFT, 0, 0)
---    AIRG.UI.PeopleIcon:SetTexture("/esoui/art/contacts/tabicon_friends_down.dds")
-    -- CREATE BUTTON FOR PROFESSION: BLACKSMITHING
-    AIRG.UI.btnBlacksmithing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonBlacksmithing", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnBlacksmithing:SetDimensions(48, 48)
-    AIRG.UI.btnBlacksmithing:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 8 , 44)
-    AIRG.UI.btnBlacksmithing:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnBlacksmithing:SetMouseOverBlendMode(0)
-    AIRG.UI.btnBlacksmithing:SetHidden(false)
-    AIRG.UI.btnBlacksmithing:SetEnabled(true)
-    AIRG.UI.btnBlacksmithing:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
-    AIRG.UI.btnBlacksmithing:SetNormalTexture("/esoui/art/icons/ability_smith_007.dds")
-    AIRG.UI.btnBlacksmithing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnBlacksmithing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_BLACKSMITHING) end)
-    -- CREATE BUTTON FOR PROFESSION: WOODWORKING
-    AIRG.UI.btnWoodworking = WINDOW_MANAGER:CreateControl("AIResearchGridButtonWoodworking", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnWoodworking:SetDimensions(48, 48)
-    AIRG.UI.btnWoodworking:SetAnchor(TOPLEFT, AIRG.UI.btnBlacksmithing, TOPRIGHT, 12 , 0)
-    AIRG.UI.btnWoodworking:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnWoodworking:SetMouseOverBlendMode(0)
-    AIRG.UI.btnWoodworking:SetHidden(false)
-    AIRG.UI.btnWoodworking:SetEnabled(true)
-    AIRG.UI.btnWoodworking:SetClickSound(SOUNDS.BLACKSMITH_EXTRACTED_BOOSTER)
-    AIRG.UI.btnWoodworking:SetNormalTexture("/esoui/art/icons/ability_tradecraft_009.dds")
-    AIRG.UI.btnWoodworking:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnWoodworking:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_WOODWORKING) end)
-    -- CREATE BUTTON FOR PROFESSION: CLOTHING
-    AIRG.UI.btnClothing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonClothing", AIResearchGrid, CT_BUTTON)
-    AIRG.UI.btnClothing:SetDimensions(48, 48)
-    AIRG.UI.btnClothing:SetAnchor(TOPLEFT, AIRG.UI.btnWoodworking, TOPRIGHT, 12 , 0)
-    AIRG.UI.btnClothing:SetState(BSTATE_NORMAL)
-    AIRG.UI.btnClothing:SetMouseOverBlendMode(0)
-    AIRG.UI.btnClothing:SetHidden(false)
-    AIRG.UI.btnClothing:SetEnabled(true)
-    AIRG.UI.btnClothing:SetClickSound(SOUNDS.CLOTHIER_EXTRACTED_BOOSTER)
-    AIRG.UI.btnClothing:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
-    AIRG.UI.btnClothing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-    AIRG.UI.btnClothing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_CLOTHIER) end)
-
-    -- BUILD THE TRAIT LABELS ON THE LEFT-SIDE using built-in language strings
-    AIRG.UI.rowLabels = {}
-    for thisTrait, j in pairs(AIRG.gridTraits) do
-        AIRG.UI.rowLabels[j] = WINDOW_MANAGER:CreateControl("AIResearchGridRowLabel" .. tostring(j), AIResearchGrid, CT_LABEL)
-        AIRG.UI.rowLabels[j]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 28*j + 70)
-        AIRG.UI.rowLabels[j]:SetText(GetString("SI_ITEMTRAITTYPE",thisTrait))       -- This is the text displayed on the screen as it's a label
-        AIRG.UI.rowLabels[j]:SetDimensions(180, 24)
-        AIRG.UI.rowLabels[j]:SetFont("ZoFontGame")
-        AIRG.UI.rowLabels[j]:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
-        AIRG.UI.rowLabels[j]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
-        AIRG.UI.rowLabels[j]:SetMouseEnabled(true)
-        AIRG.UI.rowLabels[j]:SetHandler("OnMouseEnter", function (self)
-                            ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
-                        end)
-        AIRG.UI.rowLabels[j]:SetHandler("OnMouseExit", function (self)
-                            ZO_Tooltips_HideTextTooltip()
-                        end)
-    end
-    -- Now add tooltip text to the row labels.
-    -- The tooltip functionality is automatic as part of the label control.
-    for j = 1, 9 do
-        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,1,j) -- weapons
-        rowNum = AIRG.gridTraits[tType]
-        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
-        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,9,j) -- armour
-        rowNum = AIRG.gridTraits[tType]
-        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
-    end
-    -- BUILD THE COLUMNS & GRID
-    -- Determine the maximum number of item types across all three professions. This is currently always 14
-    AIRG.maxColumns= math.max(GetNumSmithingResearchLines(CRAFTING_TYPE_BLACKSMITHING),
-            GetNumSmithingResearchLines(CRAFTING_TYPE_CLOTHIER),
-            GetNumSmithingResearchLines(CRAFTING_TYPE_WOODWORKING))
-    AIRG.UI.columnButtons = {}
-    AIRG.UI.gridButtons = {}
-    AIRG.UI.columnFooters = {}
-    for i = 1, AIRG.maxColumns do
-        -- BUILD THE COLUMN BUTTONS
-        AIRG.UI.columnButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridHeaderButton" .. tostring(i), AIResearchGrid, CT_BUTTON)
-        AIRG.UI.columnButtons[i]:SetDimensions(36, 36)
-        AIRG.UI.columnButtons[i]:SetState(BSTATE_NORMAL)
-        AIRG.UI.columnButtons[i]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 40*i + 150, 55)
-        AIRG.UI.columnButtons[i]:SetHidden(true)
-        AIRG.UI.columnButtons[i]:SetEnabled(true)
-        AIRG.UI.columnButtons[i]:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
-        AIRG.UI.columnButtons[i].text = i
-        AIRG.UI.columnButtons[i]:SetHandler("OnMouseEnter", function (self)
-                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.text)
-                                            end)
-        AIRG.UI.columnButtons[i]:SetHandler("OnMouseExit", function (self)
-                                                ZO_Tooltips_HideTextTooltip()
-                                            end)
-        -- BUILD THE GRID
-        -- There are a total of 18 traits possible. 9 armour and 9 weapon (Infused, Training and Nirnhoned on both)
-        AIRG.UI.gridButtons[i] = {}
-        for j = 1, 18 do
-            AIRG.UI.gridButtons[i][j] = WINDOW_MANAGER:CreateControl("AIResearchGridGridButton" .. tostring(i) .. "x" .. tostring(j), AIResearchGrid, CT_TEXTURE)
-            AIRG.UI.gridButtons[i][j]:SetDimensions(24, 24)
-            AIRG.UI.gridButtons[i][j]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 28*j -20)
-            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")  -- little square box
-            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
-            AIRG.UI.gridButtons[i][j]:SetHidden(false)
-            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)
-            -- Following tooltip code uses ideas contributed by Krysstof
-            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseEnter", function (self)
-                        if (self.tooltipText > 0) then      -- Check the item is being researched and has a timestamp
-					        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
-                            local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
-					        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
-    						-- loop with "registerforupdate" once per second
-    						EVENT_MANAGER:RegisterForUpdate(self.name, 1000, function()
-    						        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
-                                    local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
-    						        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
-    						    end)
-    				    end
-					end)
-            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseExit", function (self)
-						-- unregister the update event or it keeps on displaying
-						EVENT_MANAGER:UnregisterForUpdate(self.name)
-						ZO_Tooltips_HideTextTooltip()
-					end)
-        end
-        -- BUILD THE COLUMN FOOTERS
-        AIRG.UI.columnFooters[i] = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterLabel" .. tostring(i), AIResearchGrid, CT_LABEL)
-        AIRG.UI.columnFooters[i]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 516)
-        AIRG.UI.columnFooters[i]:SetDimensions(36, 24)
-        AIRG.UI.columnFooters[i]:SetFont("ZoFontGame")
-        AIRG.UI.columnFooters[i]:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
-        AIRG.UI.columnFooters[i]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
-        AIRG.UI.columnFooters[i]:SetColor(1, 1, 0.4, 1);    -- faded yellow
-    end
-    -- BUILD LABEL FOR COLUMN FOOTER "TRAIT LINE"
-    AIRG.UI.columnFooterTitle = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterTitleLabel", AIResearchGrid, CT_LABEL)
-    AIRG.UI.columnFooterTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 606)
-    AIRG.UI.columnFooterTitle:SetDimensions(180, 24)
-    AIRG.UI.columnFooterTitle:SetFont("ZoFontGame")
-    AIRG.UI.columnFooterTitle:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
-    AIRG.UI.columnFooterTitle:SetVerticalAlignment(TEXT_ALIGN_CENTER)
-    AIRG.UI.columnFooterTitle:SetColor(1, 1, 0.4, 1);       -- faded yellow
---    AIRG.UI.columnFooterTitle:SetText(GetString(SI_SMITHING_RESEARCH_LINE_HEADER))
-    AIRG.UI.columnFooterTitle:SetText(GetString(SI_CRAFTING_COMPONENT_TOOLTIP_TRAITS))
-
-    -- BUILD THE MOTIF ICONS ACROSS THE BOTTOM
-    -- Note that for now, we're just setting up 15 icons and stuff is configured manually
-    -- but we can fix it later. It's not like it's going to have an overhead on processing. :)
-    -- It's set-up inside a container frame to make hiding or showing the whole lot simpler.
-    AIRG.UI.motifSection = WINDOW_MANAGER:CreateControl("AIResearchMotifSection", AIResearchGrid, CT_CONTROL)
-    AIRG.UI.motifSection:SetDimensions(760, 50)
-    AIRG.UI.motifSection:SetAnchor(BOTTOMLEFT, AIResearchGrid, BOTTOMLEFT, -40, 0)
-    AIRG.UI.motifSection:SetHidden(not AIRG.vars.showMotifs)
-    AIResearchGrid:SetHeight(AIRG.vars.showMotifs and 706 or 636)
-    AIRG.UI.motifButtons = {}
-    for i = 1, 15 do
-        AIRG.UI.motifButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridMotifButton" .. tostring(i), AIRG.UI.motifSection, CT_TEXTURE)
-        AIRG.UI.motifButtons[i]:SetDimensions(40, 40)
-        AIRG.UI.motifButtons[i]:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 42*i +124, 0)
-        AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
-        AIRG.UI.motifButtons[i]:SetMouseEnabled(true)
-        j = AIRG.styleLookupValue[i]
-        tDesc ,_,_,_,_ = GetSmithingStyleItemInfo( AIRG.styleLookupItem[i] )
-        AIRG.UI.motifButtons[i].tooltipText = zo_strformat("<<t:1>>\n<<t:2>>", GetString("SI_ITEMSTYLE",j), tDesc)
-        AIRG.UI.motifButtons[i]:SetHandler("OnMouseEnter", function (self)
-                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
-                                            end)
-        AIRG.UI.motifButtons[i]:SetHandler("OnMouseExit", function (self)
-                                                ZO_Tooltips_HideTextTooltip()
-                                            end)
-    end
-    -- BUILD LABEL FOR STYLES
-    AIRG.UI.StyleLabel = WINDOW_MANAGER:CreateControl("AIResearchStylelabel", AIRG.UI.motifSection, CT_LABEL)
-    AIRG.UI.StyleLabel:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 5, 6)
-    AIRG.UI.StyleLabel:SetText(GetString(SI_SMITHING_HEADER_STYLE))
-    AIRG.UI.StyleLabel:SetDimensions(150, 24)
-    AIRG.UI.StyleLabel:SetFont("ZoFontGame")
-    AIRG.UI.StyleLabel:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
-
-end -- AIRG.initUI
-
--- User has clicked on one of the profession buttons
--- or we just want to refresh the display with current data
-function AIRG.OnCraftSelected(_,thisCraft)
-    if (thisCraft == nil) then
-        if (AIRG.curCraft == nil) then
-            return
-        else
-            thisCraft = AIRG.curCraft
-        end
-    end
-
-
-
-    AIRG.UI.WindowSubTitle:SetText(AIRG.craftNames[thisCraft])
-    local i,j,busy
-
-    local tType,tDesc,tKnown,tRemain,rowNum,traitCount
-    local maxLines = GetNumSmithingResearchLines(thisCraft) -- the number of columns for this profession
-    AIRG.curCraft = thisCraft
-    for i = 1, AIRG.maxColumns do
-        busy = false
-        -- "blank" the grid
-        for j = 1, 18 do
-            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
-            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
-            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)    -- effectively disable tooltip for this grid item.
-        end
-        if (i > maxLines) then
-            AIRG.UI.columnButtons[i]:SetHidden(true)
-            AIRG.UI.columnFooters[i]:SetText("")
-        else
-            local name, icon, _, _ = GetSmithingResearchLineInfo(thisCraft, i)  -- Get info on that specific item
-            AIRG.UI.columnButtons[i]:SetNormalTexture(icon)
-            AIRG.UI.columnButtons[i]:SetHidden(false)
-            AIRG.UI.columnButtons[i].text = name
-
-            traitCount = 0
-            --Check for research expiry
-            for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
-              if (tKnown > 0 and tKnown < GetTimeStamp()) then
-                AIRG.vars.data[AIRG.curCharacter][thisCraft][i][rowNum] = -1  -- Change to known
-              end
-            end
-
-
-            if  AIRG.ShowRelative
-            then
-              -- Great! relative mode! we need to address a matter of practical usage.
-              --  We need to see that we actually can research that now, because we can't research more than one item type at a time.
-              --  So we need to pre-check for item research and set the colours (of the texture) appropriately
-              for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
-                  if (tKnown > 0) then  -- researching
-                      busy = true
-                  end
-              end
-
-              for rowNum,tKnown in pairs(AIRG.relative[AIRG.curCharacter][thisCraft][i]) do
-                  AIRG.UI.gridButtons[i][rowNum].tooltipText = tKnown
-                  if (tKnown == -1) then       -- Trait is known
-                    if (busy) then
-                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.7, 0.6, 0.6, .8)   -- Dull Reddish
-                    else
-                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
-                    end
-                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
-                    traitCount = traitCount + 1
-                  end
-              end
-
-
-            else -- not relative
-              for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
-                AIRG.UI.gridButtons[i][rowNum].tooltipText = tKnown
-                if (tKnown == -1) then       -- Trait is known
-                    AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
-                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
-                    traitCount = traitCount + 1
-                elseif (tKnown > 0) then   -- Trait is being researched
-                        AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/mounts/timer_icon.dds")
-                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.5, 0.5, 1, 1)   -- Blue
-                        AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
-                else                        -- Trait is NOT known
-                    AIRG.UI.gridButtons[i][rowNum]:SetColor(1, 0.2, 0.2, 1)   -- Red
-                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/buttons/decline_up.dds")  --  an   "X".
-                end
-              end
-            end  --Relative
-
-            AIRG.UI.columnFooters[i]:SetText(traitCount)
-        end
-    end
-end -- AIRG:OnCraftSelected
-
--- Invoked when the user selected a character from the dropdown box
-function AIRG.OnCharacterSelect(charName)
-
-    if (charName == nil) then
-        return
-    end
-    AIRG.curCharacter = charName
-
-      -- The Relative Button doesn't make sense if selecting these
-    if charName == AIRG.all or charName == AIRG.playerName then
-      AIRG.UI.btnUpdateOther:SetEnabled(false)
-      AIRG.ShowRelative = false
-    else
-      AIRG.UI.btnUpdateOther:SetEnabled(true)
-    end
-
-    AIRG.DisplayStyles()
-    AIRG.OnCraftSelected()
-
-end -- AIRG.OnCharacterSelect
-
--- Deletes data for the named character from the saved data and removes them from the dropdown box.
-function AIRG.DeleteCharacter(charName)
-    -- Can't delete the current character
-    if (charName == AIRG.playerName or charName == AIRG.all or charName == AIRG.curCharacter) then
-        d(AIRG.L["DeleteFalse"])
-    else
-        if (AIRG.vars.data[charName] ~= nil) then
-            AIRG.vars.data[charName] = nil
-            d(AIRG.L["DeleteTrue"] .. charName)
-        end
-        if (AIRG.vars.styles[charName] ~= nil) then
-            AIRG.vars.styles[charName] = nil
-        end
-        AIRG.PopulateAll()
-    end
-end -- AIRG.DeleteCharacter
-
--- This function cycles through all three professions and populates the data matrix for this characters
--- This is carried out when the addon loasd to ensure the current character data is up-to-date.
--- The "if" logic in this function guesses at which profession should be default to display as the one with most research in.
-function AIRG.PopulateMatrix()
-    local curCount = 0
-    local thisCount
-        AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING  --Default for new chars
-        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_BLACKSMITHING)
-        if (thisCount > curCount) then
-          AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
-          curCount = thisCount
-        end
-        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_CLOTHIER)
-        if (thisCount > curCount) then
-          AIRG.curCraft = CRAFTING_TYPE_CLOTHIER
-            curCount = thisCount
-        end
-        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_WOODWORKING)
-        if (thisCount > curCount) then
-          AIRG.curCraft = CRAFTING_TYPE_WOODWORKING
-          curCount = thisCount
-        end
-      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_BLACKSMITHING)
-      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_WOODWORKING)
-     AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_CLOTHIER)
-end -- AIRG.PopulateMatrix
-
--- Lookup the style data for the current character and send it to saved vars.
-function AIRG.PopulateStyleData()
-    AIRG.vars.styles[AIRG.playerName] = {}    -- create a table for this character's matrix
-    local i, j, known
-    for i = 1, 15 do
-        j = AIRG.styleLookupItem[i]
-        known = IsSmithingStyleKnown(j, 1) --patternIndex set to 1, temporary workaround for changes introduced in Update 4
-        AIRG.vars.styles[AIRG.playerName][i] = known
-    end
-end -- AIRG.PopulateStyleData
-
--- When any character data changes we have to go through and create our virtual "All" from the beginning.
--- its simplified by not having to reset to unknown as traits can't be forgotton.
-function AIRG.PopulateAll()
-    local craft, item, trait, thisname, style, known
-    for thisname, _ in pairs(AIRG.vars.data) do   --iterate over all characters
-      if thisname ~= AIRG.all then                --skip our virtual
-        for craft, _ in pairs(AIRG.vars.data[thisname]) do   --iterate over all crafts
-          for item, _ in pairs(AIRG.vars.data[thisname][craft]) do   --iterate over all weapons/armour
-            for trait, _ in pairs(AIRG.vars.data[thisname][craft][item]) do   --iterate over all traits
-              if AIRG.vars.data[thisname][craft][item][trait] ~=  0 then -- researching counts as learned.
-                 AIRG.vars.data[AIRG.all][craft][item][trait] = -1
-              end
-            end
-          end
-        end
-        -- Update the Styles for this char.
-        for style, known in pairs (AIRG.vars.styles[thisname]) do   --iterate over all styles
-          if known  then
-            AIRG.vars.styles[AIRG.all][style] = true
-          end
-       end
-      end
-    end
- end  -- AIRG.PopulateAll
-
-
--- Set the icon highlights for the currently selected character
-function AIRG.DisplayStyles()
-    local i
-    if (AIRG.vars.styles[AIRG.curCharacter] == nil) then
-        for i = 1, 15 do
-            AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
-            AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
-        end
-    else
-        for i = 1, 14 do
-            if (AIRG.vars.styles[AIRG.curCharacter][i]) then
-                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "down.dds")
-                AIRG.UI.motifButtons[i]:SetColor(0.7, 1, 0.7, 1)   -- Green
-            else
-                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
-                AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
-            end
-        end
-    end
-end -- AIRG.DisplayStyles()
-
--- Look up all the data on this profession and commit to saved variables for this character.
-function AIRG.CreateDataMatrix(thisCraft)  -- for current  player, not the selected
-  local i, j
-    local tType, tKnown, tRemain, rowNum, tTargetStamp
-    local rCount = 0
-    local maxLines = GetNumSmithingResearchLines(thisCraft)     -- the number of columns for this profession
-    AIRG.vars.data[AIRG.playerName][thisCraft] = {}             -- create a table for this profession for real traits
-
-    -- Not relative updates, show all for Current Character
-    -- Cycle through items for this profession
-    for i = 1, maxLines do
-        AIRG.vars.data[AIRG.playerName][thisCraft][i] = {}      -- create a table for this item
-        -- Cycle through the traits for this item
-        for j = 1, 9 do
-            tType,_,tKnown = GetSmithingResearchLineTraitInfo(thisCraft,i,j)
-            _,tRemain = GetSmithingResearchLineTraitTimes(thisCraft,i,j)
-            rowNum = AIRG.gridTraits[tType]
-
-            if (tKnown) then
-                AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = -1       -- this trait is known
-                rCount = rCount + 1
-            else
-                if (tRemain) then
-                    tTargetStamp = GetTimeStamp() + tRemain
-                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = tTargetStamp   -- this trait is being currently researched
-                    -- The value we are setting this to is the timestamp for when the research will be complete.
-                else
-                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = 0   -- this trait is NOT known
-                end
-            end
-        end
-
-    end
-    return rCount       -- the total number of traits already researched in this profession
-end -- AIRG.CreateDataMatrix
-
-function AIRG.CreateDataMatrixRelative(thisCraft)  -- for the current selected  player, relative to the real player
-    local craft, item, trait, thisname, style, known
-
-    for thisname, _ in pairs(AIRG.vars.data) do   --iterate over all characters
-      if thisname ~= AIRG.all then                --skip our virtual
-        AIRG.relative[thisname] = {}
-        for craft, _ in pairs(AIRG.vars.data[thisname]) do   --iterate over all crafts
-          AIRG.relative[thisname][craft] = {}
-          for item, _ in pairs(AIRG.vars.data[thisname][craft]) do   --iterate over all weapons/armour
-            AIRG.relative[thisname][craft][item] = {}
-            for trait, _ in pairs(AIRG.vars.data[thisname][craft][item]) do   --iterate over all traits
-              AIRG.relative[thisname][craft][item][trait] = {}
-              if AIRG.vars.data[thisname][craft][item][trait] ==  0 then -- thischar doesn't have traits
-                if AIRG.vars.data[AIRG.playerName][craft][item][trait] ==  -1  ---PLayer Does
-                then AIRG.relative[thisname][craft][item][trait] = -1
-                else AIRG.relative[thisname][craft][item][trait] = nil
-                end
-              end
-            end
-          end
-        end
-      end
-    end
-end -- AIRG.CreateDataMatrix
-
-
-
-function AIRG.AssignGridTraits()
-    -- Translates the traitType to the correct ROW of the grid
-    AIRG.gridTraits = {}
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_POWERED] = 1
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_CHARGED] = 2
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_PRECISE] = 3
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_INFUSED] = 4
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_DEFENDING] = 5
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_TRAINING] = 6
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_SHARPENED] = 7
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_WEIGHTED] = 8
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_NIRNHONED] = 9
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_STURDY] = 10
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_IMPENETRABLE] = 11
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_REINFORCED] = 12
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_WELL_FITTED] = 13
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_TRAINING] = 14
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_INFUSED] = 15
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_EXPLORATION] = 16
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_DIVINES] = 17
-    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_NIRNHONED] = 18
-end -- AIRG.AssignGridTraits
-
-function AIRG.AssignStyleLookups()
-    -- Lookup the correct icon for the style
-    AIRG.styleLookupIcons = {}
-    AIRG.styleLookupIcons[1] = "ESOUI/art/charactercreate/charactercreate_altmericon_"
-    AIRG.styleLookupIcons[2] = "ESOUI/art/charactercreate/charactercreate_argonianicon_"
-    AIRG.styleLookupIcons[3] = "ESOUI/art/charactercreate/charactercreate_bosmericon_"
-    AIRG.styleLookupIcons[4] = "ESOUI/art/charactercreate/charactercreate_bretonicon_"
-    AIRG.styleLookupIcons[5] = "ESOUI/art/charactercreate/charactercreate_dunmericon_"
-    AIRG.styleLookupIcons[6] = "ESOUI/art/charactercreate/charactercreate_khajiiticon_"
-    AIRG.styleLookupIcons[7] = "ESOUI/art/charactercreate/charactercreate_nordicon_"
-    AIRG.styleLookupIcons[8] = "ESOUI/art/charactercreate/charactercreate_orcicon_"
-    AIRG.styleLookupIcons[9] = "ESOUI/art/charactercreate/charactercreate_redguardicon_"
-    AIRG.styleLookupIcons[10] = "ESOUI/art/charactercreate/charactercreate_imperialicon_"
-    AIRG.styleLookupIcons[11] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[12] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[13] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[14] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    AIRG.styleLookupIcons[15] = "ESOUI/art/progression/progression_indexicon_weapons_"
-    -- Translate the icon position to the in-game type. Used for text look-up
-    AIRG.styleLookupValue = {}
-    AIRG.styleLookupValue[1] = ITEMSTYLE_RACIAL_HIGH_ELF
-    AIRG.styleLookupValue[2] = ITEMSTYLE_RACIAL_ARGONIAN
-    AIRG.styleLookupValue[3] = ITEMSTYLE_RACIAL_WOOD_ELF
-    AIRG.styleLookupValue[4] = ITEMSTYLE_RACIAL_BRETON
-    AIRG.styleLookupValue[5] = ITEMSTYLE_RACIAL_DARK_ELF
-    AIRG.styleLookupValue[6] = ITEMSTYLE_RACIAL_KHAJIIT
-    AIRG.styleLookupValue[7] = ITEMSTYLE_RACIAL_NORD
-    AIRG.styleLookupValue[8] = ITEMSTYLE_RACIAL_ORC
-    AIRG.styleLookupValue[9] = ITEMSTYLE_RACIAL_REDGUARD
-    AIRG.styleLookupValue[10] = ITEMSTYLE_AREA_IMPERIAL
-    AIRG.styleLookupValue[11] = ITEMSTYLE_AREA_ANCIENT_ELF
-    AIRG.styleLookupValue[12] = ITEMSTYLE_AREA_REACH
-    AIRG.styleLookupValue[13] = ITEMSTYLE_ENEMY_DAEDRIC
-    AIRG.styleLookupValue[14] = ITEMSTYLE_ENEMY_PRIMITIVE
-    AIRG.styleLookupValue[15] = ITEMSTYLE_AREA_DWEMER
-
-    -- This is a bit of a hack, but only because of the way ESO uses Style Items with different index to styles.
-    AIRG.styleLookupItem = {}
-    AIRG.styleLookupItem[1] = 8     -- Altmer       = Adamantite
-    AIRG.styleLookupItem[2] = 7     -- Argonian     = Flint
-    AIRG.styleLookupItem[3] = 9     -- Bosmer       = Bone
-    AIRG.styleLookupItem[4] = 2     -- Breton       = Molybdenum
-    AIRG.styleLookupItem[5] = 5     -- Dunmer       = Obsidian
-    AIRG.styleLookupItem[6] = 10    -- Khajit       = Moonstone
-    AIRG.styleLookupItem[7] = 6     -- Nord         = Corundum
-    AIRG.styleLookupItem[8] = 4     -- Orc          = Manganese
-    AIRG.styleLookupItem[9] = 3     -- Redguard     = Starmetal
-    AIRG.styleLookupItem[10] = 35   -- Imperial     = Nickel
-    AIRG.styleLookupItem[11] = 16   -- Ancient Elf  = Palladium
-    AIRG.styleLookupItem[12] = 18   -- Barbarian    = Copper
-    AIRG.styleLookupItem[13] = 21   -- Daedric      = Daedra Heart
-    AIRG.styleLookupItem[14] = 20   -- Primal       = Argentum
-    AIRG.styleLookupItem[15] = 15   -- Dwemer       = Dwemer Frame
-end -- AIRG.AssignStyleLookups
-
-
-function AIRG.Initialise(eventCode, addOnName)
-	-- Only initialize our own addon
-	if (AIRG.name ~= addOnName) then return end
-    -- Language text
-    AIRG.InitialiseLanguage()
-
-    -- Load the saved variables
-    AIRG.vars = ZO_SavedVars:NewAccountWide("AIRG_SavedVariables", 2, nil, AIRG.defaults)
-    AIRG.all = AIRG.L["ALL"]		-- replace Default with localise string
-
-    -- Register Keybinding
-    ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_AIRG", "Toggle AI Research Grid")
-
-	-- Set-up some variables we'll want to refer to.
-    AIRG.craftNames = {}
-    AIRG.relative = {}
-    AIRG.craftNames[CRAFTING_TYPE_BLACKSMITHING]    = AIRG.L["BS"]
-    AIRG.craftNames[CRAFTING_TYPE_CLOTHIER]         = AIRG.L["Clothing"]
-    AIRG.craftNames[CRAFTING_TYPE_WOODWORKING]      = AIRG.L["Woodwork"]
-    AIRG.curCraft= CRAFTING_TYPE_WOODWORKING
-    AIRG.playerName = GetUnitName("player")
-    AIRG.curCharacter = GetUnitName("player")       -- Default the display to the current character
-    AIRG.AssignGridTraits()
-    AIRG.AssignStyleLookups()
-    AIRG.vars.styles[AIRG.all] = {}           -- and our virtual character
-
-    -- Create these here so the UI dropdown will have them first time around.
-    AIRG.vars.data[AIRG.playerName] = {}    -- create a table for this character's matrix
-    AIRG.vars.data[AIRG.all] = {}    -- and our virtual character
-
-  -- Create Empty data for Virtual Char set to 0, (Not known)
-    local i, j
-
-    AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING] = {}
-    -- Cycle through items for this profession
-    for i = 1, 7 do   -- Weapons
-        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i] = {}
-        -- Cycle through the traits for this item
-        for j = 1, 9 do
-                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i][j] = 0   -- set to not known
-        end
-    end
-    for i = 8, 14 do  -- Armour
-        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i] = {}
-        -- Cycle through the traits for this item
-        for j = 10, 18 do
-                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i][j] = 0   -- set to not known
-        end
-    end
-
-    AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER] = {}
-    -- Cycle through items for this profession
-    for i = 1, 14 do
-        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER][i] = {}
-        -- Cycle through the traits for this item
-        for j = 10, 18  do
-                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER][i][j] = 0   -- set to not known
-        end
-    end
-
-     AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING] = {}
-    -- Cycle through items for this profession
-    for i = 1, 5 do
-        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i] = {}
-        -- Cycle through the traits for this item
-        for j = 1, 9 do
-                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i][j] = 0   -- set to not known
-        end
-    end
-    for i = 6, 6 do  --Shields
-        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i] = {}
-        -- Cycle through the traits for this item
-        for j = 10, 18 do
-                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i][j] = 0   -- set to not known
-        end
-    end
-
-    --Create Empty Style Table
-    for i = 1, 14 do
-        AIRG.vars.styles[AIRG.all][i] = false
-    end
-
- -- AIRG.CreateDataMatrix
-
-    -- Following replaced with PlayerActivate
-    -- Query data for THIS character and populate the data matrix with fresh data.
-    --AIRG.PopulateMatrix()
-
-    -- Query data for THIS character for STYLES
-    --AIRG.PopulateStyleData()
-
-    -- UI set-up. Create frames, position labels & buttons etc.
-    AIRG.initUI()
-
-    -- REGISTER for events that aren't initialise.
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_STARTED, AIRG.ResearchStarted)
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED, AIRG.ResearchCompleted)
-
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_STYLE_LEARNED, AIRG.StyleLearned)
-
-    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_PLAYER_ACTIVATED, AIRG.PlayerActivated)
-
-    -- Create the configuration/settings menu.
-    AIRG.CreateConfigMenu()
-
-    AIRG.initialised = true
-end -- AIRG.Initialise
-
-EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_ADD_ON_LOADED, AIRG.Initialise)
--- SLASH COMMAND FUNCTIONALITY
-function AIRGslash(extra)
-    AIRG.ToggleMainWindow()
-end -- AIRGslash
-
-
-SLASH_COMMANDS["/airg"] = AIRGslash
--- EOF
+-- AI Research Grid Addon for Elder Scrolls Online
+-- Author: Stormknight/LCAmethyst
+-- "All" and "Relative"  functionality by His Dad
+-- Dwemer Motif by rkuhnjr
+
+local _
+AIRG = {}
+
+AIRG.name = "AIResearchGrid"
+AIRG.version = "3.1.5"
+AIRG.initialised = false
+AIRG.processing = false
+AIRG.all = " #ALL"  -- Default displayname for Virtual character, overrwritten by Localised version
+AIRG.ShowRelative = false  -- State of Button
+AIRG.relative= {}
+AIRG.L = {}   -- declare language strings
+
+-- Set-up the defaults options for saved variables.
+AIRG.defaults = {
+    data        = {},
+    styles      = {},
+    showMotifs = true,
+}
+
+
+function AIRG.PlayerActivated()
+        -- somehow somewhere it sometimes happens that the data is not correct completely for whatever reason
+        -- so we force a reload of the current character data when we are actually loaded into the world.
+  AIRG.PopulateMatrix()
+  AIRG.PopulateStyleData()
+  AIRG.DisplayStyles()
+  AIRG.PopulateAll()  -- do last
+
+end
+
+function AIRG.ToggleMainWindow()
+    if (AIResearchGrid:IsHidden()) then
+        AIRG.OnCraftSelected()              -- Redisplay data for the current profession
+        SetGameCameraUIMode(true)	        -- Enable mouse pointer
+        AIResearchGrid:SetHidden(false)     -- Display the addon
+        AIRG.OnCharacterSelect()
+    else
+        SetGameCameraUIMode(false)	        -- Enable mouse pointer
+        AIResearchGrid:SetHidden(true)      -- Display the addon
+    end
+end -- AIRG.ToggleMainWindow
+
+-- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_STARTED
+-- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
+function AIRG.ResearchStarted(eventCode, craftingSkillType, researchLineIndex, traitIndex)
+    AIRG.PopulateMatrix()
+    AIRG.PopulateAll()
+    -- TO DO: If it's visible, invoke a redisplay
+    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
+end -- AIRG.ResearchStarted
+
+-- Invoked by EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED
+-- (integer eventCode, integer craftingSkillType, luaindex researchLineIndex, luaindex traitIndex)
+function AIRG.ResearchCompleted()
+    AIRG.PopulateMatrix()
+    AIRG.PopulateAll()
+    -- TO DO: If it's visible, invoke a redisplay
+    AIRG.OnCraftSelected()              -- Redisplay data for the current profession
+end -- AIRG.ResearchEnded
+
+function AIRG.StyleLearned(eventCode, styleIndex)
+    AIRG.PopulateStyleData()
+    AIRG.DisplayStyles()
+    AIRG.PopulateAll()
+end -- AIRG.StyleLearned
+
+-- Invoked from AIRG.Initialise but lengthy so in it's own function to not clutter Initialise
+function AIRG.initUI()
+    -- Some local variable declaration
+    local i, j      -- used in for loops
+    local thisTrait, tType, tDesc, rowNum, charName
+    -- Initialise a table to hold all the lua generated components
+    AIRG.UI = {}
+    -- Set the main window title
+    AIRG.UI.WindowTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowTitle", AIResearchGrid, CT_LABEL)
+    AIRG.UI.WindowTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 0)
+    AIRG.UI.WindowTitle:SetFont("ZoFontAnnounceMedium")
+    AIRG.UI.WindowTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
+    AIRG.UI.WindowTitle:SetText("|c8080ffAI|r RESEARCH GRID")
+    -- Set the main window subtitle
+    AIRG.UI.WindowSubTitle = WINDOW_MANAGER:CreateControl("AIResearchGridWindowSubTitle", AIResearchGrid, CT_LABEL)
+    AIRG.UI.WindowSubTitle:SetAnchor(LEFT, AIRG.UI.WindowTitle, RIGHT, 10, 0)
+    AIRG.UI.WindowSubTitle:SetFont("ZoFontAnnounceMedium")
+    AIRG.UI.WindowSubTitle:SetHorizontalAlignment(TEXT_ALIGN_LEFT)
+    AIRG.UI.WindowSubTitle:SetColor(0, 1, 0, 1);    -- green
+    AIRG.UI.WindowSubTitle:SetText("")
+    -- Nice little line under the main title
+    -- ## Check is htis showing right?
+    AIRG.UI.TopDivider = WINDOW_MANAGER:CreateControl("AIResearchGridTopDivider", AIResearchGrid, CT_TEXTURE)
+    AIRG.UI.TopDivider:SetDimensions(760, 5)
+    AIRG.UI.TopDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 32)
+    AIRG.UI.TopDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
+    -- Nice little line under the grid
+    AIRG.UI.BottomDivider = WINDOW_MANAGER:CreateControl("AIResearchGridBottomDivider", AIResearchGrid, CT_TEXTURE)
+    AIRG.UI.BottomDivider:SetDimensions(760, 5)
+    AIRG.UI.BottomDivider:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 0, 636)
+    AIRG.UI.BottomDivider:SetTexture("/esoui/art/quest/questjournal_divider.dds")
+    AIRG.UI.BottomDivider:SetHidden(not AIRG.vars.showMotifs)
+    -- CREATE BUTTON FOR CLOSE ADDON AT TOP_RIGHT
+    AIRG.UI.btnCloseAddonFrame = WINDOW_MANAGER:CreateControl("AIResearchGridButtonCloseAddon", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnCloseAddonFrame:SetDimensions(28, 28)
+    AIRG.UI.btnCloseAddonFrame:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, 5 , 0)
+    AIRG.UI.btnCloseAddonFrame:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnCloseAddonFrame:SetMouseOverBlendMode(0)
+--    AIRG.UI.btnCloseAddonFrame:SetHidden(false)
+    AIRG.UI.btnCloseAddonFrame:SetEnabled(true)
+--    AIRG.UI.btnCloseAddonFrame:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
+    AIRG.UI.btnCloseAddonFrame:SetNormalTexture("/esoui/art/buttons/clearslot_down.dds")
+    AIRG.UI.btnCloseAddonFrame:SetMouseOverTexture("/esoui/art/buttons/clearslot_up.dds")
+    AIRG.UI.btnCloseAddonFrame:SetHandler("OnClicked", function(self) AIRG.ToggleMainWindow() end)
+
+    -- CREATE the DROPDOWN BOX for CHARACTER SELECT
+    -- Uses code based on example from Seerah
+    AIRG.UI.charDropdown = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridDropdownCharacter", AIResearchGrid, "ZO_StatsDropdownRow")
+    AIRG.UI.charDropdown:SetWidth(205) -- Defaults to 607!!!
+    AIRG.UI.charDropdown:SetAnchor(TOPRIGHT, AIResearchGrid, TOPRIGHT, -32, 0)
+    AIRG.UI.charDropdown:GetNamedChild("Dropdown"):SetWidth(200)
+    AIRG.UI.charDropdown.dropdown:SetSelectedItem(AIRG.curCharacter)  -- Set the current character as selected
+    local function OnItemSelect(_, choiceText, choice)  --this is the callback function for when an item gets selected in the dropdown
+        AIRG.OnCharacterSelect(choiceText)
+    end
+    for charName, _ in pairs(AIRG.vars.data) do
+        local entry = AIRG.UI.charDropdown.dropdown:CreateItemEntry(charName, OnItemSelect)
+        AIRG.UI.charDropdown.dropdown:AddItem(entry)
+    end
+    -- CREATE BUTTON FOR "Update Other" AT TOP_RIGHT
+    --AIRG.UI.btnUpdateOther = WINDOW_MANAGER:CreateControl("AIResearchGridButtonUpdateOther", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnUpdateOther = WINDOW_MANAGER:CreateControlFromVirtual("AIResearchGridButtonUpdateOther", AIResearchGrid, "ZO_DefaultButton")
+	--Attempt to adjust button size to content, but units are different. May not be fixable. leave for meantime.
+    local textlen = 0
+    if string.len(AIRG.L["btnRelativeOn"]) > string.len(AIRG.L["btnRelativeOff"])
+    then textlen = string.len(AIRG.L["btnRelativeOn"])
+    else textlen = string.len(AIRG.L["btnRelativeOff"])
+    end
+
+    AIRG.UI.btnUpdateOther:SetDimensions(140+textlen, 30)
+    AIRG.UI.btnUpdateOther:SetAnchor(RIGHT, AIRG.UI.charDropdown, LEFT, 0, 0)
+    AIRG.UI.btnUpdateOther:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnUpdateOther:SetMouseOverBlendMode(0)
+--    AIRG.UI.btnUpdateOther:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
+    AIRG.UI.btnUpdateOther:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnUpdateOther:SetClickSound("Click")
+    AIRG.UI.btnUpdateOther:SetDisabledFontColor(ZO_DEFAULT_DISABLED_COLOR:UnpackRGBA())
+    AIRG.UI.btnUpdateOther:SetFont("ZoFontGame")
+    AIRG.UI.btnUpdateOther:SetText(AIRG.L["btnRelativeOff"])
+    AIRG.UI.btnUpdateOther:SetEnabled(false)  -- starts pointing to current character, which can't use this
+    AIRG.UI.btnUpdateOther:SetHidden(false)
+-- enabled at end of function
+    AIRG.UI.btnUpdateOther:SetHandler("OnClicked",
+      function(self)
+                       AIRG.ShowRelative = not AIRG.ShowRelative
+                       if AIRG.ShowRelative
+                       then  self:SetText(AIRG.L["btnRelativeOn"]) -- Lime green
+  --                     else  self:SetText(AIRG.btnUpdateOtherText1 )
+                        else  self:SetText(AIRG.L["btnRelativeOff"])
+                     end
+                     AIRG.OnCraftSelected() --redisplay
+         end)
+    AIRG.UI.btnUpdateOther:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+    AIRG.UI.btnUpdateOther:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+    AIRG.UI.btnUpdateOther:SetMouseEnabled(true)
+  --
+    -- PEOPLE ICON NEXT TO THE DROPDOWN BOX.
+--    AIRG.UI.PeopleIcon = WINDOW_MANAGER:CreateControl("AIResearchGridPeopleIcon", AIResearchGrid, CT_TEXTURE)
+--    AIRG.UI.PeopleIcon:SetDimensions(40, 32)
+--    AIRG.UI.PeopleIcon:SetAnchor(TOPRIGHT, AIRG.UI.charDropdown, TOPLEFT, 0, 0)
+--    AIRG.UI.PeopleIcon:SetTexture("/esoui/art/contacts/tabicon_friends_down.dds")
+    -- CREATE BUTTON FOR PROFESSION: BLACKSMITHING
+    AIRG.UI.btnBlacksmithing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonBlacksmithing", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnBlacksmithing:SetDimensions(48, 48)
+    AIRG.UI.btnBlacksmithing:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 8 , 44)
+    AIRG.UI.btnBlacksmithing:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnBlacksmithing:SetMouseOverBlendMode(0)
+    AIRG.UI.btnBlacksmithing:SetHidden(false)
+    AIRG.UI.btnBlacksmithing:SetEnabled(true)
+    AIRG.UI.btnBlacksmithing:SetClickSound(SOUNDS.WOODWORKER_EXTRACTED_BOOSTER)
+    AIRG.UI.btnBlacksmithing:SetNormalTexture("/esoui/art/icons/ability_smith_007.dds")
+    AIRG.UI.btnBlacksmithing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnBlacksmithing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_BLACKSMITHING) end)
+    -- CREATE BUTTON FOR PROFESSION: WOODWORKING
+    AIRG.UI.btnWoodworking = WINDOW_MANAGER:CreateControl("AIResearchGridButtonWoodworking", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnWoodworking:SetDimensions(48, 48)
+    AIRG.UI.btnWoodworking:SetAnchor(TOPLEFT, AIRG.UI.btnBlacksmithing, TOPRIGHT, 12 , 0)
+    AIRG.UI.btnWoodworking:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnWoodworking:SetMouseOverBlendMode(0)
+    AIRG.UI.btnWoodworking:SetHidden(false)
+    AIRG.UI.btnWoodworking:SetEnabled(true)
+    AIRG.UI.btnWoodworking:SetClickSound(SOUNDS.BLACKSMITH_EXTRACTED_BOOSTER)
+    AIRG.UI.btnWoodworking:SetNormalTexture("/esoui/art/icons/ability_tradecraft_009.dds")
+    AIRG.UI.btnWoodworking:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnWoodworking:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_WOODWORKING) end)
+    -- CREATE BUTTON FOR PROFESSION: CLOTHING
+    AIRG.UI.btnClothing = WINDOW_MANAGER:CreateControl("AIResearchGridButtonClothing", AIResearchGrid, CT_BUTTON)
+    AIRG.UI.btnClothing:SetDimensions(48, 48)
+    AIRG.UI.btnClothing:SetAnchor(TOPLEFT, AIRG.UI.btnWoodworking, TOPRIGHT, 12 , 0)
+    AIRG.UI.btnClothing:SetState(BSTATE_NORMAL)
+    AIRG.UI.btnClothing:SetMouseOverBlendMode(0)
+    AIRG.UI.btnClothing:SetHidden(false)
+    AIRG.UI.btnClothing:SetEnabled(true)
+    AIRG.UI.btnClothing:SetClickSound(SOUNDS.CLOTHIER_EXTRACTED_BOOSTER)
+    AIRG.UI.btnClothing:SetNormalTexture("/esoui/art/icons/ability_tradecraft_008.dds")
+    AIRG.UI.btnClothing:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+    AIRG.UI.btnClothing:SetHandler("OnClicked", function(self) AIRG:OnCraftSelected(CRAFTING_TYPE_CLOTHIER) end)
+
+    -- BUILD THE TRAIT LABELS ON THE LEFT-SIDE using built-in language strings
+    AIRG.UI.rowLabels = {}
+    for thisTrait, j in pairs(AIRG.gridTraits) do
+        AIRG.UI.rowLabels[j] = WINDOW_MANAGER:CreateControl("AIResearchGridRowLabel" .. tostring(j), AIResearchGrid, CT_LABEL)
+        AIRG.UI.rowLabels[j]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 28*j + 70)
+        AIRG.UI.rowLabels[j]:SetText(GetString("SI_ITEMTRAITTYPE",thisTrait))       -- This is the text displayed on the screen as it's a label
+        AIRG.UI.rowLabels[j]:SetDimensions(180, 24)
+        AIRG.UI.rowLabels[j]:SetFont("ZoFontGame")
+        AIRG.UI.rowLabels[j]:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
+        AIRG.UI.rowLabels[j]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
+        AIRG.UI.rowLabels[j]:SetMouseEnabled(true)
+        AIRG.UI.rowLabels[j]:SetHandler("OnMouseEnter", function (self)
+                            ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
+                        end)
+        AIRG.UI.rowLabels[j]:SetHandler("OnMouseExit", function (self)
+                            ZO_Tooltips_HideTextTooltip()
+                        end)
+    end
+    -- Now add tooltip text to the row labels.
+    -- The tooltip functionality is automatic as part of the label control.
+    for j = 1, 9 do
+        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,1,j) -- weapons
+        rowNum = AIRG.gridTraits[tType]
+        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
+        tType, tDesc, _ = GetSmithingResearchLineTraitInfo(CRAFTING_TYPE_BLACKSMITHING,9,j) -- armour
+        rowNum = AIRG.gridTraits[tType]
+        AIRG.UI.rowLabels[rowNum].tooltipText = tDesc
+    end
+    -- BUILD THE COLUMNS & GRID
+    -- Determine the maximum number of item types across all three professions. This is currently always 14
+    AIRG.maxColumns= math.max(GetNumSmithingResearchLines(CRAFTING_TYPE_BLACKSMITHING),
+            GetNumSmithingResearchLines(CRAFTING_TYPE_CLOTHIER),
+            GetNumSmithingResearchLines(CRAFTING_TYPE_WOODWORKING))
+    AIRG.UI.columnButtons = {}
+    AIRG.UI.gridButtons = {}
+    AIRG.UI.columnFooters = {}
+    for i = 1, AIRG.maxColumns do
+        -- BUILD THE COLUMN BUTTONS
+        AIRG.UI.columnButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridHeaderButton" .. tostring(i), AIResearchGrid, CT_BUTTON)
+        AIRG.UI.columnButtons[i]:SetDimensions(36, 36)
+        AIRG.UI.columnButtons[i]:SetState(BSTATE_NORMAL)
+        AIRG.UI.columnButtons[i]:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 40*i + 150, 55)
+        AIRG.UI.columnButtons[i]:SetHidden(true)
+        AIRG.UI.columnButtons[i]:SetEnabled(true)
+        AIRG.UI.columnButtons[i]:SetMouseOverTexture("ESOUI/art/buttons/generic_highlight.dds")
+        AIRG.UI.columnButtons[i].text = i
+        AIRG.UI.columnButtons[i]:SetHandler("OnMouseEnter", function (self)
+                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.text)
+                                            end)
+        AIRG.UI.columnButtons[i]:SetHandler("OnMouseExit", function (self)
+                                                ZO_Tooltips_HideTextTooltip()
+                                            end)
+        -- BUILD THE GRID
+        -- There are a total of 18 traits possible. 9 armour and 9 weapon (Infused, Training and Nirnhoned on both)
+        AIRG.UI.gridButtons[i] = {}
+        for j = 1, 18 do
+            AIRG.UI.gridButtons[i][j] = WINDOW_MANAGER:CreateControl("AIResearchGridGridButton" .. tostring(i) .. "x" .. tostring(j), AIResearchGrid, CT_TEXTURE)
+            AIRG.UI.gridButtons[i][j]:SetDimensions(24, 24)
+            AIRG.UI.gridButtons[i][j]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 28*j -20)
+            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")  -- little square box
+            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
+            AIRG.UI.gridButtons[i][j]:SetHidden(false)
+            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)
+            -- Following tooltip code uses ideas contributed by Krysstof
+            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseEnter", function (self)
+                        if (self.tooltipText > 0) then      -- Check the item is being researched and has a timestamp
+					        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
+                            local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
+					        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
+    						-- loop with "registerforupdate" once per second
+    						EVENT_MANAGER:RegisterForUpdate(self.name, 1000, function()
+    						        local tRemaining = tonumber(self.tooltipText) - GetTimeStamp()
+                                    local tFormatted = FormatTimeSeconds(tRemaining, TIME_FORMAT_STYLE_DESCRIPTIVE_SHORT, TIME_FORMAT_PRECISION_SECONDS, TIME_FORMAT_DIRECTION_DESCENDING)
+    						        ZO_Tooltips_ShowTextTooltip(self, RIGHT, tFormatted)
+    						    end)
+    				    end
+					end)
+            AIRG.UI.gridButtons[i][j]:SetHandler("OnMouseExit", function (self)
+						-- unregister the update event or it keeps on displaying
+						EVENT_MANAGER:UnregisterForUpdate(self.name)
+						ZO_Tooltips_HideTextTooltip()
+					end)
+        end
+        -- BUILD THE COLUMN FOOTERS
+        AIRG.UI.columnFooters[i] = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterLabel" .. tostring(i), AIResearchGrid, CT_LABEL)
+        AIRG.UI.columnFooters[i]:SetAnchor(TOP, AIRG.UI.columnButtons[i], BOTTOM, 0, 516)
+        AIRG.UI.columnFooters[i]:SetDimensions(36, 24)
+        AIRG.UI.columnFooters[i]:SetFont("ZoFontGame")
+        AIRG.UI.columnFooters[i]:SetHorizontalAlignment(TEXT_ALIGN_CENTER)
+        AIRG.UI.columnFooters[i]:SetVerticalAlignment(TEXT_ALIGN_CENTER)
+        AIRG.UI.columnFooters[i]:SetColor(1, 1, 0.4, 1);    -- faded yellow
+    end
+    -- BUILD LABEL FOR COLUMN FOOTER "TRAIT LINE"
+    AIRG.UI.columnFooterTitle = WINDOW_MANAGER:CreateControl("AIResearchGridColumnFooterTitleLabel", AIResearchGrid, CT_LABEL)
+    AIRG.UI.columnFooterTitle:SetAnchor(TOPLEFT, AIResearchGrid, TOPLEFT, 5, 606)
+    AIRG.UI.columnFooterTitle:SetDimensions(180, 24)
+    AIRG.UI.columnFooterTitle:SetFont("ZoFontGame")
+    AIRG.UI.columnFooterTitle:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
+    AIRG.UI.columnFooterTitle:SetVerticalAlignment(TEXT_ALIGN_CENTER)
+    AIRG.UI.columnFooterTitle:SetColor(1, 1, 0.4, 1);       -- faded yellow
+--    AIRG.UI.columnFooterTitle:SetText(GetString(SI_SMITHING_RESEARCH_LINE_HEADER))
+    AIRG.UI.columnFooterTitle:SetText(GetString(SI_CRAFTING_COMPONENT_TOOLTIP_TRAITS))
+
+    -- BUILD THE MOTIF ICONS ACROSS THE BOTTOM
+    -- Note that for now, we're just setting up 15 icons and stuff is configured manually
+    -- but we can fix it later. It's not like it's going to have an overhead on processing. :)
+    -- It's set-up inside a container frame to make hiding or showing the whole lot simpler.
+    AIRG.UI.motifSection = WINDOW_MANAGER:CreateControl("AIResearchMotifSection", AIResearchGrid, CT_CONTROL)
+    AIRG.UI.motifSection:SetDimensions(760, 50)
+    AIRG.UI.motifSection:SetAnchor(BOTTOMLEFT, AIResearchGrid, BOTTOMLEFT, -40, 0)
+    AIRG.UI.motifSection:SetHidden(not AIRG.vars.showMotifs)
+    AIResearchGrid:SetHeight(AIRG.vars.showMotifs and 706 or 636)
+    AIRG.UI.motifButtons = {}
+    for i = 1, 15 do
+        AIRG.UI.motifButtons[i] = WINDOW_MANAGER:CreateControl("AIResearchGridMotifButton" .. tostring(i), AIRG.UI.motifSection, CT_TEXTURE)
+        AIRG.UI.motifButtons[i]:SetDimensions(40, 40)
+        AIRG.UI.motifButtons[i]:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 42*i +124, 0)
+        AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
+        AIRG.UI.motifButtons[i]:SetMouseEnabled(true)
+        j = AIRG.styleLookupValue[i]
+        tDesc ,_,_,_,_ = GetSmithingStyleItemInfo( AIRG.styleLookupItem[i] )
+        AIRG.UI.motifButtons[i].tooltipText = zo_strformat("<<t:1>>\n<<t:2>>", GetString("SI_ITEMSTYLE",j), tDesc)
+        AIRG.UI.motifButtons[i]:SetHandler("OnMouseEnter", function (self)
+                                                ZO_Tooltips_ShowTextTooltip(self, TOP, self.tooltipText)
+                                            end)
+        AIRG.UI.motifButtons[i]:SetHandler("OnMouseExit", function (self)
+                                                ZO_Tooltips_HideTextTooltip()
+                                            end)
+    end
+    -- BUILD LABEL FOR STYLES
+    AIRG.UI.StyleLabel = WINDOW_MANAGER:CreateControl("AIResearchStylelabel", AIRG.UI.motifSection, CT_LABEL)
+    AIRG.UI.StyleLabel:SetAnchor(TOPLEFT, AIRG.UI.motifSection, TOPLEFT, 5, 6)
+    AIRG.UI.StyleLabel:SetText(GetString(SI_SMITHING_HEADER_STYLE))
+    AIRG.UI.StyleLabel:SetDimensions(150, 24)
+    AIRG.UI.StyleLabel:SetFont("ZoFontGame")
+    AIRG.UI.StyleLabel:SetHorizontalAlignment(TEXT_ALIGN_RIGHT)
+
+end -- AIRG.initUI
+
+-- User has clicked on one of the profession buttons
+-- or we just want to refresh the display with current data
+function AIRG.OnCraftSelected(_,thisCraft)
+    if (thisCraft == nil) then
+        if (AIRG.curCraft == nil) then
+            return
+        else
+            thisCraft = AIRG.curCraft
+        end
+    end
+
+
+
+    AIRG.UI.WindowSubTitle:SetText(AIRG.craftNames[thisCraft])
+    local i,j,busy
+
+    local tType,tDesc,tKnown,tRemain,rowNum,traitCount
+    local maxLines = GetNumSmithingResearchLines(thisCraft) -- the number of columns for this profession
+    AIRG.curCraft = thisCraft
+    for i = 1, AIRG.maxColumns do
+        busy = false
+        -- "blank" the grid
+        for j = 1, 18 do
+            AIRG.UI.gridButtons[i][j]:SetColor(1, 1, 1, 0.4)
+            AIRG.UI.gridButtons[i][j]:SetTexture("/esoui/art/buttons/swatchframe_down.dds")
+            AIRG.UI.gridButtons[i][j]:SetMouseEnabled(false)    -- effectively disable tooltip for this grid item.
+        end
+        if (i > maxLines) then
+            AIRG.UI.columnButtons[i]:SetHidden(true)
+            AIRG.UI.columnFooters[i]:SetText("")
+        else
+            local name, icon, _, _ = GetSmithingResearchLineInfo(thisCraft, i)  -- Get info on that specific item
+            AIRG.UI.columnButtons[i]:SetNormalTexture(icon)
+            AIRG.UI.columnButtons[i]:SetHidden(false)
+            AIRG.UI.columnButtons[i].text = name
+
+            traitCount = 0
+            --Check for research expiry
+            for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
+              if (tKnown > 0 and tKnown < GetTimeStamp()) then
+                AIRG.vars.data[AIRG.curCharacter][thisCraft][i][rowNum] = -1  -- Change to known
+              end
+            end
+
+
+            if  AIRG.ShowRelative
+            then
+              -- Great! relative mode! we need to address a matter of practical usage.
+              --  We need to see that we actually can research that now, because we can't research more than one item type at a time.
+              --  So we need to pre-check for item research and set the colours (of the texture) appropriately
+              for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
+                  if (tKnown > 0) then  -- researching
+                      busy = true
+                  end
+              end
+
+              for rowNum,tKnown in pairs(AIRG.relative[AIRG.curCharacter][thisCraft][i]) do
+                  AIRG.UI.gridButtons[i][rowNum].tooltipText = tKnown
+                  if (tKnown == -1) then       -- Trait is known
+                    if (busy) then
+                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.7, 0.6, 0.6, .8)   -- Dull Reddish
+                    else
+                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
+                    end
+                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
+                    traitCount = traitCount + 1
+                  end
+              end
+
+
+            else -- not relative
+              for rowNum,tKnown in pairs(AIRG.vars.data[AIRG.curCharacter][thisCraft][i]) do
+                AIRG.UI.gridButtons[i][rowNum].tooltipText = tKnown
+                if (tKnown == -1) then       -- Trait is known
+                    AIRG.UI.gridButtons[i][rowNum]:SetColor(0.2, 1, 0.2, 1)   -- Green
+                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("/esoui/art/loot/loot_finesseitem.dds")
+                    traitCount = traitCount + 1
+                elseif (tKnown > 0) then   -- Trait is being researched
+                        AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/mounts/timer_icon.dds")
+                        AIRG.UI.gridButtons[i][rowNum]:SetColor(0.5, 0.5, 1, 1)   -- Blue
+                        AIRG.UI.gridButtons[i][rowNum]:SetMouseEnabled(true)
+                else                        -- Trait is NOT known
+                    AIRG.UI.gridButtons[i][rowNum]:SetColor(1, 0.2, 0.2, 1)   -- Red
+                    AIRG.UI.gridButtons[i][rowNum]:SetTexture("ESOUI/art/buttons/decline_up.dds")  --  an   "X".
+                end
+              end
+            end  --Relative
+
+            AIRG.UI.columnFooters[i]:SetText(traitCount)
+        end
+    end
+end -- AIRG:OnCraftSelected
+
+-- Invoked when the user selected a character from the dropdown box
+function AIRG.OnCharacterSelect(charName)
+
+    if (charName == nil) then
+        return
+    end
+    AIRG.curCharacter = charName
+
+      -- The Relative Button doesn't make sense if selecting these
+    if charName == AIRG.all or charName == AIRG.playerName then
+      AIRG.UI.btnUpdateOther:SetEnabled(false)
+      AIRG.ShowRelative = false
+    else
+      AIRG.UI.btnUpdateOther:SetEnabled(true)
+    end
+
+    AIRG.DisplayStyles()
+    AIRG.OnCraftSelected()
+
+end -- AIRG.OnCharacterSelect
+
+-- Deletes data for the named character from the saved data and removes them from the dropdown box.
+function AIRG.DeleteCharacter(charName)
+    -- Can't delete the current character
+    if (charName == AIRG.playerName or charName == AIRG.all or charName == AIRG.curCharacter) then
+        d(AIRG.L["DeleteFalse"])
+    else
+        if (AIRG.vars.data[charName] ~= nil) then
+            AIRG.vars.data[charName] = nil
+            d(AIRG.L["DeleteTrue"] .. charName)
+        end
+        if (AIRG.vars.styles[charName] ~= nil) then
+            AIRG.vars.styles[charName] = nil
+        end
+        AIRG.PopulateAll()
+    end
+end -- AIRG.DeleteCharacter
+
+-- This function cycles through all three professions and populates the data matrix for this characters
+-- This is carried out when the addon loasd to ensure the current character data is up-to-date.
+-- The "if" logic in this function guesses at which profession should be default to display as the one with most research in.
+function AIRG.PopulateMatrix()
+    local curCount = 0
+    local thisCount
+        AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING  --Default for new chars
+        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_BLACKSMITHING)
+        if (thisCount > curCount) then
+          AIRG.curCraft = CRAFTING_TYPE_BLACKSMITHING
+          curCount = thisCount
+        end
+        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_CLOTHIER)
+        if (thisCount > curCount) then
+          AIRG.curCraft = CRAFTING_TYPE_CLOTHIER
+            curCount = thisCount
+        end
+        thisCount = AIRG.CreateDataMatrix(CRAFTING_TYPE_WOODWORKING)
+        if (thisCount > curCount) then
+          AIRG.curCraft = CRAFTING_TYPE_WOODWORKING
+          curCount = thisCount
+        end
+      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_BLACKSMITHING)
+      AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_WOODWORKING)
+     AIRG.CreateDataMatrixRelative(CRAFTING_TYPE_CLOTHIER)
+end -- AIRG.PopulateMatrix
+
+-- Lookup the style data for the current character and send it to saved vars.
+function AIRG.PopulateStyleData()
+    AIRG.vars.styles[AIRG.playerName] = {}    -- create a table for this character's matrix
+    local i, j, known
+    for i = 1, 15 do
+        j = AIRG.styleLookupItem[i]
+        known = IsSmithingStyleKnown(j, 1) --patternIndex set to 1, temporary workaround for changes introduced in Update 4
+        AIRG.vars.styles[AIRG.playerName][i] = known
+    end
+end -- AIRG.PopulateStyleData
+
+-- When any character data changes we have to go through and create our virtual "All" from the beginning.
+-- its simplified by not having to reset to unknown as traits can't be forgotton.
+function AIRG.PopulateAll()
+    local craft, item, trait, thisname, style, known
+    for thisname, _ in pairs(AIRG.vars.data) do   --iterate over all characters
+      if thisname ~= AIRG.all then                --skip our virtual
+        for craft, _ in pairs(AIRG.vars.data[thisname]) do   --iterate over all crafts
+          for item, _ in pairs(AIRG.vars.data[thisname][craft]) do   --iterate over all weapons/armour
+            for trait, _ in pairs(AIRG.vars.data[thisname][craft][item]) do   --iterate over all traits
+              if AIRG.vars.data[thisname][craft][item][trait] ~=  0 then -- researching counts as learned.
+                 AIRG.vars.data[AIRG.all][craft][item][trait] = -1
+              end
+            end
+          end
+        end
+        -- Update the Styles for this char.
+        for style, known in pairs (AIRG.vars.styles[thisname]) do   --iterate over all styles
+          if known  then
+            AIRG.vars.styles[AIRG.all][style] = true
+          end
+       end
+      end
+    end
+ end  -- AIRG.PopulateAll
+
+
+-- Set the icon highlights for the currently selected character
+function AIRG.DisplayStyles()
+    local i
+    if (AIRG.vars.styles[AIRG.curCharacter] == nil) then
+        for i = 1, 15 do
+            AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
+            AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
+        end
+    else
+        for i = 1, 14 do
+            if (AIRG.vars.styles[AIRG.curCharacter][i]) then
+                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "down.dds")
+                AIRG.UI.motifButtons[i]:SetColor(0.7, 1, 0.7, 1)   -- Green
+            else
+                AIRG.UI.motifButtons[i]:SetTexture(AIRG.styleLookupIcons[i] .. "up.dds")
+                AIRG.UI.motifButtons[i]:SetColor(1, 1, 1, 0.7)   -- grey
+            end
+        end
+    end
+end -- AIRG.DisplayStyles()
+
+-- Look up all the data on this profession and commit to saved variables for this character.
+function AIRG.CreateDataMatrix(thisCraft)  -- for current  player, not the selected
+  local i, j
+    local tType, tKnown, tRemain, rowNum, tTargetStamp
+    local rCount = 0
+    local maxLines = GetNumSmithingResearchLines(thisCraft)     -- the number of columns for this profession
+    AIRG.vars.data[AIRG.playerName][thisCraft] = {}             -- create a table for this profession for real traits
+
+    -- Not relative updates, show all for Current Character
+    -- Cycle through items for this profession
+    for i = 1, maxLines do
+        AIRG.vars.data[AIRG.playerName][thisCraft][i] = {}      -- create a table for this item
+        -- Cycle through the traits for this item
+        for j = 1, 9 do
+            tType,_,tKnown = GetSmithingResearchLineTraitInfo(thisCraft,i,j)
+            _,tRemain = GetSmithingResearchLineTraitTimes(thisCraft,i,j)
+            rowNum = AIRG.gridTraits[tType]
+
+            if (tKnown) then
+                AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = -1       -- this trait is known
+                rCount = rCount + 1
+            else
+                if (tRemain) then
+                    tTargetStamp = GetTimeStamp() + tRemain
+                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = tTargetStamp   -- this trait is being currently researched
+                    -- The value we are setting this to is the timestamp for when the research will be complete.
+                else
+                    AIRG.vars.data[AIRG.playerName][thisCraft][i][rowNum] = 0   -- this trait is NOT known
+                end
+            end
+        end
+
+    end
+    return rCount       -- the total number of traits already researched in this profession
+end -- AIRG.CreateDataMatrix
+
+function AIRG.CreateDataMatrixRelative(thisCraft)  -- for the current selected  player, relative to the real player
+    local craft, item, trait, thisname, style, known
+
+    for thisname, _ in pairs(AIRG.vars.data) do   --iterate over all characters
+      if thisname ~= AIRG.all then                --skip our virtual
+        AIRG.relative[thisname] = {}
+        for craft, _ in pairs(AIRG.vars.data[thisname]) do   --iterate over all crafts
+          AIRG.relative[thisname][craft] = {}
+          for item, _ in pairs(AIRG.vars.data[thisname][craft]) do   --iterate over all weapons/armour
+            AIRG.relative[thisname][craft][item] = {}
+            for trait, _ in pairs(AIRG.vars.data[thisname][craft][item]) do   --iterate over all traits
+              AIRG.relative[thisname][craft][item][trait] = {}
+              if AIRG.vars.data[thisname][craft][item][trait] ==  0 then -- thischar doesn't have traits
+                if AIRG.vars.data[AIRG.playerName][craft][item][trait] ==  -1  ---PLayer Does
+                then AIRG.relative[thisname][craft][item][trait] = -1
+                else AIRG.relative[thisname][craft][item][trait] = nil
+                end
+              end
+            end
+          end
+        end
+      end
+    end
+end -- AIRG.CreateDataMatrix
+
+
+
+function AIRG.AssignGridTraits()
+    -- Translates the traitType to the correct ROW of the grid
+    AIRG.gridTraits = {}
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_POWERED] = 1
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_CHARGED] = 2
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_PRECISE] = 3
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_INFUSED] = 4
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_DEFENDING] = 5
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_TRAINING] = 6
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_SHARPENED] = 7
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_WEIGHTED] = 8
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_WEAPON_NIRNHONED] = 9
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_STURDY] = 10
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_IMPENETRABLE] = 11
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_REINFORCED] = 12
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_WELL_FITTED] = 13
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_TRAINING] = 14
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_INFUSED] = 15
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_EXPLORATION] = 16
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_DIVINES] = 17
+    AIRG.gridTraits[ITEM_TRAIT_TYPE_ARMOR_NIRNHONED] = 18
+end -- AIRG.AssignGridTraits
+
+function AIRG.AssignStyleLookups()
+    -- Lookup the correct icon for the style
+    AIRG.styleLookupIcons = {}
+    AIRG.styleLookupIcons[1] = "ESOUI/art/charactercreate/charactercreate_altmericon_"
+    AIRG.styleLookupIcons[2] = "ESOUI/art/charactercreate/charactercreate_argonianicon_"
+    AIRG.styleLookupIcons[3] = "ESOUI/art/charactercreate/charactercreate_bosmericon_"
+    AIRG.styleLookupIcons[4] = "ESOUI/art/charactercreate/charactercreate_bretonicon_"
+    AIRG.styleLookupIcons[5] = "ESOUI/art/charactercreate/charactercreate_dunmericon_"
+    AIRG.styleLookupIcons[6] = "ESOUI/art/charactercreate/charactercreate_khajiiticon_"
+    AIRG.styleLookupIcons[7] = "ESOUI/art/charactercreate/charactercreate_nordicon_"
+    AIRG.styleLookupIcons[8] = "ESOUI/art/charactercreate/charactercreate_orcicon_"
+    AIRG.styleLookupIcons[9] = "ESOUI/art/charactercreate/charactercreate_redguardicon_"
+    AIRG.styleLookupIcons[10] = "ESOUI/art/charactercreate/charactercreate_imperialicon_"
+    AIRG.styleLookupIcons[11] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[12] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[13] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[14] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    AIRG.styleLookupIcons[15] = "ESOUI/art/progression/progression_indexicon_weapons_"
+    -- Translate the icon position to the in-game type. Used for text look-up
+    AIRG.styleLookupValue = {}
+    AIRG.styleLookupValue[1] = ITEMSTYLE_RACIAL_HIGH_ELF
+    AIRG.styleLookupValue[2] = ITEMSTYLE_RACIAL_ARGONIAN
+    AIRG.styleLookupValue[3] = ITEMSTYLE_RACIAL_WOOD_ELF
+    AIRG.styleLookupValue[4] = ITEMSTYLE_RACIAL_BRETON
+    AIRG.styleLookupValue[5] = ITEMSTYLE_RACIAL_DARK_ELF
+    AIRG.styleLookupValue[6] = ITEMSTYLE_RACIAL_KHAJIIT
+    AIRG.styleLookupValue[7] = ITEMSTYLE_RACIAL_NORD
+    AIRG.styleLookupValue[8] = ITEMSTYLE_RACIAL_ORC
+    AIRG.styleLookupValue[9] = ITEMSTYLE_RACIAL_REDGUARD
+    AIRG.styleLookupValue[10] = ITEMSTYLE_AREA_IMPERIAL
+    AIRG.styleLookupValue[11] = ITEMSTYLE_AREA_ANCIENT_ELF
+    AIRG.styleLookupValue[12] = ITEMSTYLE_AREA_REACH
+    AIRG.styleLookupValue[13] = ITEMSTYLE_ENEMY_DAEDRIC
+    AIRG.styleLookupValue[14] = ITEMSTYLE_ENEMY_PRIMITIVE
+    AIRG.styleLookupValue[15] = ITEMSTYLE_AREA_DWEMER
+
+    -- This is a bit of a hack, but only because of the way ESO uses Style Items with different index to styles.
+    AIRG.styleLookupItem = {}
+    AIRG.styleLookupItem[1] = 8     -- Altmer       = Adamantite
+    AIRG.styleLookupItem[2] = 7     -- Argonian     = Flint
+    AIRG.styleLookupItem[3] = 9     -- Bosmer       = Bone
+    AIRG.styleLookupItem[4] = 2     -- Breton       = Molybdenum
+    AIRG.styleLookupItem[5] = 5     -- Dunmer       = Obsidian
+    AIRG.styleLookupItem[6] = 10    -- Khajit       = Moonstone
+    AIRG.styleLookupItem[7] = 6     -- Nord         = Corundum
+    AIRG.styleLookupItem[8] = 4     -- Orc          = Manganese
+    AIRG.styleLookupItem[9] = 3     -- Redguard     = Starmetal
+    AIRG.styleLookupItem[10] = 35   -- Imperial     = Nickel
+    AIRG.styleLookupItem[11] = 16   -- Ancient Elf  = Palladium
+    AIRG.styleLookupItem[12] = 18   -- Barbarian    = Copper
+    AIRG.styleLookupItem[13] = 21   -- Daedric      = Daedra Heart
+    AIRG.styleLookupItem[14] = 20   -- Primal       = Argentum
+    AIRG.styleLookupItem[15] = 15   -- Dwemer       = Dwemer Frame
+end -- AIRG.AssignStyleLookups
+
+
+function AIRG.Initialise(eventCode, addOnName)
+	-- Only initialize our own addon
+	if (AIRG.name ~= addOnName) then return end
+    -- Language text
+    AIRG.InitialiseLanguage()
+
+    -- Load the saved variables
+    AIRG.vars = ZO_SavedVars:NewAccountWide("AIRG_SavedVariables", 2, nil, AIRG.defaults)
+    AIRG.all = AIRG.L["ALL"]		-- replace Default with localise string
+
+    -- Register Keybinding
+    ZO_CreateStringId("SI_BINDING_NAME_TOGGLE_AIRG", "Toggle AI Research Grid")
+
+	-- Set-up some variables we'll want to refer to.
+    AIRG.craftNames = {}
+    AIRG.relative = {}
+    AIRG.craftNames[CRAFTING_TYPE_BLACKSMITHING]    = AIRG.L["BS"]
+    AIRG.craftNames[CRAFTING_TYPE_CLOTHIER]         = AIRG.L["Clothing"]
+    AIRG.craftNames[CRAFTING_TYPE_WOODWORKING]      = AIRG.L["Woodwork"]
+    AIRG.curCraft= CRAFTING_TYPE_WOODWORKING
+    AIRG.playerName = GetUnitName("player")
+    AIRG.curCharacter = GetUnitName("player")       -- Default the display to the current character
+    AIRG.AssignGridTraits()
+    AIRG.AssignStyleLookups()
+    AIRG.vars.styles[AIRG.all] = {}           -- and our virtual character
+
+    -- Create these here so the UI dropdown will have them first time around.
+    AIRG.vars.data[AIRG.playerName] = {}    -- create a table for this character's matrix
+    AIRG.vars.data[AIRG.all] = {}    -- and our virtual character
+
+  -- Create Empty data for Virtual Char set to 0, (Not known)
+    local i, j
+
+    AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING] = {}
+    -- Cycle through items for this profession
+    for i = 1, 7 do   -- Weapons
+        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i] = {}
+        -- Cycle through the traits for this item
+        for j = 1, 9 do
+                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i][j] = 0   -- set to not known
+        end
+    end
+    for i = 8, 14 do  -- Armour
+        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i] = {}
+        -- Cycle through the traits for this item
+        for j = 10, 18 do
+                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_BLACKSMITHING][i][j] = 0   -- set to not known
+        end
+    end
+
+    AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER] = {}
+    -- Cycle through items for this profession
+    for i = 1, 14 do
+        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER][i] = {}
+        -- Cycle through the traits for this item
+        for j = 10, 18  do
+                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_CLOTHIER][i][j] = 0   -- set to not known
+        end
+    end
+
+     AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING] = {}
+    -- Cycle through items for this profession
+    for i = 1, 5 do
+        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i] = {}
+        -- Cycle through the traits for this item
+        for j = 1, 9 do
+                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i][j] = 0   -- set to not known
+        end
+    end
+    for i = 6, 6 do  --Shields
+        AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i] = {}
+        -- Cycle through the traits for this item
+        for j = 10, 18 do
+                       AIRG.vars.data[AIRG.all][CRAFTING_TYPE_WOODWORKING][i][j] = 0   -- set to not known
+        end
+    end
+
+    --Create Empty Style Table
+    for i = 1, 14 do
+        AIRG.vars.styles[AIRG.all][i] = false
+    end
+
+ -- AIRG.CreateDataMatrix
+
+    -- Following replaced with PlayerActivate
+    -- Query data for THIS character and populate the data matrix with fresh data.
+    --AIRG.PopulateMatrix()
+
+    -- Query data for THIS character for STYLES
+    --AIRG.PopulateStyleData()
+
+    -- UI set-up. Create frames, position labels & buttons etc.
+    AIRG.initUI()
+
+    -- REGISTER for events that aren't initialise.
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_STARTED, AIRG.ResearchStarted)
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_SMITHING_TRAIT_RESEARCH_COMPLETED, AIRG.ResearchCompleted)
+
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_STYLE_LEARNED, AIRG.StyleLearned)
+
+    EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_PLAYER_ACTIVATED, AIRG.PlayerActivated)
+
+    -- Create the configuration/settings menu.
+    AIRG.CreateConfigMenu()
+
+    AIRG.initialised = true
+end -- AIRG.Initialise
+
+EVENT_MANAGER:RegisterForEvent("AIRG", EVENT_ADD_ON_LOADED, AIRG.Initialise)
+-- SLASH COMMAND FUNCTIONALITY
+function AIRGslash(extra)
+    AIRG.ToggleMainWindow()
+end -- AIRGslash
+
+
+SLASH_COMMANDS["/airg"] = AIRGslash
+-- EOF
diff --git a/doc/changelog.txt b/doc/changelog.txt
index be097f0..5e12c21 100644
--- a/doc/changelog.txt
+++ b/doc/changelog.txt
@@ -1,95 +1,101 @@
-2014-12-12 V3.1.6
-	New Feature
-	None
-	Bugs Fixed
-	None
-	Other
-	doc folder added, prepared for better localisation, set up for git on esoui
-
-2014-12-09 V3.1.5
-	New Feature
-	Show Dwemer Motifs (not tested, the author doesn't have any)  by rkuhnjr
-	Bugs Fixed
-	None
-
-2014-12-05 V3.1.4
-	New Feature
-	Localization files now used for relative button, but translations not provided
-	Bugs Fixed
-	None
-	Note: this file does not have a txt extension, for good reason!
-
-2014-12-05 V3.1.2
-	New Feature
-	None
-	Bugs Fixed
-	Deleting charater data for selected char caused crash
-	In relative mode, scrolling through chars would not update for completed research.
-
-2014-12-05 V3.1
-	New features
-	If using the relative mode but the destination character is already researching that item, the icon will be a dull red tick.
-	Characters can only research 1 trait in a item at at time, no matter how many research slots might be available.
-
-2014-12-03  V3.0.0  Sent to Stormknight and CDG
-	Bugs Fixed
-	-- might not display correctly on a char with no traits learned
-	--if trait timer completes on another char, the trait goes green, but the icon remains the hourglass.
-	New Feature
-	Add a button to put it in relative mode.
-		Provided you have one other char in there (it is disabled for #all and the current player), it will show the traits that the current player can make (or will be able to make if still in research) that the selected char doesn't have. This is for when you are trying to consolidate traits on to your main crafting chars, to get that magical "8" traits known. If you are like me, you might get alts to learn traits because you don't have the bank space to hold the item.
-
-
-
-2014-12-01  V3.0.0  Sent to Stormknight and CDG
-	New Feature
-		Added #ALL
-
-2.3
-- Attempt to fix bug where some items show up as unresearched while they are ...
-
-2.2
-- API 100009, merged fixes made by Garkin. (Will reset saved variables)
-
-2.1
-- API 100008
-
-2.0
-- Updated for 1.2.3 : Veteran Crypt of Hearts
-
-1.3.2.
-- Update for API version number.
-
-1.3.1
-- [Oops] I'd forgotten the DE and FR language files!
-
-1.3.0
-- [Feature] Added options page - ability to hide motifs section.
-- [Feature] Added tooltips to the timers on the grid, showing remaining time.
-- [Fix] Correctly identifies when you have learned a new style motif.
-- [Fix] Correctly identifies when you have learned a new trait.
-
-1.2.3
-- [Fix] Code tidy & optimisation ready for additional features.
-
-1.2.2
-- [Fix] Minor bug fixes and typo corrections.
-
-1.2.1
-- [Fix] Removed debug mode from the /airg command.
-- [Feature] Added close window button to the top-right of the frame.
-
-1.2.0
-- [Feature] Now has motifs!
-- [Fix] Correctly blanks column totals where they shouldn't be displayed.
-
-1.1.0
-- [Feature] Now has support for multiple characters, viewing info on all characters for the account.
-- [Fix] Most localization issues resolved.
-
-1.0.2
-- [Fix] Keybind now uses SI_KEYBINDINGS_LAYER_GENERAL instead of "General"
-
-1.0.1
-- Tidied up the design slightly
+2014-12-12 V3.1.7
+	New Feature
+	None
+	Bugs Fixed
+	Styles not showing highlighted on first load
+
+2014-12-12 V3.1.6
+	New Feature
+	None
+	Bugs Fixed
+	None
+	Other
+	doc folder added, prepared for better localisation, set up for git on esoui
+
+2014-12-09 V3.1.5
+	New Feature
+	Show Dwemer Motifs (not tested, the author doesn't have any)  by rkuhnjr
+	Bugs Fixed
+	None
+
+2014-12-05 V3.1.4
+	New Feature
+	Localization files now used for relative button, but translations not provided
+	Bugs Fixed
+	None
+	Note: this file does not have a txt extension, for good reason!
+
+2014-12-05 V3.1.2
+	New Feature
+	None
+	Bugs Fixed
+	Deleting charater data for selected char caused crash
+	In relative mode, scrolling through chars would not update for completed research.
+
+2014-12-05 V3.1
+	New features
+	If using the relative mode but the destination character is already researching that item, the icon will be a dull red tick.
+	Characters can only research 1 trait in a item at at time, no matter how many research slots might be available.
+
+2014-12-03  V3.0.0  Sent to Stormknight and CDG
+	Bugs Fixed
+	-- might not display correctly on a char with no traits learned
+	--if trait timer completes on another char, the trait goes green, but the icon remains the hourglass.
+	New Feature
+	Add a button to put it in relative mode.
+		Provided you have one other char in there (it is disabled for #all and the current player), it will show the traits that the current player can make (or will be able to make if still in research) that the selected char doesn't have. This is for when you are trying to consolidate traits on to your main crafting chars, to get that magical "8" traits known. If you are like me, you might get alts to learn traits because you don't have the bank space to hold the item.
+
+
+
+2014-12-01  V3.0.0  Sent to Stormknight and CDG
+	New Feature
+		Added #ALL
+
+2.3
+- Attempt to fix bug where some items show up as unresearched while they are ...
+
+2.2
+- API 100009, merged fixes made by Garkin. (Will reset saved variables)
+
+2.1
+- API 100008
+
+2.0
+- Updated for 1.2.3 : Veteran Crypt of Hearts
+
+1.3.2.
+- Update for API version number.
+
+1.3.1
+- [Oops] I'd forgotten the DE and FR language files!
+
+1.3.0
+- [Feature] Added options page - ability to hide motifs section.
+- [Feature] Added tooltips to the timers on the grid, showing remaining time.
+- [Fix] Correctly identifies when you have learned a new style motif.
+- [Fix] Correctly identifies when you have learned a new trait.
+
+1.2.3
+- [Fix] Code tidy & optimisation ready for additional features.
+
+1.2.2
+- [Fix] Minor bug fixes and typo corrections.
+
+1.2.1
+- [Fix] Removed debug mode from the /airg command.
+- [Feature] Added close window button to the top-right of the frame.
+
+1.2.0
+- [Feature] Now has motifs!
+- [Fix] Correctly blanks column totals where they shouldn't be displayed.
+
+1.1.0
+- [Feature] Now has support for multiple characters, viewing info on all characters for the account.
+- [Fix] Most localization issues resolved.
+
+1.0.2
+- [Fix] Keybind now uses SI_KEYBINDINGS_LAYER_GENERAL instead of "General"
+
+1.0.1
+- Tidied up the design slightly
 - [Feature] Added proper tooltips to the items at the top of each column and also to the trait names.
\ No newline at end of file