diff --git a/Librarian.lua b/Librarian.lua
index b21af2a..be8108a 100644
--- a/Librarian.lua
+++ b/Librarian.lua
@@ -21,17 +21,44 @@ local scrollChild
local sortField = "Found"
local sortAscending = false
+local time_formats = {
+ { name = "12 hour", value = TIME_FORMAT_PRECISION_TWELVE_HOUR},
+ { name = "24 hour", value = TIME_FORMAT_PRECISION_TWENTY_FOUR_HOUR}
+}
+
function Librarian:Initialise()
scrollChild = LibrarianFrameScrollContainer:GetNamedChild("ScrollChild")
scrollChild:SetAnchor(TOPRIGHT, nil, TOPRIGHT, -5, 0)
self.savedVars = ZO_SavedVars:New("Librarian_SavedVariables", 1, nil, self.defaults, nil)
+ if self.savedVars.setting_time_format == nil then
+ self.savedVars.setting_time_format = (GetCVar("Language.2") == "en") and TIME_FORMAT_PRECISION_TWELVE_HOUR or TIME_FORMAT_PRECISION_TWENTY_FOUR_HOUR
+ end
+
+ self:InitialiseSettings()
+
self:SortBooks()
self:InitializeKeybindStripDescriptors()
self:InitializeScene()
end
+function Librarian:InitialiseSettings()
+ local LAM = LibStub("LibAddonMenu-1.0")
+ local optionsPanel = LAM:CreateControlPanel("LibrarianOptions", "Librarian")
+
+ local time_formats_list = map(time_formats, function(item) return item.name end)
+ d(self.savedVars.setting_time_format)
+
+ LAM:AddDropdown(optionsPanel, "LibrarianOptionsTimeFormat", "Time Format",
+ "Select a format to display times in.", time_formats_list,
+ function() return getName(time_formats, self.savedVars.setting_time_format) end,
+ function(format)
+ self.savedVars.setting_time_format = getValue(time_formats, format)
+ self:LayoutBooks()
+ end)
+end
+
function Librarian:InitializeKeybindStripDescriptors()
self.keybindStripDescriptor =
{
@@ -255,10 +282,6 @@ function Librarian:OnMouseExit(buttonPart)
end
function Librarian:FormatClockTime(time)
- if(CLOCK_FORMAT == nil) then
- CLOCK_FORMAT = (GetCVar("Language.2") == "en") and TIME_FORMAT_PRECISION_TWELVE_HOUR or TIME_FORMAT_PRECISION_TWENTY_FOUR_HOUR
- end
-
local midnightSeconds = GetSecondsSinceMidnight()
local utcSeconds = GetTimeStamp() % 86400
local offset = midnightSeconds - utcSeconds
@@ -267,7 +290,7 @@ function Librarian:FormatClockTime(time)
end
local dateString = GetDateStringFromTimestamp(time)
- local timeString = ZO_FormatTime((time + offset) % 86400, TIME_FORMAT_STYLE_CLOCK_TIME, CLOCK_FORMAT)
+ local timeString = ZO_FormatTime((time + offset) % 86400, TIME_FORMAT_STYLE_CLOCK_TIME, self.savedVars.setting_time_format)
return string.format("%s %s", dateString, timeString)
end
@@ -281,6 +304,26 @@ local function OnAddonLoaded(event, addon)
end
end
+function map(tbl, f)
+ local t = {}
+ for k,v in pairs(tbl) do
+ t[k] = f(v)
+ end
+ return t
+end
+
+function getValue(tbl, name)
+ for _,p in pairs(tbl) do
+ if p.name == name then return p.value end
+ end
+end
+
+function getName(tbl, value)
+ for _,p in pairs(tbl) do
+ if p.value == value then return p.name end
+ end
+end
+
local function OnShowBook(eventCode, title, body, medium, showTitle)
Librarian:StoreBook(title, body, medium, showTitle)
end
diff --git a/Librarian.txt b/Librarian.txt
index 2744ee1..45a9858 100644
--- a/Librarian.txt
+++ b/Librarian.txt
@@ -3,6 +3,9 @@
## APIVersion: 100003
## SavedVariables: Librarian_SavedVariables
+Libs\LibStub\LibStub.lua
+Libs\LibAddonMenu-1.0\LibAddonMenu-1.0.lua
+
Librarian.lua
Librarian.xml
Bindings.xml
\ No newline at end of file
diff --git a/Libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua b/Libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
new file mode 100644
index 0000000..3a4e13d
--- /dev/null
+++ b/Libs/LibAddonMenu-1.0/LibAddonMenu-1.0.lua
@@ -0,0 +1,357 @@
+local MAJOR, MINOR = "LibAddonMenu-1.0", 4
+local lam, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+if not lam then return end --the same or newer version of this lib is already loaded into memory
+
+--UPVALUES--
+lam.lastAddedControl = {}
+local lastAddedControl = lam.lastAddedControl
+local wm = GetWindowManager()
+local strformat = string.format
+local tostring = tostring
+local round = zo_round
+local optionsWindow = ZO_OptionsWindowSettingsScrollChild
+
+--maybe return the controls from the creation functions?
+
+function lam:CreateControlPanel(controlPanelID, controlPanelName)
+ local panelID
+
+ if _G[controlPanelID] then
+ panelID = _G[controlPanelID]
+ return panelID
+ end
+
+ ZO_OptionsWindow_AddUserPanel(controlPanelID, controlPanelName)
+
+ --disables Defaults button because we don't need it, but keybind still works :/ ...
+ panelID = _G[controlPanelID]
+ ZO_PreHook("ZO_OptionsWindow_ChangePanels", function(panel)
+ local enable = (panel ~= panelID)
+ ZO_OptionsWindowResetToDefaultButton:SetEnabled(enable)
+ ZO_OptionsWindowResetToDefaultButton:SetKeybindEnabled(enable)
+ end)
+
+ return panelID
+end
+
+function lam:AddHeader(panelID, controlName, text)
+ local header = wm:CreateControlFromVirtual(controlName, optionsWindow, lastAddedControl[panelID] and "ZO_Options_SectionTitle_WithDivider" or "ZO_Options_SectionTitle")
+ if lastAddedControl[panelID] then
+ header:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 15)
+ else
+ header:SetAnchor(TOPLEFT)
+ end
+ header.controlType = OPTIONS_SECTION_TITLE
+ header.panel = panelID
+ header.text = text
+
+ ZO_OptionsWindow_InitializeControl(header)
+
+ lastAddedControl[panelID] = header
+end
+
+
+--To-Do list:
+--extra sub-options window out to the right?? (or maybe addon list?)
+--find alternatives to handler hooks
+
+function lam:AddSlider(panelID, controlName, text, tooltip, minValue, maxValue, step, getFunc, setFunc, warning, warningText)
+ local slider = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Slider")
+ slider:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+ slider.controlType = OPTIONS_SLIDER
+ slider.system = SETTING_TYPE_UI
+ slider.panel = panelID
+ slider.text = text
+ slider.tooltipText = tooltip
+ slider.showValue = true
+ slider.showValueMin = minValue
+ slider.showValueMax = maxValue
+ local range = maxValue - minValue
+ local slidercontrol = slider:GetNamedChild("Slider")
+ local slidervalue = slider:GetNamedChild("ValueLabel")
+ slidercontrol:SetValueStep(1/range * step)
+ slider:SetHandler("OnShow", function()
+ local curValue = getFunc()
+ slidercontrol:SetValue((curValue - minValue)/range)
+ slidervalue:SetText(tostring(curValue))
+ end)
+ slidercontrol:SetHandler("OnValueChanged", function (self, value)
+ self:SetValue(value)
+ value = round(value*range + minValue)
+ slidervalue:SetText(strformat("%d", value))
+ end)
+ slidercontrol:SetHandler("OnSliderReleased", function(self, value)
+ value = round(value*range + minValue)
+ setFunc(value)
+ end)
+
+ if warning then
+ slider.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", slider, "ZO_Options_WarningIcon")
+ slider.warning:SetAnchor(RIGHT, slidercontrol, LEFT, -5, 0)
+ slider.warning.tooltipText = warningText
+ end
+
+ ZO_OptionsWindow_InitializeControl(slider)
+
+ lastAddedControl[panelID] = slider
+end
+
+function lam:AddDropdown(panelID, controlName, text, tooltip, validChoices, getFunc, setFunc, warning, warningText)
+ local dropdown = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Dropdown")
+ dropdown:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+ dropdown.controlType = OPTIONS_DROPDOWN
+ dropdown.system = SETTING_TYPE_UI
+ dropdown.panel = panelID
+ dropdown.text = text
+ dropdown.tooltipText = tooltip
+ dropdown.valid = validChoices
+ local dropmenu = ZO_ComboBox_ObjectFromContainer(GetControl(dropdown, "Dropdown"))
+ local setText = dropmenu.m_selectedItemText.SetText
+ local selectedName
+ ZO_PreHookHandler(dropmenu.m_selectedItemText, "OnTextChanged", function(self)
+ if dropmenu.m_selectedItemData then
+ selectedName = dropmenu.m_selectedItemData.name
+ setText(self, selectedName)
+ setFunc(selectedName)
+ end
+ end)
+ dropdown:SetHandler("OnShow", function()
+ dropmenu:SetSelectedItem(getFunc())
+ end)
+
+ if warning then
+ dropdown.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", dropdown, "ZO_Options_WarningIcon")
+ dropdown.warning:SetAnchor(RIGHT, dropdown:GetNamedChild("Dropdown"), LEFT, -5, 0)
+ dropdown.warning.tooltipText = warningText
+ end
+
+ ZO_OptionsWindow_InitializeControl(dropdown)
+
+ lastAddedControl[panelID] = dropdown
+end
+
+function lam:AddCheckbox(panelID, controlName, text, tooltip, getFunc, setFunc, warning, warningText)
+ local checkbox = wm:CreateControlFromVirtual(controlName, optionsWindow, "ZO_Options_Checkbox")
+ checkbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+ checkbox.controlType = OPTIONS_CHECKBOX
+ checkbox.system = SETTING_TYPE_UI
+ checkbox.settingId = _G[strformat("SETTING_%s", controlName)]
+ checkbox.panel = panelID
+ checkbox.text = text
+ checkbox.tooltipText = tooltip
+
+ local checkboxButton = checkbox:GetNamedChild("Checkbox")
+
+ ZO_PreHookHandler(checkbox, "OnShow", function()
+ checkboxButton:SetState(getFunc() and 1 or 0)
+ checkboxButton:toggleFunction(getFunc())
+ end)
+ ZO_PreHookHandler(checkboxButton, "OnClicked", function() setFunc(not getFunc()) end)
+
+ if warning then
+ checkbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", checkbox, "ZO_Options_WarningIcon")
+ checkbox.warning:SetAnchor(RIGHT, checkboxButton, LEFT, -5, 0)
+ checkbox.warning.tooltipText = warningText
+ end
+
+ ZO_OptionsWindow_InitializeControl(checkbox)
+
+ lastAddedControl[panelID] = checkbox
+end
+
+function lam:AddColorPicker(panelID, controlName, text, tooltip, getFunc, setFunc, warning, warningText)
+ local colorpicker = wm:CreateTopLevelWindow(controlName)
+ colorpicker:SetParent(optionsWindow)
+ colorpicker:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
+ colorpicker:SetResizeToFitDescendents(true)
+ colorpicker:SetWidth(510)
+ colorpicker:SetMouseEnabled(true)
+
+ colorpicker.label = wm:CreateControl(controlName.."Label", colorpicker, CT_LABEL)
+ local label = colorpicker.label
+ label:SetDimensions(300, 26)
+ label:SetAnchor(TOPLEFT)
+ label:SetFont("ZoFontWinH4")
+ label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+ label:SetText(text)
+
+ colorpicker.color = wm:CreateControl(controlName.."Color", colorpicker, CT_CONTROL)
+ local color = colorpicker.color
+ color:SetDimensions(200,26)
+ color:SetAnchor(RIGHT)
+
+ color.thumb = wm:CreateControl(controlName.."ColorThumb", color, CT_TEXTURE)
+ local thumb = color.thumb
+ thumb:SetDimensions(36, 18)
+ thumb:SetAnchor(LEFT, color, LEFT, 4, 0)
+ local r, g, b, a = getFunc()
+ thumb:SetColor(r, g, b, a or 1)
+
+ color.border = wm:CreateControl(controlName.."ColorBorder", color, CT_TEXTURE)
+ local border = color.border
+ border:SetTexture("EsoUI\\Art\\ChatWindow\\chatOptions_bgColSwatch_frame.dds")
+ border:SetTextureCoords(0, .625, 0, .8125)
+ border:SetDimensions(40, 22)
+ border:SetAnchor(CENTER, thumb, CENTER, 0, 0)
+
+ local ColorPickerCallback
+ if not ColorPickerCallback then
+ ColorPickerCallback = function(r, g, b, a)
+ thumb:SetColor(r, g, b, a or 1)
+ setFunc(r, g, b, a)
+ end
+ end
+
+ colorpicker.controlType = OPTIONS_CUSTOM
+ colorpicker.customSetupFunction = function(colorpicker)
+ colorpicker:SetHandler("OnMouseUp", function(self, btn, upInside)
+ if upInside then
+ local r, g, b, a = getFunc()
+ COLOR_PICKER:Show(ColorPickerCallback, r, g, b, a, text)
+ end
+ end)
+ end
+ colorpicker.panel = panelID
+ colorpicker.tooltipText = tooltip
+ colorpicker:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+ colorpicker:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+
+ if warning then
+ colorpicker.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", colorpicker, "ZO_Options_WarningIcon")
+ colorpicker.warning:SetAnchor(RIGHT, colorpicker:GetNamedChild("Color"), LEFT, -5, 0)
+ colorpicker.warning.tooltipText = warningText
+ end
+
+ ZO_OptionsWindow_InitializeControl(colorpicker)
+
+ lastAddedControl[panelID] = colorpicker
+end
+
+function lam:AddEditBox(panelID, controlName, text, tooltip, isMultiLine, getFunc, setFunc, warning, warningText)
+ local editbox = wm:CreateTopLevelWindow(controlName)
+ editbox:SetParent(optionsWindow)
+ editbox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
+ editbox:SetResizeToFitDescendents(true)
+ editbox:SetWidth(510)
+ editbox:SetMouseEnabled(true)
+
+ editbox.label = wm:CreateControl(controlName.."Label", editbox, CT_LABEL)
+ local label = editbox.label
+ label:SetDimensions(300, 26)
+ label:SetAnchor(TOPLEFT)
+ label:SetFont("ZoFontWinH4")
+ label:SetWrapMode(TEXT_WRAP_MODE_ELLIPSIS)
+ label:SetText(text)
+
+ editbox.bg = wm:CreateControlFromVirtual(controlName.."BG", editbox, "ZO_EditBackdrop")
+ local bg = editbox.bg
+ bg:SetDimensions(200,isMultiLine and 100 or 24)
+ bg:SetAnchor(RIGHT)
+ editbox.edit = wm:CreateControlFromVirtual(controlName.."Edit", bg, isMultiLine and "ZO_DefaultEditMultiLineForBackdrop" or "ZO_DefaultEditForBackdrop")
+ editbox.edit:SetText(getFunc())
+ editbox.edit:SetHandler("OnFocusLost", function(self) setFunc(self:GetText()) end)
+
+
+ editbox.panel = panelID
+ editbox.tooltipText = tooltip
+ editbox:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+ editbox:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+
+ if warning then
+ editbox.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", editbox, "ZO_Options_WarningIcon")
+ editbox.warning:SetAnchor(TOPRIGHT, editbox:GetNamedChild("BG"), TOPLEFT, -5, 0)
+ editbox.warning.tooltipText = warningText
+ end
+
+ ZO_OptionsWindow_InitializeControl(editbox)
+
+ lastAddedControl[panelID] = editbox
+end
+
+function lam:AddButton(panelID, controlName, text, tooltip, onClick, warning, warningText)
+ local button = wm:CreateTopLevelWindow(controlName)
+ button:SetParent(optionsWindow)
+ button:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 6)
+ button:SetDimensions(510, 28)
+ button:SetMouseEnabled(true)
+
+ button.btn = wm:CreateControlFromVirtual(controlName.."Button", button, "ZO_DefaultButton")
+ local btn = button.btn
+ btn:SetAnchor(TOPRIGHT)
+ btn:SetWidth(200)
+ btn:SetText(text)
+ btn:SetHandler("OnClicked", onClick)
+
+ button.controlType = OPTIONS_CUSTOM
+ button.customSetupFunction = function() end --move handlers into this function? (since I created a function...)
+ button.panel = panelID
+ btn.tooltipText = tooltip
+ btn:SetHandler("OnMouseEnter", ZO_Options_OnMouseEnter)
+ btn:SetHandler("OnMouseExit", ZO_Options_OnMouseExit)
+
+ if warning then
+ button.warning = wm:CreateControlFromVirtual(controlName.."WarningIcon", button, "ZO_Options_WarningIcon")
+ button.warning:SetAnchor(RIGHT, btn, LEFT, -5, 0)
+ button.warning.tooltipText = warningText
+ end
+
+ ZO_OptionsWindow_InitializeControl(button)
+
+ lastAddedControl[panelID] = button
+end
+
+function lam:AddDescription(panelID, controlName, text, titleText)
+ local textBox = wm:CreateTopLevelWindow(controlName)
+ textBox:SetParent(optionsWindow)
+ textBox:SetAnchor(TOPLEFT, lastAddedControl[panelID], BOTTOMLEFT, 0, 10)
+ textBox:SetResizeToFitDescendents(true)
+ textBox:SetWidth(510)
+
+ if titleText then
+ textBox.title = wm:CreateControl(controlName.."Title", textBox, CT_LABEL)
+ local title = textBox.title
+ title:SetWidth(510)
+ title:SetAnchor(TOPLEFT, textBox, TOPLEFT)
+ title:SetFont("ZoFontWinH4")
+ title:SetText(headerText)
+ end
+
+ textBox.desc = wm:CreateControl(controlName.."Text", textBox, CT_LABEL)
+ local desc = textBox.desc
+ desc:SetWidth(510)
+ if titleText then
+ desc:SetAnchor(TOPLEFT, textBox.title, BOTTOMLEFT)
+ else
+ desc:SetAnchor(TOPLEFT)
+ end
+ desc:SetVerticalAlignment(TEXT_ALIGN_TOP)
+ desc:SetFont("ZoFontGame")
+ desc:SetText(text)
+
+ textBox.controlType = OPTIONS_CUSTOM
+ textBox.panel = panelID
+
+ ZO_OptionsWindow_InitializeControl(textBox)
+
+ lastAddedControl[panelID] = textBox
+end
+
+
+--test controls--
+--[[local controlPanelID = lam:CreateControlPanel("ZAM_ADDON_OPTIONS", "ZAM Addons")
+lam:AddHeader(controlPanelID, "ZAM_Addons_TESTADDON", "TEST ADDON")
+lam:AddDescription(controlPanelID, "ZAM_Addons_TESTDESC", "This is a test description.", "Header")
+lam:AddSlider(controlPanelID, "ZAM_TESTSLIDER", "Test slider", "Adjust the slider.", 1, 10, 1, function() return 7 end, function(value) end, true, "needs UI reload")
+lam:AddDropdown(controlPanelID, "ZAM_TESTDROPDOWN", "Test Dropdown", "Pick something!", {"thing 1", "thing 2", "thing 3"}, function() return "thing 2" end, function(self,valueString) print(valueString) end)
+local checkbox1 = true
+lam:AddCheckbox(controlPanelID, "ZAM_TESTCHECKBOX", "Test Checkbox", "On or off?", function() return checkbox1 end, function(value) checkbox1 = not checkbox1 print(value, checkbox1) end)
+lam:AddColorPicker(controlPanelID, "ZAM_TESTCOLORPICKER", "Test color picker", "What's your favorite color?", function() return 1, 1, 0 end, function(r,g,b) print(r,g,b) end)
+lam:AddEditBox(controlPanelID, "ZAM_TESTEDITBOX", "Test Edit Box", "This is a tooltip!", false, function() return "hi" end, function(text) print(text) end)
+lam:AddHeader(controlPanelID, "ZAM_Addons_TESTADDON2", "TEST ADDON 2")
+local checkbox2 = false
+lam:AddCheckbox(controlPanelID, "ZAM_TESTCHECKBOX2", "Test Checkbox 2", "On or off?", function() return checkbox2 end, function(value) checkbox2 = not checkbox2 print(value, checkbox2) end)
+lam:AddButton(controlPanelID, "ZAM_TESTBUTTON", "Test Button", "Click me", function() print("hi") end, true, "oh noez!")
+lam:AddEditBox(controlPanelID, "ZAM_TESTEDITBOX2", "Test Edit Box 2", "This is a tooltip!", true, function() return "hi" end, function(text) print(text) end, true, "warning text")
+lam:AddSlider(controlPanelID, "ZAM_TESTSLIDER2", "Test slider 2", "Adjust the slider.", 50, 100, 10, function() return 80 end, function(value) end)
+lam:AddDropdown(controlPanelID, "ZAM_TESTDROPDOWN2", "Test Dropdown 2", "Pick something!", {"thing 4", "thing 5", "thing 6"}, function() return "thing 6" end, function(self,valueString) print(valueString) end)
+]]--
\ No newline at end of file
diff --git a/Libs/LibStub/LibStub.lua b/Libs/LibStub/LibStub.lua
new file mode 100644
index 0000000..bfd96df
--- /dev/null
+++ b/Libs/LibStub/LibStub.lua
@@ -0,0 +1,34 @@
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+-- LibStub developed for World of Warcraft by above members of the WowAce community.
+-- Ported to Elder Scrolls Online by Seerah
+
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 1 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+local strformat = string.format
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):strformat(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ function LibStub:IterateLibraries() return pairs(self.libs) end
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end