1 -- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
2 -- LibStub is hereby placed in the Public Domain
3 -- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
4 local LIBSTUB_MAJOR
, LIBSTUB_MINOR
= "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
5 local LibStub
= _G
[LIBSTUB_MAJOR
]
7 -- Check to see is this version of the stub is obsolete
8 if not LibStub
or LibStub
.minor
< LIBSTUB_MINOR
then
9 LibStub
= LibStub
or {libs
= {}, minors
= {} }
10 _G
[LIBSTUB_MAJOR
] = LibStub
11 LibStub
.minor
= LIBSTUB_MINOR
13 -- LibStub:NewLibrary(major, minor)
14 -- major (string) - the major version of the library
15 -- minor (string or number ) - the minor version of the library
17 -- returns nil if a newer or same version of the lib is already present
18 -- returns empty library object or old library object if upgrade is needed
19 function LibStub
:NewLibrary(major
, minor
)
20 assert(type(major
) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
21 minor
= assert(tonumber(strmatch(minor
, "%d+")), "Minor version must either be a number or contain a number.")
23 local oldminor
= self
.minors
[major
]
24 if oldminor
and oldminor
>= minor
then return nil end
25 self
.minors
[major
], self
.libs
[major
] = minor
, self
.libs
[major
] or {}
26 return self
.libs
[major
], oldminor
29 -- LibStub:GetLibrary(major, [silent])
30 -- major (string) - the major version of the library
31 -- silent (boolean) - if true, library is optional, silently return nil if its not found
33 -- throws an error if the library can not be found (except silent is set)
34 -- returns the library object if found
35 function LibStub
:GetLibrary(major
, silent
)
36 if not self
.libs
[major
] and not silent
then
37 error(("Cannot find a library instance of %q."):format(tostring(major
)), 2)
39 return self
.libs
[major
], self
.minors
[major
]
42 -- LibStub:IterateLibraries()
44 -- Returns an iterator for the currently registered libraries
45 function LibStub
:IterateLibraries()
46 return pairs(self
.libs
)
49 setmetatable(LibStub
, { __call
= LibStub
.GetLibrary
})
52 --[[-------------------------------------------------------------------------
53 Copyright (c) 2006-2007, Dongle Development Team
56 Redistribution and use in source and binary forms, with or without
57 modification, are permitted provided that the following conditions are
60 * Redistributions of source code must retain the above copyright
61 notice, this list of conditions and the following disclaimer.
62 * Redistributions in binary form must reproduce the above
63 copyright notice, this list of conditions and the following
64 disclaimer in the documentation and/or other materials provided
65 with the distribution.
66 * Neither the name of the Dongle Development Team nor the names of
67 its contributors may be used to endorse or promote products derived
68 from this software without specific prior written permission.
70 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
71 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
72 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
73 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
74 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
75 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
76 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
77 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
78 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
79 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
80 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
81 ---------------------------------------------------------------------------]]
83 --[[-------------------------------------------------------------------------
84 Begin Library Implementation
85 ---------------------------------------------------------------------------]]
86 local major
= "OptionHouse-1.1"
87 local minor
= tonumber(string.match("$Revision: 619 $", "(%d+)") or 1)
89 assert(LibStub
, string.format("%s requires LibStub.", major
))
91 local OHInstance
, oldRevision
= LibStub
:NewLibrary(major
, minor
)
92 if( not OHInstance
) then return end
95 ["ERROR_NO_FRAME"] = "No frame returned for the addon \"%s\", category \"%s\", sub category \"%s\".",
96 ["NO_FUNC_PASSED"] = "You must associate a function with a category.",
97 ["BAD_ARGUMENT"] = "bad argument #%d to '%s' (%s expected, got %s)",
98 ["MUST_CALL"] = "You must call '%s' from an OptionHouse addon object.",
99 ["ADDON_ALREADYREG"] = "The addon '%s' is already registered with OptionHouse.",
100 ["UNKNOWN_TAB"] = "Cannot open tab #%d, only %d tabs are registered.",
101 ["CATEGORY_ALREADYREG"] = "The category '%s' already exists in '%s'",
102 ["NO_CATEGORYEXISTS"] = "No category named '%s' in '%s' exists.",
103 ["NO_SUBCATEXISTS"] = "No sub-category '%s' exists in '%s' for the addon '%s'.",
104 ["NO_PARENTCAT"] = "No parent category named '%s' exists in %s'",
105 ["SUBCATEGORY_ALREADYREG"] = "The sub-category named '%s' already exists in the category '%s' for '%s'",
106 ["UNKNOWN_FRAMETYPE"] = "Unknown frame type given '%s', only 'main', 'perf', 'addon', 'config' are supported.",
107 ["OPTION_HOUSE"] = "Option House",
108 ["ENTERED_COMBAT"] = "|cFF33FF99Option House|r: Configuration window closed due to entering combat.",
109 ["SEARCH"] = "Search...",
110 ["ADDON_OPTIONS"] = "Addons",
111 ["VERSION"] = "Version: %s",
112 ["AUTHOR"] = "Author: %s",
113 ["TOTAL_SUBCATEGORIES"] = "Sub Categories: %d",
114 ["TAB_MANAGEMENT"] = "Management",
115 ["TAB_PERFORMANCE"] = "Performance",
118 local function assert(level
,condition
,message
)
119 if( not condition
) then
124 local function argcheck(value
, num
, ...)
125 if( type(num
) ~= "number" ) then
126 error(L
["BAD_ARGUMENT"]:format(2, "argcheck", "number", type(num
)), 1)
129 for i
=1,select("#", ...) do
130 if( type(value
) == select(i
, ...) ) then return end
133 local types
= string.join(", ", ...)
134 local name
= string.match(debugstack(2,2,0), ": in function [`<](.-)['>]")
135 error(L
["BAD_ARGUMENT"]:format(num
, name
, types
, type(value
)), 3)
139 local OptionHouse
= {}
140 local tabfunctions
= {}
141 local methods
= {"RegisterCategory", "RegisterSubCategory", "RemoveCategory", "RemoveSubCategory"}
148 local function resizeTab(tab
)
149 local textWidth
= tab
:GetFontString():GetWidth()
151 tab
.middleActive
:SetWidth(textWidth
)
152 tab
.middleInactive
:SetWidth(textWidth
)
154 tab
:SetWidth((2 * tab
.leftActive
:GetWidth()) + textWidth
)
155 tab
.highlightTexture
:SetWidth(textWidth
+ 20)
158 local function tabSelected(tab
)
159 tab
:SetTextColor(HIGHLIGHT_FONT_COLOR
.r
, HIGHLIGHT_FONT_COLOR
.g
, HIGHLIGHT_FONT_COLOR
.b
)
160 tab
.highlightTexture
:Hide()
162 tab
.leftActive
:Show()
163 tab
.middleActive
:Show()
164 tab
.rightActive
:Show()
166 tab
.leftInactive
:Hide()
167 tab
.middleInactive
:Hide()
168 tab
.rightInactive
:Hide()
171 local function tabDeselected(tab
)
172 tab
:SetTextColor(NORMAL_FONT_COLOR
.r
, NORMAL_FONT_COLOR
.g
, NORMAL_FONT_COLOR
.b
)
173 tab
.highlightTexture
:Show()
175 tab
.leftInactive
:Show()
176 tab
.middleInactive
:Show()
177 tab
.rightInactive
:Show()
179 tab
.leftActive
:Hide()
180 tab
.middleActive
:Hide()
181 tab
.rightActive
:Hide()
184 local function setTab(id
)
185 if( frame
.selectedTab
) then
186 tabDeselected(frame
.tabs
[frame
.selectedTab
])
189 frame
.selectedTab
= id
190 tabSelected(frame
.tabs
[id
])
193 local function tabOnClick(self
)
195 if( type(self
) ~= "number" ) then
203 for tabID
, tab
in pairs(tabfunctions
) do
204 if( tabID
== id
) then
205 if( type(tab
.func
) == "function" ) then
208 tab
.handler
[tab
.func
](tab
.handler
)
211 if( tab
.type == "browse" ) then
212 frame
.topLeft
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Browse-TopLeft")
213 frame
.top
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Browse-Top")
214 frame
.topRight
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Browse-TopRight")
215 frame
.bottomLeft
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Browse-BotLeft")
216 frame
.bottom
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Browse-Bot")
217 frame
.bottomRight
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Browse-BotRight")
218 elseif( tab
.type == "bid" ) then
219 frame
.topLeft
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Bid-TopLeft")
220 frame
.top
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Bid-Top")
221 frame
.topRight
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Bid-TopRight")
222 frame
.bottomLeft
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Bid-BotLeft")
223 frame
.bottom
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Bid-Bot")
224 frame
.bottomRight
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-Bid-BotRight")
227 elseif( type(tab
.func
) == "function" ) then
230 tab
.handler
[tab
.func
](tab
.handler
, true)
235 local function createTab(text
, id
)
236 local tab
= frame
.tabs
[id
]
238 tab
= CreateFrame("Button", nil, frame
)
239 tab
:SetHighlightFontObject(GameFontHighlightSmall
)
240 tab
:SetTextFontObject(GameFontNormalSmall
)
241 tab
:SetHighlightTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
246 tab
:SetScript("OnClick", tabOnClick
)
247 tab
:GetFontString():SetPoint("CENTER", 0, 2)
249 tab
.highlightTexture
= tab
:GetHighlightTexture()
250 tab
.highlightTexture
:ClearAllPoints()
251 tab
.highlightTexture
:SetPoint("CENTER", tab
:GetFontString(), 0, 0)
252 tab
.highlightTexture
:SetBlendMode("ADD")
254 -- TAB SELECTED TEXTURES
255 tab
.leftActive
= tab
:CreateTexture(nil, "ARTWORK")
256 tab
.leftActive
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ActiveTab")
257 tab
.leftActive
:SetHeight(32)
258 tab
.leftActive
:SetWidth(20)
259 tab
.leftActive
:SetPoint("TOPLEFT", tab
, "TOPLEFT")
260 tab
.leftActive
:SetTexCoord(0, 0.15625, 0, 1.0)
262 tab
.middleActive
= tab
:CreateTexture(nil, "ARTWORK")
263 tab
.middleActive
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ActiveTab")
264 tab
.middleActive
:SetHeight(32)
265 tab
.middleActive
:SetWidth(20)
266 tab
.middleActive
:SetPoint("LEFT", tab
.leftActive
, "RIGHT")
267 tab
.middleActive
:SetTexCoord(0.15625, 0.84375, 0, 1.0)
269 tab
.rightActive
= tab
:CreateTexture(nil, "ARTWORK")
270 tab
.rightActive
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ActiveTab")
271 tab
.rightActive
:SetHeight(32)
272 tab
.rightActive
:SetWidth(20)
273 tab
.rightActive
:SetPoint("LEFT", tab
.middleActive
, "RIGHT")
274 tab
.rightActive
:SetTexCoord(0.84375, 1.0, 0, 1.0)
276 -- TAB DESELECTED TEXTURES
277 tab
.leftInactive
= tab
:CreateTexture(nil, "ARTWORK")
278 tab
.leftInactive
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-InActiveTab")
279 tab
.leftInactive
:SetHeight(32)
280 tab
.leftInactive
:SetWidth(20)
281 tab
.leftInactive
:SetPoint("TOPLEFT", tab
, "TOPLEFT")
282 tab
.leftInactive
:SetTexCoord(0, 0.15625, 0, 1.0)
284 tab
.middleInactive
= tab
:CreateTexture(nil, "ARTWORK")
285 tab
.middleInactive
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-InActiveTab")
286 tab
.middleInactive
:SetHeight(32)
287 tab
.middleInactive
:SetWidth(20)
288 tab
.middleInactive
:SetPoint("LEFT", tab
.leftInactive
, "RIGHT")
289 tab
.middleInactive
:SetTexCoord(0.15625, 0.84375, 0, 1.0)
291 tab
.rightInactive
= tab
:CreateTexture(nil, "ARTWORK")
292 tab
.rightInactive
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-InActiveTab")
293 tab
.rightInactive
:SetHeight(32)
294 tab
.rightInactive
:SetWidth(20)
295 tab
.rightInactive
:SetPoint("LEFT", tab
.middleInactive
, "RIGHT")
296 tab
.rightInactive
:SetTexCoord(0.84375, 1.0, 0, 1.0)
298 frame
.totalTabs
= frame
.totalTabs
+ 1
309 tab
:SetPoint("TOPLEFT", frame
, "BOTTOMLEFT", 15, 11)
311 tab
:SetPoint("TOPLEFT", frame
.tabs
[id
- 1], "TOPRIGHT", -8, 0)
316 local function onVerticalScroll(self
, offset
)
317 offset
= ceil(offset
)
319 self
.bar
:SetValue(offset
)
320 self
.offset
= ceil(offset
/ self
.displayNum
)
322 if( self
.offset
< 0 ) then
326 local min, max = self
.bar
:GetMinMaxValues()
328 if( min == offset
) then
334 if( max == offset
) then
343 local function onMouseWheel(self
, offset
)
344 if( self
.scroll
) then self
= self
.scroll
end
345 if( offset
> 0 ) then
346 self
.bar
:SetValue(self
.bar
:GetValue() - (self
.bar
:GetHeight() / 2))
348 self
.bar
:SetValue(self
.bar
:GetValue() + (self
.bar
:GetHeight() / 2))
352 local function onParentMouseWheel(self
, offset
)
353 onMouseWheel(self
.scroll
, offset
)
356 local function updateScroll(scroll
, totalRows
)
357 local max = (totalRows
- scroll
.displayNum
) * scroll
.displayNum
359 -- Macs are unhappy if max is less then the min
364 scroll
.bar
:SetMinMaxValues(0, max)
366 if( totalRows
> scroll
.displayNum
) then
371 scroll
.bar
:GetThumbTexture():Show()
377 scroll
.bar
:GetThumbTexture():Hide()
381 local function onValueChanged(self
, offset
)
382 self
:GetParent():SetVerticalScroll(offset
)
385 local function scrollButtonUp(self
)
386 local parent
= self
:GetParent()
387 parent
:SetValue(parent
:GetValue() - (parent
:GetHeight() / 2))
388 PlaySound("UChatScrollButton")
391 local function scrollButtonDown(self
)
392 local parent
= self
:GetParent()
393 parent
:SetValue(parent
:GetValue() + (parent
:GetHeight() / 2))
394 PlaySound("UChatScrollButton")
397 local function createScrollFrame(frame
, displayNum
, onScroll
)
398 frame
:EnableMouseWheel(true)
399 frame
:SetScript("OnMouseWheel", onParentMouseWheel
)
401 frame
.scroll
= CreateFrame("ScrollFrame", nil, frame
)
402 frame
.scroll
:EnableMouseWheel(true)
403 frame
.scroll
:SetWidth(16)
404 frame
.scroll
:SetHeight(270)
405 frame
.scroll
:SetScript("OnVerticalScroll", onVerticalScroll
)
406 frame
.scroll
:SetScript("OnMouseWheel", onMouseWheel
)
408 frame
.scroll
.offset
= 0
409 frame
.scroll
.displayNum
= displayNum
410 frame
.scroll
.updateFunc
= onScroll
412 -- Actual bar for scrolling
413 frame
.scroll
.bar
= CreateFrame("Slider", nil, frame
.scroll
)
414 frame
.scroll
.bar
:SetValueStep(frame
.scroll
.displayNum
)
415 frame
.scroll
.bar
:SetMinMaxValues(0, 0)
416 frame
.scroll
.bar
:SetValue(0)
417 frame
.scroll
.bar
:SetWidth(16)
418 frame
.scroll
.bar
:SetScript("OnValueChanged", onValueChanged
)
419 frame
.scroll
.bar
:SetPoint("TOPLEFT", frame
.scroll
, "TOPRIGHT", 6, -16)
420 frame
.scroll
.bar
:SetPoint("BOTTOMLEFT", frame
.scroll
, "BOTTOMRIGHT", 6, -16)
423 frame
.scroll
.up
= CreateFrame("Button", nil, frame
.scroll
.bar
, "UIPanelScrollUpButtonTemplate")
424 frame
.scroll
.up
:ClearAllPoints()
425 frame
.scroll
.up
:SetPoint( "BOTTOM", frame
.scroll
.bar
, "TOP" )
426 frame
.scroll
.up
:SetScript("OnClick", scrollButtonUp
)
428 frame
.scroll
.down
= CreateFrame("Button", nil, frame
.scroll
.bar
, "UIPanelScrollDownButtonTemplate")
429 frame
.scroll
.down
:ClearAllPoints()
430 frame
.scroll
.down
:SetPoint( "TOP", frame
.scroll
.bar
, "BOTTOM" )
431 frame
.scroll
.down
:SetScript("OnClick", scrollButtonDown
)
433 -- That square thingy that shows where the bar is
434 frame
.scroll
.bar
:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
435 local thumb
= frame
.scroll
.bar
:GetThumbTexture()
439 thumb
:SetTexCoord(0.25, 0.75, 0.25, 0.75)
442 frame
.scroll
.barUpTexture
= frame
.scroll
:CreateTexture(nil, "BACKGROUND")
443 frame
.scroll
.barUpTexture
:SetWidth(31)
444 frame
.scroll
.barUpTexture
:SetHeight(256)
445 frame
.scroll
.barUpTexture
:SetPoint("TOPLEFT", frame
.scroll
.up
, "TOPLEFT", -7, 5)
446 frame
.scroll
.barUpTexture
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar")
447 frame
.scroll
.barUpTexture
:SetTexCoord(0, 0.484375, 0, 1.0)
449 frame
.scroll
.barDownTexture
= frame
.scroll
:CreateTexture(nil, "BACKGROUND")
450 frame
.scroll
.barDownTexture
:SetWidth(31)
451 frame
.scroll
.barDownTexture
:SetHeight(106)
452 frame
.scroll
.barDownTexture
:SetPoint("BOTTOMLEFT", frame
.scroll
.down
, "BOTTOMLEFT", -7, -3)
453 frame
.scroll
.barDownTexture
:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-ScrollBar")
454 frame
.scroll
.barDownTexture
:SetTexCoord(0.515625, 1.0, 0, 0.4140625)
458 local function focusGained(self
)
459 if( self
.searchText
) then
460 self
.searchText
= nil
462 self
:SetTextColor(1, 1, 1, 1)
466 local function focusLost(self
)
467 if( not self
.searchText
and string.trim(self
:GetText()) == "" ) then
468 self
.searchText
= true
469 self
:SetText(L
["SEARCH"])
470 self
:SetTextColor(0.90, 0.90, 0.90, 0.80)
474 local function createSearchInput(frame
, onChange
)
475 frame
.search
= CreateFrame("EditBox", nil, frame
, "InputBoxTemplate")
476 frame
.search
:SetHeight(19)
477 frame
.search
:SetWidth(150)
478 frame
.search
:SetAutoFocus(false)
479 frame
.search
:ClearAllPoints()
480 frame
.search
:SetPoint("CENTER", frame
, "BOTTOMLEFT", 100, 25)
482 frame
.search
.searchText
= true
483 frame
.search
:SetText(L
["SEARCH"])
484 frame
.search
:SetTextColor(0.90, 0.90, 0.90, 0.80)
485 frame
.search
:SetScript("OnTextChanged", onChange
)
486 frame
.search
:SetScript("OnEditFocusGained", focusGained
)
487 frame
.search
:SetScript("OnEditFocusLost", focusLost
)
490 -- ADDON CONFIGURATION
491 local function showTooltip(self
)
492 if( self
.tooltip
) then
493 GameTooltip
:SetOwner(self
, "ANCHOR_RIGHT")
494 GameTooltip
:SetText(self
.tooltip
, nil, nil, nil, nil, 1)
498 local function hideTooltip()
502 local function sortCategories(a
, b
)
507 return ( a
.name
< b
.name
)
510 -- Adds the actual row, will attempt to reuse the current row if able to
511 local function addCategoryRow(type, name
, tooltip
, data
, parent
, addon
)
512 local frame
= regFrames
.addon
513 for i
=1, #(frame
.categories
) do
514 -- Match type/name first
515 if( frame
.categories
[i
].type == type and frame
.categories
[i
].name
== name
) then
516 -- Then make sure it's correct addons parent, if it's a category
517 if( (parent
and frame
.categories
[i
].parent
and frame
.categories
[i
].parent
== parent
) or (not parent
and not frame
.categories
[i
].parent
) ) then
518 -- Now make sure it's the correct addon if it's a sub category
519 if( (addon
and frame
.categories
[i
].addon
and frame
.categories
[i
].addon
== addon
) or (not addon
and not frame
.categories
[i
].addon
) ) then
520 frame
.categories
[i
].tooltip
= tooltip
521 frame
.categories
[i
].data
= data
528 table.insert(frame
.categories
, {name
= name
, type = type, tooltip
= tooltip
, data
= data
, parent
= parent
, addon
= addon
} )
529 frame
.resortList
= true
532 -- This removes the entire addon, we don't use this unless
533 -- we're removing the last category
534 local function removeAddonListing(addon
)
535 local frame
= regFrames
.addon
536 for i
=#(frame
.categories
), 1, -1 do
537 if( frame
.categories
[i
].addon
== addon
) then
538 table.remove(frame
.categories
, i
)
543 -- Remove a specific category and/or sub category listing
544 -- without needing to recreate the entire list
545 local function removeCategoryListing(addon
, name
)
546 local frame
= regFrames
.addon
547 for i
=#(frame
.categories
), 1, -1 do
548 -- Remove the category requested
549 if( frame
.categories
[i
].type == "category" and frame
.categories
[i
].name
== name
and frame
.categories
[i
].addon
== addon
) then
550 table.remove(frame
.categories
, i
)
552 -- Remove all of it's sub categories
553 elseif( frame
.categories
[i
].type == "subcat" and frame
.categories
[i
].parent
== name
and frame
.categories
[i
].addon
== addon
) then
554 table.remove(frame
.categories
, i
)
559 local function removeSubCategoryListing(addon
, parentCat
, name
)
560 local frame
= regFrames
.addon
561 for i
=#(frame
.categories
), 1, -1 do
562 -- Remove the specific sub category
563 if( frame
.categories
[i
].type == "subcat" and frame
.categories
[i
].name
== name
and frame
.categories
[i
].parent
== parentCat
and frame
.categories
[i
].addon
== addon
) then
564 table.remove(frame
.categories
, i
)
569 -- We have a seperate function for adding addons
570 -- so we can update a single addon out of the entire list
571 -- if it's categories/sub categories get changed, or a new ones added
572 local function addCategoryListing(name
, addon
)
573 local tooltip
= "|cffffffff" .. (addon
.title
or name
) .. "|r"
576 if( addon
.version
) then
577 tooltip
= tooltip
.. "\n" .. string.format(L
["VERSION"], addon
.version
)
580 if( addon
.author
) then
581 tooltip
= tooltip
.. "\n" .. string.format(L
["AUTHOR"], addon
.author
)
584 -- One category, make clicking the addon open that category
585 if( addon
.totalCats
== 1 and addon
.totalSubs
== 0 ) then
586 for catName
, cat
in pairs(addon
.categories
) do
588 data
.parentCat
= catName
592 -- Multiple categories, or sub categories
594 for catName
, cat
in pairs(addon
.categories
) do
595 cat
.parentCat
= catName
596 addCategoryRow("category", catName
, cat
.totalSubs
> 0 and string.format(L
["TOTAL_SUBCATEGORIES"], cat
.totalSubs
), cat
, name
, name
)
598 for subCatName
, subCat
in pairs(cat
.sub
) do
599 subCat
.parentCat
= catName
600 addCategoryRow("subcat", subCatName
, nil, subCat
, catName
, name
)
605 addCategoryRow("addon", name
, (addon
.version
or addon
.author
) and tooltip
, data
, nil, name
)
608 -- Recreates the entire listing
609 local function createCategoryListing()
610 regFrames
.addon
.categories
= {}
612 for name
, addon
in pairs(addons
) do
613 addCategoryListing(name
, addon
)
617 local function openConfigFrame(data
)
618 local frame
= regFrames
.addon
620 -- Clicking on an addon with multiple categories or sub categories will cause no data
622 -- Make sure the frames hidden when only the addon button is selected
623 if( frame
.shownFrame
) then
624 frame
.shownFrame
:Hide()
629 if( data
.handler
or data
.func
) then
632 if( type(data
.func
) == "string" ) then
633 data
.frame
= data
.handler
[data
.func
](data
.handler
, data
.parentCat
or frame
.selectedCategory
, frame
.selectedSubCat
)
634 elseif( type(data
.handler
) == "function" ) then
635 data
.frame
= data
.handler(data
.parentCat
or frame
.selectedCategory
, frame
.selectedSubCat
)
638 -- Mostly this is for authors, but it lets us clean up the logic a bit
639 if( not data
.frame
) then
640 error(string.format(L
["ERROR_NO_FRAME"], frame
.selectedAddon
, data
.parentCat
or frame
.selectedCategory
, frame
.selectedSubCat
), 3)
643 -- Validate location/width/height and force parent
644 if( not data
.frame
:GetPoint() ) then
645 data
.frame
:SetPoint("TOPLEFT", frame
, "TOPLEFT", 190, -103)
648 if( data
.frame
:GetWidth() > 630 or data
.frame
:GetWidth() == 0 ) then
649 data
.frame
:SetWidth(630)
652 if( data
.frame
:GetHeight() > 305 or data
.frame
:GetHeight() == 0 ) then
653 data
.frame
:SetHeight(305)
656 data
.frame
:SetParent(frame
)
657 data
.frame
:SetFrameStrata("DIALOG")
659 if( not data
.noCache
) then
662 -- Figure out which category we're modifying
663 if( frame
.selectedSubCat
~= "" ) then
664 category
= addons
[frame
.selectedAddon
].categories
[frame
.selectedCategory
].sub
[frame
.selectedSubCat
]
665 elseif( frame
.selectedCategory
~= "" ) then
666 category
= addons
[frame
.selectedAddon
].categories
[frame
.selectedCategory
]
667 elseif( frame
.selectedAddon
~= "" ) then
668 for catName
, _
in pairs(addons
[frame
.selectedAddon
].categories
) do
669 category
= addons
[frame
.selectedAddon
].categories
[catName
]
673 -- Remove the handler/func and save the frame for next time
675 category
.handler
= nil
677 category
.frame
= data
.frame
682 if( frame
.shownFrame
) then
683 frame
.shownFrame
:Hide()
686 -- Now show the current one
687 if( data
.frame
and frame
.selectedAddon
~= "" ) then
689 frame
.shownFrame
= data
.frame
693 -- Displays the actual button
694 local function displayCategoryRow(type, text
, data
, tooltip
, highlighted
)
695 local frame
= regFrames
.addon
697 -- We have to let this run completely
698 -- so we know how many rows we have total
699 frame
.totalRows
= frame
.totalRows
+ 1
700 if( frame
.totalRows
<= frame
.scroll
.offset
or frame
.rowID
>= 15 ) then
704 frame
.rowID
= frame
.rowID
+ 1
706 local button
= frame
.buttons
[frame
.rowID
]
707 local line
= frame
.lines
[frame
.rowID
]
709 if( highlighted
) then
710 button
:LockHighlight()
712 button
:UnlockHighlight()
715 if( type == "addon" ) then
717 button
:GetFontString():SetPoint("LEFT", button
, "LEFT", 4, 0)
718 button
:GetNormalTexture():SetAlpha(1.0)
721 elseif( type == "category" ) then
722 button
:SetText(HIGHLIGHT_FONT_COLOR_CODE
..text
..FONT_COLOR_CODE_CLOSE
)
723 button
:GetFontString():SetPoint("LEFT", button
, "LEFT", 12, 0)
724 button
:GetNormalTexture():SetAlpha(0.4)
727 elseif( type == "subcat" ) then
728 button
:SetText(HIGHLIGHT_FONT_COLOR_CODE
..text
..FONT_COLOR_CODE_CLOSE
)
729 button
:GetFontString():SetPoint("LEFT", button
, "LEFT", 20, 0)
730 button
:GetNormalTexture():SetAlpha(0.0)
731 line
:SetTexCoord(0, 0.4375, 0, 0.625)
735 button
.fs
= button
:GetFontString()
736 button
.tooltip
= tooltip
739 button
.catText
= text
744 local function updateConfigList(openAlso
)
745 local frame
= regFrames
.addon
750 local searchBy
= string.trim(string.lower(frame
.search
:GetText()))
751 if( searchBy
== "" or frame
.search
.searchText
) then
755 -- Make sure stuff matches our search results
756 for id
, row
in pairs(frame
.categories
) do
757 if( searchBy
and not string.match(string.lower(row
.name
), searchBy
) ) then
758 frame
.categories
[id
].hide
= true
760 frame
.categories
[id
].hide
= nil
764 -- Resort list if needed
765 if( frame
.resortList
) then
766 table.sort(frame
.categories
, sortCategories
)
767 frame
.resortList
= nil
772 for _
, addon
in pairs(frame
.categories
) do
773 if( not addon
.hide
and addon
.type == "addon" ) then
775 if( addon
.name
== frame
.selectedAddon
) then
776 displayCategoryRow(addon
.type, addon
.name
, addon
.data
, addon
.tooltip
, true)
777 for _
, cat
in pairs(frame
.categories
) do
778 -- Show all the categories with the addon as the parent
779 if( not cat
.hide
and cat
.parent
== addon
.name
and cat
.type == "category" ) then
780 -- Total categories of the selected addon
781 if( cat
.name
== frame
.selectedCategory
) then
782 displayCategoryRow(cat
.type, cat
.name
, cat
.data
, cat
.tooltip
, true)
785 for _
, subCat
in pairs(frame
.categories
) do
786 -- We don't have to check type, because it's the only one that has .addon set
787 if( not subCat
.hide
and subCat
.parent
== cat
.name
and subCat
.addon
== addon
.name
) then
788 -- Total sub categories of the selected addons selected category
789 displayCategoryRow(subCat
.type, subCat
.name
, subCat
.data
, subCat
.tooltip
, subCat
.name
== frame
.selectedSubCat
)
798 -- Turns the line from straight down to a curve at the end
800 frame
.lines
[lastID
]:SetTexCoord(0.4375, 0.875, 0, 0.625)
803 -- Okay open the category then
804 if( not opened
and openAlso
) then
808 displayCategoryRow(cat
.type, cat
.name
, cat
.data
, cat
.tooltip
)
813 if( not opened
and openAlso
) then
817 displayCategoryRow(addon
.type, addon
.name
, addon
.data
, addon
.tooltip
)
823 openConfigFrame(opened
)
826 updateScroll(frame
.scroll
, frame
.totalRows
)
829 if( frame
.totalRows
> 15 ) then
834 local button
= frame
.buttons
[i
]
835 if( frame
.totalRows
> 15 ) then
842 local wrapAt
= wrapSize
843 if( button
.type == "category" ) then
845 elseif( frame
.buttons
[i
].type == "subcat" ) then
849 if( button
.fs
:GetStringWidth() > wrapAt
) then
850 button
.fs
:SetWidth(wrapAt
)
852 button
.fs
:SetWidth(button
.fs
:GetStringWidth())
856 -- We have less then 15 rows used
857 -- and our index is equal or past our current
858 if( frame
.rowID
< 15 and i
> frame
.rowID
) then
864 local function expandConfigList(self
)
865 local frame
= regFrames
.addon
867 if( self
.type == "addon" ) then
868 if( frame
.selectedAddon
== self
.catText
) then
869 frame
.selectedAddon
= ""
871 frame
.selectedAddon
= self
.catText
874 frame
.selectedCategory
= ""
875 frame
.selectedSubCat
= ""
877 elseif( self
.type == "category" ) then
878 if( frame
.selectedCategory
== self
.catText
) then
879 frame
.selectedCategory
= ""
882 frame
.selectedCategory
= self
.catText
885 frame
.selectedSubCat
= ""
887 elseif( self
.type == "subcat" ) then
888 if( frame
.selectedSubCat
== self
.catText
) then
889 frame
.selectedSubCat
= ""
891 -- Make sure the frame gets hidden when deselecting
892 self
.data
= addons
[frame
.selectedAddon
].categories
[frame
.selectedCategory
]
894 frame
.selectedSubCat
= self
.catText
898 openConfigFrame(self
.data
)
903 local function createAddonFrame(hide
)
904 local frame
= regFrames
.addon
906 if( frame
and hide
) then
911 elseif( not frame
) then
912 frame
= CreateFrame("Frame", nil, regFrames
.main
)
913 frame
:SetFrameStrata("DIALOG")
914 frame
:SetAllPoints(regFrames
.main
)
916 regFrames
.addon
= frame
917 OptionHouseFrames
.addon
= frame
922 local button
= CreateFrame("Button", nil, frame
)
923 frame
.buttons
[i
] = button
925 button
:SetHighlightFontObject(GameFontHighlightSmall
)
926 button
:SetTextFontObject(GameFontNormalSmall
)
927 button
:SetScript("OnClick", expandConfigList
)
928 button
:SetScript("OnEnter", showTooltip
)
929 button
:SetScript("OnLeave", hideTooltip
)
933 button
:SetNormalTexture("Interface\\AuctionFrame\\UI-AuctionFrame-FilterBG")
934 button
:GetNormalTexture():SetTexCoord(0, 0.53125, 0, 0.625)
936 button
:SetHighlightTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
937 button
:GetHighlightTexture():SetBlendMode("ADD")
939 -- For sub categories only
940 local line
= button
:CreateTexture(nil, "BACKGROUND")
941 frame
.lines
[i
] = line
945 line
:SetPoint("LEFT", 13, 0)
946 line
:SetTexture("Interface\\AuctionFrame\\UI-AuctionFrame-FilterLines")
947 line
:SetTexCoord(0, 0.4375, 0, 0.625)
950 button
:SetPoint("TOPLEFT", frame
.buttons
[i
- 1], "BOTTOMLEFT", 0, 0)
952 button
:SetPoint("TOPLEFT", 23, -105)
956 createScrollFrame(frame
, 15, updateConfigList
)
957 frame
.scroll
:SetPoint("TOPRIGHT", frame
, "TOPLEFT", 158, -105)
959 createSearchInput(frame
, updateConfigList
)
960 createCategoryListing()
964 frame
.selectedAddon
= ""
965 frame
.selectedCategory
= ""
966 frame
.selectedSubCat
= ""
968 -- Hide the open config frame
969 if( frame
.shownFrame
) then
970 frame
.shownFrame
:Hide()
977 local function createOHFrame()
978 if( regFrames
.main
) then
982 frame
= CreateFrame("Frame", nil, UIParent
)
983 frame
:CreateTitleRegion()
984 frame
:SetClampedToScreen(true)
985 frame
:SetMovable(false)
986 frame
:SetFrameStrata("DIALOG")
989 frame
:SetPoint("TOPLEFT", 0, -104)
993 regFrames
.main
= frame
994 OptionHouseFrames
.main
= frame
996 -- If we don't hide it ourself, the panel layout becomes messed up
999 frame
:SetAttribute("UIPanelLayout-defined", true)
1000 frame
:SetAttribute("UIPanelLayout-enabled", true)
1001 --~ frame:SetAttribute("UIPanelLayout-area", "doublewide") -- This is broken in the Blizzy code >< Slouken's been sent a fix
1002 frame
:SetAttribute("UIPanelLayout-area", "left")
1003 frame
:SetAttribute("UIPanelLayout-whileDead", true)
1004 table.insert(UISpecialFrames
, name
)
1006 local title
= frame
:GetTitleRegion()
1009 title
:SetPoint("TOPLEFT", 75, -15)
1011 -- Embedded version wont include the icon cause authors are more whiny then users
1012 if( not IsAddOnLoaded("OptionHouse") ) then
1013 local texture
= frame
:CreateTexture(nil, "OVERLAY")
1014 texture
:SetWidth(57)
1015 texture
:SetHeight(57)
1016 texture
:SetPoint("TOPLEFT", 9, -7)
1017 SetPortraitTexture(texture
, "player")
1019 local texture
= frame
:CreateTexture(nil, "OVERLAY")
1020 texture
:SetWidth(128)
1021 texture
:SetHeight(128)
1022 texture
:SetPoint("TOPLEFT", 9, -2)
1023 texture
:SetTexture("Interface\\AddOns\\OptionHouse\\GnomePortrait")
1026 local title
= frame
:CreateFontString(nil, "OVERLAY")
1027 title
:SetFontObject(GameFontNormal
)
1028 title
:SetPoint("TOP", 0, -18)
1029 title
:SetText(L
["OPTION_HOUSE"])
1031 frame
.topLeft
= frame
:CreateTexture(nil, "ARTWORK")
1032 frame
.topLeft
:SetWidth(256)
1033 frame
.topLeft
:SetHeight(256)
1034 frame
.topLeft
:SetPoint("TOPLEFT", 0, 0)
1036 frame
.top
= frame
:CreateTexture(nil, "ARTWORK")
1037 frame
.top
:SetWidth(320)
1038 frame
.top
:SetHeight(256)
1039 frame
.top
:SetPoint("TOPLEFT", 256, 0)
1041 frame
.topRight
= frame
:CreateTexture(nil, "ARTWORK")
1042 frame
.topRight
:SetWidth(256)
1043 frame
.topRight
:SetHeight(256)
1044 frame
.topRight
:SetPoint("TOPLEFT", frame
.top
, "TOPRIGHT", 0, 0)
1046 frame
.bottomLeft
= frame
:CreateTexture(nil, "ARTWORK")
1047 frame
.bottomLeft
:SetWidth(256)
1048 frame
.bottomLeft
:SetHeight(256)
1049 frame
.bottomLeft
:SetPoint("TOPLEFT", 0, -256)
1051 frame
.bottom
= frame
:CreateTexture(nil, "ARTWORK")
1052 frame
.bottom
:SetWidth(320)
1053 frame
.bottom
:SetHeight(256)
1054 frame
.bottom
:SetPoint("TOPLEFT", 256, -256)
1056 frame
.bottomRight
= frame
:CreateTexture(nil, "ARTWORK")
1057 frame
.bottomRight
:SetWidth(256)
1058 frame
.bottomRight
:SetHeight(256)
1059 frame
.bottomRight
:SetPoint("TOPLEFT", frame
.bottom
, "TOPRIGHT", 0, 0)
1061 -- Make sure the configuration tab is first
1062 local tabs
= {{func
= createAddonFrame
, text
= L
["ADDON_OPTIONS"], type = "browse"}}
1063 createTab(L
["ADDON_OPTIONS"], 1)
1065 for id
, tab
in pairs(tabfunctions
) do
1066 table.insert(tabs
, tab
)
1067 createTab(tab
.text
, id
+ 1)
1072 local button
= CreateFrame("Button", nil, frame
, "UIPanelCloseButton")
1073 button
:SetPoint("TOPRIGHT", 3, -8)
1074 button
:SetScript("OnClick", function()
1080 -- While these aren't locked down to prevent being used
1081 -- You ARE using them are your own risk for future compatability
1082 function OptionHouse
:CreateSearchInput(frame
, onChange
)
1083 createSearchInput(frame
, onChange
)
1086 function OptionHouse
:UpdateScroll(scroll
, totalRows
)
1087 updateScroll(scroll
, totalRows
)
1090 function OptionHouse
:CreateScrollFrame(frame
, displayNum
, onScroll
)
1091 createScrollFrame(frame
, displayNum
, onScroll
)
1094 function OptionHouse
.RegisterTab(self
, text
, func
, type)
1095 -- Simple, effective you can't register a tab unless we list it here
1096 -- I highly doubt will ever need to add another one
1097 if( text
~= L
["TAB_MANAGEMENT"] and text
~= L
["TAB_PERFORMANCE"] ) then return end
1099 table.insert(tabfunctions
, {func
= func
, handler
= self
, text
= text
, type = type})
1101 -- Will create all of the tabs when the frame is created if needed
1102 if( not frame
) then
1106 createTab(text
, #(tabfunctions
))
1109 function OptionHouse
.UnregisterTab(self
, text
)
1110 for i
=#(tabfunctions
), 1, -1 do
1111 if( tabfunctions
[i
].text
== text
) then
1112 table.remove(tabfunctions
, i
)
1116 for i
=1, frame
.totalTabs
do
1117 if( tabfunctions
[i
] ) then
1118 createTab(tabfunctions
[i
].text
, i
)
1120 frame
.tabs
[i
]:Hide()
1125 function OptionHouse
.GetAddOnData(self
, name
)
1126 if( not addons
[name
] ) then
1127 return nil, nil, nil
1130 return addons
[name
].title
, addons
[name
].author
, addons
[name
].version
1133 function OptionHouse
.RegisterFrame(self
, type, frame
)
1134 if( type ~= "addon" and type ~= "manage" and type ~= "perf" and type ~= "main" ) then
1135 error(string.format(L
["UNKNOWN_FRAMETYPE"], type), 3)
1138 regFrames
[type] = frame
1139 OptionHouseFrames
[type] = frame
1143 function OptionHouse
:GetFrame(type)
1144 if( type ~= "addon" and type ~= "manage" and type ~= "perf" and type ~= "main" ) then
1145 error(string.format(L
["UNKNOWN_FRAMETYPE"], type), 3)
1148 return regFrames
[type]
1151 function OptionHouse
:Open(addonName
, parentCat
, childCat
)
1152 argcheck(addonName
, 1, "string", "nil")
1153 argcheck(parentCat
, 2, "string", "nil")
1154 argcheck(childCat
, 3, "string", "nil")
1159 if( not addonName
) then
1164 regFrames
.addon
.selectedAddon
= addonName
or ""
1165 regFrames
.addon
.selectedCategory
= parentCat
or ""
1166 regFrames
.addon
.selectedSubCat
= childCat
or ""
1168 updateConfigList(true)
1172 function OptionHouse
:OpenTab(id
)
1173 argcheck(id
, 1, "number")
1174 assert(3, #(tabfunctions
) > id
, string.format(L
["UNKNOWN_TAB"], id
, #(tabfunctions
)))
1181 function OptionHouse
:RegisterAddOn(name
, title
, author
, version
)
1182 argcheck(name
, 1, "string")
1183 argcheck(title
, 2, "string", "nil")
1184 argcheck(author
, 3, "string", "nil")
1185 argcheck(version
, 4, "string", "number", "nil")
1186 assert(3, not addons
[name
], string.format(L
["ADDON_ALREADYREG"], name
))
1188 addons
[name
] = {title
= title
, author
= author
, version
= version
, totalCats
= 0, totalSubs
= 0, categories
= {}}
1189 addons
[name
].obj
= {name
= name
}
1191 -- So we can upgrade the function pointer if a newer rev is found
1192 for id
, method
in pairs(methods
) do
1193 addons
[name
].obj
[method
] = OptionHouse
[method
]
1196 if( regFrames
.addon
) then
1197 addCategoryListing(name
, addons
[name
])
1201 return addons
[name
].obj
1204 function OptionHouse
.RegisterCategory(addon
, name
, handler
, func
, noCache
)
1205 argcheck(name
, 2, "string")
1206 argcheck(handler
, 3, "string", "function", "table")
1207 argcheck(func
, 4, "string", "function", "nil")
1208 argcheck(noCache
, 5, "boolean", "number", "nil")
1209 assert(3, handler
or func
, L
["NO_FUNC_PASSED"])
1210 assert(3, addons
[addon
.name
], string.format(L
["MUST_CALL"], "RegisterCategory"))
1211 assert(3, addons
[addon
.name
].categories
, string.format(L
["CATEGORY_ALREADYREG"], name
, addon
.name
))
1213 -- Category numbers are required so we know when to skip it because only one category/sub cat exists
1214 addons
[addon
.name
].totalCats
= addons
[addon
.name
].totalCats
+ 1
1215 addons
[addon
.name
].categories
[name
] = {func
= func
, handler
= handler
, noCache
= noCache
, sub
= {}, totalSubs
= 0}
1217 if( regFrames
.addon
) then
1218 addCategoryListing(addon
.name
, addons
[addon
.name
])
1223 function OptionHouse
.RegisterSubCategory(addon
, parentCat
, name
, handler
, func
, noCache
)
1224 argcheck(parentCat
, 2, "string")
1225 argcheck(name
, 3, "string")
1226 argcheck(handler
, 4, "string", "function", "table")
1227 argcheck(func
, 5, "string", "function", "nil")
1228 argcheck(noCache
, 6, "boolean", "number", "nil")
1229 assert(3, handler
or func
, L
["NO_FUNC_PASSED"])
1230 assert(3, addons
[addon
.name
], string.format(L
["MUST_CALL"], "RegisterSubCategory"))
1231 assert(3, addons
[addon
.name
].categories
[parentCat
], string.format(L
["NO_PARENTCAT"], parentCat
, addon
.name
))
1232 assert(3, not addons
[addon
.name
].categories
[parentCat
].sub
[name
], string.format(L
["SUBCATEGORY_ALREADYREG"], name
, parentCat
, addon
.name
))
1234 addons
[addon
.name
].totalSubs
= addons
[addon
.name
].totalSubs
+ 1
1235 addons
[addon
.name
].categories
[parentCat
].totalSubs
= addons
[addon
.name
].categories
[parentCat
].totalSubs
+ 1
1236 addons
[addon
.name
].categories
[parentCat
].sub
[name
] = {handler
= handler
, func
= func
, noCache
= noCache
}
1238 if( regFrames
.addon
) then
1239 addCategoryListing(addon
.name
, addons
[addon
.name
])
1244 function OptionHouse
.RemoveCategory(addon
, name
)
1245 argcheck(name
, 2, "string")
1246 assert(3, addons
[addon
.name
], string.format(L
["MUST_CALL"], "RemoveCategory"))
1247 assert(3, addons
[addon
.name
].categories
[name
], string.format(L
["NO_CATEGORYEXISTS"], name
, addon
.name
))
1249 addons
[addon
.name
].totalCats
= addons
[addon
.name
].totalCats
- 1
1250 addons
[addon
.name
].totalSubs
= addons
[addon
.name
].totalSubs
- addons
[addon
.name
].categories
[name
].totalSubs
1251 addons
[addon
.name
].categories
[name
] = nil
1253 if( regFrames
.addon
) then
1254 if( addons
[addon
.name
].totalCats
== 0 ) then
1255 removeAddonListing(addon
.name
)
1257 removeCategoryListing(addon
.name
, name
)
1264 function OptionHouse
.RemoveSubCategory(addon
, parentCat
, name
)
1265 argcheck(parentCat
, 2, "string")
1266 argcheck(name
, 2, "string")
1267 assert(3, addons
[addon
.name
], string.format(L
["MUST_CALL"], "RemoveSubCategory"))
1268 assert(3, addons
[addon
.name
].categories
[parentCat
], string.format(L
["NO_PARENTCAT"], name
, addon
.name
))
1269 assert(3, addons
[addon
.name
].categories
[parentCat
].sub
[name
], string.format(L
["NO_SUBCATEXISTS"], name
, parentCat
, addon
.name
))
1271 addons
[addon
.name
].totalSubs
= addons
[addon
.name
].totalSubs
- 1
1272 addons
[addon
.name
].categories
[parentCat
].totalSubs
= addons
[addon
.name
].categories
[parentCat
].totalSubs
- 1
1273 addons
[addon
.name
].categories
[parentCat
].sub
[name
] = nil
1275 if( regFrames
.addon
) then
1276 -- If this means we only have no more sub categories
1277 -- and only one category we need to change how it works
1278 if( addons
[addon
.name
].totalSubs
== 0 and addons
[addon
.name
].totalCats
== 1 ) then
1279 removeAddonListing(addon
.name
)
1280 addCategoryListing(addon
.name
, addons
[addon
.name
])
1282 removeSubCategoryListing(addon
.name
, parentCat
, name
)
1289 function OptionHouse
:GetVersion() return major
, minor
end
1291 local function instanceLoaded()
1292 if( oldRevision
) then
1293 addons
= OHInstance
.addons
or addons
1294 evtFrame
= OHInstance
.evtFrame
or evtFrame
1295 tabfunctions
= OHInstance
.tabfunctions
or tabfunctions
1297 -- Secure headers are supported so don't want the window stuck open in combat
1298 evtFrame
= CreateFrame("Frame")
1299 evtFrame
:RegisterEvent("PLAYER_REGEN_DISABLED")
1300 evtFrame
:RegisterEvent("ADDON_LOADED")
1301 evtFrame
:SetScript("OnEvent",function(self
, event
)
1302 if( event
== "PLAYER_REGEN_DISABLED" and frame
and frame
:IsShown() ) then
1304 DEFAULT_CHAT_FRAME
:AddMessage(L
["ENTERED_COMBAT"])
1308 -- Make sure it hasn't been created already.
1309 -- don't have to upgrade the referance because it just uses the slash command
1310 -- which will upgrade below to use the current version anyway
1311 if( not GameMenuButtonOptionHouse
) then
1312 local menubutton
= CreateFrame("Button", "GameMenuButtonOptionHouse", GameMenuFrame
, "GameMenuButtonTemplate")
1313 menubutton
:SetText(L
["OPTION_HOUSE"])
1314 menubutton
:SetScript("OnClick", function()
1315 PlaySound("igMainMenuOption")
1316 HideUIPanel(GameMenuFrame
)
1317 SlashCmdList
["OPTHOUSE"]()
1320 -- Position below "Interface Options"
1321 local a1
, fr
, a2
, x
, y
= GameMenuButtonKeybindings
:GetPoint()
1322 menubutton
:SetPoint(a1
, fr
, a2
, x
, y
)
1324 GameMenuButtonKeybindings
:SetPoint(a1
, menubutton
, a2
, x
, y
)
1325 GameMenuFrame
:SetHeight(GameMenuFrame
:GetHeight() + 25)
1329 OptionHouseFrames
= OptionHouseFrames
or {}
1331 OptionHouse
.addons
= addons
1332 OptionHouse
.evtFrame
= evtFrame
1333 OptionHouse
.tabfunctions
= tabfunctions
1335 -- Upgrade functions to point towards the latest revision
1336 for name
, addon
in pairs(addons
) do
1337 for _
, method
in pairs(methods
) do
1338 addon
.obj
[method
] = OptionHouse
[method
]
1342 SLASH_OPTHOUSE1
= "/opthouse"
1343 SLASH_OPTHOUSE2
= "/oh"
1344 SlashCmdList
["OPTHOUSE"] = function(...)
1345 if( select(1, ...) == "" ) then
1348 OptionHouse
:Open(...)
1352 -- Now make it active
1353 for k
, v
in pairs(OptionHouse
) do