Create Subfolder
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local StateBar = Bartender4.StateBar.prototype
|
||||
local ActionBar = setmetatable({}, {__index = StateBar})
|
||||
Bartender4.ActionBar = ActionBar
|
||||
|
||||
--[[===================================================================================
|
||||
ActionBar Prototype
|
||||
===================================================================================]]--
|
||||
|
||||
local initialPosition
|
||||
do
|
||||
-- Sets the Bar to its initial Position in the Center of the Screen
|
||||
function initialPosition(bar)
|
||||
bar:ClearSetPoint("CENTER", 0, -250 + (bar.id-1) * 38)
|
||||
bar:SavePosition()
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply the specified config to the bar and refresh all settings
|
||||
function ActionBar:ApplyConfig(config)
|
||||
StateBar.ApplyConfig(self, config)
|
||||
|
||||
if not self.config.position.x then initialPosition(self) end
|
||||
|
||||
self:UpdateButtons()
|
||||
end
|
||||
|
||||
-- Update the number of buttons in our bar, creating new ones if necessary
|
||||
function ActionBar:UpdateButtons(numbuttons)
|
||||
if numbuttons then
|
||||
self.config.buttons = min(numbuttons, 12)
|
||||
else
|
||||
numbuttons = min(self.config.buttons, 12)
|
||||
end
|
||||
|
||||
local buttons = self.buttons or {}
|
||||
|
||||
local updateBindings = (numbuttons > #buttons)
|
||||
-- create more buttons if needed
|
||||
for i = (#buttons+1), numbuttons do
|
||||
buttons[i] = Bartender4.Button:Create(i, self)
|
||||
end
|
||||
|
||||
-- show active buttons
|
||||
for i = 1, numbuttons do
|
||||
buttons[i]:SetParent(self)
|
||||
buttons[i]:Show()
|
||||
buttons[i]:SetAttribute("statehidden", nil)
|
||||
buttons[i]:Update()
|
||||
end
|
||||
|
||||
-- hide inactive buttons
|
||||
for i = (numbuttons + 1), #buttons do
|
||||
buttons[i]:Hide()
|
||||
buttons[i]:SetParent(UIParent)
|
||||
buttons[i]:SetAttribute("statehidden", true)
|
||||
end
|
||||
|
||||
self.numbuttons = numbuttons
|
||||
self.buttons = buttons
|
||||
|
||||
self:UpdateButtonLayout()
|
||||
self:SetGrid()
|
||||
if updateBindings and self.id == "1" then
|
||||
self.module:ReassignBindings()
|
||||
end
|
||||
|
||||
-- need to re-set clickthrough after creating new buttons
|
||||
self:SetClickThrough()
|
||||
self:UpdateSelfCast() -- update selfcast and states
|
||||
end
|
||||
|
||||
function ActionBar:SkinChanged(...)
|
||||
StateBar.SkinChanged(self, ...)
|
||||
self:ForAll("Update")
|
||||
end
|
||||
|
||||
|
||||
--[[===================================================================================
|
||||
ActionBar Config Interface
|
||||
===================================================================================]]--
|
||||
|
||||
|
||||
-- get the current number of buttons
|
||||
function ActionBar:GetButtons()
|
||||
return self.config.buttons
|
||||
end
|
||||
|
||||
-- set the number of buttons and refresh layout
|
||||
ActionBar.SetButtons = ActionBar.UpdateButtons
|
||||
|
||||
function ActionBar:GetEnabled()
|
||||
return true
|
||||
end
|
||||
|
||||
function ActionBar:SetEnabled(state)
|
||||
if not state then
|
||||
self.module:DisableBar(self.id)
|
||||
end
|
||||
end
|
||||
|
||||
function ActionBar:GetGrid()
|
||||
return self.config.showgrid
|
||||
end
|
||||
|
||||
function ActionBar:SetGrid(state)
|
||||
if state ~= nil then
|
||||
self.config.showgrid = state
|
||||
end
|
||||
if self.config.showgrid then
|
||||
self:ForAll("ShowGrid")
|
||||
else
|
||||
self:ForAll("HideGrid")
|
||||
end
|
||||
self:ForAll("UpdateGrid")
|
||||
end
|
||||
@@ -0,0 +1,235 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
local BT4ActionBars = Bartender4:NewModule("ActionBars", "AceEvent-3.0")
|
||||
|
||||
local ActionBar, ActionBar_MT
|
||||
|
||||
local abdefaults = {
|
||||
['**'] = Bartender4:Merge({
|
||||
enabled = true,
|
||||
buttons = 12,
|
||||
hidemacrotext = false,
|
||||
showgrid = false,
|
||||
}, Bartender4.StateBar.defaults),
|
||||
[1] = {
|
||||
states = {
|
||||
enabled = true,
|
||||
possess = true,
|
||||
actionbar = true,
|
||||
stance = {
|
||||
DRUID = { bear = 9, cat = 7, prowl = 8 },
|
||||
WARRIOR = { battle = 7, def = 8, berserker = 9 },
|
||||
ROGUE = { stealth = 7, shadowdance = 7 },
|
||||
HERO = { bear = 9, cat = 7, prowl = 8, stealth = 7, shadowdance = 7, battle = 7, def = 8, berserker = 9 },
|
||||
},
|
||||
},
|
||||
visibility = {
|
||||
vehicleui = false,
|
||||
},
|
||||
},
|
||||
[7] = {
|
||||
enabled = false,
|
||||
},
|
||||
[8] = {
|
||||
enabled = false,
|
||||
},
|
||||
[9] = {
|
||||
enabled = false,
|
||||
},
|
||||
[10] = {
|
||||
enabled = false,
|
||||
},
|
||||
}
|
||||
|
||||
local defaults = {
|
||||
profile = {
|
||||
actionbars = abdefaults,
|
||||
}
|
||||
}
|
||||
|
||||
function BT4ActionBars:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("ActionBars", defaults)
|
||||
|
||||
-- fetch the prototype information
|
||||
ActionBar = Bartender4.ActionBar
|
||||
ActionBar_MT = {__index = ActionBar}
|
||||
end
|
||||
|
||||
|
||||
local LBF = LibStub("LibButtonFacade", true)
|
||||
|
||||
-- setup the 10 actionbars
|
||||
local first = true
|
||||
function BT4ActionBars:OnEnable()
|
||||
if first then
|
||||
self.playerclass = select(2, UnitClass("player"))
|
||||
self.actionbars = {}
|
||||
|
||||
for i=1,10 do
|
||||
local config = self.db.profile.actionbars[i]
|
||||
if config.enabled then
|
||||
self.actionbars[i] = self:Create(i, config)
|
||||
else
|
||||
self:CreateBarOption(i, self.disabledoptions)
|
||||
end
|
||||
end
|
||||
|
||||
first = nil
|
||||
end
|
||||
|
||||
self:RegisterEvent("UPDATE_BINDINGS", "ReassignBindings")
|
||||
self:ReassignBindings()
|
||||
end
|
||||
|
||||
function BT4ActionBars:SetupOptions()
|
||||
if not self.options then
|
||||
-- empty table to hold the bar options
|
||||
self.options = {}
|
||||
|
||||
-- template for disabled bars
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = {
|
||||
type = "toggle",
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable/Disable the bar."],
|
||||
set = function(info, v) if v then BT4ActionBars:EnableBar(info[2]) end end,
|
||||
get = function() return false end,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- iterate over bars and create their option tables
|
||||
for i=1,10 do
|
||||
local config = self.db.profile.actionbars[i]
|
||||
if config.enabled then
|
||||
self:CreateBarOption(i)
|
||||
else
|
||||
self:CreateBarOption(i, self.disabledoptions)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Applys the config in the current profile to all active Bars
|
||||
function BT4ActionBars:ApplyConfig()
|
||||
for i=1,10 do
|
||||
local config = self.db.profile.actionbars[i]
|
||||
-- make sure the bar has its current config object if it exists already
|
||||
if self.actionbars[i] then
|
||||
self.actionbars[i].config = config
|
||||
end
|
||||
if config.enabled then
|
||||
self:EnableBar(i)
|
||||
else
|
||||
self:DisableBar(i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we do not allow to disable the actionbars module
|
||||
function BT4ActionBars:ToggleModule()
|
||||
return
|
||||
end
|
||||
|
||||
function BT4ActionBars:UpdateButtons(force)
|
||||
for i,v in ipairs(self.actionbars) do
|
||||
for j,button in ipairs(v.buttons) do
|
||||
button:UpdateAction(force)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BT4ActionBars:ReassignBindings()
|
||||
if InCombatLockdown() then return end
|
||||
if not self.actionbars or not self.actionbars[1] then return end
|
||||
local frame = self.actionbars[1]
|
||||
ClearOverrideBindings(frame)
|
||||
for i = 1,min(#frame.buttons, 12) do
|
||||
local button, real_button = ("ACTIONBUTTON%d"):format(i), ("BT4Button%d"):format(i)
|
||||
for k=1, select('#', GetBindingKey(button)) do
|
||||
local key = select(k, GetBindingKey(button))
|
||||
SetOverrideBindingClick(frame, false, key, real_button)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, 120 do
|
||||
-- rename old bindings from <buttonname>Secure to only <buttonname>
|
||||
local button, real_button = ("CLICK BT4Button%dSecure:LeftButton"):format(i), ("BT4Button%d"):format(i)
|
||||
|
||||
for k=1, select('#', GetBindingKey(button)) do
|
||||
local key = select(k, GetBindingKey(button))
|
||||
if key and key ~= "" then
|
||||
SetBindingClick(key, real_button, "LeftButton")
|
||||
end
|
||||
end
|
||||
end
|
||||
SaveBindings(GetCurrentBindingSet() or 1)
|
||||
end
|
||||
|
||||
-- Creates a new bar object based on the id and the specified config
|
||||
function BT4ActionBars:Create(id, config)
|
||||
local id = tostring(id)
|
||||
local bar = setmetatable(Bartender4.StateBar:Create(id, config, (L["Bar %s"]):format(id)), ActionBar_MT)
|
||||
bar.module = self
|
||||
|
||||
self:CreateBarOption(id)
|
||||
|
||||
bar:ApplyConfig()
|
||||
|
||||
return bar
|
||||
end
|
||||
|
||||
function BT4ActionBars:DisableBar(id)
|
||||
id = tonumber(id)
|
||||
local bar = self.actionbars[id]
|
||||
if not bar then return end
|
||||
|
||||
bar.config.enabled = false
|
||||
bar:Disable()
|
||||
self:CreateBarOption(id, self.disabledoptions)
|
||||
end
|
||||
|
||||
function BT4ActionBars:EnableBar(id)
|
||||
id = tonumber(id)
|
||||
local bar = self.actionbars[id]
|
||||
local config = self.db.profile.actionbars[id]
|
||||
config.enabled = true
|
||||
if not bar then
|
||||
bar = self:Create(id, config)
|
||||
self.actionbars[id] = bar
|
||||
else
|
||||
bar.disabled = nil
|
||||
self:CreateBarOption(id)
|
||||
bar:ApplyConfig(config)
|
||||
end
|
||||
if not Bartender4.Locked then
|
||||
bar:Unlock()
|
||||
end
|
||||
end
|
||||
|
||||
function BT4ActionBars:GetAll()
|
||||
return pairs(self.actionbars)
|
||||
end
|
||||
|
||||
function BT4ActionBars:ForAll(method, ...)
|
||||
for _, bar in self:GetAll() do
|
||||
local func = bar[method]
|
||||
if func then
|
||||
func(bar, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function BT4ActionBars:ForAllButtons(...)
|
||||
self:ForAll("ForAll", ...)
|
||||
end
|
||||
@@ -0,0 +1,515 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
--[[
|
||||
Action Button Template
|
||||
|
||||
Note:
|
||||
Some IDs produce a special behaviour!
|
||||
- Button ID 132 (Last Button in Possess Bar) Creates a Leave Vehicle Button
|
||||
]]
|
||||
|
||||
local specialButtons = {
|
||||
[132] = { icon = "Interface\\Icons\\Spell_Shadow_SacrificialShield", tooltip = LEAVE_VEHICLE}, -- Vehicle Leave Button
|
||||
}
|
||||
|
||||
local Button = CreateFrame("CheckButton")
|
||||
local Button_MT = {__index = Button}
|
||||
|
||||
local onEnter, onLeave, onUpdate, onDragUpdate
|
||||
|
||||
-- upvalues
|
||||
local _G = _G
|
||||
local format = string.format
|
||||
local IsUsableAction, IsActionInRange, GetActionTexture, ActionHasRange = IsUsableAction, IsActionInRange, GetActionTexture, ActionHasRange
|
||||
local ATTACK_BUTTON_FLASH_TIME, RANGE_INDICATOR, TOOLTIP_UPDATE_TIME = ATTACK_BUTTON_FLASH_TIME, RANGE_INDICATOR, TOOLTIP_UPDATE_TIME
|
||||
|
||||
local Bartender4 = Bartender4
|
||||
local LBF = LibStub("LibButtonFacade", true)
|
||||
local KeyBound = LibStub("LibKeyBound-1.0")
|
||||
|
||||
Bartender4.Button = {}
|
||||
Bartender4.Button.prototype = Button
|
||||
Button.BT4init = true
|
||||
function Bartender4.Button:Create(id, parent)
|
||||
local absid = (parent.id - 1) * 12 + id
|
||||
local name = ("BT4Button%d"):format(absid)
|
||||
local button = setmetatable(CreateFrame("CheckButton", name, parent, "ActionBarButtonTemplate"), Button_MT)
|
||||
-- work around for "blocked" message when using /click macros
|
||||
GetClickFrame(name)
|
||||
|
||||
-- Backwards Compat to pre-4.2.0 button names/layout
|
||||
_G[name .. "Secure"] = button
|
||||
button.Secure = button
|
||||
|
||||
button.rid = id
|
||||
button.id = absid
|
||||
button.parent = parent
|
||||
button.stateactions = {}
|
||||
|
||||
button:SetRealNormalTexture("")
|
||||
local oldNT = _G[("%sNormalTexture"):format(name)]
|
||||
oldNT:Hide()
|
||||
|
||||
button.normalTexture = button:CreateTexture(("%sBTNT"):format(name))
|
||||
button.normalTexture:SetWidth(66)
|
||||
button.normalTexture:SetHeight(66)
|
||||
button.normalTexture:ClearAllPoints()
|
||||
button.normalTexture:SetPoint("CENTER", 0, -1)
|
||||
button.normalTexture:Show()
|
||||
|
||||
|
||||
--button:SetFrameStrata("MEDIUM")
|
||||
|
||||
-- overwrite some scripts with out customized versions
|
||||
button:SetScript("OnEnter", onEnter)
|
||||
button:SetScript("OnUpdate", onUpdate)
|
||||
button:SetScript("OnDragStart", onDragUpdate)
|
||||
--button:SetScript("OnReceiveDrag", nil)
|
||||
|
||||
button.icon = _G[("%sIcon"):format(name)]
|
||||
button.border = _G[("%sBorder"):format(name)]
|
||||
button.cooldown = _G[("%sCooldown"):format(name)]
|
||||
button.macroName = _G[("%sName"):format(name)]
|
||||
button.hotkey = _G[("%sHotKey"):format(name)]
|
||||
button.count = _G[("%sCount"):format(name)]
|
||||
button.flash = _G[("%sFlash"):format(name)]
|
||||
button.flash:Hide()
|
||||
|
||||
button:SetAttribute("type", "action")
|
||||
button:SetAttribute("action", absid)
|
||||
button:SetAttribute("useparent-unit", nil);
|
||||
button:SetAttribute("useparent-actionpage", nil);
|
||||
button:SetAttribute("buttonlock", Bartender4.db.profile.buttonlock)
|
||||
|
||||
button:UpdateSelfCast()
|
||||
|
||||
parent:WrapScript(button, "OnDragStart", [[
|
||||
local action = self:GetAttribute("action")
|
||||
if action and (not self:GetAttribute("buttonlock") or IsModifiedClick("PICKUPACTION")) then
|
||||
return "action", action
|
||||
end
|
||||
]], [[
|
||||
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
|
||||
]])
|
||||
|
||||
parent:WrapScript(button, "OnReceiveDrag", [[]], [[
|
||||
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
|
||||
]])
|
||||
|
||||
button:SetAttribute("UpdateAutoAssist", [[
|
||||
self:SetAttribute("assisttype", nil)
|
||||
self:SetAttribute("unit", nil)
|
||||
if self:GetAttribute("autoassist") then
|
||||
local action = self:GetAttribute("action")
|
||||
local type, id, subtype = GetActionInfo(action)
|
||||
if type == "spell" and id > 0 then
|
||||
if IsHelpfulSpell(id, subtype) then
|
||||
self:SetAttribute("assisttype", 1)
|
||||
self:SetAttribute("unit", G_assist_help)
|
||||
elseif IsHarmfulSpell(id, subtype) then
|
||||
self:SetAttribute("assisttype", 2)
|
||||
self:SetAttribute("unit", G_assist_harm)
|
||||
end
|
||||
end
|
||||
end
|
||||
]])
|
||||
|
||||
button:SetAttribute('_childupdate-init', [[
|
||||
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
|
||||
]])
|
||||
|
||||
button:SetAttribute('_childupdate-state', [[
|
||||
self:SetAttribute("state", message)
|
||||
local action = self:GetAttribute("action-" .. message)
|
||||
if not action then return end
|
||||
if action == 132 then
|
||||
self:SetAttribute("type", "click")
|
||||
if not self:GetAttribute("isSpecial") then
|
||||
self:SetAttribute("showgrid", self:GetAttribute("showgrid") + 1)
|
||||
self:SetAttribute("isSpecial", true)
|
||||
end
|
||||
else
|
||||
if action > 120 and action <= 126 then
|
||||
self:SetAttribute("type", "click")
|
||||
else
|
||||
self:SetAttribute("type", "action")
|
||||
end
|
||||
if self:GetAttribute("isSpecial") then
|
||||
self:SetAttribute("isSpecial", nil)
|
||||
self:SetAttribute("showgrid", max(0, self:GetAttribute("showgrid") - 1))
|
||||
end
|
||||
end
|
||||
self:SetAttribute("action", action)
|
||||
|
||||
-- fix unit on state change
|
||||
if action <= 120 and self:GetAttribute("autoassist") then
|
||||
control:RunFor(self, self:GetAttribute("UpdateAutoAssist"))
|
||||
else
|
||||
self:SetAttribute("unit", nil)
|
||||
end
|
||||
G_state = message
|
||||
]])
|
||||
|
||||
button:SetAttribute('_childupdate-assist-help', [[
|
||||
G_assist_help = message
|
||||
if self:GetAttribute("assisttype") == 1 then
|
||||
self:SetAttribute("unit", message)
|
||||
end
|
||||
]])
|
||||
|
||||
button:SetAttribute('_childupdate-assist-harm', [[
|
||||
G_assist_harm = message
|
||||
if self:GetAttribute("assisttype") == 2 then
|
||||
self:SetAttribute("unit", message)
|
||||
end
|
||||
]])
|
||||
|
||||
button.SecureInit = true
|
||||
|
||||
if LBF and parent.LBFGroup then
|
||||
local group = parent.LBFGroup
|
||||
group:AddButton(button)
|
||||
end
|
||||
|
||||
if button.parent.config.showgrid then
|
||||
button:ShowGrid()
|
||||
end
|
||||
|
||||
--self:UpdateAction(true)
|
||||
button:UpdateHotkeys()
|
||||
button:UpdateUsable()
|
||||
button:UpdateGrid()
|
||||
button:ToggleButtonElements()
|
||||
|
||||
for page = 0,11,1 do
|
||||
local action = (page == 0) and button.id or (button.rid + (page - 1) * 12)
|
||||
button:SetStateAction(page, action)
|
||||
end
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
function onDragUpdate(self)
|
||||
ActionButton_UpdateState(self)
|
||||
ActionButton_UpdateFlash(self)
|
||||
end
|
||||
|
||||
function onEnter(self)
|
||||
if not (Bartender4.db.profile.tooltip == "nocombat" and InCombatLockdown()) and Bartender4.db.profile.tooltip ~= "disabled" then
|
||||
self:SetTooltip(self)
|
||||
end
|
||||
KeyBound:Set(self)
|
||||
end
|
||||
|
||||
function onUpdate(self, elapsed)
|
||||
if self.flashing == 1 then
|
||||
self.flashtime = self.flashtime - elapsed
|
||||
if self.flashtime <= 0 then
|
||||
local overtime = -self.flashtime
|
||||
if overtime >= ATTACK_BUTTON_FLASH_TIME then
|
||||
overtime = 0
|
||||
end
|
||||
self.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime
|
||||
|
||||
local flashTexture = self.flash
|
||||
if flashTexture:IsShown() then
|
||||
flashTexture:Hide()
|
||||
else
|
||||
flashTexture:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.rangeTimer then
|
||||
self.rangeTimer = self.rangeTimer - elapsed
|
||||
if self.rangeTimer <= 0 then
|
||||
local valid = IsActionInRange(self.action)
|
||||
self.outOfRange = (valid == 0)
|
||||
|
||||
local oor = Bartender4.db.profile.outofrange
|
||||
if oor == "hotkey" then
|
||||
local hotkey = self.hotkey
|
||||
local hkshown = hotkey:GetText() == RANGE_INDICATOR
|
||||
if valid and hkshown then
|
||||
hotkey:Show()
|
||||
elseif hkshown then
|
||||
hotkey:Hide()
|
||||
end
|
||||
|
||||
if self.outOfRange then
|
||||
local oorc = Bartender4.db.profile.colors.range
|
||||
hotkey:SetVertexColor(oorc.r, oorc.g, oorc.b)
|
||||
else
|
||||
hotkey:SetVertexColor(1.0, 1.0, 1.0)
|
||||
end
|
||||
elseif oor == "button" then
|
||||
self:UpdateUsable()
|
||||
end
|
||||
self.rangeTimer = TOOLTIP_UPDATE_TIME
|
||||
end
|
||||
end
|
||||
end
|
||||
Bartender4.Button.onUpdate = onUpdate
|
||||
|
||||
local function updateIcon(self)
|
||||
if self.action then
|
||||
if specialButtons[self.action] then
|
||||
if not LBF then
|
||||
self.normalTexture:SetTexCoord(0, 0, 0, 0)
|
||||
end
|
||||
self.icon:SetTexture(specialButtons[self.action].icon)
|
||||
self.icon:Show()
|
||||
self:UpdateUsable()
|
||||
elseif not LBF then
|
||||
if GetActionTexture(self.action) then
|
||||
self.normalTexture:SetTexCoord(0, 0, 0, 0)
|
||||
else
|
||||
self.normalTexture:SetTexCoord(-0.15, 1.15, -0.15, 1.17)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateFunc(self)
|
||||
local parent = self:GetParent()
|
||||
if not self.BT4init or not parent.BT4BarType then return end
|
||||
self:UpdateRange()
|
||||
updateIcon(self)
|
||||
|
||||
if self.SecureInit and not InCombatLockdown() then
|
||||
local parent = self:GetParent()
|
||||
parent:SetFrameRef("upd", self)
|
||||
parent:Execute([[
|
||||
local frame = self:GetFrameRef("upd")
|
||||
control:RunFor(frame, frame:GetAttribute("UpdateAutoAssist"))
|
||||
]])
|
||||
end
|
||||
end
|
||||
|
||||
hooksecurefunc("ActionButton_Update", updateFunc)
|
||||
|
||||
Button.SetRealNormalTexture = Button.SetNormalTexture
|
||||
function Button:SetNormalTexture(...)
|
||||
self.normalTexture:SetTexture(...)
|
||||
end
|
||||
|
||||
Button.GetRealNormalTexture = Button.GetNormalTexture
|
||||
function Button:GetNormalTexture()
|
||||
return self.normalTexture
|
||||
end
|
||||
|
||||
function Button:UpdateStates()
|
||||
self:SetAttribute("autoassist", self.parent.config.autoassist)
|
||||
end
|
||||
|
||||
function Button:SetStateAction(state, action)
|
||||
self.stateactions[state] = action
|
||||
self:RefreshStateAction(state)
|
||||
end
|
||||
|
||||
function Button:RefreshStateAction(state)
|
||||
local state = tonumber(state or self:GetAttribute("state")) or 0
|
||||
local action = self.stateactions[state]
|
||||
assert(action, ("No valid action for state %d on button %d of Bar %d"):format(state, self.rid, self.parent.id))
|
||||
self:SetAttribute("action-"..state, action)
|
||||
|
||||
if action > 120 and action <= 126 then
|
||||
self:SetAttribute("clickbutton", _G["VehicleMenuBarActionButton"..tostring(action-120)])
|
||||
elseif action == 132 then
|
||||
self:SetAttribute("clickbutton", PossessButton2)
|
||||
end
|
||||
end
|
||||
|
||||
function Button:UpdateSelfCast()
|
||||
self:SetAttribute("checkmouseovercast", true)
|
||||
self:SetAttribute("checkselfcast", Bartender4.db.profile.selfcastmodifier and true or nil)
|
||||
self:SetAttribute("checkfocuscast", Bartender4.db.profile.focuscastmodifier and true or nil)
|
||||
self:SetAttribute("unit2", Bartender4.db.profile.selfcastrightclick and "player" or nil)
|
||||
end
|
||||
|
||||
function Button:GetActionID()
|
||||
return self.action
|
||||
end
|
||||
|
||||
function Button:Update()
|
||||
self:UpdateAction(true)
|
||||
self:UpdateHotkeys()
|
||||
self:ToggleButtonElements()
|
||||
self:UpdateRange()
|
||||
end
|
||||
|
||||
function Button:UpdateAction(force)
|
||||
ActionButton_UpdateAction(self)
|
||||
end
|
||||
|
||||
function Button:ToggleButtonElements()
|
||||
if self.parent.config.hidemacrotext then
|
||||
self.macroName:Hide()
|
||||
else
|
||||
self.macroName:Show()
|
||||
end
|
||||
end
|
||||
|
||||
hooksecurefunc("ActionButton_UpdateHotkeys", function(self, ...)
|
||||
local parent = self:GetParent()
|
||||
if not self.BT4init or not parent.BT4BarType then return end
|
||||
|
||||
self:UpdateHotkeys()
|
||||
end)
|
||||
|
||||
function Button:UpdateHotkeys()
|
||||
local key = self:GetHotkey() or ""
|
||||
local hotkey = self.hotkey
|
||||
|
||||
if key == "" or self.parent.config.hidehotkey then
|
||||
hotkey:SetText(RANGE_INDICATOR)
|
||||
hotkey:SetPoint("TOPLEFT", self, "TOPLEFT", 1, -2)
|
||||
hotkey:Hide()
|
||||
else
|
||||
hotkey:SetText(key)
|
||||
hotkey:SetPoint("TOPLEFT", self, "TOPLEFT", -2, -2)
|
||||
hotkey:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function Button:GetHotkey()
|
||||
local key = ((self.id <= 12) and GetBindingKey(format("ACTIONBUTTON%d", self.id))) or GetBindingKey("CLICK "..self:GetName()..":LeftButton")
|
||||
return key and KeyBound:ToShortKey(key)
|
||||
end
|
||||
|
||||
function Button:GetBindings()
|
||||
local keys, binding = ""
|
||||
|
||||
if self.id <= 12 then
|
||||
binding = format("ACTIONBUTTON%d", self.id)
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys ~= "" then
|
||||
keys = keys .. ', '
|
||||
end
|
||||
keys = keys .. GetBindingText(hotKey,'KEY_')
|
||||
end
|
||||
end
|
||||
|
||||
binding = "CLICK "..self:GetName()..":LeftButton"
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys ~= "" then
|
||||
keys = keys .. ', '
|
||||
end
|
||||
keys = keys .. GetBindingText(hotKey,'KEY_')
|
||||
end
|
||||
|
||||
return keys
|
||||
end
|
||||
|
||||
function Button:SetKey(key)
|
||||
if self.id <= 12 then
|
||||
SetBinding(key, format("ACTIONBUTTON%d", self.id))
|
||||
else
|
||||
SetBindingClick(key, self:GetName(), 'LeftButton')
|
||||
end
|
||||
end
|
||||
|
||||
function Button:ClearBindings()
|
||||
if self.id <= 12 then
|
||||
local binding = format("ACTIONBUTTON%d", self.id)
|
||||
while GetBindingKey(binding) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
end
|
||||
local binding = "CLICK "..self:GetName()..":LeftButton"
|
||||
while GetBindingKey(binding) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
end
|
||||
|
||||
local actionTmpl = "BT4 Bar %d Button %d"
|
||||
function Button:GetActionName()
|
||||
return format(actionTmpl, self.parent.id, self.rid)
|
||||
end
|
||||
|
||||
hooksecurefunc("ActionButton_UpdateUsable", function(self)
|
||||
if self.BT4init then
|
||||
self:UpdateUsable()
|
||||
end
|
||||
end)
|
||||
|
||||
function Button:UpdateUsable()
|
||||
local isUsable, notEnoughMana = IsUsableAction(self.action)
|
||||
local icon = self.icon
|
||||
|
||||
if Bartender4.db.profile.outofrange == "button" and self.outOfRange then
|
||||
local oorc = Bartender4.db.profile.colors.range
|
||||
icon:SetVertexColor(oorc.r, oorc.g, oorc.b)
|
||||
else
|
||||
if isUsable or specialButtons[self.action] then
|
||||
icon:SetVertexColor(1.0, 1.0, 1.0)
|
||||
elseif notEnoughMana then
|
||||
local oomc = Bartender4.db.profile.colors.mana
|
||||
icon:SetVertexColor(oomc.r, oomc.g, oomc.b)
|
||||
else
|
||||
icon:SetVertexColor(0.4, 0.4, 0.4)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Button:UpdateRange()
|
||||
if Bartender4.db.profile.outofrange == "none" or not ActionHasRange(self.action) then
|
||||
self.rangeTimer = nil
|
||||
self.outOfRange = nil
|
||||
end
|
||||
self.hotkey:SetVertexColor(1.0, 1.0, 1.0)
|
||||
self:UpdateUsable()
|
||||
onUpdate(self, 10)
|
||||
end
|
||||
|
||||
function Button:SetTooltip()
|
||||
if ( GetCVar("UberTooltips") == "1" ) then
|
||||
GameTooltip_SetDefaultAnchor(GameTooltip, self)
|
||||
else
|
||||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||||
end
|
||||
|
||||
if specialButtons[self.action] then
|
||||
GameTooltip:SetText(specialButtons[self.action].tooltip)
|
||||
self.UpdateTooltip = self.SetTooltip
|
||||
else
|
||||
if ( GameTooltip:SetAction(self.action) ) then
|
||||
self.UpdateTooltip = self.SetTooltip
|
||||
else
|
||||
self.UpdateTooltip = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Button:UpdateGrid()
|
||||
if self:GetAttribute("showgrid") > 0 then
|
||||
ActionButton_ShowGrid(self)
|
||||
else
|
||||
ActionButton_HideGrid(self)
|
||||
end
|
||||
end
|
||||
|
||||
function Button:ShowGrid()
|
||||
if not self.gridShown then
|
||||
self.gridShown = true
|
||||
self:SetAttribute("showgrid", self:GetAttribute("showgrid") + 1)
|
||||
self:UpdateGrid()
|
||||
end
|
||||
end
|
||||
|
||||
function Button:HideGrid()
|
||||
if self.gridShown then
|
||||
self.gridShown = nil
|
||||
self:SetAttribute("showgrid", max(0, self:GetAttribute("showgrid") - 1))
|
||||
self:UpdateGrid()
|
||||
end
|
||||
end
|
||||
|
||||
function Button:ClearSetPoint(...)
|
||||
self:ClearAllPoints()
|
||||
self:SetPoint(...)
|
||||
end
|
||||
@@ -0,0 +1,124 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
-- register module
|
||||
local BagBarMod = Bartender4:NewModule("BagBar", "AceHook-3.0")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
local LBF = LibStub("LibButtonFacade", true)
|
||||
|
||||
-- create prototype information
|
||||
local BagBar = setmetatable({}, {__index = ButtonBar})
|
||||
|
||||
local table_insert = table.insert
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = true,
|
||||
keyring = false,
|
||||
onebag = false,
|
||||
visibility = {
|
||||
possess = false,
|
||||
},
|
||||
}, Bartender4.ButtonBar.defaults) }
|
||||
|
||||
function BagBarMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("BagBar", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
local noopFunc = function() end
|
||||
|
||||
function BagBarMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.ButtonBar:Create("BagBar", self.db.profile, L["Bag Bar"]), {__index = BagBar})
|
||||
end
|
||||
self.bar:Enable()
|
||||
self:ToggleOptions()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
function BagBarMod:ApplyConfig()
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
end
|
||||
|
||||
function BagBar:ApplyConfig(config)
|
||||
ButtonBar.ApplyConfig(self, config)
|
||||
|
||||
if not self.config.position.x then
|
||||
self:ClearSetPoint("CENTER", 142, -18)
|
||||
self:SavePosition()
|
||||
end
|
||||
|
||||
self:FeedButtons()
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function clearSetPoint(btn, ...)
|
||||
btn:ClearAllPoints()
|
||||
btn:SetPoint(...)
|
||||
end
|
||||
|
||||
BagBar.button_width = 30
|
||||
BagBar.button_height = 30
|
||||
BagBarMod.button_count = 5
|
||||
function BagBar:FeedButtons()
|
||||
local count = 1
|
||||
if self.buttons then
|
||||
while next(self.buttons) do
|
||||
local btn = table.remove(self.buttons)
|
||||
btn:Hide()
|
||||
btn:SetParent(UIParent)
|
||||
btn:ClearSetPoint("CENTER")
|
||||
if btn ~= KeyRingButton and btn.LBFButtonData then
|
||||
local group = self.LBFGroup
|
||||
group:RemoveButton(btn)
|
||||
end
|
||||
end
|
||||
else
|
||||
self.buttons = {}
|
||||
end
|
||||
|
||||
if self.config.keyring then
|
||||
table_insert(self.buttons, KeyRingButton)
|
||||
count = count + 1
|
||||
end
|
||||
|
||||
if not self.config.onebag then
|
||||
table_insert(self.buttons, CharacterBag3Slot)
|
||||
table_insert(self.buttons, CharacterBag2Slot)
|
||||
table_insert(self.buttons, CharacterBag1Slot)
|
||||
table_insert(self.buttons, CharacterBag0Slot)
|
||||
count = count + 4
|
||||
end
|
||||
|
||||
table_insert(self.buttons, MainMenuBarBackpackButton)
|
||||
|
||||
for i,v in pairs(self.buttons) do
|
||||
v:SetParent(self)
|
||||
v:Show()
|
||||
if v ~= KeyRingButton then
|
||||
v:SetNormalTexture("")
|
||||
|
||||
if LBF then
|
||||
local group = self.LBFGroup
|
||||
if not v.LBFButtonData then
|
||||
v.LBFButtonData = {
|
||||
Button = v,
|
||||
Icon = _G[v:GetName() .. "IconTexture"],
|
||||
}
|
||||
end
|
||||
group:AddButton(v, v.LBFButtonData)
|
||||
end
|
||||
end
|
||||
|
||||
v.ClearSetPoint = clearSetPoint
|
||||
end
|
||||
|
||||
BagBarMod.button_count = count
|
||||
if BagBarMod.optionobject then
|
||||
BagBarMod.optionobject.table.general.args.rows.max = count
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,519 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
--[[
|
||||
Generic Bar Frame Template
|
||||
]]
|
||||
local Bar = CreateFrame("Button")
|
||||
local Bar_MT = {__index = Bar}
|
||||
|
||||
local table_concat, table_insert = table.concat, table.insert
|
||||
|
||||
--[[===================================================================================
|
||||
Universal Bar Contructor
|
||||
===================================================================================]]--
|
||||
|
||||
local defaults = {
|
||||
alpha = 1,
|
||||
fadeout = false,
|
||||
fadeoutalpha = 0.1,
|
||||
fadeoutdelay = 0.2,
|
||||
visibility = {
|
||||
vehicleui = true,
|
||||
stance = {},
|
||||
},
|
||||
position = {
|
||||
scale = 1,
|
||||
growVertical = "DOWN",
|
||||
growHorizontal = "RIGHT",
|
||||
},
|
||||
clickthrough = false,
|
||||
}
|
||||
|
||||
local Sticky = LibStub("LibSimpleSticky-1.0")
|
||||
local LibWin = LibStub("LibWindow-1.1")
|
||||
local snapBars = { WorldFrame, UIParent }
|
||||
|
||||
local barOnEnter, barOnLeave, barOnDragStart, barOnDragStop, barOnClick, barOnUpdateFunc, barOnAttributeChanged
|
||||
do
|
||||
function barOnEnter(self)
|
||||
if not self:GetParent().isMoving then
|
||||
self:SetBackdropBorderColor(0.5, 0.5, 0, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function barOnLeave(self)
|
||||
self:SetBackdropBorderColor(0, 0, 0, 0)
|
||||
end
|
||||
|
||||
local function barReAnchorForSnap(self)
|
||||
local x,y,anchor = nil, nil, self:GetAnchor()
|
||||
x = (self.config.position.growHorizontal == "RIGHT") and self:GetLeft() or self:GetRight()
|
||||
y = (self.config.position.growVertical == "DOWN") and self:GetTop() or self:GetBottom()
|
||||
self:ClearSetPoint(anchor, UIParent, "BOTTOMLEFT", x, y)
|
||||
self:SetWidth(self.overlay:GetWidth())
|
||||
self:SetHeight(self.overlay:GetHeight())
|
||||
end
|
||||
|
||||
local function barReAnchorNormal(self)
|
||||
local x,y,anchor = nil, nil, self:GetAnchor()
|
||||
x = (self.config.position.growHorizontal == "RIGHT") and self:GetLeft() or self:GetRight()
|
||||
y = (self.config.position.growVertical == "DOWN") and self:GetTop() or self:GetBottom()
|
||||
self:ClearSetPoint(anchor, UIParent, "BOTTOMLEFT", x, y)
|
||||
self:SetWidth(1)
|
||||
self:SetHeight(1)
|
||||
end
|
||||
|
||||
function barOnDragStart(self)
|
||||
local parent = self:GetParent()
|
||||
if Bartender4.db.profile.snapping then
|
||||
local offset = 8 - (parent.config.padding or 0)
|
||||
-- we need to re-anchor the bar and set its proper width for snaping to work properly
|
||||
barReAnchorForSnap(parent)
|
||||
Sticky:StartMoving(parent, snapBars, offset, offset, offset, offset)
|
||||
else
|
||||
parent:StartMoving()
|
||||
end
|
||||
self:SetBackdropBorderColor(0, 0, 0, 0)
|
||||
parent.isMoving = true
|
||||
end
|
||||
|
||||
function barOnDragStop(self)
|
||||
local parent = self:GetParent()
|
||||
if parent.isMoving then
|
||||
if Bartender4.db.profile.snapping then
|
||||
local sticky, stickTo = Sticky:StopMoving(parent)
|
||||
barReAnchorNormal(parent)
|
||||
--Bartender4:Print(sticky, stickTo and stickTo:GetName() or nil)
|
||||
else
|
||||
parent:StopMovingOrSizing()
|
||||
end
|
||||
parent:SavePosition()
|
||||
parent.isMoving = nil
|
||||
end
|
||||
end
|
||||
|
||||
function barOnClick(self)
|
||||
-- TODO: Hide/Show bar on Click
|
||||
-- TODO: Once dropdown config is stable, show dropdown on rightclick
|
||||
end
|
||||
|
||||
function barOnUpdateFunc(self, elapsed)
|
||||
self.elapsed = self.elapsed + elapsed
|
||||
if self.elapsed > self.config.fadeoutdelay then
|
||||
self:ControlFadeOut(self.elapsed)
|
||||
self.elapsed = 0
|
||||
end
|
||||
end
|
||||
|
||||
function barOnAttributeChanged(self, attribute, value)
|
||||
if attribute == "fade" then
|
||||
if value then
|
||||
self:SetScript("OnUpdate", barOnUpdateFunc)
|
||||
self:ControlFadeOut()
|
||||
else
|
||||
self:SetScript("OnUpdate", nil)
|
||||
self.faded = nil
|
||||
self:SetConfigAlpha()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local barregistry = {}
|
||||
Bartender4.Bar = {}
|
||||
Bartender4.Bar.defaults = defaults
|
||||
Bartender4.Bar.prototype = Bar
|
||||
Bartender4.Bar.barregistry = barregistry
|
||||
function Bartender4.Bar:Create(id, config, name)
|
||||
id = tostring(id)
|
||||
assert(not barregistry[id], "duplicated entry in barregistry.")
|
||||
|
||||
local bar = setmetatable(CreateFrame("Frame", ("BT4Bar%s"):format(id), UIParent, "SecureHandlerStateTemplate"), Bar_MT)
|
||||
barregistry[id] = bar
|
||||
|
||||
bar.id = id
|
||||
bar.name = name or id
|
||||
bar.config = config
|
||||
bar:SetMovable(true)
|
||||
bar:HookScript("OnAttributeChanged", barOnAttributeChanged)
|
||||
|
||||
bar:SetWidth(1)
|
||||
bar:SetHeight(1)
|
||||
|
||||
local overlay = CreateFrame("Button", bar:GetName() .. "Overlay", bar)
|
||||
bar.overlay = overlay
|
||||
overlay.bar = bar
|
||||
table_insert(snapBars, overlay)
|
||||
overlay:EnableMouse(true)
|
||||
overlay:RegisterForDrag("LeftButton")
|
||||
overlay:RegisterForClicks("LeftButtonUp")
|
||||
overlay:SetBackdrop({
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
tile = true,
|
||||
tileSize = 16,
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
edgeSize = 16,
|
||||
insets = {left = 5, right = 3, top = 3, bottom = 5}
|
||||
})
|
||||
overlay:SetBackdropColor(0, 1, 0, 0.5)
|
||||
overlay:SetBackdropBorderColor(0.5, 0.5, 0, 0)
|
||||
overlay.Text = overlay:CreateFontString(nil, "ARTWORK")
|
||||
overlay.Text:SetFontObject(GameFontNormal)
|
||||
overlay.Text:SetText(name)
|
||||
overlay.Text:Show()
|
||||
overlay.Text:ClearAllPoints()
|
||||
overlay.Text:SetPoint("CENTER", overlay, "CENTER")
|
||||
|
||||
overlay:SetScript("OnEnter", barOnEnter)
|
||||
overlay:SetScript("OnLeave", barOnLeave)
|
||||
overlay:SetScript("OnDragStart", barOnDragStart)
|
||||
overlay:SetScript("OnDragStop", barOnDragStop)
|
||||
overlay:SetScript("OnClick", barOnClick)
|
||||
|
||||
overlay:SetFrameLevel(bar:GetFrameLevel() + 10)
|
||||
bar:AnchorOverlay()
|
||||
overlay:Hide()
|
||||
|
||||
bar.elapsed = 0
|
||||
bar.hidedriver = {}
|
||||
|
||||
return bar
|
||||
end
|
||||
|
||||
function Bartender4.Bar:GetAll()
|
||||
return pairs(barregistry)
|
||||
end
|
||||
|
||||
function Bartender4.Bar:ForAll(method, ...)
|
||||
for _,bar in self:GetAll() do
|
||||
local func = bar[method]
|
||||
if func then
|
||||
func(bar, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[===================================================================================
|
||||
Universal Bar Prototype
|
||||
===================================================================================]]--
|
||||
|
||||
Bar.BT4BarType = "Bar"
|
||||
|
||||
function Bar:ApplyConfig(config)
|
||||
if config then
|
||||
self.config = config
|
||||
end
|
||||
LibWin.RegisterConfig(self, self.config.position)
|
||||
|
||||
self:UpgradeConfig()
|
||||
if self.disabled then return end
|
||||
|
||||
if Bartender4.Locked then
|
||||
self:Lock()
|
||||
else
|
||||
self:Unlock()
|
||||
end
|
||||
self:LoadPosition()
|
||||
self:SetConfigScale()
|
||||
self:SetConfigAlpha()
|
||||
self:SetClickThrough()
|
||||
self:InitVisibilityDriver()
|
||||
end
|
||||
|
||||
function Bar:GetAnchor()
|
||||
return ((self.config.position.growVertical == "DOWN") and "TOP" or "BOTTOM") .. ((self.config.position.growHorizontal == "RIGHT") and "LEFT" or "RIGHT")
|
||||
end
|
||||
|
||||
function Bar:AnchorOverlay()
|
||||
self.overlay:ClearAllPoints()
|
||||
local anchor = self:GetAnchor()
|
||||
self.overlay:SetPoint(anchor, self, anchor)
|
||||
end
|
||||
|
||||
function Bar:UpgradeConfig()
|
||||
local version = self.config.version or 1
|
||||
if version < 2 then
|
||||
-- LibWindow migration, move scale into position
|
||||
if self.config.scale then
|
||||
self.config.position.scale = self.config.scale
|
||||
self.config.scale = nil
|
||||
end
|
||||
-- LibWindow migration, update position data
|
||||
do
|
||||
local pos = self.config.position
|
||||
self:SetScale(pos.scale)
|
||||
local x, y, s = pos.x, pos.y, self:GetEffectiveScale()
|
||||
local point, relPoint = pos.point, pos.relPoint
|
||||
if x and y and point and relPoint then
|
||||
x, y = x/s, y/s
|
||||
self:ClearSetPoint(point, UIParent, relPoint, x, y)
|
||||
self:SavePosition()
|
||||
pos.relPoint = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if version < 3 then
|
||||
-- Size adjustment is done in first SetSize
|
||||
self.needSizeFix = true
|
||||
end
|
||||
self.config.version = Bartender4.CONFIG_VERSION
|
||||
end
|
||||
|
||||
function Bar:Unlock()
|
||||
if self.disabled or self.unlocked then return end
|
||||
self.unlocked = true
|
||||
self:DisableVisibilityDriver()
|
||||
self:Show()
|
||||
self.overlay:Show()
|
||||
end
|
||||
|
||||
function Bar:Lock()
|
||||
if self.disabled or not self.unlocked then return end
|
||||
self.unlocked = nil
|
||||
self:StopDragging()
|
||||
|
||||
self:ApplyVisibilityDriver()
|
||||
|
||||
self.overlay:Hide()
|
||||
end
|
||||
|
||||
function Bar:StopDragging()
|
||||
barOnDragStop(self.overlay)
|
||||
end
|
||||
|
||||
function Bar:LoadPosition()
|
||||
LibWin.RestorePosition(self)
|
||||
end
|
||||
|
||||
function Bar:SavePosition()
|
||||
LibWin.SavePosition(self)
|
||||
end
|
||||
|
||||
function Bar:SetSize(width, height)
|
||||
self.overlay:SetWidth(width)
|
||||
self.overlay:SetHeight(height or width)
|
||||
if self.needSizeFix then
|
||||
self:SetWidth(width)
|
||||
self:SetHeight(height or width)
|
||||
local x, y = self:GetLeft(), self:GetTop()
|
||||
self:ClearSetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x, y)
|
||||
self:SetWidth(1)
|
||||
self:SetHeight(1)
|
||||
self:SavePosition()
|
||||
self.needSizeFix = nil
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:GetConfigAlpha()
|
||||
return self.config.alpha
|
||||
end
|
||||
|
||||
function Bar:SetConfigAlpha(alpha)
|
||||
if alpha then
|
||||
self.config.alpha = alpha
|
||||
end
|
||||
if not self.faded then
|
||||
self:SetAlpha(self.config.alpha)
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:GetConfigScale()
|
||||
return self.config.position.scale
|
||||
end
|
||||
|
||||
function Bar:SetConfigScale(scale)
|
||||
if scale then
|
||||
LibWin.SetScale(self, scale)
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:GetClickThrough()
|
||||
return self.config.clickthrough
|
||||
end
|
||||
|
||||
function Bar:SetClickThrough(click)
|
||||
if click ~= nil then
|
||||
self.config.clickthrough = click
|
||||
end
|
||||
if self.ControlClickThrough then
|
||||
self:ControlClickThrough()
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:GetFadeOut()
|
||||
return self.config.fadeout
|
||||
end
|
||||
|
||||
function Bar:SetFadeOut(fadeout)
|
||||
if fadeout ~= nil then
|
||||
self.config.fadeout = fadeout
|
||||
self:InitVisibilityDriver()
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:GetFadeOutAlpha()
|
||||
return self.config.fadeoutalpha
|
||||
end
|
||||
|
||||
function Bar:SetFadeOutAlpha(fadealpha)
|
||||
if fadealpha ~= nil then
|
||||
self.config.fadeoutalpha = fadealpha
|
||||
end
|
||||
if self.faded then
|
||||
self:SetAlpha(self.config.fadeoutalpha)
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:GetFadeOutDelay()
|
||||
return self.config.fadeoutdelay
|
||||
end
|
||||
|
||||
function Bar:SetFadeOutDelay(delay)
|
||||
if delay ~= nil then
|
||||
self.config.fadeoutdelay = delay
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:ControlFadeOut()
|
||||
if self.faded and MouseIsOver(self.overlay) then
|
||||
self:SetAlpha(self.config.alpha)
|
||||
self.faded = nil
|
||||
elseif not self.faded and not MouseIsOver(self.overlay) then
|
||||
local fade = self:GetAttribute("fade")
|
||||
if tonumber(fade) then
|
||||
fade = min(max(fade, 0), 100) / 100
|
||||
self:SetAlpha(fade)
|
||||
else
|
||||
self:SetAlpha(self.config.fadeoutalpha or 0)
|
||||
end
|
||||
self.faded = true
|
||||
end
|
||||
end
|
||||
|
||||
local directVisCond = {
|
||||
pet = true,
|
||||
nopet = true,
|
||||
combat = true,
|
||||
nocombat = true,
|
||||
mounted = true,
|
||||
}
|
||||
function Bar:InitVisibilityDriver(returnOnly)
|
||||
local tmpDriver
|
||||
if returnOnly then
|
||||
tmpDriver = self.hidedriver
|
||||
else
|
||||
UnregisterStateDriver(self, 'vis')
|
||||
end
|
||||
self.hidedriver = {}
|
||||
|
||||
self:SetAttribute("_onstate-vis", [[
|
||||
if not newstate then return end
|
||||
if newstate == "show" then
|
||||
self:Show()
|
||||
self:SetAttribute("fade", false)
|
||||
elseif strsub(newstate, 1, 4) == "fade" then
|
||||
self:Show()
|
||||
self:SetAttribute("fade", (newstate == "fade") and true or strsub(newstate, 6))
|
||||
elseif newstate == "hide" then
|
||||
self:Hide()
|
||||
end
|
||||
]])
|
||||
|
||||
if self.config.visibility.custom and not returnOnly then
|
||||
table_insert(self.hidedriver, self.config.visibility.customdata or "")
|
||||
else
|
||||
for key, value in pairs(self.config.visibility) do
|
||||
if value then
|
||||
if key == "always" then
|
||||
table_insert(self.hidedriver, "hide")
|
||||
elseif key == "possess" then
|
||||
table_insert(self.hidedriver, "[bonusbar:5]hide")
|
||||
elseif key == "vehicleui" then
|
||||
table_insert(self.hidedriver, "[vehicleui]hide")
|
||||
elseif key == "vehicle" then
|
||||
table_insert(self.hidedriver, "[target=vehicle,exists]hide")
|
||||
elseif directVisCond[key] then
|
||||
table_insert(self.hidedriver, ("[%s]hide"):format(key))
|
||||
elseif key == "stance" then
|
||||
for k,v in pairs(value) do
|
||||
if v then
|
||||
table_insert(self.hidedriver, ("[stance:%d]hide"):format(k))
|
||||
end
|
||||
end
|
||||
elseif key == "custom" or key == "customdata" then
|
||||
-- do nothing
|
||||
else
|
||||
Bartender4:Print("Invalid visibility state: "..key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table_insert(self.hidedriver, self.config.fadeout and "fade" or "show")
|
||||
|
||||
if not returnOnly then
|
||||
self:ApplyVisibilityDriver()
|
||||
else
|
||||
self.hidedriver, tmpDriver = tmpDriver, self.hidedriver
|
||||
return table_concat(tmpDriver, ";")
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:ApplyVisibilityDriver()
|
||||
if self.unlocked then return end
|
||||
-- default state is shown
|
||||
local driver = table_concat(self.hidedriver, ";")
|
||||
RegisterStateDriver(self, "vis", driver)
|
||||
end
|
||||
|
||||
function Bar:DisableVisibilityDriver()
|
||||
UnregisterStateDriver(self, "vis")
|
||||
self:SetAttribute("state-vis", "show")
|
||||
self:Show()
|
||||
end
|
||||
|
||||
function Bar:GetVisibilityOption(option, index)
|
||||
if option == "stance" then
|
||||
return self.config.visibility.stance[index]
|
||||
else
|
||||
return self.config.visibility[option]
|
||||
end
|
||||
end
|
||||
|
||||
function Bar:SetVisibilityOption(option, value, arg)
|
||||
if option == "stance" then
|
||||
self.config.visibility.stance[value] = arg
|
||||
else
|
||||
self.config.visibility[option] = value
|
||||
end
|
||||
self:InitVisibilityDriver()
|
||||
end
|
||||
|
||||
function Bar:CopyCustomConditionals()
|
||||
self.config.visibility.customdata = self:InitVisibilityDriver(true)
|
||||
self:InitVisibilityDriver()
|
||||
end
|
||||
|
||||
function Bar:Enable()
|
||||
if not self.disabled then return end
|
||||
self.disabled = nil
|
||||
end
|
||||
|
||||
function Bar:Disable()
|
||||
if self.disabled then return end
|
||||
self:Lock()
|
||||
self.disabled = true
|
||||
self:UnregisterAllEvents()
|
||||
self:DisableVisibilityDriver()
|
||||
self:SetAttribute("state-vis", nil)
|
||||
self:Hide()
|
||||
end
|
||||
|
||||
--[[
|
||||
Lazyness functions
|
||||
]]
|
||||
function Bar:ClearSetPoint(...)
|
||||
self:ClearAllPoints()
|
||||
self:SetPoint(...)
|
||||
end
|
||||
@@ -0,0 +1,439 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local AceAddon = LibStub("AceAddon-3.0")
|
||||
Bartender4 = AceAddon:NewAddon("Bartender4", "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0")
|
||||
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local LDB = LibStub("LibDataBroker-1.1", true)
|
||||
local LDBIcon = LibStub("LibDBIcon-1.0", true)
|
||||
|
||||
local defaults = {
|
||||
profile = {
|
||||
tooltip = "enabled",
|
||||
buttonlock = false,
|
||||
outofrange = "button",
|
||||
colors = { range = { r = 0.8, g = 0.1, b = 0.1 }, mana = { r = 0.5, g = 0.5, b = 1.0 } },
|
||||
selfcastmodifier = true,
|
||||
focuscastmodifier = true,
|
||||
selfcastrightclick = false,
|
||||
snapping = true,
|
||||
blizzardVehicle = false,
|
||||
minimapIcon = {},
|
||||
}
|
||||
}
|
||||
|
||||
Bartender4.CONFIG_VERSION = 3
|
||||
|
||||
function Bartender4:OnInitialize()
|
||||
self.db = LibStub("AceDB-3.0"):New("Bartender4DB", defaults)
|
||||
self.db.RegisterCallback(self, "OnProfileChanged", "UpdateModuleConfigs")
|
||||
self.db.RegisterCallback(self, "OnProfileCopied", "UpdateModuleConfigs")
|
||||
self.db.RegisterCallback(self, "OnProfileReset", "UpdateModuleConfigs")
|
||||
|
||||
self:SetupOptions()
|
||||
|
||||
self.Locked = true
|
||||
self:RegisterEvent("PLAYER_REGEN_DISABLED", "CombatLockdown")
|
||||
|
||||
self:HideBlizzard()
|
||||
self:UpdateBlizzardVehicle()
|
||||
|
||||
if LDB then
|
||||
createLDBLauncher()
|
||||
end
|
||||
|
||||
BINDING_HEADER_Bartender4 = "Bartender4"
|
||||
BINDING_CATEGORY_Bartender4 = "Action Bars"
|
||||
for i=1,10 do
|
||||
if i > 1 then
|
||||
_G[('BINDING_CATEGORY_BT4BLANK%d'):format(i)] = "Action Bars" -- myBindings2 compat
|
||||
_G[('BINDING_HEADER_BT4BLANK%d'):format(i)] = "Bartender4 " .. L["Bar %s"]:format(i)
|
||||
end
|
||||
for k=1,12 do
|
||||
_G[("BINDING_NAME_CLICK BT4Button%d:LeftButton"):format(((i-1)*12)+k)] = ("Bartender4 %s %s"):format(L["Bar %s"]:format(i), L["Button %s"]:format(k))
|
||||
end
|
||||
end
|
||||
BINDING_HEADER_BT4PET = "Bartender4 " .. L["Pet Bar"]
|
||||
BINDING_CATEGORY_BT4PET = "Action Bars"
|
||||
BINDING_HEADER_BT4STANCE = "Bartender4 " .. L["Stance Bar"]
|
||||
BINDING_CATEGORY_BT4STANCE = "Action Bars"
|
||||
for k=1,10 do
|
||||
_G[("BINDING_NAME_CLICK BT4PetButton%d:LeftButton"):format(k)] = ("Bartender4 %s %s"):format(L["Pet Bar"], L["Button %s"]:format(k))
|
||||
_G[("BINDING_NAME_CLICK BT4StanceButton%d:LeftButton"):format(k)] = ("Bartender4 %s %s"):format(L["Stance Bar"], L["Button %s"]:format(k))
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:HideBlizzard()
|
||||
--MultiActionBar_Update = function() end
|
||||
MultiActionBar_UpdateGrid = function() end
|
||||
|
||||
-- Hide MultiBar Buttons, but keep the bars alive
|
||||
for i=1,12 do
|
||||
_G["ActionButton" .. i]:Hide()
|
||||
_G["ActionButton" .. i]:UnregisterAllEvents()
|
||||
|
||||
_G["MultiBarBottomLeftButton" .. i]:Hide()
|
||||
_G["MultiBarBottomLeftButton" .. i]:UnregisterAllEvents()
|
||||
|
||||
_G["MultiBarBottomRightButton" .. i]:Hide()
|
||||
_G["MultiBarBottomRightButton" .. i]:UnregisterAllEvents()
|
||||
|
||||
_G["MultiBarRightButton" .. i]:Hide()
|
||||
_G["MultiBarRightButton" .. i]:UnregisterAllEvents()
|
||||
|
||||
_G["MultiBarLeftButton" .. i]:Hide()
|
||||
_G["MultiBarLeftButton" .. i]:UnregisterAllEvents()
|
||||
end
|
||||
--UIPARENT_MANAGED_FRAME_POSITIONS['MultiBarRight'] = nil
|
||||
--UIPARENT_MANAGED_FRAME_POSITIONS['MultiBarLeft'] = nil
|
||||
--UIPARENT_MANAGED_FRAME_POSITIONS['MultiBarBottomLeft'] = nil
|
||||
--UIPARENT_MANAGED_FRAME_POSITIONS['MultiBarBottomRight'] = nil
|
||||
UIPARENT_MANAGED_FRAME_POSITIONS['MainMenuBar'] = nil
|
||||
UIPARENT_MANAGED_FRAME_POSITIONS['ShapeshiftBarFrame'] = nil
|
||||
UIPARENT_MANAGED_FRAME_POSITIONS['PossessBarFrame'] = nil
|
||||
UIPARENT_MANAGED_FRAME_POSITIONS['PETACTIONBAR_YPOS'] = nil
|
||||
|
||||
MainMenuBar:UnregisterAllEvents()
|
||||
MainMenuBar:Hide()
|
||||
|
||||
--MainMenuBarArtFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("BAG_UPDATE")
|
||||
MainMenuBarArtFrame:UnregisterEvent("ACTIONBAR_PAGE_CHANGED")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("KNOWN_CURRENCY_TYPES_UPDATE")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("CURRENCY_DISPLAY_UPDATE")
|
||||
MainMenuBarArtFrame:UnregisterEvent("ADDON_LOADED")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("UNIT_ENTERING_VEHICLE")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("UNIT_ENTERED_VEHICLE")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("UNIT_EXITING_VEHICLE")
|
||||
--MainMenuBarArtFrame:UnregisterEvent("UNIT_EXITED_VEHICLE")
|
||||
MainMenuBarArtFrame:Hide()
|
||||
|
||||
--MainMenuExpBar:UnregisterAllEvents()
|
||||
--MainMenuExpBar:Hide()
|
||||
|
||||
ShapeshiftBarFrame:UnregisterAllEvents()
|
||||
ShapeshiftBarFrame:Hide()
|
||||
|
||||
BonusActionBarFrame:UnregisterAllEvents()
|
||||
BonusActionBarFrame:Hide()
|
||||
|
||||
PossessBarFrame:UnregisterAllEvents()
|
||||
PossessBarFrame:Hide()
|
||||
|
||||
if PlayerTalentFrame then
|
||||
PlayerTalentFrame:UnregisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
|
||||
else
|
||||
hooksecurefunc('TalentFrame_LoadUI', function() PlayerTalentFrame:UnregisterEvent('ACTIVE_TALENT_GROUP_CHANGED') end)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ function Bartender4:OnEnable()
|
||||
--
|
||||
end
|
||||
--]]
|
||||
|
||||
function Bartender4:RegisterDefaultsKey(key, subdefaults)
|
||||
defaults.profile[key] = subdefaults
|
||||
|
||||
self.db:RegisterDefaults(defaults)
|
||||
end
|
||||
|
||||
function Bartender4:UpdateModuleConfigs()
|
||||
local unlock = false
|
||||
if not self.Locked then
|
||||
self:Lock()
|
||||
unlock = true
|
||||
end
|
||||
|
||||
for k,v in AceAddon:IterateModulesOfAddon(self) do
|
||||
v:ToggleModule()
|
||||
if v:IsEnabled() and type(v.ApplyConfig) == "function" then
|
||||
v:ApplyConfig()
|
||||
end
|
||||
end
|
||||
if LDB and LDBIcon then
|
||||
LDBIcon:Refresh("Bartender4", Bartender4.db.profile.minimapIcon)
|
||||
end
|
||||
|
||||
self:UpdateBlizzardVehicle()
|
||||
|
||||
if unlock then
|
||||
self:Unlock()
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:UpdateBlizzardVehicle()
|
||||
if self.db.profile.blizzardVehicle then
|
||||
MainMenuBarArtFrame:RegisterEvent("UNIT_ENTERING_VEHICLE")
|
||||
MainMenuBarArtFrame:RegisterEvent("UNIT_ENTERED_VEHICLE")
|
||||
MainMenuBarArtFrame:RegisterEvent("UNIT_EXITING_VEHICLE")
|
||||
MainMenuBarArtFrame:RegisterEvent("UNIT_EXITED_VEHICLE")
|
||||
MainMenuBarArtFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
local vehicleModule = Bartender4:GetModule("Vehicle", true)
|
||||
vehicleModule:Disable()
|
||||
vehicleModule.blizzardVehicle = true
|
||||
|
||||
RegisterStateDriver(MainMenuBar, "visibility", "hide")
|
||||
RegisterStateDriver(ShapeshiftBarFrame, "visibility", "hide")
|
||||
RegisterStateDriver(PossessBarFrame, "visibility", "hide")
|
||||
|
||||
if not self.vehicleController then
|
||||
self.vehicleController = CreateFrame("Frame", nil, UIParent, "SecureHandlerStateTemplate")
|
||||
self.vehicleController:SetAttribute("_onstate-vehicle", [[
|
||||
if newstate == "vehicle" then
|
||||
for i=1,6 do
|
||||
local button, vbutton = ("ACTIONBUTTON%d"):format(i), ("VehicleMenuBarActionButton%d"):format(i)
|
||||
for k=1,select('#', GetBindingKey(button)) do
|
||||
local key = select(k, GetBindingKey(button))
|
||||
self:SetBindingClick(true, key, vbutton)
|
||||
end
|
||||
end
|
||||
else
|
||||
self:ClearBindings()
|
||||
end
|
||||
]])
|
||||
end
|
||||
RegisterStateDriver(self.vehicleController, "vehicle", "[vehicleui]vehicle;novehicle")
|
||||
local btn = "VehicleMenuBarActionButton%d"
|
||||
for i=1,6 do
|
||||
local name = btn:format(i)
|
||||
local button = _G[name]
|
||||
button.UpdateUsable = Bartender4.Button.prototype.UpdateUsable
|
||||
button:SetScript("OnUpdate", Bartender4.Button.onUpdate)
|
||||
button.icon = _G[("%sIcon"):format(name)]
|
||||
button.border = _G[("%sBorder"):format(name)]
|
||||
button.cooldown = _G[("%sCooldown"):format(name)]
|
||||
button.macroName = _G[("%sName"):format(name)]
|
||||
button.hotkey = _G[("%sHotKey"):format(name)]
|
||||
button.count = _G[("%sCount"):format(name)]
|
||||
button.flash = _G[("%sFlash"):format(name)]
|
||||
button.BT4init = true
|
||||
button:SetParent(VehicleMenuBarActionButtonFrame)
|
||||
end
|
||||
else
|
||||
MainMenuBarArtFrame:UnregisterEvent("UNIT_ENTERING_VEHICLE")
|
||||
MainMenuBarArtFrame:UnregisterEvent("UNIT_ENTERED_VEHICLE")
|
||||
MainMenuBarArtFrame:UnregisterEvent("UNIT_EXITING_VEHICLE")
|
||||
MainMenuBarArtFrame:UnregisterEvent("UNIT_EXITED_VEHICLE")
|
||||
MainMenuBarArtFrame:UnregisterEvent("PLAYER_ENTERING_WORLD")
|
||||
|
||||
local vehicleModule = Bartender4:GetModule("Vehicle")
|
||||
vehicleModule.blizzardVehicle = nil
|
||||
if vehicleModule.db and vehicleModule.db.profile.enabled then
|
||||
vehicleModule:Enable()
|
||||
end
|
||||
UnregisterStateDriver(MainMenuBar, "visibility")
|
||||
UnregisterStateDriver(ShapeshiftBarFrame, "visibility")
|
||||
UnregisterStateDriver(PossessBarFrame, "visibility")
|
||||
if self.vehicleController then
|
||||
UnregisterStateDriver(self.vehicleController, "vehicle")
|
||||
end
|
||||
local btn = "VehicleMenuBarActionButton%d"
|
||||
for i=1,6 do
|
||||
local name = btn:format(i)
|
||||
local button = _G[name]
|
||||
button.BT4init = nil
|
||||
button:SetScript("OnUpdate", ActionButton_OnUpdate)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:CombatLockdown()
|
||||
self:Lock()
|
||||
LibStub("AceConfigDialog-3.0"):Close("Bartender4")
|
||||
end
|
||||
|
||||
function Bartender4:ToggleLock()
|
||||
if self.Locked then
|
||||
self:Unlock()
|
||||
else
|
||||
self:Lock()
|
||||
end
|
||||
end
|
||||
|
||||
local getSnap, setSnap
|
||||
do
|
||||
function getSnap()
|
||||
return Bartender4.db.profile.snapping
|
||||
end
|
||||
|
||||
function setSnap(value)
|
||||
Bartender4.Bar:ForAll("StopDragging")
|
||||
Bartender4.db.profile.snapping = value
|
||||
LibStub("AceConfigRegistry-3.0"):NotifyChange("Bartender4")
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:ShowUnlockDialog()
|
||||
if not self.unlock_dialog then
|
||||
local f = CreateFrame('Frame', 'Bartender4Dialog', UIParent)
|
||||
f:SetFrameStrata('DIALOG')
|
||||
f:SetToplevel(true)
|
||||
f:EnableMouse(true)
|
||||
f:SetClampedToScreen(true)
|
||||
f:SetWidth(360)
|
||||
f:SetHeight(110)
|
||||
f:SetBackdrop{
|
||||
bgFile='Interface\\DialogFrame\\UI-DialogBox-Background' ,
|
||||
edgeFile='Interface\\DialogFrame\\UI-DialogBox-Border',
|
||||
tile = true,
|
||||
insets = {left = 11, right = 12, top = 12, bottom = 11},
|
||||
tileSize = 32,
|
||||
edgeSize = 32,
|
||||
}
|
||||
f:SetPoint('TOP', 0, -50)
|
||||
f:Hide()
|
||||
f:SetScript('OnShow', function() PlaySound('igMainMenuOption') end)
|
||||
f:SetScript('OnHide', function() PlaySound('gsTitleOptionExit') end)
|
||||
|
||||
local tr = f:CreateTitleRegion()
|
||||
tr:SetAllPoints(f)
|
||||
|
||||
local header = f:CreateTexture(nil, 'ARTWORK')
|
||||
header:SetTexture('Interface\\DialogFrame\\UI-DialogBox-Header')
|
||||
header:SetWidth(256); header:SetHeight(64)
|
||||
header:SetPoint('TOP', 0, 12)
|
||||
|
||||
local title = f:CreateFontString('ARTWORK')
|
||||
title:SetFontObject('GameFontNormal')
|
||||
title:SetPoint('TOP', header, 'TOP', 0, -14)
|
||||
title:SetText(L["Bartender4"])
|
||||
|
||||
local desc = f:CreateFontString('ARTWORK')
|
||||
desc:SetFontObject('GameFontHighlight')
|
||||
desc:SetJustifyV('TOP')
|
||||
desc:SetJustifyH('LEFT')
|
||||
desc:SetPoint('TOPLEFT', 18, -32)
|
||||
desc:SetPoint('BOTTOMRIGHT', -18, 48)
|
||||
desc:SetText(L["Bars unlocked. Move them now and click Lock when you are done."])
|
||||
|
||||
local snapping = CreateFrame('CheckButton', 'Bartender4Snapping', f, 'OptionsCheckButtonTemplate')
|
||||
_G[snapping:GetName() .. 'Text']:SetText(L["Bar Snapping"])
|
||||
|
||||
snapping:SetScript('OnShow', function(self)
|
||||
self:SetChecked(getSnap())
|
||||
end)
|
||||
|
||||
snapping:SetScript('OnClick', function(self)
|
||||
setSnap(snapping:GetChecked())
|
||||
end)
|
||||
|
||||
local lockBars = CreateFrame('CheckButton', 'Bartender4DialogLock', f, 'OptionsButtonTemplate')
|
||||
getglobal(lockBars:GetName() .. 'Text'):SetText(L["Lock"])
|
||||
|
||||
lockBars:SetScript('OnClick', function(self)
|
||||
Bartender4:Lock()
|
||||
LibStub("AceConfigRegistry-3.0"):NotifyChange("Bartender4")
|
||||
end)
|
||||
|
||||
--position buttons
|
||||
snapping:SetPoint('BOTTOMLEFT', 14, 10)
|
||||
lockBars:SetPoint('BOTTOMRIGHT', -14, 14)
|
||||
|
||||
self.unlock_dialog = f
|
||||
end
|
||||
self.unlock_dialog:Show()
|
||||
end
|
||||
|
||||
function Bartender4:HideUnlockDialog()
|
||||
if self.unlock_dialog then
|
||||
self.unlock_dialog:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:Unlock()
|
||||
if self.Locked then
|
||||
self.Locked = false
|
||||
Bartender4.Bar:ForAll("Unlock")
|
||||
self:ShowUnlockDialog()
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:Lock()
|
||||
if not self.Locked then
|
||||
self.Locked = true
|
||||
Bartender4.Bar:ForAll("Lock")
|
||||
self:HideUnlockDialog()
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:Merge(target, source)
|
||||
if type(target) ~= "table" then target = {} end
|
||||
for k,v in pairs(source) do
|
||||
if type(v) == "table" then
|
||||
target[k] = self:Merge(target[k], v)
|
||||
elseif not target[k] then
|
||||
target[k] = v
|
||||
end
|
||||
end
|
||||
return target
|
||||
end
|
||||
|
||||
Bartender4.modulePrototype = {}
|
||||
function Bartender4.modulePrototype:ToggleModule(info, value)
|
||||
if value ~= nil then
|
||||
self.db.profile.enabled = value
|
||||
else
|
||||
value = self.db.profile.enabled
|
||||
end
|
||||
if value and not self:IsEnabled() then
|
||||
self:Enable()
|
||||
elseif not value and self:IsEnabled() then
|
||||
self:Disable()
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4.modulePrototype:ToggleOptions()
|
||||
if self.options then
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4.modulePrototype:OnDisable()
|
||||
if not self.bar then return end
|
||||
-- assign new config table
|
||||
self.bar.config = self.db.profile
|
||||
self.bar:Disable()
|
||||
self:ToggleOptions()
|
||||
end
|
||||
|
||||
Bartender4:SetDefaultModulePrototype(Bartender4.modulePrototype)
|
||||
|
||||
function createLDBLauncher()
|
||||
local L_BT_LEFT = L["|cffffff00Click|r to toggle bar lock"]
|
||||
local L_BT_RIGHT = L["|cffffff00Right-click|r to open the options menu"]
|
||||
|
||||
local LDBObj = LibStub("LibDataBroker-1.1"):NewDataObject("Bartender4", {
|
||||
type = "launcher",
|
||||
label = "Bartender4",
|
||||
OnClick = function(_, msg)
|
||||
if msg == "LeftButton" then
|
||||
if Bartender4.Locked then
|
||||
Bartender4["Unlock"](Bartender4)
|
||||
else
|
||||
Bartender4["Lock"](Bartender4)
|
||||
end
|
||||
elseif msg == "RightButton" then
|
||||
if LibStub("AceConfigDialog-3.0").OpenFrames["Bartender4"] then
|
||||
LibStub("AceConfigDialog-3.0"):Close("Bartender4")
|
||||
else
|
||||
LibStub("AceConfigDialog-3.0"):Open("Bartender4")
|
||||
end
|
||||
end
|
||||
end,
|
||||
icon = "Interface\\Icons\\INV_Drink_05",
|
||||
OnTooltipShow = function(tooltip)
|
||||
if not tooltip or not tooltip.AddLine then return end
|
||||
tooltip:AddLine("Bartender4")
|
||||
tooltip:AddLine(L_BT_LEFT)
|
||||
tooltip:AddLine(L_BT_RIGHT)
|
||||
end,
|
||||
})
|
||||
|
||||
if LDBIcon then
|
||||
LDBIcon:Register("Bartender4", LDBObj, Bartender4.db.profile.minimapIcon)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,76 @@
|
||||
## Interface: 30300
|
||||
## X-Curse-Packaged-Version: 4.4.2-2-g3b02ee4
|
||||
## X-Curse-Project-Name: Bartender4
|
||||
## X-Curse-Project-ID: bartender4
|
||||
## X-Curse-Repository-ID: wow/bartender4/mainline
|
||||
|
||||
## Title: Bartender4
|
||||
## Notes: Simple and Advanced combined - Bartender4 ActionBar AddOn (CoA fork: [aura:Name] / [form:Name] paging)
|
||||
|
||||
## Version: 4.4.2-2-g3b02ee4-coa1
|
||||
|
||||
## Author: Nevcairiel
|
||||
## X-Email: h.leppkes at gmail dot com
|
||||
|
||||
## X-Category: Action Bars
|
||||
## X-Website: http://www.wowace.com/projects/bartender4/
|
||||
## X-License: All rights reserved.
|
||||
|
||||
## SavedVariables: Bartender4DB
|
||||
## OptionalDeps: Ace3, ButtonFacade, LibKeyBound-1.0, LibDBIcon-1.0, LibWindow-1.1
|
||||
|
||||
#@no-lib-strip@
|
||||
libs\LibStub\LibStub.lua
|
||||
libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
|
||||
#@end-no-lib-strip@
|
||||
|
||||
libs\LibDataBroker-1.1.lua
|
||||
|
||||
#@no-lib-strip@
|
||||
libs\AceAddon-3.0\AceAddon-3.0.xml
|
||||
libs\AceDB-3.0\AceDB-3.0.xml
|
||||
libs\AceDBOptions-3.0\AceDBOptions-3.0.xml
|
||||
libs\AceEvent-3.0\AceEvent-3.0.xml
|
||||
libs\AceConsole-3.0\AceConsole-3.0.xml
|
||||
libs\AceHook-3.0\AceHook-3.0.xml
|
||||
libs\AceLocale-3.0\AceLocale-3.0.xml
|
||||
libs\AceGUI-3.0\AceGUI-3.0.xml
|
||||
libs\AceConfig-3.0\AceConfig-3.0.xml
|
||||
|
||||
libs\LibKeyBound-1.0\lib.xml
|
||||
libs\LibDBIcon-1.0\LibDBIcon-1.0.lua
|
||||
libs\LibWindow-1.1\LibWindow-1.1.lua
|
||||
#@end-no-lib-strip@
|
||||
|
||||
libs\SimpleSticky.lua
|
||||
|
||||
locale\locale.xml
|
||||
|
||||
## Core ##
|
||||
Bartender4.lua
|
||||
|
||||
## Prototypes ##
|
||||
Bar.lua
|
||||
ButtonBar.lua
|
||||
StateBar.lua
|
||||
ActionBar.lua
|
||||
|
||||
## CoA patches ##
|
||||
CoAAuraConditionals.lua
|
||||
|
||||
## Buttons ##
|
||||
ActionButton.lua
|
||||
PetButton.lua
|
||||
|
||||
## Modules ##
|
||||
ActionBars.lua
|
||||
BagBar.lua
|
||||
PetBar.lua
|
||||
StanceBar.lua
|
||||
MicroMenu.lua
|
||||
RepXPBar.lua
|
||||
VehicleBar.lua
|
||||
MultiCastBar.lua
|
||||
|
||||
## Options ##
|
||||
Options\Options.xml
|
||||
@@ -0,0 +1,150 @@
|
||||
<Bindings>
|
||||
<Binding name="BTTOGGLEACTIONBARLOCK" header="Bartender4" >
|
||||
if InCombatLockdown() then
|
||||
print("Cannot change the button lock during combat.")
|
||||
return
|
||||
end
|
||||
Bartender4.db.profile.buttonlock = not Bartender4.db.profile.buttonlock
|
||||
Bartender4.Bar:ForAll("ForAll", "SetAttribute", "buttonlock", Bartender4.db.profile.buttonlock)
|
||||
</Binding>
|
||||
<Binding name="CLICK BT4Button1:LeftButton" />
|
||||
<Binding name="CLICK BT4Button2:LeftButton" />
|
||||
<Binding name="CLICK BT4Button3:LeftButton" />
|
||||
<Binding name="CLICK BT4Button4:LeftButton" />
|
||||
<Binding name="CLICK BT4Button5:LeftButton" />
|
||||
<Binding name="CLICK BT4Button6:LeftButton" />
|
||||
<Binding name="CLICK BT4Button7:LeftButton" />
|
||||
<Binding name="CLICK BT4Button8:LeftButton" />
|
||||
<Binding name="CLICK BT4Button9:LeftButton" />
|
||||
<Binding name="CLICK BT4Button10:LeftButton" />
|
||||
<Binding name="CLICK BT4Button11:LeftButton" />
|
||||
<Binding name="CLICK BT4Button12:LeftButton" />
|
||||
<Binding name="CLICK BT4Button13:LeftButton" header="BT4BLANK2" />
|
||||
<Binding name="CLICK BT4Button14:LeftButton" />
|
||||
<Binding name="CLICK BT4Button15:LeftButton" />
|
||||
<Binding name="CLICK BT4Button16:LeftButton" />
|
||||
<Binding name="CLICK BT4Button17:LeftButton" />
|
||||
<Binding name="CLICK BT4Button18:LeftButton" />
|
||||
<Binding name="CLICK BT4Button19:LeftButton" />
|
||||
<Binding name="CLICK BT4Button20:LeftButton" />
|
||||
<Binding name="CLICK BT4Button21:LeftButton" />
|
||||
<Binding name="CLICK BT4Button22:LeftButton" />
|
||||
<Binding name="CLICK BT4Button23:LeftButton" />
|
||||
<Binding name="CLICK BT4Button24:LeftButton" />
|
||||
<Binding name="CLICK BT4Button25:LeftButton" header="BT4BLANK3" />
|
||||
<Binding name="CLICK BT4Button26:LeftButton" />
|
||||
<Binding name="CLICK BT4Button27:LeftButton" />
|
||||
<Binding name="CLICK BT4Button28:LeftButton" />
|
||||
<Binding name="CLICK BT4Button29:LeftButton" />
|
||||
<Binding name="CLICK BT4Button30:LeftButton" />
|
||||
<Binding name="CLICK BT4Button31:LeftButton" />
|
||||
<Binding name="CLICK BT4Button32:LeftButton" />
|
||||
<Binding name="CLICK BT4Button33:LeftButton" />
|
||||
<Binding name="CLICK BT4Button34:LeftButton" />
|
||||
<Binding name="CLICK BT4Button35:LeftButton" />
|
||||
<Binding name="CLICK BT4Button36:LeftButton" />
|
||||
<Binding name="CLICK BT4Button37:LeftButton" header="BT4BLANK4" />
|
||||
<Binding name="CLICK BT4Button38:LeftButton" />
|
||||
<Binding name="CLICK BT4Button39:LeftButton" />
|
||||
<Binding name="CLICK BT4Button40:LeftButton" />
|
||||
<Binding name="CLICK BT4Button41:LeftButton" />
|
||||
<Binding name="CLICK BT4Button42:LeftButton" />
|
||||
<Binding name="CLICK BT4Button43:LeftButton" />
|
||||
<Binding name="CLICK BT4Button44:LeftButton" />
|
||||
<Binding name="CLICK BT4Button45:LeftButton" />
|
||||
<Binding name="CLICK BT4Button46:LeftButton" />
|
||||
<Binding name="CLICK BT4Button47:LeftButton" />
|
||||
<Binding name="CLICK BT4Button48:LeftButton" />
|
||||
<Binding name="CLICK BT4Button49:LeftButton" header="BT4BLANK5" />
|
||||
<Binding name="CLICK BT4Button50:LeftButton" />
|
||||
<Binding name="CLICK BT4Button51:LeftButton" />
|
||||
<Binding name="CLICK BT4Button52:LeftButton" />
|
||||
<Binding name="CLICK BT4Button53:LeftButton" />
|
||||
<Binding name="CLICK BT4Button54:LeftButton" />
|
||||
<Binding name="CLICK BT4Button55:LeftButton" />
|
||||
<Binding name="CLICK BT4Button56:LeftButton" />
|
||||
<Binding name="CLICK BT4Button57:LeftButton" />
|
||||
<Binding name="CLICK BT4Button58:LeftButton" />
|
||||
<Binding name="CLICK BT4Button59:LeftButton" />
|
||||
<Binding name="CLICK BT4Button60:LeftButton" />
|
||||
<Binding name="CLICK BT4Button61:LeftButton" header="BT4BLANK6" />
|
||||
<Binding name="CLICK BT4Button62:LeftButton" />
|
||||
<Binding name="CLICK BT4Button63:LeftButton" />
|
||||
<Binding name="CLICK BT4Button64:LeftButton" />
|
||||
<Binding name="CLICK BT4Button65:LeftButton" />
|
||||
<Binding name="CLICK BT4Button66:LeftButton" />
|
||||
<Binding name="CLICK BT4Button67:LeftButton" />
|
||||
<Binding name="CLICK BT4Button68:LeftButton" />
|
||||
<Binding name="CLICK BT4Button69:LeftButton" />
|
||||
<Binding name="CLICK BT4Button70:LeftButton" />
|
||||
<Binding name="CLICK BT4Button71:LeftButton" />
|
||||
<Binding name="CLICK BT4Button72:LeftButton" />
|
||||
<Binding name="CLICK BT4Button73:LeftButton" header="BT4BLANK7" />
|
||||
<Binding name="CLICK BT4Button74:LeftButton" />
|
||||
<Binding name="CLICK BT4Button75:LeftButton" />
|
||||
<Binding name="CLICK BT4Button76:LeftButton" />
|
||||
<Binding name="CLICK BT4Button77:LeftButton" />
|
||||
<Binding name="CLICK BT4Button78:LeftButton" />
|
||||
<Binding name="CLICK BT4Button79:LeftButton" />
|
||||
<Binding name="CLICK BT4Button80:LeftButton" />
|
||||
<Binding name="CLICK BT4Button81:LeftButton" />
|
||||
<Binding name="CLICK BT4Button82:LeftButton" />
|
||||
<Binding name="CLICK BT4Button83:LeftButton" />
|
||||
<Binding name="CLICK BT4Button84:LeftButton" />
|
||||
<Binding name="CLICK BT4Button85:LeftButton" header="BT4BLANK8" />
|
||||
<Binding name="CLICK BT4Button86:LeftButton" />
|
||||
<Binding name="CLICK BT4Button87:LeftButton" />
|
||||
<Binding name="CLICK BT4Button88:LeftButton" />
|
||||
<Binding name="CLICK BT4Button89:LeftButton" />
|
||||
<Binding name="CLICK BT4Button90:LeftButton" />
|
||||
<Binding name="CLICK BT4Button91:LeftButton" />
|
||||
<Binding name="CLICK BT4Button92:LeftButton" />
|
||||
<Binding name="CLICK BT4Button93:LeftButton" />
|
||||
<Binding name="CLICK BT4Button94:LeftButton" />
|
||||
<Binding name="CLICK BT4Button95:LeftButton" />
|
||||
<Binding name="CLICK BT4Button96:LeftButton" />
|
||||
<Binding name="CLICK BT4Button97:LeftButton" header="BT4BLANK9" />
|
||||
<Binding name="CLICK BT4Button98:LeftButton" />
|
||||
<Binding name="CLICK BT4Button99:LeftButton" />
|
||||
<Binding name="CLICK BT4Button100:LeftButton" />
|
||||
<Binding name="CLICK BT4Button101:LeftButton" />
|
||||
<Binding name="CLICK BT4Button102:LeftButton" />
|
||||
<Binding name="CLICK BT4Button103:LeftButton" />
|
||||
<Binding name="CLICK BT4Button104:LeftButton" />
|
||||
<Binding name="CLICK BT4Button105:LeftButton" />
|
||||
<Binding name="CLICK BT4Button106:LeftButton" />
|
||||
<Binding name="CLICK BT4Button107:LeftButton" />
|
||||
<Binding name="CLICK BT4Button108:LeftButton" />
|
||||
<Binding name="CLICK BT4Button109:LeftButton" header="BT4BLANK10" />
|
||||
<Binding name="CLICK BT4Button110:LeftButton" />
|
||||
<Binding name="CLICK BT4Button111:LeftButton" />
|
||||
<Binding name="CLICK BT4Button112:LeftButton" />
|
||||
<Binding name="CLICK BT4Button113:LeftButton" />
|
||||
<Binding name="CLICK BT4Button114:LeftButton" />
|
||||
<Binding name="CLICK BT4Button115:LeftButton" />
|
||||
<Binding name="CLICK BT4Button116:LeftButton" />
|
||||
<Binding name="CLICK BT4Button117:LeftButton" />
|
||||
<Binding name="CLICK BT4Button118:LeftButton" />
|
||||
<Binding name="CLICK BT4Button119:LeftButton" />
|
||||
<Binding name="CLICK BT4Button120:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton1:LeftButton" header="BT4PET" />
|
||||
<Binding name="CLICK BT4PetButton2:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton3:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton4:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton5:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton6:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton7:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton8:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton9:LeftButton" />
|
||||
<Binding name="CLICK BT4PetButton10:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton1:LeftButton" header="BT4STANCE" />
|
||||
<Binding name="CLICK BT4StanceButton2:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton3:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton4:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton5:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton6:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton7:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton8:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton9:LeftButton" />
|
||||
<Binding name="CLICK BT4StanceButton10:LeftButton" />
|
||||
</Bindings>
|
||||
@@ -0,0 +1,259 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
--[[ Generic Template for a Bar which contains Buttons ]]
|
||||
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
local ButtonBar = setmetatable({}, {__index = Bar})
|
||||
local ButtonBar_MT = {__index = ButtonBar}
|
||||
|
||||
local defaults = Bartender4:Merge({
|
||||
padding = 2,
|
||||
rows = 1,
|
||||
hidemacrotext = false,
|
||||
hidehotkey = false,
|
||||
skin = {
|
||||
ID = "DreamLayout",
|
||||
Backdrop = true,
|
||||
Gloss = 0,
|
||||
Zoom = false,
|
||||
Colors = {},
|
||||
},
|
||||
}, Bartender4.Bar.defaults)
|
||||
|
||||
Bartender4.ButtonBar = {}
|
||||
Bartender4.ButtonBar.prototype = ButtonBar
|
||||
Bartender4.ButtonBar.defaults = defaults
|
||||
|
||||
local LBF = LibStub("LibButtonFacade", true)
|
||||
|
||||
function Bartender4.ButtonBar:Create(id, config, name)
|
||||
local bar = setmetatable(Bartender4.Bar:Create(id, config, name), ButtonBar_MT)
|
||||
|
||||
if LBF then
|
||||
bar.LBFGroup = LBF:Group("Bartender4", tostring(id))
|
||||
bar.LBFGroup.SkinID = config.skin.ID or "Blizzard"
|
||||
bar.LBFGroup.Backdrop = config.skin.Backdrop
|
||||
bar.LBFGroup.Gloss = config.skin.Gloss
|
||||
bar.LBFGroup.Colors = config.skin.Colors
|
||||
|
||||
LBF:RegisterSkinCallback("Bartender4", self.SkinChanged, self)
|
||||
end
|
||||
|
||||
return bar
|
||||
end
|
||||
|
||||
local barregistry = Bartender4.Bar.barregistry
|
||||
function Bartender4.ButtonBar:SkinChanged(SkinID, Gloss, Backdrop, Group, Button, Colors)
|
||||
local bar = barregistry[tostring(Group)]
|
||||
if not bar then return end
|
||||
|
||||
bar:SkinChanged(SkinID, Gloss, Backdrop, Colors, Button)
|
||||
end
|
||||
|
||||
ButtonBar.BT4BarType = "ButtonBar"
|
||||
|
||||
function ButtonBar:UpdateSkin()
|
||||
if not self.LBFGroup then return end
|
||||
local config = self.config
|
||||
self.LBFGroup:Skin(config.skin.ID, config.skin.Gloss, config.skin.Backdrop, config.skin.Colors)
|
||||
end
|
||||
|
||||
function ButtonBar:ApplyConfig(config)
|
||||
Bar.ApplyConfig(self, config)
|
||||
ButtonBar.UpdateSkin(self)
|
||||
-- any module inherting this template should call UpdateButtonLayout after setting up its buttons, we cannot call it here
|
||||
--self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
-- get the current padding
|
||||
function ButtonBar:GetPadding()
|
||||
return self.config.padding
|
||||
end
|
||||
|
||||
-- set the padding and refresh layout
|
||||
function ButtonBar:SetPadding(pad)
|
||||
if pad ~= nil then
|
||||
self.config.padding = pad
|
||||
end
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
|
||||
-- get the current number of rows
|
||||
function ButtonBar:GetRows()
|
||||
return self.config.rows
|
||||
end
|
||||
|
||||
-- set the number of rows and refresh layout
|
||||
function ButtonBar:SetRows(rows)
|
||||
if rows ~= nil then
|
||||
self.config.rows = rows
|
||||
end
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function ButtonBar:GetZoom()
|
||||
return self.config.skin.Zoom
|
||||
end
|
||||
|
||||
function ButtonBar:SetZoom(zoom)
|
||||
self.config.skin.Zoom = zoom
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function ButtonBar:SetHideMacroText(state)
|
||||
if state ~= nil then
|
||||
self.config.hidemacrotext = state
|
||||
end
|
||||
self:ForAll("Update")
|
||||
end
|
||||
|
||||
function ButtonBar:GetHideMacroText()
|
||||
return self.config.hidemacrotext
|
||||
end
|
||||
|
||||
function ButtonBar:SetHideHotkey(state)
|
||||
if state ~= nil then
|
||||
self.config.hidehotkey = state
|
||||
end
|
||||
self:ForAll("Update")
|
||||
end
|
||||
|
||||
function ButtonBar:GetHideHotkey()
|
||||
return self.config.hidehotkey
|
||||
end
|
||||
|
||||
function ButtonBar:SetHGrowth(value)
|
||||
self.config.position.growHorizontal = value
|
||||
self:AnchorOverlay()
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function ButtonBar:GetHGrowth()
|
||||
return self.config.position.growHorizontal
|
||||
end
|
||||
|
||||
function ButtonBar:SetVGrowth(value)
|
||||
self.config.position.growVertical = value
|
||||
self:AnchorOverlay()
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function ButtonBar:GetVGrowth()
|
||||
return self.config.position.growVertical
|
||||
end
|
||||
|
||||
|
||||
ButtonBar.ClickThroughSupport = true
|
||||
function ButtonBar:SetClickThrough(click)
|
||||
if click ~= nil then
|
||||
self.config.clickthrough = click
|
||||
end
|
||||
self:ForAll("EnableMouse", not self.config.clickthrough)
|
||||
end
|
||||
|
||||
local math_floor = math.floor
|
||||
local math_ceil = math.ceil
|
||||
-- align the buttons and correct the size of the bar overlay frame
|
||||
ButtonBar.button_width = 36
|
||||
ButtonBar.button_height = 36
|
||||
function ButtonBar:UpdateButtonLayout()
|
||||
local buttons = self.buttons
|
||||
local pad = self:GetPadding()
|
||||
|
||||
local numbuttons = self.numbuttons or #buttons
|
||||
|
||||
-- bail out if the bar has no buttons, for whatever reason
|
||||
-- (eg. stanceless class, or no stances learned yet, etc.)
|
||||
if numbuttons == 0 then return end
|
||||
|
||||
local Rows = self:GetRows()
|
||||
local ButtonPerRow = math_ceil(numbuttons / Rows) -- just a precaution
|
||||
Rows = math_ceil(numbuttons / ButtonPerRow)
|
||||
if Rows > numbuttons then
|
||||
Rows = numbuttons
|
||||
ButtonPerRow = 1
|
||||
end
|
||||
|
||||
local hpad = pad + (self.hpad_offset or 0)
|
||||
local vpad = pad + (self.vpad_offset or 0)
|
||||
|
||||
self:SetSize((self.button_width + hpad) * ButtonPerRow - pad + 10, (self.button_height + vpad) * Rows - pad + 10)
|
||||
|
||||
local h1, h2, v1, v2
|
||||
local xOff, yOff
|
||||
if self.config.position.growHorizontal == "RIGHT" then
|
||||
h1, h2 = "LEFT", "RIGHT"
|
||||
xOff = 5
|
||||
else
|
||||
h1, h2 = "RIGHT", "LEFT"
|
||||
xOff = -3
|
||||
|
||||
hpad = -hpad
|
||||
end
|
||||
|
||||
if self.config.position.growVertical == "DOWN" then
|
||||
v1, v2 = "TOP", "BOTTOM"
|
||||
yOff = -3
|
||||
else
|
||||
v1, v2 = "BOTTOM", "TOP"
|
||||
yOff = 5
|
||||
|
||||
vpad = -vpad
|
||||
end
|
||||
|
||||
-- anchor button 1
|
||||
local anchor = self:GetAnchor()
|
||||
buttons[1]:ClearSetPoint(anchor, self, anchor, xOff - (self.hpad_offset or 0), yOff - (self.vpad_offset or 0))
|
||||
|
||||
-- and anchor all other buttons relative to our button 1
|
||||
for i = 2, numbuttons do
|
||||
-- jump into a new row
|
||||
if ((i-1) % ButtonPerRow) == 0 then
|
||||
buttons[i]:ClearSetPoint(v1 .. h1, buttons[i-ButtonPerRow], v2 .. h1, 0, -vpad)
|
||||
-- align to the previous button
|
||||
else
|
||||
buttons[i]:ClearSetPoint("TOP" .. h1, buttons[i-1], "TOP" .. h2, hpad, 0)
|
||||
end
|
||||
end
|
||||
|
||||
if not LBF then
|
||||
for i = 1, #buttons do
|
||||
local button = buttons[i]
|
||||
if button.icon and self.config.skin.Zoom then
|
||||
button.icon:SetTexCoord(0.07,0.93,0.07,0.93)
|
||||
elseif button.icon then
|
||||
button.icon:SetTexCoord(0,1,0,1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ButtonBar:SkinChanged(SkinID, Gloss, Backdrop, Colors)
|
||||
self.config.skin.ID = SkinID
|
||||
self.config.skin.Gloss = Gloss
|
||||
self.config.skin.Backdrop = Backdrop
|
||||
self.config.skin.Colors = Colors
|
||||
end
|
||||
|
||||
--[[===================================================================================
|
||||
Utility function
|
||||
===================================================================================]]--
|
||||
|
||||
-- get a iterator over all buttons
|
||||
function ButtonBar:GetAll()
|
||||
return pairs(self.buttons)
|
||||
end
|
||||
|
||||
-- execute a member function on all buttons
|
||||
function ButtonBar:ForAll(method, ...)
|
||||
if not self.buttons then return end
|
||||
for _, button in self:GetAll() do
|
||||
local func = button[method]
|
||||
if func then
|
||||
func(button, ...)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,111 @@
|
||||
--[[
|
||||
CoA Bartender4 patch — translate [aura:Name] / [form:Name] /
|
||||
non-numeric [stance:Name] in paging conditionals into [stance:N].
|
||||
|
||||
Why: Blizzard's secure macro parser (SecureCmdOptionParse) only
|
||||
accepts a numeric index for [stance:] / [form:] and has no [aura:]
|
||||
keyword at all. Addons cannot register new conditionals into the
|
||||
secure parser. So the only honest place to do this is *before* we
|
||||
hand the string to RegisterStateDriver — we resolve form names to
|
||||
indices via GetShapeshiftFormInfo() and rewrite the keyword.
|
||||
|
||||
Scope: only shapeshift forms are resolvable this way. That covers
|
||||
Druid, Warrior stances, Death Knight presences, Priest Shadowform,
|
||||
and every CoA custom-class form (Venomancer, Wildkin, etc.) since
|
||||
those all live in the shapeshift bar. Non-form auras (regular
|
||||
buffs) cannot be expressed as a stance index and would need a
|
||||
synthetic state-driver attribute — out of scope here.
|
||||
|
||||
Usage in Bartender4 paging:
|
||||
[aura:Beetle Form]6;1 -- equivalent to [stance:1]6;1 (if Beetle Form is form 1)
|
||||
[form:Beetle Form]6;1
|
||||
[stance:Beetle Form]6;1
|
||||
[stance:Beetle Form/Wasp Form]6;1 -- slash-list works too
|
||||
[noaura:Beetle Form]2
|
||||
|
||||
All three keywords (aura, form, stance) are accepted equivalently
|
||||
when the value is a non-numeric form name. Numeric values pass
|
||||
through unchanged. Unresolvable names are left as-is so the failure
|
||||
is visible at conditional-parse time rather than silently swallowed.
|
||||
]]
|
||||
|
||||
local Bartender4 = _G.Bartender4
|
||||
if not Bartender4 then return end
|
||||
|
||||
local KEYWORDS = { "nostance", "noform", "noaura", "stance", "form", "aura" }
|
||||
local KEYWORD_OUT = {
|
||||
stance = "stance", form = "stance", aura = "stance",
|
||||
nostance = "nostance", noform = "nostance", noaura = "nostance",
|
||||
}
|
||||
|
||||
local function shapeshiftIndexByName(name)
|
||||
if type(GetNumShapeshiftForms) ~= "function" or type(GetShapeshiftFormInfo) ~= "function" then
|
||||
return nil
|
||||
end
|
||||
local n = GetNumShapeshiftForms() or 0
|
||||
local lname = name:lower()
|
||||
for i = 1, n do
|
||||
local _, fname = GetShapeshiftFormInfo(i)
|
||||
if fname and fname:lower() == lname then
|
||||
return i
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function translateValueList(values)
|
||||
local parts, anyTranslated = {}, false
|
||||
for v in values:gmatch("[^/]+") do
|
||||
local trimmed = v:match("^%s*(.-)%s*$") or v
|
||||
if trimmed:match("^%d+$") or trimmed == "" then
|
||||
parts[#parts + 1] = trimmed
|
||||
else
|
||||
local idx = shapeshiftIndexByName(trimmed)
|
||||
if idx then
|
||||
parts[#parts + 1] = tostring(idx)
|
||||
anyTranslated = true
|
||||
else
|
||||
parts[#parts + 1] = trimmed
|
||||
end
|
||||
end
|
||||
end
|
||||
return table.concat(parts, "/"), anyTranslated
|
||||
end
|
||||
|
||||
function Bartender4:CoATranslateConditionals(s)
|
||||
if type(s) ~= "string" or s == "" then return s end
|
||||
for _, kw in ipairs(KEYWORDS) do
|
||||
local outKw = KEYWORD_OUT[kw]
|
||||
s = s:gsub(kw .. ":([^,%]]+)", function(value)
|
||||
local newValue, didTranslate = translateValueList(value)
|
||||
if didTranslate then
|
||||
return outKw .. ":" .. newValue
|
||||
end
|
||||
return nil
|
||||
end)
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
-- Re-apply paging when shapeshift form set changes (new form learned,
|
||||
-- spec respec, etc.) so freshly-resolvable names take effect without
|
||||
-- a /reload. Skipped during combat lockdown — RegisterStateDriver is
|
||||
-- secure and the SetAttribute calls inside UpdateStates would taint.
|
||||
local refresh = CreateFrame("Frame")
|
||||
refresh:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
|
||||
refresh:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
refresh:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
local pendingRefresh = false
|
||||
refresh:SetScript("OnEvent", function(self, event)
|
||||
if InCombatLockdown and InCombatLockdown() then
|
||||
pendingRefresh = true
|
||||
return
|
||||
end
|
||||
if event == "PLAYER_REGEN_ENABLED" and not pendingRefresh then return end
|
||||
pendingRefresh = false
|
||||
local mod = Bartender4 and Bartender4.GetModule and Bartender4:GetModule("ActionBars", true)
|
||||
if not mod or not mod.actionbars then return end
|
||||
for _, bar in pairs(mod.actionbars) do
|
||||
if bar and bar.UpdateStates then bar:UpdateStates() end
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,98 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
-- register module
|
||||
local MicroMenuMod = Bartender4:NewModule("MicroMenu", "AceHook-3.0")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
-- create prototype information
|
||||
local MicroMenuBar = setmetatable({}, {__index = ButtonBar})
|
||||
|
||||
local table_insert = table.insert
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = true,
|
||||
vertical = false,
|
||||
visibility = {
|
||||
possess = false,
|
||||
},
|
||||
padding = -3,
|
||||
position = {
|
||||
scale = 0.8,
|
||||
},
|
||||
}, Bartender4.ButtonBar.defaults) }
|
||||
|
||||
function MicroMenuMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("MicroMenu", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
function MicroMenuMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.ButtonBar:Create("MicroMenu", self.db.profile, L["Micro Menu"]), {__index = MicroMenuBar})
|
||||
local buttons = {}
|
||||
table_insert(buttons, CharacterMicroButton)
|
||||
table_insert(buttons, SpellbookMicroButton)
|
||||
table_insert(buttons, TalentMicroButton)
|
||||
table_insert(buttons, AchievementMicroButton)
|
||||
table_insert(buttons, QuestLogMicroButton)
|
||||
table_insert(buttons, SocialsMicroButton)
|
||||
table_insert(buttons, LFDMicroButton)
|
||||
table_insert(buttons, PathToAscensionMicroButton)
|
||||
table_insert(buttons, MainMenuMicroButton)
|
||||
table_insert(buttons, HelpMicroButton)
|
||||
table_insert(buttons, ChallengesMicroButton)
|
||||
self.bar.buttons = buttons
|
||||
|
||||
MicroMenuMod.button_count = #buttons
|
||||
|
||||
self:SecureHook("UpdateMicroButtons")
|
||||
|
||||
for i,v in pairs(buttons) do
|
||||
v:SetParent(self.bar)
|
||||
v:Show()
|
||||
v:SetFrameLevel(self.bar:GetFrameLevel() + 1)
|
||||
v.ClearSetPoint = self.bar.ClearSetPoint
|
||||
end
|
||||
end
|
||||
self.bar:Enable()
|
||||
self:ToggleOptions()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
function MicroMenuMod:ApplyConfig()
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
end
|
||||
|
||||
function MicroMenuMod:RestoreButtons()
|
||||
if not self:IsEnabled() then return end
|
||||
for k,v in pairs(self.bar.buttons) do
|
||||
v:SetParent(self.bar)
|
||||
v:Show()
|
||||
end
|
||||
self.bar:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function MicroMenuMod:UpdateMicroButtons()
|
||||
if MainMenuBar.state == "player" then
|
||||
self:RestoreButtons()
|
||||
end
|
||||
end
|
||||
|
||||
MicroMenuBar.button_width = 27
|
||||
MicroMenuBar.button_height = 40
|
||||
MicroMenuBar.vpad_offset = 0
|
||||
function MicroMenuBar:ApplyConfig(config)
|
||||
ButtonBar.ApplyConfig(self, config)
|
||||
|
||||
if not self.config.position.x then
|
||||
self:ClearSetPoint("CENTER", -105, 30)
|
||||
self:SavePosition()
|
||||
end
|
||||
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
@@ -0,0 +1,74 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
|
||||
if not HasMultiCastActionBar then return end
|
||||
|
||||
local classMask = UnitClassMask("player")
|
||||
|
||||
if not bit.contains(EnumUtil.CombineMasks(Enum.ClassMask.SHAMAN, Enum.ClassMask.HERO), classMask) then
|
||||
return
|
||||
end
|
||||
|
||||
-- fetch upvalues
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = true,
|
||||
}, Bartender4.Bar.defaults) }
|
||||
|
||||
-- register module
|
||||
local MultiCastMod = Bartender4:NewModule("MultiCast")
|
||||
|
||||
-- create prototype information
|
||||
local MultiCastBar = setmetatable({}, {__index = Bar})
|
||||
|
||||
local function OnShowMultiCastActionBar()
|
||||
if MultiCastMod:IsEnabled() then
|
||||
MultiCastMod:ApplyConfig()
|
||||
end
|
||||
end
|
||||
|
||||
function MultiCastMod:OnInitialize()
|
||||
hooksecurefunc("ShowMultiCastActionBar", OnShowMultiCastActionBar)
|
||||
self.db = Bartender4.db:RegisterNamespace("MultiCast", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
function MultiCastMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.Bar:Create("MultiCast", self.db.profile, L["Totem Bar"]), {__index = MultiCastBar})
|
||||
self.bar.content = MultiCastActionBarFrame
|
||||
self.bar.content:SetScript("OnShow", nil)
|
||||
self.bar.content:SetScript("OnHide", nil)
|
||||
self.bar.content:SetScript("OnUpdate", nil)
|
||||
self.bar.content.ignoreFramePositionManager = true
|
||||
|
||||
self.bar.content:SetParent(self.bar)
|
||||
self.bar.content:Show()
|
||||
self.bar.content:SetFrameLevel(self.bar:GetFrameLevel() + 1)
|
||||
end
|
||||
self.bar:Enable()
|
||||
self:ToggleOptions()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
function MultiCastMod:ApplyConfig()
|
||||
if not self:IsEnabled() then return end
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
end
|
||||
|
||||
function MultiCastBar:ApplyConfig(config)
|
||||
Bar.ApplyConfig(self, config)
|
||||
|
||||
self:PerformLayout()
|
||||
end
|
||||
|
||||
function MultiCastBar:PerformLayout()
|
||||
self:SetSize(230, 40)
|
||||
local bar = self.content
|
||||
bar:ClearAllPoints()
|
||||
bar:SetPoint("TOPLEFT", self, "TOPLEFT", 3, 1)
|
||||
end
|
||||
@@ -0,0 +1,216 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
--------------------------
|
||||
-- Edit box --
|
||||
--------------------------
|
||||
--[[
|
||||
Events :
|
||||
OnTextChanged
|
||||
OnEnterPressed
|
||||
|
||||
]]
|
||||
do
|
||||
local Type = "NumberEditBox"
|
||||
local Version = 1
|
||||
|
||||
local function OnAcquire(self)
|
||||
self:SetDisabled(false)
|
||||
self.showbutton = true
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self:SetDisabled(false)
|
||||
end
|
||||
|
||||
local function Control_OnEnter(this)
|
||||
this.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(this)
|
||||
this.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function EditBox_OnEscapePressed(this)
|
||||
this:ClearFocus()
|
||||
end
|
||||
|
||||
local function ShowButton(self)
|
||||
if self.showbutton then
|
||||
self.button:Show()
|
||||
self.editbox:SetTextInsets(0,20,3,3)
|
||||
end
|
||||
end
|
||||
|
||||
local function HideButton(self)
|
||||
self.button:Hide()
|
||||
self.editbox:SetTextInsets(0,0,3,3)
|
||||
end
|
||||
|
||||
local function EditBox_OnEnterPressed(this)
|
||||
local self = this.obj
|
||||
local value = tonumber(this:GetText()) or 0
|
||||
local cancel = self:Fire("OnEnterPressed",value)
|
||||
if not cancel then
|
||||
HideButton(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function Button_OnClick(this)
|
||||
local editbox = this.obj.editbox
|
||||
editbox:ClearFocus()
|
||||
EditBox_OnEnterPressed(editbox)
|
||||
end
|
||||
|
||||
local function EditBox_OnTextChanged(this)
|
||||
local self = this.obj
|
||||
local value = tonumber(this:GetText()) or 0
|
||||
if value ~= self.lastvalue then
|
||||
self:Fire("OnTextChanged",value)
|
||||
self.lastvalue = value
|
||||
ShowButton(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetDisabled(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.editbox:EnableMouse(false)
|
||||
self.editbox:ClearFocus()
|
||||
self.editbox:SetTextColor(0.5,0.5,0.5)
|
||||
self.label:SetTextColor(0.5,0.5,0.5)
|
||||
else
|
||||
self.editbox:EnableMouse(true)
|
||||
self.editbox:SetTextColor(1,1,1)
|
||||
self.label:SetTextColor(1,.82,0)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetText(self, text)
|
||||
self.lastvalue = tonumber(text) or 0
|
||||
self.editbox:SetText(tostring(self.lastvalue))
|
||||
self.editbox:SetCursorPosition(0)
|
||||
HideButton(self)
|
||||
end
|
||||
|
||||
local function SetWidth(self, width)
|
||||
self.frame:SetWidth(width)
|
||||
end
|
||||
|
||||
local function SetLabel(self, text)
|
||||
if text and text ~= "" then
|
||||
self.label:SetText(text)
|
||||
self.label:Show()
|
||||
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
|
||||
self.frame:SetHeight(60)
|
||||
self.alignoffset = 30
|
||||
else
|
||||
self.label:SetText("")
|
||||
self.label:Hide()
|
||||
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
|
||||
self.frame:SetHeight(42)
|
||||
self.alignoffset = 12
|
||||
end
|
||||
end
|
||||
|
||||
local function ModButton_OnClick(self)
|
||||
local value = self.obj.lastvalue
|
||||
value = math.floor(value + 0.5) + self.adjust
|
||||
self.obj.editbox:SetText(tostring(value))
|
||||
EditBox_OnEnterPressed(self.obj.editbox)
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local num = AceGUI:GetNextWidgetNum(Type)
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local editbox = CreateFrame("EditBox","AceGUI-3.0NumberEditBox"..num,frame,"InputBoxTemplate")
|
||||
|
||||
local self = {}
|
||||
self.type = Type
|
||||
self.num = num
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
|
||||
self.SetDisabled = SetDisabled
|
||||
self.SetText = SetText
|
||||
self.SetWidth = SetWidth
|
||||
self.SetLabel = SetLabel
|
||||
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
self.editbox = editbox
|
||||
editbox.obj = self
|
||||
|
||||
self.alignoffset = 30
|
||||
|
||||
frame:SetHeight(60)
|
||||
frame:SetWidth(200)
|
||||
|
||||
editbox:SetScript("OnEnter",Control_OnEnter)
|
||||
editbox:SetScript("OnLeave",Control_OnLeave)
|
||||
|
||||
editbox:SetAutoFocus(false)
|
||||
editbox:SetFontObject(ChatFontNormal)
|
||||
editbox:SetScript("OnEscapePressed",EditBox_OnEscapePressed)
|
||||
editbox:SetScript("OnEnterPressed",EditBox_OnEnterPressed)
|
||||
editbox:SetScript("OnTextChanged",EditBox_OnTextChanged)
|
||||
|
||||
editbox:SetTextInsets(0,0,3,3)
|
||||
editbox:SetMaxLetters(256)
|
||||
|
||||
editbox:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",6,15)
|
||||
editbox:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,15)
|
||||
editbox:SetHeight(19)
|
||||
|
||||
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
|
||||
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-2)
|
||||
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,-2)
|
||||
label:SetJustifyH("LEFT")
|
||||
label:SetHeight(18)
|
||||
self.label = label
|
||||
|
||||
local button = CreateFrame("Button",nil,editbox,"UIPanelButtonTemplate")
|
||||
button:SetWidth(40)
|
||||
button:SetHeight(20)
|
||||
button:SetPoint("RIGHT",editbox,"RIGHT",-2,0)
|
||||
button:SetText(OKAY)
|
||||
button:SetScript("OnClick", Button_OnClick)
|
||||
button:Hide()
|
||||
|
||||
self.button = button
|
||||
button.obj = self
|
||||
|
||||
local minus = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
|
||||
minus:SetWidth(20)
|
||||
minus:SetHeight(15)
|
||||
minus:SetPoint("TOPLEFT", editbox, "BOTTOMLEFT", -4, 0)
|
||||
minus:SetText("-")
|
||||
minus:Show()
|
||||
minus.adjust = -1
|
||||
minus:SetScript("OnClick", ModButton_OnClick)
|
||||
minus:SetFrameLevel(editbox:GetFrameLevel() + 2)
|
||||
|
||||
self.minus = minus
|
||||
minus.obj = self
|
||||
|
||||
local plus = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
|
||||
plus:SetWidth(20)
|
||||
plus:SetHeight(15)
|
||||
plus:SetPoint("TOPRIGHT", editbox, "BOTTOMRIGHT", -2, 0)
|
||||
plus:SetText("+")
|
||||
plus:Show()
|
||||
plus.adjust = 1
|
||||
plus:SetScript("OnClick", ModButton_OnClick)
|
||||
plus:SetFrameLevel(editbox:GetFrameLevel() + 2)
|
||||
|
||||
self.plus = plus
|
||||
plus.obj = self
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,121 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
local StateBar = Bartender4.StateBar.prototype
|
||||
local ActionBar = Bartender4.ActionBar
|
||||
|
||||
--[[===================================================================================
|
||||
ActionBar Options
|
||||
===================================================================================]]--
|
||||
|
||||
local module = Bartender4:GetModule("ActionBars")
|
||||
|
||||
-- option utilty functions
|
||||
local optGetter, optSetter
|
||||
do
|
||||
local optionMap, getBar, callFunc
|
||||
-- maps option keys to function names
|
||||
optionMap = {
|
||||
buttons = "Buttons",
|
||||
enabled = "Enabled",
|
||||
grid = "Grid",
|
||||
}
|
||||
|
||||
-- retrieves a valid bar object from the modules actionbars table
|
||||
function getBar(id)
|
||||
local bar = module.actionbars[tonumber(id)]
|
||||
assert(bar, ("Invalid bar id in options table. (%s)"):format(id))
|
||||
return bar
|
||||
end
|
||||
|
||||
-- calls a function on the bar
|
||||
function callFunc(bar, type, option, ...)
|
||||
local func = type .. (optionMap[option] or option)
|
||||
assert(bar[func], ("Invalid get/set function %s in bar %s."):format(func, bar.id))
|
||||
return bar[func](bar, ...)
|
||||
end
|
||||
|
||||
-- universal function to get a option
|
||||
function optGetter(info)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return callFunc(bar, "Get", option)
|
||||
end
|
||||
|
||||
-- universal function to set a option
|
||||
function optSetter(info, ...)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return callFunc(bar, "Set", option, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- returns the option table used for all action bars
|
||||
-- creates it, if the first time called
|
||||
-- the Universal Bar option table is merged into this, alot of stuff gets inherited.
|
||||
function module:GetOptionsTable()
|
||||
return self:GetOptionsObject().table
|
||||
end
|
||||
|
||||
function module:GetOptionsObject()
|
||||
if not self.baroptions then
|
||||
local obj = StateBar.GetOptionObject(self)
|
||||
|
||||
local cat_general = {
|
||||
enabled ={
|
||||
order = 4,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable/Disable the bar."],
|
||||
type = "toggle",
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
grid = {
|
||||
order = 60,
|
||||
type = "toggle",
|
||||
name = L["Button Grid"],
|
||||
desc = L["Toggle the button grid."],
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
buttons = {
|
||||
order = 50,
|
||||
name = L["Buttons"],
|
||||
desc = L["Number of buttons."],
|
||||
type = "range",
|
||||
min = 1, max = 12, step = 1,
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
}
|
||||
obj:AddElementGroup("general", cat_general)
|
||||
self.baroptions = obj
|
||||
end
|
||||
|
||||
return self.baroptions
|
||||
end
|
||||
|
||||
function module:CreateBarOption(id, options)
|
||||
if not self.options then return end
|
||||
|
||||
if not options then
|
||||
options = self:GetOptionsTable()
|
||||
end
|
||||
|
||||
id = tostring(id)
|
||||
if not self.options[id] then
|
||||
self.options[id] = {
|
||||
order = 10 + tonumber(id),
|
||||
type = "group",
|
||||
name = (L["Bar %s"]):format(id),
|
||||
desc = (L["Configure Bar %s"]):format(id),
|
||||
childGroups = "tab",
|
||||
}
|
||||
end
|
||||
self.options[id].args = options
|
||||
|
||||
-- register options in the BT GUI
|
||||
Bartender4:RegisterBarOptions(id, self.options[id])
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local BagBarMod = Bartender4:GetModule("BagBar")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
function BagBarMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = ButtonBar:GetOptionObject()
|
||||
self.optionobject.table.general.args.rows.max = self.button_count
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the Bag Bar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
local onebag = {
|
||||
type = "toggle",
|
||||
order = 80,
|
||||
name = L["One Bag"],
|
||||
desc = L["Only show one Bag Button in the BagBar."],
|
||||
get = function() return self.db.profile.onebag end,
|
||||
set = function(info, state) self.db.profile.onebag = state; self.bar:FeedButtons(); self.bar:UpdateButtonLayout() end,
|
||||
}
|
||||
self.optionobject:AddElement("general", "onebag", onebag)
|
||||
|
||||
local keyring = {
|
||||
type = "toggle",
|
||||
order = 80,
|
||||
name = L["Keyring"],
|
||||
desc = L["Show the keyring button."],
|
||||
get = function() return self.db.profile.keyring end,
|
||||
set = function(info, state) self.db.profile.keyring = state; self.bar:FeedButtons(); self.bar:UpdateButtonLayout() end,
|
||||
}
|
||||
self.optionobject:AddElement("general", "keyring", keyring)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.options = {
|
||||
order = 30,
|
||||
type = "group",
|
||||
name = L["Bag Bar"],
|
||||
desc = L["Configure the Bag Bar"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
Bartender4:RegisterBarOptions("BagBar", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,475 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
|
||||
--[[===================================================================================
|
||||
Bar Options
|
||||
===================================================================================]]--
|
||||
|
||||
local barregistry = Bartender4.Bar.barregistry
|
||||
|
||||
local function round(num, idp)
|
||||
local mult = 10^(idp or 0)
|
||||
return math.floor(num * mult + 0.5) / mult
|
||||
end
|
||||
|
||||
-- option utilty functions
|
||||
local optGetter, optSetter, visibilityGetter, visibilitySetter, customEnabled, customDisabled, customCopy, clickThroughVis, posGet, posSet, centerHorz, centerVert, resetPos
|
||||
do
|
||||
local getBar, optionMap, callFunc
|
||||
-- maps option keys to function names
|
||||
optionMap = {
|
||||
alpha = "ConfigAlpha",
|
||||
scale = "ConfigScale",
|
||||
fadeout = "FadeOut",
|
||||
fadeoutalpha = "FadeOutAlpha",
|
||||
fadeoutdelay = "FadeOutDelay",
|
||||
clickthrough = "ClickThrough",
|
||||
}
|
||||
|
||||
-- retrieves a valid bar object from the barregistry table
|
||||
function getBar(id)
|
||||
local bar = barregistry[tostring(id)]
|
||||
assert(bar, ("Invalid bar id in options table. (%s)"):format(id))
|
||||
return bar
|
||||
end
|
||||
|
||||
-- calls a function on the bar
|
||||
function callFunc(bar, type, option, ...)
|
||||
local func = type .. (optionMap[option] or option)
|
||||
assert(bar[func], ("Invalid get/set function %s in bar %s."):format(func, bar.id))
|
||||
return bar[func](bar, ...)
|
||||
end
|
||||
|
||||
-- universal function to get a option
|
||||
function optGetter(info)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return callFunc(bar, "Get", option)
|
||||
end
|
||||
|
||||
-- universal function to set a option
|
||||
function optSetter(info, ...)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return callFunc(bar, "Set", option, ...)
|
||||
end
|
||||
|
||||
function visibilityGetter(info, ...)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return bar:GetVisibilityOption(option, ...)
|
||||
end
|
||||
|
||||
function visibilitySetter(info, ...)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
bar:SetVisibilityOption(option, ...)
|
||||
end
|
||||
|
||||
function customEnabled(info)
|
||||
local bar = getBar(info[2])
|
||||
return bar:GetVisibilityOption("custom")
|
||||
end
|
||||
|
||||
function customDisabled(info)
|
||||
local bar = getBar(info[2])
|
||||
return not bar:GetVisibilityOption("custom")
|
||||
end
|
||||
|
||||
function customCopy(info)
|
||||
local bar = getBar(info[2])
|
||||
bar:CopyCustomConditionals()
|
||||
end
|
||||
|
||||
function clickThroughVis(info)
|
||||
local bar = getBar(info[2])
|
||||
return (not bar.ClickThroughSupport)
|
||||
end
|
||||
|
||||
function posGet(info)
|
||||
local bar = getBar(info[2])
|
||||
local opt = info.arg or info[#info]
|
||||
if opt == "x" or opt == "y" then
|
||||
local v = bar.config.position[opt]
|
||||
return tostring(round(v, 5))
|
||||
end
|
||||
return bar.config.position[opt]
|
||||
end
|
||||
|
||||
function posSet(info, value)
|
||||
local bar = getBar(info[2])
|
||||
local opt = info.arg or info[#info]
|
||||
if opt == "x" or opt == "y" then
|
||||
value = tonumber(value)
|
||||
end
|
||||
bar.config.position[opt] = value
|
||||
bar:LoadPosition()
|
||||
end
|
||||
|
||||
function centerHorz(info)
|
||||
local bar = getBar(info[2])
|
||||
local pos = bar.config.position
|
||||
local x_mod = (pos.growHorizontal == "RIGHT") and -1 or 1
|
||||
pos.x = (bar.overlay:GetWidth() / 2) * pos.scale * x_mod
|
||||
if pos.point == "CENTER" or pos.point == "LEFT" or pos.point == "RIGHT" then -- no special handling
|
||||
pos.point = "CENTER"
|
||||
else
|
||||
pos.point = pos.point:gsub("LEFT", ""):gsub("RIGHT", "")
|
||||
end
|
||||
bar:LoadPosition()
|
||||
end
|
||||
|
||||
function centerVert(info)
|
||||
local bar = getBar(info[2])
|
||||
local pos = bar.config.position
|
||||
local y_mod = (pos.growVertical == "DOWN") and 1 or -1
|
||||
pos.y = (bar.overlay:GetHeight() / 2) * pos.scale * y_mod
|
||||
if pos.point == "CENTER" or pos.point == "TOP" or pos.point == "BOTTOM" then -- no special handling
|
||||
pos.point = "CENTER"
|
||||
else
|
||||
pos.point = pos.point:gsub("TOP", ""):gsub("BOTTOM", "")
|
||||
end
|
||||
bar:LoadPosition()
|
||||
end
|
||||
|
||||
function resetPos(info)
|
||||
local bar = getBar(info[2])
|
||||
local pos = bar.config.position
|
||||
local x_mod = (pos.growHorizontal == "RIGHT") and -1 or 1
|
||||
local y_mod = (pos.growVertical == "DOWN") and 1 or -1
|
||||
pos.x = (bar.overlay:GetWidth() / 2) * pos.scale * x_mod
|
||||
pos.y = (bar.overlay:GetHeight() / 2) * pos.scale * y_mod
|
||||
pos.point = "CENTER"
|
||||
bar:LoadPosition()
|
||||
end
|
||||
end
|
||||
|
||||
local _, class = UnitClass("player")
|
||||
local stanceClasses = {
|
||||
DRUID = true,
|
||||
HERO = true,
|
||||
WARRIOR = true,
|
||||
WARLOCK = true,
|
||||
PRIEST = true,
|
||||
ROGUE = true,
|
||||
}
|
||||
|
||||
local function getStanceTable()
|
||||
local tbl = {}
|
||||
|
||||
if class ~= "WARRIOR" then
|
||||
tbl[0] = L["No Stance/Form"]
|
||||
end
|
||||
|
||||
local num = GetNumShapeshiftForms()
|
||||
for i = 1, num do
|
||||
tbl[i] = select(2, GetShapeshiftFormInfo(i))
|
||||
end
|
||||
-- HACK: Metamorphosis work around, it is on slot 1 in GetShapeshiftFormInfo() but stance:2 is active..
|
||||
if class == "WARLOCK" and tbl[1] == GetSpellInfo(59672) then
|
||||
tbl[2], tbl[1] = tbl[1], nil
|
||||
end
|
||||
|
||||
if class == "ROGUE" and tbl[1] == GetSpellInfo(51713) then -- shadow dance hack
|
||||
tbl[3], tbl[1] = tbl[1], nil
|
||||
end
|
||||
return tbl
|
||||
end
|
||||
|
||||
local validAnchors = {
|
||||
CENTER = "CENTER",
|
||||
LEFT = "LEFT",
|
||||
RIGHT = "RIGHT",
|
||||
TOP = "TOP",
|
||||
TOPLEFT = "TOPLEFT",
|
||||
TOPRIGHT = "TOPRIGHT",
|
||||
BOTTOM = "BOTTOM",
|
||||
BOTTOMLEFT = "BOTTOMLEFT",
|
||||
BOTTOMRIGHT = "BOTTOMRIGHT",
|
||||
}
|
||||
|
||||
local options
|
||||
function Bar:GetOptionObject()
|
||||
local otbl = {
|
||||
general = {
|
||||
type = "group",
|
||||
cmdInline = true,
|
||||
name = L["General Settings"],
|
||||
order = 1,
|
||||
args = {
|
||||
styleheader = {
|
||||
order = 10,
|
||||
type = "header",
|
||||
name = L["Bar Style & Layout"],
|
||||
},
|
||||
alpha = {
|
||||
order = 20,
|
||||
name = L["Alpha"],
|
||||
desc = L["Configure the alpha of the bar."],
|
||||
type = "range",
|
||||
min = 0, max = 1, bigStep = 0.05,
|
||||
isPercent = true,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
},
|
||||
scale = {
|
||||
order = 30,
|
||||
name = L["Scale"],
|
||||
desc = L["Configure the scale of the bar."],
|
||||
type = "range",
|
||||
min = 0, softMin = .1, softMax = 2, bigStep = 0.05,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
},
|
||||
clickthrough = {
|
||||
order = 200,
|
||||
name = L["Click-Through"],
|
||||
desc = L["Disable any reaction to mouse events on this bar, making the bar click-through."],
|
||||
type = "toggle",
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
hidden = clickThroughVis,
|
||||
width = "full",
|
||||
},
|
||||
},
|
||||
},
|
||||
visibility = {
|
||||
type = "group",
|
||||
name = L["Visibility"],
|
||||
order = 2,
|
||||
get = visibilityGetter,
|
||||
set = visibilitySetter,
|
||||
args = {
|
||||
info = {
|
||||
order = 1,
|
||||
type = "description",
|
||||
name = L["The bar default is to be visible all the time, you can configure conditions here to control when the bar should be hidden."] .. "\n",
|
||||
},
|
||||
fadeout = {
|
||||
order = 5,
|
||||
name = L["Fade Out"],
|
||||
desc = L["Enable the FadeOut mode"],
|
||||
type = "toggle",
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
width = "full",
|
||||
},
|
||||
fadeoutalpha = {
|
||||
order = 6,
|
||||
name = L["Fade Out Alpha"],
|
||||
desc = L["Configure the Fade Out Alpha"],
|
||||
type = "range",
|
||||
min = 0, max = 1, bigStep = 0.05,
|
||||
isPercent = true,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
},
|
||||
fadeoutdelay = {
|
||||
order = 7,
|
||||
name = L["Fade Out Delay"],
|
||||
desc = L["Configure the Fade Out Delay"],
|
||||
type = "range",
|
||||
min = 0, softMax = 1, bigStep = 0.01,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
},
|
||||
fadeNl = {
|
||||
order = 8,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
always = {
|
||||
order = 10,
|
||||
type = "toggle",
|
||||
name = L["Always Hide"],
|
||||
desc = L["You can set the bar to be always hidden, if you only wish to access it using key-bindings."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
possess = {
|
||||
order = 15,
|
||||
type = "toggle",
|
||||
name = L["Hide when Possessing"],
|
||||
desc = L["Hide this bar when you are possessing a NPC."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
vehicle = {
|
||||
order = 16,
|
||||
type = "toggle",
|
||||
name = L["Hide on Vehicle"],
|
||||
desc = L["Hide this bar when you are riding on a vehicle."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
vehicleui = {
|
||||
order = 17,
|
||||
type = "toggle",
|
||||
name = L["Hide with Vehicle UI"],
|
||||
desc = L["Hide this bar when the game wants to show a vehicle UI."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
combat = {
|
||||
order = 20,
|
||||
type = "toggle",
|
||||
name = L["Hide in Combat"],
|
||||
desc = L["This bar will be hidden once you enter combat."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
nocombat = {
|
||||
order = 21,
|
||||
type = "toggle",
|
||||
name = L["Hide out of Combat"],
|
||||
desc = L["This bar will be hidden whenever you are not in combat."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
pet = {
|
||||
order = 30,
|
||||
type = "toggle",
|
||||
name = L["Hide with pet"],
|
||||
desc = L["Hide this bar when you have a pet."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
nopet = {
|
||||
order = 31,
|
||||
type = "toggle",
|
||||
name = L["Hide without pet"],
|
||||
desc = L["Hide this bar when you have no pet."],
|
||||
disabled = customEnabled,
|
||||
},
|
||||
stance = {
|
||||
order = 50,
|
||||
type = "multiselect",
|
||||
name = L["Hide in Stance/Form"],
|
||||
desc = L["Hide this bar in a specific Stance or Form."],
|
||||
values = getStanceTable,
|
||||
hidden = function() return (not stanceClasses[class]) end,
|
||||
disabled = customEnabled,
|
||||
},
|
||||
customNl = {
|
||||
order = 98,
|
||||
type = "description",
|
||||
name = "\n",
|
||||
},
|
||||
customHeader = {
|
||||
order = 99,
|
||||
type = "header",
|
||||
name = L["Custom Conditionals"],
|
||||
},
|
||||
custom = {
|
||||
order = 100,
|
||||
type = "toggle",
|
||||
name = L["Use Custom Condition"],
|
||||
desc = L["Enable the use of a custom condition, disabling all of the above."],
|
||||
},
|
||||
customCopy = {
|
||||
order = 101,
|
||||
type = "execute",
|
||||
name = L["Copy Conditionals"],
|
||||
desc = L["Create a copy of the auto-generated conditionals in the custom configuration as a base template."],
|
||||
func = customCopy,
|
||||
},
|
||||
customDesc = {
|
||||
order = 102,
|
||||
type = "description",
|
||||
name = L["Note: Enabling Custom Conditionals will disable all of the above settings!"],
|
||||
},
|
||||
customdata = {
|
||||
order = 103,
|
||||
type = "input",
|
||||
name = L["Custom Conditionals"],
|
||||
desc = L["You can use any macro conditionals in the custom string, using \"show\" and \"hide\" as values.\n\nExample: [combat]hide;show"],
|
||||
width = "full",
|
||||
multiline = true,
|
||||
disabled = customDisabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
position = {
|
||||
type = "group",
|
||||
name = L["Positioning"],
|
||||
order = 20,
|
||||
args = {
|
||||
info = {
|
||||
order = 1,
|
||||
type = "description",
|
||||
name = L["The Positioning options here will allow you to position the bar to your liking and with an absolute precision."],
|
||||
},
|
||||
point = {
|
||||
order = 10,
|
||||
type = "select",
|
||||
name = L["Anchor"],
|
||||
desc = L["Change the current anchor point of the bar."],
|
||||
values = validAnchors,
|
||||
get = posGet,
|
||||
set = posSet,
|
||||
},
|
||||
scale = {
|
||||
order = 11,
|
||||
name = L["Scale"],
|
||||
desc = L["Configure the scale of the bar."],
|
||||
type = "range",
|
||||
min = 0, softMin = .1, softMax = 2, bigStep = 0.05,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
},
|
||||
nl1 = {
|
||||
order = 12,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
x = {
|
||||
order = 20,
|
||||
type = "input",
|
||||
name = L["X Offset"],
|
||||
desc = L["Offset in X direction (horizontal) from the given anchor point."],
|
||||
get = posGet,
|
||||
set = posSet,
|
||||
dialogControl = "NumberEditBox",
|
||||
},
|
||||
y = {
|
||||
order = 21,
|
||||
type = "input",
|
||||
name = L["Y Offset"],
|
||||
desc = L["Offset in Y direction (vertical) from the given anchor point."],
|
||||
get = posGet,
|
||||
set = posSet,
|
||||
dialogControl = "NumberEditBox",
|
||||
},
|
||||
nl2 = {
|
||||
order = 25,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
centerhorz = {
|
||||
order = 31,
|
||||
type = "execute",
|
||||
name = L["Center Horizontally"],
|
||||
desc = L["Centers the bar horizontally on screen."],
|
||||
func = centerHorz,
|
||||
},
|
||||
centervert = {
|
||||
order = 31,
|
||||
type = "execute",
|
||||
name = L["Center Vertically"],
|
||||
desc = L["Centers the bar vertically on screen."],
|
||||
func = centerVert,
|
||||
},
|
||||
nl2 = {
|
||||
order = 35,
|
||||
type = "description",
|
||||
name = " ",
|
||||
},
|
||||
reset = {
|
||||
order = 40,
|
||||
type = "execute",
|
||||
name = L["Reset Position"],
|
||||
desc = L["Reset the position of this bar completly if it ended up off-screen and you cannot reach it anymore."],
|
||||
func = resetPos,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
return Bartender4:NewOptionObject(otbl)
|
||||
end
|
||||
@@ -0,0 +1,131 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
--[[===================================================================================
|
||||
Bar Options
|
||||
===================================================================================]]--
|
||||
|
||||
-- option utilty functions
|
||||
local optGetter, optSetter
|
||||
do
|
||||
local getBar, optionMap, callFunc
|
||||
local barregistry = Bartender4.Bar.barregistry
|
||||
-- maps option keys to function names
|
||||
optionMap = {
|
||||
rows = "Rows",
|
||||
padding = "Padding",
|
||||
zoom = "Zoom",
|
||||
macrotext = "HideMacroText",
|
||||
hotkey = "HideHotkey",
|
||||
vgrowth = "VGrowth",
|
||||
hgrowth = "HGrowth",
|
||||
}
|
||||
|
||||
-- retrieves a valid bar object from the barregistry table
|
||||
function getBar(id)
|
||||
local bar = barregistry[tostring(id)]
|
||||
assert(bar, ("Invalid bar id in options table. (%s)"):format(id))
|
||||
return bar
|
||||
end
|
||||
|
||||
-- calls a function on the bar
|
||||
function callFunc(bar, type, option, ...)
|
||||
local func = type .. (optionMap[option] or option)
|
||||
assert(bar[func], ("Invalid get/set function %s in bar %s."):format(func, bar.id))
|
||||
return bar[func](bar, ...)
|
||||
end
|
||||
|
||||
-- universal function to get a option
|
||||
function optGetter(info)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return callFunc(bar, "Get", option)
|
||||
end
|
||||
|
||||
-- universal function to set a option
|
||||
function optSetter(info, ...)
|
||||
local bar = getBar(info[2])
|
||||
local option = info[#info]
|
||||
return callFunc(bar, "Set", option, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function ButtonBar:GetOptionObject()
|
||||
local obj = Bar.GetOptionObject()
|
||||
local otbl_general = {
|
||||
padding = {
|
||||
order = 40,
|
||||
type = "range",
|
||||
name = L["Padding"],
|
||||
desc = L["Configure the padding of the buttons."],
|
||||
softMin = -10, softMax = 20, bigStep = 1,
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
zoom = {
|
||||
order = 59,
|
||||
name = L["Zoom"],
|
||||
type = "toggle",
|
||||
desc = L["Toggle Button Zoom\nFor more style options you need to install ButtonFacade"],
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
hidden = function() return LibStub("LibButtonFacade", true) and true or false end,
|
||||
},
|
||||
rows = {
|
||||
order = 70,
|
||||
name = L["Rows"],
|
||||
desc = L["Number of rows."],
|
||||
type = "range",
|
||||
min = 1, max = 12, step = 1,
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
vgrowth = {
|
||||
order = 75,
|
||||
name = L["Vertical Growth"],
|
||||
desc = L["Vertical growth direction for this bar."],
|
||||
type = "select",
|
||||
values = {UP = L["Up"], DOWN = L["Down"]},
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
hgrowth = {
|
||||
order = 76,
|
||||
name = L["Horizontal Growth"],
|
||||
desc = L["Horizontal growth direction for this bar."],
|
||||
type = "select",
|
||||
values = {LEFT = L["Left"], RIGHT = L["Right"]},
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
hidedesc = {
|
||||
order = 80,
|
||||
name = L["Button Look"],
|
||||
type = "header",
|
||||
},
|
||||
macrotext = {
|
||||
order = 81,
|
||||
type = "toggle",
|
||||
name = L["Hide Macro Text"],
|
||||
desc = L["Hide the Macro Text on the buttons of this bar."],
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
hotkey = {
|
||||
order = 82,
|
||||
type = "toggle",
|
||||
name = L["Hide Hotkey"],
|
||||
desc = L["Hide the Hotkey on the buttons of this bar."],
|
||||
set = optSetter,
|
||||
get = optGetter,
|
||||
},
|
||||
}
|
||||
obj:AddElementGroup("general", otbl_general)
|
||||
return obj
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local MicroMenuMod = Bartender4:GetModule("MicroMenu")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
function MicroMenuMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = ButtonBar:GetOptionObject()
|
||||
self.optionobject.table.general.args.rows.max = self.button_count
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the Micro Menu"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.options = {
|
||||
order = 30,
|
||||
type = "group",
|
||||
name = L["Micro Menu"],
|
||||
desc = L["Configure the Micro Menu"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
self.optionobject.table.general.args.padding.min = -30
|
||||
Bartender4:RegisterBarOptions("MicroMenu", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
|
||||
if not HasMultiCastActionBar then return end
|
||||
|
||||
local classMask = UnitClassMask("player")
|
||||
|
||||
if not bit.contains(EnumUtil.CombineMasks(Enum.ClassMask.SHAMAN, Enum.ClassMask.HERO), classMask) then
|
||||
return
|
||||
end
|
||||
|
||||
-- fetch upvalues
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
|
||||
local MultiCastMod = Bartender4:GetModule("MultiCast")
|
||||
|
||||
function MultiCastMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = Bar:GetOptionObject()
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the Totem Bar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.options = {
|
||||
order = 100,
|
||||
type = "group",
|
||||
name = L["Totem Bar"],
|
||||
desc = L["Configure the Totem Bar"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
Bartender4:RegisterBarOptions("MultiCast", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,316 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
|
||||
|
||||
local getFunc, setFunc
|
||||
do
|
||||
function getFunc(info)
|
||||
return (info.arg and Bartender4.db.profile[info.arg] or Bartender4.db.profile[info[#info]])
|
||||
end
|
||||
|
||||
function setFunc(info, value)
|
||||
local key = info.arg or info[#info]
|
||||
Bartender4.db.profile[key] = value
|
||||
end
|
||||
end
|
||||
|
||||
local KB = LibStub("LibKeyBound-1.0")
|
||||
local LDBIcon = LibStub("LibDBIcon-1.0", true)
|
||||
local function getOptions()
|
||||
if not Bartender4.options then
|
||||
Bartender4.options = {
|
||||
type = "group",
|
||||
name = "Bartender4",
|
||||
icon = "Interface\\Icons\\INV_Drink_05",
|
||||
childGroups = "tree",
|
||||
plugins = {},
|
||||
args = {
|
||||
lock = {
|
||||
order = 1,
|
||||
type = "toggle",
|
||||
name = L["Lock"],
|
||||
desc = L["Lock all bars."],
|
||||
get = function() return Bartender4.Locked end,
|
||||
set = function(info, value) Bartender4[value and "Lock" or "Unlock"](Bartender4) end,
|
||||
width = "half",
|
||||
},
|
||||
buttonlock = {
|
||||
order = 2,
|
||||
type = "toggle",
|
||||
name = L["Button Lock"],
|
||||
desc = L["Lock the buttons."],
|
||||
get = function() return Bartender4.db.profile.buttonlock end,
|
||||
set = function(info, value)
|
||||
Bartender4.db.profile.buttonlock = value
|
||||
Bartender4.Bar:ForAll("ForAll", "SetAttribute", "buttonlock", value)
|
||||
end,
|
||||
},
|
||||
minimapIcon = {
|
||||
order = 3,
|
||||
type = "toggle",
|
||||
name = L["Minimap Icon"],
|
||||
desc = L["Show a Icon to open the config at the Minimap"],
|
||||
get = function() return not Bartender4.db.profile.minimapIcon.hide end,
|
||||
set = function(info, value) Bartender4.db.profile.minimapIcon.hide = not value; LDBIcon[value and "Show" or "Hide"](LDBIcon, "Bartender4") end,
|
||||
disabled = function() return not LDBIcon end,
|
||||
},
|
||||
kb = {
|
||||
order = 4,
|
||||
type = "execute",
|
||||
name = L["Key Bindings"],
|
||||
desc = L["Switch to key-binding mode"],
|
||||
func = function()
|
||||
KB:Toggle()
|
||||
AceConfigDialog:Close("Bartender4")
|
||||
end,
|
||||
},
|
||||
bars = {
|
||||
order = 20,
|
||||
type = "group",
|
||||
name = L["Bars"],
|
||||
args = {
|
||||
options = {
|
||||
type = "group",
|
||||
order = 0,
|
||||
name = function(info) if info.uiType == "dialog" then return "" else return L["Bar Options"] end end,
|
||||
guiInline = true,
|
||||
args = {
|
||||
blizzardVehicle = {
|
||||
order = 1,
|
||||
type = "toggle",
|
||||
name = L["Use Blizzard Vehicle UI"],
|
||||
desc = L["Enable the use of the Blizzard Vehicle UI, hiding any Bartender4 bars in the meantime."],
|
||||
width = "full",
|
||||
get = getFunc,
|
||||
set = function(info, value)
|
||||
if UnitHasVehicleUI("player") then
|
||||
Bartender4:Print(L["You have to exit the vehicle in order to be able to change the Vehicle UI settings."])
|
||||
return
|
||||
end
|
||||
Bartender4.db.profile.blizzardVehicle = value
|
||||
Bartender4:UpdateBlizzardVehicle()
|
||||
end,
|
||||
},
|
||||
selfcastmodifier = {
|
||||
order = 10,
|
||||
type = "toggle",
|
||||
name = L["Self-Cast by modifier"],
|
||||
desc = L["Toggle the use of the modifier-based self-cast functionality."],
|
||||
get = getFunc,
|
||||
set = function(info, value)
|
||||
Bartender4.db.profile.selfcastmodifier = value
|
||||
Bartender4.Bar:ForAll("UpdateSelfCast")
|
||||
end,
|
||||
},
|
||||
setselfcastmod = {
|
||||
order = 20,
|
||||
type = "select",
|
||||
name = L["Self-Cast Modifier"],
|
||||
desc = L["Select the Self-Cast Modifier"],
|
||||
get = function(info) return GetModifiedClick("SELFCAST") end,
|
||||
set = function(info, value) SetModifiedClick("SELFCAST", value); SaveBindings(GetCurrentBindingSet() or 1) end,
|
||||
values = { NONE = L["None"], ALT = L["ALT"], SHIFT = L["SHIFT"], CTRL = L["CTRL"] },
|
||||
},
|
||||
selfcast_nl = {
|
||||
order = 30,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
focuscastmodifier = {
|
||||
order = 50,
|
||||
type = "toggle",
|
||||
name = L["Focus-Cast by modifier"],
|
||||
desc = L["Toggle the use of the modifier-based focus-cast functionality."],
|
||||
get = getFunc,
|
||||
set = function(info, value)
|
||||
Bartender4.db.profile.focuscastmodifier = value
|
||||
Bartender4.Bar:ForAll("UpdateSelfCast")
|
||||
end,
|
||||
},
|
||||
setfocuscastmod = {
|
||||
order = 60,
|
||||
type = "select",
|
||||
name = L["Focus-Cast Modifier"],
|
||||
desc = L["Select the Focus-Cast Modifier"],
|
||||
get = function(info) return GetModifiedClick("FOCUSCAST") end,
|
||||
set = function(info, value) SetModifiedClick("FOCUSCAST", value); SaveBindings(GetCurrentBindingSet() or 1) end,
|
||||
values = { NONE = L["None"], ALT = L["ALT"], SHIFT = L["SHIFT"], CTRL = L["CTRL"] },
|
||||
},
|
||||
focuscast_nl = {
|
||||
order = 70,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
selfcastrightclick = {
|
||||
order = 80,
|
||||
type = "toggle",
|
||||
name = L["Right-click Self-Cast"],
|
||||
desc = L["Toggle the use of the right-click self-cast functionality."],
|
||||
get = getFunc,
|
||||
set = function(info, value)
|
||||
Bartender4.db.profile.selfcastrightclick = value
|
||||
Bartender4.Bar:ForAll("UpdateSelfCast")
|
||||
end,
|
||||
},
|
||||
rightclickselfcast_nl = {
|
||||
order = 90,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
range = {
|
||||
order = 100,
|
||||
name = L["Out of Range Indicator"],
|
||||
desc = L["Configure how the Out of Range Indicator should display on the buttons."],
|
||||
type = "select",
|
||||
style = "dropdown",
|
||||
get = function()
|
||||
return Bartender4.db.profile.outofrange
|
||||
end,
|
||||
set = function(info, value)
|
||||
Bartender4.db.profile.outofrange = value
|
||||
Bartender4.Bar:ForAll("ApplyConfig")
|
||||
end,
|
||||
values = { none = L["No Display"], button = L["Full Button Mode"], hotkey = L["Hotkey Mode"] },
|
||||
},
|
||||
colors = {
|
||||
order = 130,
|
||||
type = "group",
|
||||
guiInline = true,
|
||||
name = L["Colors"],
|
||||
get = function(info)
|
||||
local color = Bartender4.db.profile.colors[info[#info]]
|
||||
return color.r, color.g, color.b
|
||||
end,
|
||||
set = function(info, r, g, b)
|
||||
local color = Bartender4.db.profile.colors[info[#info]]
|
||||
color.r, color.g, color.b = r, g, b
|
||||
Bartender4.Bar:ForAll("ApplyConfig")
|
||||
end,
|
||||
args = {
|
||||
range = {
|
||||
order = 1,
|
||||
type = "color",
|
||||
name = L["Out of Range Indicator"],
|
||||
desc = L["Specify the Color of the Out of Range Indicator"],
|
||||
},
|
||||
mana = {
|
||||
order = 2,
|
||||
type = "color",
|
||||
name = L["Out of Mana Indicator"],
|
||||
desc = L["Specify the Color of the Out of Mana Indicator"],
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip = {
|
||||
order = 200,
|
||||
name = L["Button Tooltip"],
|
||||
type = "select",
|
||||
desc = L["Configure the Button Tooltip."],
|
||||
values = { ["disabled"] = L["Disabled"], ["nocombat"] = L["Disabled in Combat"], ["enabled"] = L["Enabled"] },
|
||||
get = function() return Bartender4.db.profile.tooltip end,
|
||||
set = function(info, value) Bartender4.db.profile.tooltip = value end,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
faq = {
|
||||
name = L["FAQ"],
|
||||
desc = L["Frequently Asked Questions"],
|
||||
type = "group",
|
||||
order = 200,
|
||||
args = {
|
||||
faq = {
|
||||
type = "description",
|
||||
name = L["FAQ_TEXT"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
Bartender4.options.plugins.profiles = { profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(Bartender4.db) }
|
||||
for k,v in Bartender4:IterateModules() do
|
||||
if v.SetupOptions then
|
||||
v:SetupOptions()
|
||||
end
|
||||
end
|
||||
end
|
||||
return Bartender4.options
|
||||
end
|
||||
|
||||
function Bartender4:ChatCommand(input)
|
||||
if InCombatLockdown() then
|
||||
self:Print(L["Cannot access options during combat."])
|
||||
return
|
||||
end
|
||||
if not input or input:trim() == "" then
|
||||
LibStub("AceConfigDialog-3.0"):Open("Bartender4")
|
||||
else
|
||||
LibStub("AceConfigCmd-3.0").HandleCommand(Bartender4, "bt", "Bartender4", input)
|
||||
end
|
||||
end
|
||||
|
||||
function Bartender4:SetupOptions()
|
||||
LibStub("AceConfig-3.0"):RegisterOptionsTable("Bartender4", getOptions)
|
||||
AceConfigDialog:SetDefaultSize("Bartender4", 680,525)
|
||||
self:RegisterChatCommand( "bar", "ChatCommand")
|
||||
self:RegisterChatCommand( "bt", "ChatCommand")
|
||||
self:RegisterChatCommand( "bt4", "ChatCommand")
|
||||
self:RegisterChatCommand( "bartender", "ChatCommand")
|
||||
self:RegisterChatCommand( "bartender4", "ChatCommand")
|
||||
end
|
||||
|
||||
function Bartender4:RegisterModuleOptions(key, table)
|
||||
if not self.options then
|
||||
error("Options table has not been created yet, respond to the callback!", 2)
|
||||
end
|
||||
self.options.plugins[key] = { [key] = table }
|
||||
end
|
||||
|
||||
function Bartender4:RegisterBarOptions(id, table)
|
||||
if not self.options then
|
||||
error("Options table has not been created yet, respond to the callback!", 2)
|
||||
end
|
||||
self.options.args.bars.args[id] = table
|
||||
end
|
||||
|
||||
local optionParent = {}
|
||||
function optionParent:NewCategory(category, data)
|
||||
self.table[category] = data
|
||||
end
|
||||
|
||||
local ov = nil
|
||||
function optionParent:AddElement(category, element, data, ...)
|
||||
local lvl = self.table[category]
|
||||
for i = 1, select('#', ...) do
|
||||
local key = select(i, ...)
|
||||
if not (lvl.args[key] and lvl.args[key].args) then
|
||||
error(("Sub-Level Key %s does not exist in options group or is no sub-group."):format(key), ov and 3 or 2)
|
||||
end
|
||||
lvl = lvl.args[key]
|
||||
end
|
||||
|
||||
lvl.args[element] = data
|
||||
end
|
||||
|
||||
function optionParent:AddElementGroup(category, data, ...)
|
||||
ov = true
|
||||
for k,v in pairs(data) do
|
||||
self:AddElement(category, k, v, ...)
|
||||
end
|
||||
ov = nil
|
||||
end
|
||||
|
||||
function Bartender4:NewOptionObject(otbl)
|
||||
if not otbl then otbl = {} end
|
||||
local tbl = { table = otbl }
|
||||
for k, v in pairs(optionParent) do
|
||||
tbl[k] = v
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceGUIWidget-NumberEditBox.lua"/>
|
||||
|
||||
<Script file="Options.lua"/>
|
||||
|
||||
<Script file="Bar.lua"/>
|
||||
<Script file="ButtonBar.lua"/>
|
||||
<Script file="StateBar.lua"/>
|
||||
|
||||
<Script file="ActionBar.lua"/>
|
||||
<Script file="BagBar.lua"/>
|
||||
<Script file="MicroMenu.lua"/>
|
||||
<Script file="PetBar.lua"/>
|
||||
<Script file="StanceBar.lua"/>
|
||||
<Script file="RepXPBar.lua"/>
|
||||
<Script file="VehicleBar.lua"/>
|
||||
<Script file="MultiCastBar.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,51 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local PetBarMod = Bartender4:GetModule("PetBar")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
function PetBarMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = ButtonBar:GetOptionObject()
|
||||
|
||||
self.optionobject.table.general.args.rows.max = 10
|
||||
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the PetBar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.options = {
|
||||
order = 30,
|
||||
type = "group",
|
||||
name = L["Pet Bar"],
|
||||
desc = L["Configure the Pet Bar"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
Bartender4:RegisterBarOptions("PetBar", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,85 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
-- fetch upvalues
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
|
||||
local RepBarMod = Bartender4:GetModule("RepBar")
|
||||
|
||||
function RepBarMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = Bar:GetOptionObject()
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the Reputation Bar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.options = {
|
||||
order = 100,
|
||||
type = "group",
|
||||
name = L["Reputation Bar"],
|
||||
desc = L["Configure the Reputation Bar"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
Bartender4:RegisterBarOptions("Rep", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
|
||||
local XPBarMod = Bartender4:GetModule("XPBar")
|
||||
|
||||
function XPBarMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = Bar:GetOptionObject()
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the XP Bar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.options = {
|
||||
order = 101,
|
||||
type = "group",
|
||||
name = L["XP Bar"],
|
||||
desc = L["Configure the XP Bar"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
Bartender4:RegisterBarOptions("XP", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
-- module
|
||||
local StanceBarMod = Bartender4:GetModule("StanceBar")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
function StanceBarMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = ButtonBar:GetOptionObject()
|
||||
self.optionobject.table.general.args.rows.max = self.button_count
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the StanceBar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.options = {
|
||||
order = 30,
|
||||
type = "group",
|
||||
name = L["Stance Bar"],
|
||||
desc = L["Configure the Stance Bar"],
|
||||
childGroups = "tab",
|
||||
disabled = function(info) return GetNumShapeshiftForms() == 0 end,
|
||||
}
|
||||
Bartender4:RegisterBarOptions("StanceBar", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,286 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
local StateBar = Bartender4.StateBar.prototype
|
||||
|
||||
local optGetter, optSetter, getBar
|
||||
do
|
||||
local optionMap, callFunc
|
||||
local barregistry = Bartender4.Bar.barregistry
|
||||
|
||||
optionMap = {
|
||||
stance = "StanceStateOption",
|
||||
enabled = "StateOption",
|
||||
def_state = "DefaultState",
|
||||
states = "StateOption",
|
||||
actionbar = "StateOption",
|
||||
possess = "StateOption",
|
||||
autoassist = "ConfigAutoAssist",
|
||||
customEnabled = "StateOption",
|
||||
custom = "StateOption",
|
||||
customCopy = "CopyCustomConditionals",
|
||||
}
|
||||
-- retrieves a valid bar object from the barregistry table
|
||||
function getBar(id)
|
||||
local bar = barregistry[tostring(id)]
|
||||
assert(bar, ("Invalid bar id in options table. (%s)"):format(id))
|
||||
return bar
|
||||
end
|
||||
|
||||
-- calls a function on the bar
|
||||
function callFunc(bar, type, option, ...)
|
||||
local func = type .. (optionMap[option] or option)
|
||||
assert(bar[func], ("Invalid get/set function %s in bar %s."):format(func, bar.id))
|
||||
return bar[func](bar, ...)
|
||||
end
|
||||
|
||||
-- universal function to get a option
|
||||
function optGetter(info)
|
||||
local bar = getBar(info[2])
|
||||
local option = info.arg or info[#info]
|
||||
return callFunc(bar, "Get", option, info[#info])
|
||||
end
|
||||
|
||||
-- universal function to set a option
|
||||
function optSetter(info, ...)
|
||||
local bar = getBar(info[2])
|
||||
local option = info.arg or info[#info]
|
||||
return callFunc(bar, "Set", option, info[#info], ...)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local hasStances
|
||||
|
||||
local validStanceTable = {
|
||||
[0] = L["Don't Page"],
|
||||
(L["Page %2d"]):format(1),
|
||||
(L["Page %2d"]):format(2),
|
||||
(L["Page %2d"]):format(3),
|
||||
(L["Page %2d"]):format(4),
|
||||
(L["Page %2d"]):format(5),
|
||||
(L["Page %2d"]):format(6),
|
||||
(L["Page %2d"]):format(7),
|
||||
(L["Page %2d"]):format(8),
|
||||
(L["Page %2d"]):format(9),
|
||||
(L["Page %2d"]):format(10)
|
||||
}
|
||||
|
||||
|
||||
local _, playerclass = UnitClass("player")
|
||||
|
||||
local function createOptionGroup(k, id)
|
||||
local tbl = {
|
||||
order = 10 * k,
|
||||
type = "select",
|
||||
arg = "stance",
|
||||
values = validStanceTable,
|
||||
name = Bartender4.StanceMap[playerclass][k].name,
|
||||
}
|
||||
return tbl
|
||||
end
|
||||
|
||||
local disabledFunc = function(info)
|
||||
local bar = getBar(info[2])
|
||||
return not bar:GetStateOption("enabled")
|
||||
end
|
||||
|
||||
local stateOffOrCustomOn = function(info)
|
||||
local bar = getBar(info[2])
|
||||
return (not bar:GetStateOption("enabled")) or (bar:GetStateOption("customEnabled"))
|
||||
end
|
||||
|
||||
local stateOffOrCustomOff = function(info)
|
||||
local bar = getBar(info[2])
|
||||
return (not bar:GetStateOption("enabled")) or (not bar:GetStateOption("customEnabled"))
|
||||
end
|
||||
|
||||
function StateBar:GetOptionObject()
|
||||
local obj = ButtonBar.GetOptionObject()
|
||||
local options = {
|
||||
enabled = {
|
||||
order = 1,
|
||||
type = "toggle",
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable State-based Button Swaping"],
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
},
|
||||
sep1 = {
|
||||
order = 2,
|
||||
type = "description",
|
||||
name = "",
|
||||
},
|
||||
autoassist = {
|
||||
order = 3,
|
||||
type = "toggle",
|
||||
name = L["Auto-Assist"],
|
||||
desc = L["Enable Auto-Assist for this bar.\n Auto-Assist will automatically try to cast on your target's target if your target is no valid target for the selected spell."],
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
width = "full",
|
||||
},
|
||||
possess = {
|
||||
order = 5,
|
||||
type = "toggle",
|
||||
name = L["Possess Bar"],
|
||||
desc = L["Switch this bar to the Possess Bar when possessing a npc (eg. Mind Control)"],
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = stateOffOrCustomOn,
|
||||
},
|
||||
actionbar = {
|
||||
order = 6,
|
||||
type = "toggle",
|
||||
name = L["ActionBar Paging"],
|
||||
desc = L["Enable Bar Switching based on the actionbar controls provided by the game. \nSee Blizzard Key Bindings for assignments - Usually Shift-Mouse Wheel and Shift+1 - Shift+6."],
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = stateOffOrCustomOn,
|
||||
},
|
||||
def_desc = {
|
||||
order = 10,
|
||||
type = "description",
|
||||
name = L["The default behaviour of this bar when no state-based paging option affects it."],
|
||||
},
|
||||
def_state = {
|
||||
order = 11,
|
||||
type = "select",
|
||||
name = L["Default Bar State"],
|
||||
values = validStanceTable,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = stateOffOrCustomOn,
|
||||
},
|
||||
modifiers = {
|
||||
order = 30,
|
||||
type = "group",
|
||||
inline = true,
|
||||
name = "",
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = stateOffOrCustomOn,
|
||||
args = {
|
||||
header = {
|
||||
order = 1,
|
||||
type = "header",
|
||||
name = L["Modifier Based Switching"],
|
||||
},
|
||||
ctrl = {
|
||||
order = 10,
|
||||
type = "select",
|
||||
name = L["CTRL"],
|
||||
arg = "states",
|
||||
values = validStanceTable,
|
||||
desc = (L["Configure actionbar paging when the %s key is down."]):format(L["CTRL"]),
|
||||
--width = "half",
|
||||
},
|
||||
alt = {
|
||||
order = 15,
|
||||
type = "select",
|
||||
name = L["ALT"],
|
||||
arg = "states",
|
||||
values = validStanceTable,
|
||||
desc = (L["Configure actionbar paging when the %s key is down."]):format(L["ALT"]),
|
||||
--width = "half",
|
||||
},
|
||||
shift = {
|
||||
order = 20,
|
||||
type = "select",
|
||||
name = L["SHIFT"],
|
||||
arg = "states",
|
||||
values = validStanceTable,
|
||||
desc = (L["Configure actionbar paging when the %s key is down."]):format(L["SHIFT"]),
|
||||
--width = "half",
|
||||
},
|
||||
},
|
||||
},
|
||||
stances = {
|
||||
order = 20,
|
||||
type = "group",
|
||||
inline = true,
|
||||
name = "",
|
||||
hidden = function() return not (Bartender4.StanceMap[playerclass]) end,
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = stateOffOrCustomOn,
|
||||
args = {
|
||||
stance_header = {
|
||||
order = 1,
|
||||
type = "header",
|
||||
name = L["Stance Configuration"],
|
||||
},
|
||||
},
|
||||
},
|
||||
customNl = {
|
||||
order = 48,
|
||||
type = "description",
|
||||
name = "\n",
|
||||
},
|
||||
customHeader = {
|
||||
order = 49,
|
||||
type = "header",
|
||||
name = L["Custom Conditionals"],
|
||||
},
|
||||
customEnabled = {
|
||||
order = 50,
|
||||
type = "toggle",
|
||||
name = L["Use Custom Condition"],
|
||||
desc = L["Enable the use of a custom condition, disabling all of the above."],
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = disabledFunc,
|
||||
--width = "double",
|
||||
},
|
||||
customCopy = {
|
||||
order = 51,
|
||||
type = "execute",
|
||||
name = L["Copy Conditionals"],
|
||||
desc = L["Create a copy of the auto-generated conditionals in the custom configuration as a base template."],
|
||||
func = optSetter,
|
||||
disabled = disabledFunc,
|
||||
},
|
||||
customDesc = {
|
||||
order = 52,
|
||||
type = "description",
|
||||
name = L["Note: Enabling Custom Conditionals will disable all of the above settings!"],
|
||||
},
|
||||
custom = {
|
||||
order = 55,
|
||||
type = "input",
|
||||
name = L["Custom Conditionals"],
|
||||
desc = L["You can use any macro conditionals in the custom string, using the number of the bar as target value.\nExample: [form:1]9;0"],
|
||||
width = "full",
|
||||
get = optGetter,
|
||||
set = optSetter,
|
||||
disabled = stateOffOrCustomOff,
|
||||
multiline = true,
|
||||
},
|
||||
}
|
||||
|
||||
do
|
||||
local defstancemap = Bartender4.StanceMap[playerclass]
|
||||
if defstancemap then
|
||||
for k,v in pairs(defstancemap) do
|
||||
if not options.stances.args[v.id] then
|
||||
options.stances.args[v.id] = createOptionGroup(k, v.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local states = {
|
||||
type = "group",
|
||||
name = L["State Configuration"],
|
||||
order = 5,
|
||||
args = options,
|
||||
}
|
||||
obj:NewCategory("state", states)
|
||||
|
||||
return obj
|
||||
end
|
||||
@@ -0,0 +1,49 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
local VehicleBarMod = Bartender4:GetModule("Vehicle")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
function VehicleBarMod:SetupOptions()
|
||||
if not self.options then
|
||||
self.optionobject = ButtonBar:GetOptionObject()
|
||||
self.optionobject.table.general.args.rows.max = self.button_count
|
||||
local enabled = {
|
||||
type = "toggle",
|
||||
order = 1,
|
||||
name = L["Enabled"],
|
||||
desc = L["Enable the Vehicle Bar"],
|
||||
get = function() return self.db.profile.enabled end,
|
||||
set = "ToggleModule",
|
||||
handler = self,
|
||||
}
|
||||
self.optionobject:AddElement("general", "enabled", enabled)
|
||||
|
||||
self.disabledoptions = {
|
||||
general = {
|
||||
type = "group",
|
||||
name = L["General Settings"],
|
||||
cmdInline = true,
|
||||
order = 1,
|
||||
args = {
|
||||
enabled = enabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.options = {
|
||||
order = 30,
|
||||
type = "group",
|
||||
name = L["VehicleBar"],
|
||||
desc = L["Configure the VehicleBar"],
|
||||
childGroups = "tab",
|
||||
}
|
||||
self.optionobject.table.general.args.padding.min = -30
|
||||
Bartender4:RegisterBarOptions("Vehicle", self.options)
|
||||
end
|
||||
self.options.args = self:IsEnabled() and self.optionobject.table or self.disabledoptions
|
||||
end
|
||||
@@ -0,0 +1,110 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
-- register module
|
||||
local PetBarMod = Bartender4:NewModule("PetBar", "AceEvent-3.0")
|
||||
|
||||
-- fetch upvalues
|
||||
local ActionBars = Bartender4:GetModule("ActionBars")
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
-- create prototype information
|
||||
local PetBar = setmetatable({}, {__index = ButtonBar})
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = true,
|
||||
hidehotkey = true,
|
||||
visibility = {
|
||||
nopet = true,
|
||||
vehicle = true,
|
||||
},
|
||||
}, Bartender4.ButtonBar.defaults) }
|
||||
|
||||
function PetBarMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("PetBar", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
function PetBarMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.ButtonBar:Create("PetBar", self.db.profile, L["Pet Bar"]), {__index = PetBar})
|
||||
|
||||
local buttons = {}
|
||||
for i=1,10 do
|
||||
buttons[i] = Bartender4.PetButton:Create(i, self.bar)
|
||||
end
|
||||
self.bar.buttons = buttons
|
||||
|
||||
self.bar:SetScript("OnEvent", PetBar.OnEvent)
|
||||
end
|
||||
self.bar:Enable()
|
||||
|
||||
self.bar:RegisterEvent("PLAYER_CONTROL_LOST")
|
||||
self.bar:RegisterEvent("PLAYER_CONTROL_GAINED")
|
||||
self.bar:RegisterEvent("PLAYER_FARSIGHT_FOCUS_CHANGED")
|
||||
self.bar:RegisterEvent("UNIT_PET")
|
||||
self.bar:RegisterEvent("UNIT_FLAGS")
|
||||
self.bar:RegisterEvent("UNIT_AURA")
|
||||
self.bar:RegisterEvent("PET_BAR_UPDATE")
|
||||
self.bar:RegisterEvent("PET_BAR_UPDATE_COOLDOWN")
|
||||
self.bar:RegisterEvent("PET_BAR_SHOWGRID")
|
||||
self.bar:RegisterEvent("PET_BAR_HIDEGRID")
|
||||
|
||||
self:ApplyConfig()
|
||||
self:ToggleOptions()
|
||||
|
||||
self:RegisterEvent("UPDATE_BINDINGS", "ReassignBindings")
|
||||
self:ReassignBindings()
|
||||
end
|
||||
|
||||
function PetBarMod:ReassignBindings()
|
||||
if InCombatLockdown() then return end
|
||||
if not self.bar or not self.bar.buttons then return end
|
||||
ClearOverrideBindings(self.bar)
|
||||
for i = 1, 10 do
|
||||
local button, real_button = ("BONUSACTIONBUTTON%d"):format(i), ("BT4PetButton%d"):format(i)
|
||||
for k=1, select('#', GetBindingKey(button)) do
|
||||
local key = select(k, GetBindingKey(button))
|
||||
SetOverrideBindingClick(self.bar, false, key, real_button)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PetBarMod:ApplyConfig()
|
||||
if not self:IsEnabled() then return end
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
self:ReassignBindings()
|
||||
end
|
||||
|
||||
PetBar.button_width = 30
|
||||
PetBar.button_height = 30
|
||||
function PetBar:OnEvent(event, arg1)
|
||||
if event == "PET_BAR_UPDATE" or
|
||||
(event == "UNIT_PET" and arg1 == "player") or
|
||||
((event == "UNIT_FLAGS" or event == "UNIT_AURA") and arg1 == "pet") or
|
||||
event == "PLAYER_CONTROL_LOST" or event == "PLAYER_CONTROL_GAINED" or event == "PLAYER_FARSIGHT_FOCUS_CHANGED"
|
||||
then
|
||||
self:ForAll("Update")
|
||||
elseif event == "PET_BAR_UPDATE_COOLDOWN" then
|
||||
self:ForAll("UpdateCooldown")
|
||||
elseif event == "PET_BAR_SHOWGRID" then
|
||||
self:ForAll("ShowGrid")
|
||||
elseif event == "PET_BAR_HIDEGRID" then
|
||||
self:ForAll("HideGrid")
|
||||
end
|
||||
end
|
||||
|
||||
function PetBar:ApplyConfig(config)
|
||||
ButtonBar.ApplyConfig(self, config)
|
||||
|
||||
if not self.config.position.x then
|
||||
self:ClearSetPoint("CENTER", 0, 70)
|
||||
self:SavePosition()
|
||||
end
|
||||
|
||||
self:UpdateButtonLayout()
|
||||
self:ForAll("Update")
|
||||
self:ForAll("ApplyStyle", self.config.style)
|
||||
end
|
||||
@@ -0,0 +1,266 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
--[[
|
||||
Pet Button template
|
||||
]]
|
||||
|
||||
local PetButtonPrototype = CreateFrame("CheckButton")
|
||||
local PetButton_MT = {__index = PetButtonPrototype}
|
||||
|
||||
local LBF = LibStub("LibButtonFacade", true)
|
||||
local KeyBound = LibStub("LibKeyBound-1.0")
|
||||
|
||||
-- upvalues
|
||||
local _G = _G
|
||||
local format = string.format
|
||||
|
||||
local function onEnter(self, ...)
|
||||
if not (Bartender4.db.profile.tooltip == "nocombat" and InCombatLockdown()) and Bartender4.db.profile.tooltip ~= "disabled" then
|
||||
self:OnEnter(...)
|
||||
end
|
||||
KeyBound:Set(self)
|
||||
end
|
||||
|
||||
local function onDragStart(self)
|
||||
if InCombatLockdown() then return end
|
||||
if not Bartender4.db.profile.buttonlock or IsModifiedClick("PICKUPACTION") then
|
||||
self:SetChecked(0)
|
||||
PickupPetAction(self.id)
|
||||
self:Update()
|
||||
end
|
||||
end
|
||||
|
||||
local function onReceiveDrag(self)
|
||||
if InCombatLockdown() then return end
|
||||
self:SetChecked(0)
|
||||
PickupPetAction(self.id)
|
||||
self:Update()
|
||||
end
|
||||
|
||||
Bartender4.PetButton = {}
|
||||
Bartender4.PetButton.prototype = PetButtonPrototype
|
||||
function Bartender4.PetButton:Create(id, parent)
|
||||
local name = "BT4PetButton" .. id
|
||||
local button = setmetatable(CreateFrame("CheckButton", name, parent, "PetActionButtonTemplate"), PetButton_MT)
|
||||
button.showgrid = 0
|
||||
button.id = id
|
||||
button.parent = parent
|
||||
|
||||
button:SetFrameStrata("MEDIUM")
|
||||
button:SetID(id)
|
||||
|
||||
button:UnregisterAllEvents()
|
||||
button:SetScript("OnEvent", nil)
|
||||
|
||||
button.OnEnter = button:GetScript("OnEnter")
|
||||
button:SetScript("OnEnter", onEnter)
|
||||
|
||||
button:SetScript("OnDragStart", onDragStart)
|
||||
button:SetScript("OnReceiveDrag", onReceiveDrag)
|
||||
|
||||
button.flash = _G[name .. "Flash"]
|
||||
button.cooldown = _G[name .. "Cooldown"]
|
||||
button.icon = _G[name .. "Icon"]
|
||||
button.autocastable = _G[name .. "AutoCastable"]
|
||||
button.autocast = _G[name .. "Shine"]
|
||||
button.hotkey = _G[name .. "HotKey"]
|
||||
|
||||
button:SetNormalTexture("")
|
||||
local oldNT = button:GetNormalTexture()
|
||||
oldNT:Hide()
|
||||
|
||||
button.normalTexture = button:CreateTexture(("%sBTNT"):format(name))
|
||||
button.normalTexture:SetAllPoints(oldNT)
|
||||
|
||||
button.pushedTexture = button:GetPushedTexture()
|
||||
button.highlightTexture = button:GetHighlightTexture()
|
||||
|
||||
button.textureCache = {}
|
||||
button.textureCache.pushed = button.pushedTexture:GetTexture()
|
||||
button.textureCache.highlight = button.highlightTexture:GetTexture()
|
||||
|
||||
if LBF then
|
||||
local group = parent.LBFGroup
|
||||
button.LBFButtonData = {
|
||||
Button = button,
|
||||
Normal = button.normalTexture,
|
||||
}
|
||||
group:AddButton(button, button.LBFButtonData)
|
||||
end
|
||||
return button
|
||||
end
|
||||
|
||||
function PetButtonPrototype:Update()
|
||||
local name, subtext, texture, isToken, isActive, autoCastAllowed, autoCastEnabled = GetPetActionInfo(self.id)
|
||||
|
||||
if not isToken then
|
||||
self.icon:SetTexture(texture)
|
||||
self.tooltipName = name;
|
||||
else
|
||||
self.icon:SetTexture(_G[texture])
|
||||
self.tooltipName = _G[name]
|
||||
end
|
||||
|
||||
self.isToken = isToken
|
||||
self.tooltipSubtext = subtext
|
||||
self:SetChecked(isActive and 1 or 0)
|
||||
if autoCastAllowed and not autoCastEnabled then
|
||||
self.autocastable:Show()
|
||||
AutoCastShine_AutoCastStop(self.autocast)
|
||||
elseif autoCastAllowed then
|
||||
self.autocastable:Hide()
|
||||
AutoCastShine_AutoCastStart(self.autocast)
|
||||
else
|
||||
self.autocastable:Hide()
|
||||
AutoCastShine_AutoCastStop(self.autocast)
|
||||
end
|
||||
|
||||
if texture then
|
||||
if GetPetActionsUsable() then
|
||||
SetDesaturation(self.icon, nil)
|
||||
else
|
||||
SetDesaturation(self.icon, 1)
|
||||
end
|
||||
self.icon:Show()
|
||||
self.normalTexture:SetTexture("Interface\\Buttons\\UI-Quickslot2")
|
||||
self.normalTexture:SetTexCoord(0, 0, 0, 0)
|
||||
self:ShowButton()
|
||||
self.normalTexture:Show()
|
||||
if self.overlay then
|
||||
self.overlay:Show()
|
||||
end
|
||||
else
|
||||
self.icon:Hide()
|
||||
self.normalTexture:SetTexture("Interface\\Buttons\\UI-Quickslot")
|
||||
self.normalTexture:SetTexCoord(-0.1, 1.1, -0.1, 1.12)
|
||||
self:HideButton()
|
||||
if self.showgrid == 0 and not self.parent.config.showgrid then
|
||||
self.normalTexture:Hide()
|
||||
if self.overlay then
|
||||
self.overlay:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
self:UpdateCooldown()
|
||||
self:UpdateHotkeys()
|
||||
end
|
||||
|
||||
function PetButtonPrototype:UpdateHotkeys()
|
||||
local key = self:GetHotkey() or ""
|
||||
local hotkey = self.hotkey
|
||||
|
||||
if key == "" or self.parent.config.hidehotkey then
|
||||
hotkey:Hide()
|
||||
else
|
||||
hotkey:SetText(key)
|
||||
hotkey:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function PetButtonPrototype:ShowButton()
|
||||
self.pushedTexture:SetTexture(self.textureCache.pushed)
|
||||
self.highlightTexture:SetTexture(self.textureCache.highlight)
|
||||
if LBF then
|
||||
local backdrop, gloss = LBF:GetBackdropLayer(self), LBF:GetGlossLayer(self)
|
||||
if backdrop then
|
||||
backdrop:Show()
|
||||
end
|
||||
if gloss then
|
||||
gloss:Show()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PetButtonPrototype:HideButton()
|
||||
self.textureCache.pushed = self.pushedTexture:GetTexture()
|
||||
self.textureCache.highlight = self.highlightTexture:GetTexture()
|
||||
|
||||
self.pushedTexture:SetTexture("")
|
||||
self.highlightTexture:SetTexture("")
|
||||
if LBF then
|
||||
local backdrop, gloss = LBF:GetBackdropLayer(self), LBF:GetGlossLayer(self)
|
||||
if backdrop then
|
||||
backdrop:Hide()
|
||||
end
|
||||
if gloss then
|
||||
gloss:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function PetButtonPrototype:ShowGrid()
|
||||
self.showgrid = self.showgrid + 1
|
||||
self.normalTexture:Show()
|
||||
end
|
||||
|
||||
function PetButtonPrototype:HideGrid()
|
||||
if self.showgrid > 0 then self.showgrid = self.showgrid - 1 end
|
||||
if self.showgrid == 0 and not (GetPetActionInfo(self.id)) and not self.parent.config.showgrid then
|
||||
self.normalTexture:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function PetButtonPrototype:UpdateCooldown()
|
||||
local start, duration, enable = GetPetActionCooldown(self.id)
|
||||
CooldownFrame_SetTimer(self.cooldown, start, duration, enable)
|
||||
end
|
||||
|
||||
function PetButtonPrototype:GetHotkey()
|
||||
local key = GetBindingKey(format("BONUSACTIONBUTTON%d", self.id)) or GetBindingKey("CLICK "..self:GetName()..":LeftButton")
|
||||
return key and KeyBound:ToShortKey(key)
|
||||
end
|
||||
|
||||
function PetButtonPrototype:GetBindings()
|
||||
local keys, binding = ""
|
||||
|
||||
binding = format("BONUSACTIONBUTTON%d", self.id)
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys ~= "" then
|
||||
keys = keys .. ', '
|
||||
end
|
||||
keys = keys .. GetBindingText(hotKey,'KEY_')
|
||||
end
|
||||
|
||||
binding = "CLICK "..self:GetName()..":LeftButton"
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys ~= "" then
|
||||
keys = keys .. ', '
|
||||
end
|
||||
keys = keys.. GetBindingText(hotKey,'KEY_')
|
||||
end
|
||||
|
||||
return keys
|
||||
end
|
||||
|
||||
function PetButtonPrototype:SetKey(key)
|
||||
SetBinding(key, format("BONUSACTIONBUTTON%d", self.id))
|
||||
end
|
||||
|
||||
function PetButtonPrototype:ClearBindings()
|
||||
local binding = format("BONUSACTIONBUTTON%d", self:GetID())
|
||||
while GetBindingKey(binding) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
|
||||
binding = "CLICK "..self:GetName()..":LeftButton"
|
||||
while GetBindingKey(binding) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
end
|
||||
|
||||
local actionTmpl = "Pet Button %d (%s)"
|
||||
function PetButtonPrototype:GetActionName()
|
||||
local id = self.id
|
||||
local name, _, _, token = GetPetActionInfo(id)
|
||||
if token and name then name = _G[name] end
|
||||
return format(actionTmpl, id, name or "empty")
|
||||
end
|
||||
|
||||
function PetButtonPrototype:ClearSetPoint(...)
|
||||
self:ClearAllPoints()
|
||||
self:SetPoint(...)
|
||||
end
|
||||
@@ -0,0 +1,96 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
|
||||
-- fetch upvalues
|
||||
local Bar = Bartender4.Bar.prototype
|
||||
|
||||
local table_insert = table.insert
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = false,
|
||||
}, Bartender4.Bar.defaults) }
|
||||
|
||||
-- register module
|
||||
local RepBarMod = Bartender4:NewModule("RepBar")
|
||||
|
||||
-- create prototype information
|
||||
local RepBar = setmetatable({}, {__index = Bar})
|
||||
|
||||
function RepBarMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("RepBar", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
function RepBarMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.Bar:Create("Rep", self.db.profile, L["Reputation Bar"]), {__index = RepBar})
|
||||
self.bar.content = ReputationWatchBar
|
||||
|
||||
hooksecurefunc("ReputationWatchBar_Update", function() self.bar:PerformLayout() end)
|
||||
|
||||
self.bar.content:SetParent(self.bar)
|
||||
self.bar.content:Show()
|
||||
self.bar.content:SetFrameLevel(self.bar:GetFrameLevel() + 1)
|
||||
end
|
||||
self.bar:Enable()
|
||||
self:ToggleOptions()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
function RepBarMod:ApplyConfig()
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
end
|
||||
|
||||
function RepBar:ApplyConfig(config)
|
||||
Bar.ApplyConfig(self, config)
|
||||
|
||||
self:PerformLayout()
|
||||
end
|
||||
|
||||
function RepBar:PerformLayout()
|
||||
self:SetSize(1032, 21)
|
||||
local bar = self.content
|
||||
bar:ClearAllPoints()
|
||||
bar:SetPoint("TOPLEFT", self, "TOPLEFT", 5, -3)
|
||||
end
|
||||
|
||||
RepBar.ClickThroughSupport = true
|
||||
function RepBar:ControlClickThrough()
|
||||
self.content:EnableMouse(not self.config.clickthrough)
|
||||
end
|
||||
|
||||
|
||||
-- register module
|
||||
local XPBarMod = Bartender4:NewModule("XPBar")
|
||||
|
||||
-- create prototype information
|
||||
local XPBar = setmetatable({}, {__index = Bar})
|
||||
|
||||
function XPBarMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("XPBar", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
function XPBarMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.Bar:Create("XP", self.db.profile, L["XP Bar"]), {__index = XPBar})
|
||||
self.bar.content = MainMenuExpBar
|
||||
|
||||
self.bar.content:SetParent(self.bar)
|
||||
self.bar.content:Show()
|
||||
self.bar.content:SetFrameLevel(self.bar:GetFrameLevel() + 1)
|
||||
end
|
||||
self.bar:Enable()
|
||||
self:ToggleOptions()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
XPBarMod.ApplyConfig = RepBarMod.ApplyConfig
|
||||
XPBar.ApplyConfig = RepBar.ApplyConfig
|
||||
XPBar.PerformLayout = RepBar.PerformLayout
|
||||
|
||||
XPBar.ClickThroughSupport = true
|
||||
XPBar.ControlClickThrough = RepBar.ControlClickThrough
|
||||
@@ -0,0 +1,269 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
-- register module
|
||||
local StanceBarMod = Bartender4:NewModule("StanceBar", "AceEvent-3.0")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
-- create prototype information
|
||||
local StanceBar = setmetatable({}, {__index = ButtonBar})
|
||||
local StanceButtonPrototype = CreateFrame("CheckButton")
|
||||
local StanceButton_MT = {__index = StanceButtonPrototype}
|
||||
|
||||
local format = string.format
|
||||
|
||||
local LBF = LibStub("LibButtonFacade", true)
|
||||
local KeyBound = LibStub("LibKeyBound-1.0")
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = true,
|
||||
position = {
|
||||
scale = 1.5,
|
||||
},
|
||||
hidehotkey = true,
|
||||
}, Bartender4.ButtonBar.defaults) }
|
||||
|
||||
function StanceBarMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("StanceBar", defaults)
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
|
||||
function StanceBarMod:OnEnable()
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.ButtonBar:Create("StanceBar", self.db.profile, L["Stance Bar"]), {__index = StanceBar})
|
||||
self.bar:SetScript("OnEvent", StanceBar.OnEvent)
|
||||
end
|
||||
self.bar:Enable()
|
||||
|
||||
self:ToggleOptions()
|
||||
self.bar:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
self.bar:RegisterEvent("UPDATE_SHAPESHIFT_FORMS")
|
||||
self.bar:RegisterEvent("SPELL_UPDATE_COOLDOWN")
|
||||
self.bar:RegisterEvent("SPELL_UPDATE_USABLE")
|
||||
self.bar:RegisterEvent("PLAYER_AURAS_CHANGED")
|
||||
self.bar:RegisterEvent("PLAYER_REGEN_ENABLED")
|
||||
self.bar:RegisterEvent("ACTIONBAR_PAGE_CHANGED")
|
||||
self:RegisterEvent("UPDATE_BINDINGS", "ReassignBindings")
|
||||
self:ReassignBindings()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
StanceBarMod.button_count = 10
|
||||
|
||||
function StanceBarMod:ApplyConfig()
|
||||
if not self:IsEnabled() then return end
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
|
||||
if GetNumShapeshiftForms() == 0 then
|
||||
self:Disable()
|
||||
end
|
||||
end
|
||||
|
||||
function StanceBarMod:ReassignBindings()
|
||||
if InCombatLockdown() then return end
|
||||
if not self.bar or not self.bar.buttons then return end
|
||||
ClearOverrideBindings(self.bar)
|
||||
for i = 1, min(#self.bar.buttons, 10) do
|
||||
local button, real_button = ("SHAPESHIFTBUTTON%d"):format(i), ("BT4StanceButton%d"):format(i)
|
||||
for k=1, select('#', GetBindingKey(button)) do
|
||||
local key = select(k, GetBindingKey(button))
|
||||
SetOverrideBindingClick(self.bar, false, key, real_button)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function StanceButtonPrototype:Update()
|
||||
if not self:IsShown() then return end
|
||||
local id = self:GetID()
|
||||
local texture, name, isActive, isCastable = GetShapeshiftFormInfo(id)
|
||||
|
||||
self.icon:SetTexture(texture)
|
||||
|
||||
-- manage cooldowns
|
||||
if texture then
|
||||
self.cooldown:Show()
|
||||
else
|
||||
self.cooldown:Hide()
|
||||
end
|
||||
local start, duration, enable = GetShapeshiftFormCooldown(id)
|
||||
CooldownFrame_SetTimer(self.cooldown, start, duration, enable)
|
||||
|
||||
if isActive then
|
||||
self:SetChecked(1)
|
||||
else
|
||||
self:SetChecked(0)
|
||||
end
|
||||
|
||||
if isCastable then
|
||||
self.icon:SetVertexColor(1.0, 1.0, 1.0)
|
||||
else
|
||||
self.icon:SetVertexColor(0.4, 0.4, 0.4)
|
||||
end
|
||||
|
||||
self:UpdateHotkeys()
|
||||
end
|
||||
|
||||
function StanceButtonPrototype:UpdateHotkeys()
|
||||
local key = self:GetHotkey() or ""
|
||||
local hotkey = self.hotkey
|
||||
|
||||
if key == "" or self.parent.config.hidehotkey then
|
||||
hotkey:Hide()
|
||||
else
|
||||
hotkey:SetText(key)
|
||||
hotkey:Show()
|
||||
end
|
||||
end
|
||||
|
||||
function StanceButtonPrototype:GetHotkey()
|
||||
local key = GetBindingKey(format("SHAPESHIFTBUTTON%d", self:GetID())) or GetBindingKey("CLICK "..self:GetName()..":LeftButton")
|
||||
return key and KeyBound:ToShortKey(key)
|
||||
end
|
||||
|
||||
function StanceButtonPrototype:GetBindings()
|
||||
local keys, binding = ""
|
||||
|
||||
binding = format("SHAPESHIFTBUTTON%d", self:GetID())
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys ~= "" then
|
||||
keys = keys .. ', '
|
||||
end
|
||||
keys = keys .. GetBindingText(hotKey,'KEY_')
|
||||
end
|
||||
|
||||
binding = "CLICK "..self:GetName()..":LeftButton"
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys ~= "" then
|
||||
keys = keys .. ', '
|
||||
end
|
||||
keys = keys.. GetBindingText(hotKey,'KEY_')
|
||||
end
|
||||
|
||||
return keys
|
||||
end
|
||||
|
||||
function StanceButtonPrototype:SetKey(key)
|
||||
SetBinding(key, format("SHAPESHIFTBUTTON%d", self:GetID()))
|
||||
end
|
||||
|
||||
function StanceButtonPrototype:ClearBindings()
|
||||
local binding = format("SHAPESHIFTBUTTON%d", self:GetID())
|
||||
while GetBindingKey(binding) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
|
||||
binding = "CLICK "..self:GetName()..":LeftButton"
|
||||
while GetBindingKey(binding) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
end
|
||||
|
||||
local actionTmpl = "Stance Button %d (%s)"
|
||||
function StanceButtonPrototype:GetActionName()
|
||||
local id = self:GetID()
|
||||
return format(actionTmpl, id, select(2, GetShapeshiftFormInfo(id)))
|
||||
end
|
||||
|
||||
|
||||
function StanceButtonPrototype:ClearSetPoint(...)
|
||||
self:ClearAllPoints()
|
||||
self:SetPoint(...)
|
||||
end
|
||||
|
||||
local function onEnter(self, ...)
|
||||
if not (Bartender4.db.profile.tooltip == "nocombat" and InCombatLockdown()) and Bartender4.db.profile.tooltip ~= "disabled" then
|
||||
self:OnEnter(...)
|
||||
end
|
||||
KeyBound:Set(self)
|
||||
end
|
||||
|
||||
function StanceBarMod:CreateStanceButton(id)
|
||||
local button = setmetatable(CreateFrame("CheckButton", "BT4StanceButton" .. id, self.bar, "ShapeshiftButtonTemplate"), StanceButton_MT)
|
||||
button.parent = self.bar
|
||||
button:SetID(id)
|
||||
button.icon = _G[button:GetName() .. "Icon"]
|
||||
button.cooldown = _G[button:GetName() .. "Cooldown"]
|
||||
button.hotkey = _G[button:GetName() .. "HotKey"]
|
||||
button.normalTexture = button:GetNormalTexture()
|
||||
button.normalTexture:SetTexture("")
|
||||
-- button.checkedTexture = button:GetCheckedTexture()
|
||||
-- button.checkedTexture:SetTexture("")
|
||||
|
||||
button.OnEnter = button:GetScript("OnEnter")
|
||||
button:SetScript("OnEnter", onEnter)
|
||||
|
||||
if LBF then
|
||||
local group = self.bar.LBFGroup
|
||||
button.LBFButtonData = {
|
||||
Button = button
|
||||
}
|
||||
group:AddButton(button, button.LBFButtonData)
|
||||
end
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
function StanceBar:ApplyConfig(config)
|
||||
ButtonBar.ApplyConfig(self, config)
|
||||
|
||||
if not self.config.position.x then
|
||||
self:ClearSetPoint("CENTER", -55, -10)
|
||||
self:SavePosition()
|
||||
end
|
||||
|
||||
self:UpdateStanceButtons()
|
||||
self:ForAll("ApplyStyle", self.config.style)
|
||||
end
|
||||
|
||||
StanceBar.button_width = 30
|
||||
StanceBar.button_height = 30
|
||||
function StanceBar:UpdateStanceButtons()
|
||||
local buttons = self.buttons or {}
|
||||
|
||||
local num_stances = GetNumShapeshiftForms()
|
||||
|
||||
local updateBindings = (num_stances > #buttons)
|
||||
|
||||
for i = (#buttons+1), num_stances do
|
||||
buttons[i] = StanceBarMod:CreateStanceButton(i)
|
||||
end
|
||||
|
||||
for i = 1, num_stances do
|
||||
buttons[i]:Show()
|
||||
buttons[i]:Update()
|
||||
end
|
||||
|
||||
for i = num_stances+1, #buttons do
|
||||
buttons[i]:Hide()
|
||||
end
|
||||
|
||||
StanceBarMod.button_count = num_stances
|
||||
if StanceBarMod.optionobject then
|
||||
StanceBarMod.optionobject.table.general.args.rows.max = num_stances
|
||||
end
|
||||
|
||||
self.buttons = buttons
|
||||
|
||||
self:UpdateButtonLayout()
|
||||
if updateBindings then
|
||||
StanceBarMod:ReassignBindings()
|
||||
end
|
||||
self.disabled = (GetNumShapeshiftForms() == 0) and true or nil
|
||||
|
||||
-- need to re-set clickthrough after creating new buttons
|
||||
self:SetClickThrough()
|
||||
end
|
||||
|
||||
function StanceBar:OnEvent(event, ...)
|
||||
if event == "PLAYER_ENTERING_WORLD" or event == "UPDATE_SHAPESHIFT_FORMS" and not InCombatLockdown() then
|
||||
self:UpdateStanceButtons()
|
||||
else
|
||||
self:ForAll("Update")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,290 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
--[[ Generic Template for a ButtonBar with state control ]]
|
||||
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
local StateBar = setmetatable({}, {__index = ButtonBar})
|
||||
local StateBar_MT = {__index = StateBar}
|
||||
|
||||
local defaults = Bartender4:Merge({
|
||||
autoassist = false,
|
||||
states = {
|
||||
enabled = false,
|
||||
possess = false,
|
||||
actionbar = false,
|
||||
default = 0,
|
||||
ctrl = 0,
|
||||
alt = 0,
|
||||
shift = 0,
|
||||
stance = {
|
||||
['*'] = {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, Bartender4.ButtonBar.defaults)
|
||||
|
||||
Bartender4.StateBar = {}
|
||||
Bartender4.StateBar.prototype = StateBar
|
||||
Bartender4.StateBar.defaults = defaults
|
||||
|
||||
function Bartender4.StateBar:Create(id, config, name)
|
||||
local bar = setmetatable(Bartender4.ButtonBar:Create(id, config, name), StateBar_MT)
|
||||
|
||||
return bar
|
||||
end
|
||||
|
||||
StateBar.BT4BarType = "StateBar"
|
||||
|
||||
function StateBar:ApplyConfig(config)
|
||||
ButtonBar.ApplyConfig(self, config)
|
||||
-- We cannot call UpdateStates or UpdateSelfCast now, because the buttons are not yet created *sad*
|
||||
end
|
||||
|
||||
--------------------------------------------------------------
|
||||
-- Stance Management
|
||||
|
||||
local table_insert = table.insert
|
||||
local table_concat = table.concat
|
||||
local fmt = string.format
|
||||
|
||||
local modifiers = { "ctrl", "alt", "shift" }
|
||||
|
||||
local _, playerclass = UnitClass("player")
|
||||
|
||||
-- specifiy the available stances for each class
|
||||
local DefaultStanceMap = setmetatable({}, { __index = function(t,k)
|
||||
local newT = nil
|
||||
if k == "WARRIOR" then
|
||||
newT = {
|
||||
{ id = "battle", name = GetSpellInfo(2457), index = 1},
|
||||
{ id = "def", name = GetSpellInfo(71), index = 2 },
|
||||
{ id = "berserker", name = GetSpellInfo(2458), index = 3 },
|
||||
}
|
||||
elseif k == "DRUID" then
|
||||
newT = {
|
||||
{ id = "bear", name = GetSpellInfo(5487), index = 3 },
|
||||
{ id = "cat", name = GetSpellInfo(768), index = 1 },
|
||||
-- prowl is virtual, no real stance
|
||||
{ id = "prowl", name = ("%s (%s)"):format((GetSpellInfo(768)), (GetSpellInfo(5215))), index = false},
|
||||
{ id = "moonkin", name = GetSpellInfo(24858), index = 4 },
|
||||
{ id = "treeoflife", name = GetSpellInfo(33891), index = 2 },
|
||||
}
|
||||
elseif k == "ROGUE" then
|
||||
newT = {
|
||||
{ id = "stealth", name = GetSpellInfo(1784), index = 1 },
|
||||
{ id = "shadowdance", name = GetSpellInfo(51713), index = 2 },
|
||||
}
|
||||
elseif k == "PRIEST" then
|
||||
newT = {
|
||||
{ id = "shadowform", name = GetSpellInfo(15473), index = 1 },
|
||||
}
|
||||
elseif k == "WARLOCK" then
|
||||
newT = {
|
||||
{ id = "metamorphosis", name = GetSpellInfo(59672), index = 2, type = "form"},
|
||||
}
|
||||
elseif k == "HERO" then
|
||||
newT = {
|
||||
-- Warrior
|
||||
{ id = "battle", name = GetSpellInfo(2457), index = 1},
|
||||
{ id = "def", name = GetSpellInfo(71), index = 2 },
|
||||
{ id = "berserker", name = GetSpellInfo(2458), index = 3 },
|
||||
|
||||
-- Druid
|
||||
{ id = "bear", name = GetSpellInfo(5487), index = 3 },
|
||||
{ id = "cat", name = GetSpellInfo(768), index = 1 },
|
||||
-- prowl is virtual, no real stance
|
||||
{ id = "prowl", name = ("%s (%s)"):format((GetSpellInfo(768)), (GetSpellInfo(5215))), index = false},
|
||||
{ id = "moonkin", name = GetSpellInfo(24858), index = 4 },
|
||||
{ id = "treeoflife", name = GetSpellInfo(33891), index = 2 },
|
||||
|
||||
-- Rogue
|
||||
{ id = "stealth", name = GetSpellInfo(1784), index = 1 },
|
||||
{ id = "shadowdance", name = GetSpellInfo(51713), index = 2 },
|
||||
|
||||
-- Priest
|
||||
{ id = "shadowform", name = GetSpellInfo(15473), index = 1 },
|
||||
|
||||
-- Warlock
|
||||
{ id = "metamorphosis", name = GetSpellInfo(59672), index = 2, type = "form"},
|
||||
}
|
||||
end
|
||||
rawset(t, k, newT)
|
||||
|
||||
return newT
|
||||
end})
|
||||
Bartender4.StanceMap = DefaultStanceMap
|
||||
|
||||
local stancemap
|
||||
function StateBar:UpdateStates(returnOnly)
|
||||
if not self.buttons then return end
|
||||
self.statebutton = {}
|
||||
if not stancemap and DefaultStanceMap[playerclass] then
|
||||
stancemap = DefaultStanceMap[playerclass]
|
||||
end
|
||||
|
||||
local statedriver
|
||||
if not self:GetStateOption("enabled") then
|
||||
statedriver = "0"
|
||||
elseif returnOnly or not self:GetStateOption("customEnabled") then
|
||||
statedriver = {}
|
||||
local stateconfig = self.config.states
|
||||
-- arguments will be parsed from left to right, so we have a priority here
|
||||
|
||||
-- possessing will always be the most important change, if enabled
|
||||
if self:GetStateOption("possess") then
|
||||
table_insert(statedriver, "[bonusbar:5]11")
|
||||
end
|
||||
|
||||
-- highest priority have our temporary quick-swap keys
|
||||
for _,v in pairs(modifiers) do
|
||||
local page = self:GetStateOption(v)
|
||||
if page and page ~= 0 then
|
||||
table_insert(statedriver, fmt("[mod:%s]%s", v, page))
|
||||
end
|
||||
end
|
||||
|
||||
-- second priority the manual changes using the ActionBar options
|
||||
if self:GetStateOption("actionbar") then
|
||||
for i=2,6 do
|
||||
table_insert(statedriver, fmt("[bar:%s]%s", i, i))
|
||||
end
|
||||
end
|
||||
|
||||
-- third priority the stances
|
||||
if stancemap then
|
||||
if not stateconfig.stance[playerclass] then stateconfig.stance[playerclass] = {} end
|
||||
for i,v in pairs(stancemap) do
|
||||
local state = self:GetStanceState(v)
|
||||
if state and state ~= 0 and v.index then
|
||||
-- hack for druid prowl, since its no real "stance", but we want to handle it anyway
|
||||
if (playerclass == "DRUID" or playerclass == "HERO") and v.id == "cat" then
|
||||
local prowl = self:GetStanceState("prowl")
|
||||
if prowl and prowl ~= 0 then
|
||||
table_insert(statedriver, fmt("[bonusbar:%s,stealth:1]%s", v.index, prowl))
|
||||
end
|
||||
end
|
||||
table_insert(statedriver, fmt("[%s:%s]%s", v.type or "bonusbar", v.index, state))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table_insert(statedriver, tostring(self:GetDefaultState() or 0))
|
||||
statedriver = table_concat(statedriver, ";")
|
||||
if returnOnly then
|
||||
return statedriver
|
||||
end
|
||||
else
|
||||
statedriver = self:GetStateOption("custom")
|
||||
end
|
||||
|
||||
self:SetAttribute("_onstate-page", [[
|
||||
self:SetAttribute("state", newstate)
|
||||
control:ChildUpdate("state", newstate)
|
||||
]])
|
||||
|
||||
UnregisterStateDriver(self, "page")
|
||||
self:SetAttribute("state-page", "0")
|
||||
|
||||
-- CoA: rewrite [aura:Name] / [form:Name] / [stance:Name] -> [stance:N]
|
||||
if Bartender4.CoATranslateConditionals then
|
||||
statedriver = Bartender4:CoATranslateConditionals(statedriver)
|
||||
end
|
||||
RegisterStateDriver(self, "page", statedriver or "0")
|
||||
|
||||
self:SetAttribute("_onstate-assist-help", [[
|
||||
local state = (newstate ~= "nil") and newstate or nil
|
||||
control:ChildUpdate("assist-help", state)
|
||||
]])
|
||||
|
||||
self:SetAttribute("_onstate-assist-harm", [[
|
||||
local state = (newstate ~= "nil") and newstate or nil
|
||||
control:ChildUpdate("assist-harm", state)
|
||||
]])
|
||||
|
||||
local preSelf = ""
|
||||
if Bartender4.db.profile.selfcastmodifier then
|
||||
preSelf = "[mod:SELFCAST]player;"
|
||||
end
|
||||
|
||||
local preFocus = ""
|
||||
if Bartender4.db.profile.focuscastmodifier then
|
||||
preFocus = "[mod:FOCUSCAST,target=focus,exists,nodead]focus;"
|
||||
end
|
||||
|
||||
UnregisterStateDriver(self, "assist-help")
|
||||
self:SetAttribute("state-assist-help", "nil")
|
||||
UnregisterStateDriver(self, "assist-harm")
|
||||
self:SetAttribute("state-assist-harm", "nil")
|
||||
|
||||
if self.config.autoassist then
|
||||
RegisterStateDriver(self, "assist-help", ("%s%s[help]nil; [target=targettarget, help]targettarget; nil"):format(preSelf, preFocus))
|
||||
RegisterStateDriver(self, "assist-harm", ("%s[harm]nil; [target=targettarget, harm]targettarget; nil"):format(preFocus))
|
||||
end
|
||||
|
||||
self:ForAll("UpdateStates")
|
||||
self:Execute([[
|
||||
control:ChildUpdate("init")
|
||||
]])
|
||||
end
|
||||
|
||||
function StateBar:GetStanceState(stance)
|
||||
local stanceconfig = self.config.states.stance[playerclass]
|
||||
if type(stance) == "table" then
|
||||
state = stanceconfig[stance.id]
|
||||
else
|
||||
state = stanceconfig[stance]
|
||||
end
|
||||
return state or 0
|
||||
end
|
||||
|
||||
function StateBar:GetStanceStateOption(stance)
|
||||
local state = self:GetStanceState(stance)
|
||||
return state
|
||||
end
|
||||
|
||||
function StateBar:SetStanceStateOption(stance, state)
|
||||
local stanceconfig = self.config.states.stance[playerclass]
|
||||
stanceconfig[stance] = state
|
||||
self:UpdateStates()
|
||||
end
|
||||
|
||||
function StateBar:GetStateOption(key)
|
||||
return self.config.states[key]
|
||||
end
|
||||
|
||||
function StateBar:SetStateOption(key, value)
|
||||
self.config.states[key] = value
|
||||
self:UpdateStates()
|
||||
end
|
||||
|
||||
function StateBar:GetDefaultState()
|
||||
return self.config.states.default
|
||||
end
|
||||
|
||||
function StateBar:SetDefaultState(_, value)
|
||||
self.config.states.default = value
|
||||
self:UpdateStates()
|
||||
end
|
||||
|
||||
function StateBar:GetConfigAutoAssist()
|
||||
return self.config.autoassist
|
||||
end
|
||||
|
||||
function StateBar:SetConfigAutoAssist(_, value)
|
||||
if value ~= nil then
|
||||
self.config.autoassist = value
|
||||
end
|
||||
self:UpdateStates()
|
||||
end
|
||||
|
||||
function StateBar:SetCopyCustomConditionals()
|
||||
self.config.states.custom = self:UpdateStates(true)
|
||||
self:UpdateStates()
|
||||
end
|
||||
|
||||
function StateBar:UpdateSelfCast()
|
||||
self:ForAll("UpdateSelfCast")
|
||||
self:UpdateStates()
|
||||
end
|
||||
@@ -0,0 +1,126 @@
|
||||
--[[
|
||||
Copyright (c) 2009, Hendrik "Nevcairiel" Leppkes < h.leppkes at gmail dot com >
|
||||
All rights reserved.
|
||||
]]
|
||||
local L = LibStub("AceLocale-3.0"):GetLocale("Bartender4")
|
||||
-- register module
|
||||
local VehicleBarMod = Bartender4:NewModule("Vehicle")
|
||||
|
||||
-- fetch upvalues
|
||||
local ButtonBar = Bartender4.ButtonBar.prototype
|
||||
|
||||
-- create prototype information
|
||||
local VehicleBar = setmetatable({}, {__index = ButtonBar})
|
||||
|
||||
local table_insert = table.insert
|
||||
|
||||
local defaults = { profile = Bartender4:Merge({
|
||||
enabled = true,
|
||||
visibility = {
|
||||
custom = true,
|
||||
customdata = "[target=vehicle,exists]show;hide"
|
||||
},
|
||||
}, Bartender4.ButtonBar.defaults) }
|
||||
|
||||
function VehicleBarMod:OnInitialize()
|
||||
self.db = Bartender4.db:RegisterNamespace("Vehicle", defaults)
|
||||
if self.blizzardVehicle then
|
||||
self:SetEnabledState(false)
|
||||
else
|
||||
self:SetEnabledState(self.db.profile.enabled)
|
||||
end
|
||||
end
|
||||
|
||||
function VehicleBarMod:OnEnable()
|
||||
if self.blizzardVehicle then
|
||||
self:Disable()
|
||||
return
|
||||
end
|
||||
if not self.bar then
|
||||
self.bar = setmetatable(Bartender4.ButtonBar:Create("Vehicle", self.db.profile, L["Vehicle Bar"], true), {__index = VehicleBar})
|
||||
local buttons = {VehicleMenuBarLeaveButton, VehicleMenuBarPitchUpButton, VehicleMenuBarPitchDownButton}
|
||||
self.bar.buttons = buttons
|
||||
|
||||
VehicleBarMod.button_count = 3
|
||||
|
||||
for i,v in pairs(buttons) do
|
||||
v:SetParent(self.bar)
|
||||
v:Show()
|
||||
v.ClearSetPoint = self.bar.ClearSetPoint
|
||||
end
|
||||
|
||||
self.bar:SetScript("OnEvent", self.bar.OnEvent)
|
||||
self.bar:RegisterEvent("UNIT_ENTERED_VEHICLE")
|
||||
|
||||
-- setup button skins
|
||||
VehicleMenuBarPitchUpButton:GetNormalTexture():SetTexture([[Interface\Vehicles\UI-Vehicles-Button-Pitch-Up]])
|
||||
VehicleMenuBarPitchUpButton:GetNormalTexture():SetTexCoord(0.21875, 0.765625, 0.234375, 0.78125)
|
||||
VehicleMenuBarPitchUpButton:GetPushedTexture():SetTexture([[Interface\Vehicles\UI-Vehicles-Button-Pitch-Down]])
|
||||
VehicleMenuBarPitchUpButton:GetPushedTexture():SetTexCoord(0.21875, 0.765625, 0.234375, 0.78125)
|
||||
|
||||
VehicleMenuBarPitchDownButton:GetNormalTexture():SetTexture([[Interface\Vehicles\UI-Vehicles-Button-PitchDown-Up]])
|
||||
VehicleMenuBarPitchDownButton:GetNormalTexture():SetTexCoord(0.21875, 0.765625, 0.234375, 0.78125)
|
||||
VehicleMenuBarPitchDownButton:GetPushedTexture():SetTexture([[Interface\Vehicles\UI-Vehicles-Button-PitchDown-Down]])
|
||||
VehicleMenuBarPitchDownButton:GetPushedTexture():SetTexCoord(0.21875, 0.765625, 0.234375, 0.78125)
|
||||
|
||||
VehicleMenuBarLeaveButton:GetNormalTexture():SetTexture([[Interface\Vehicles\UI-Vehicles-Button-Exit-Up]])
|
||||
VehicleMenuBarLeaveButton:GetNormalTexture():SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
|
||||
VehicleMenuBarLeaveButton:GetPushedTexture():SetTexture([[Interface\Vehicles\UI-Vehicles-Button-Exit-Down]])
|
||||
VehicleMenuBarLeaveButton:GetPushedTexture():SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375)
|
||||
end
|
||||
self.bar:Enable()
|
||||
self:ToggleOptions()
|
||||
self:ApplyConfig()
|
||||
end
|
||||
|
||||
function VehicleBarMod:OnDisable()
|
||||
Bartender4.modulePrototype.OnDisable(self)
|
||||
VehicleMenuBarPitchUpButton:SetParent(VehicleMenuBar)
|
||||
VehicleMenuBarPitchUpButton:ClearAllPoints()
|
||||
VehicleMenuBarPitchDownButton:SetParent(VehicleMenuBar)
|
||||
VehicleMenuBarPitchDownButton:ClearAllPoints()
|
||||
VehicleMenuBarLeaveButton:SetParent(VehicleMenuBar)
|
||||
VehicleMenuBarLeaveButton:ClearAllPoints()
|
||||
end
|
||||
|
||||
function VehicleBarMod:ApplyConfig()
|
||||
self.bar:ApplyConfig(self.db.profile)
|
||||
end
|
||||
|
||||
VehicleBar.button_width = 40
|
||||
VehicleBar.button_height = 40
|
||||
VehicleBar.LBFOverride = true
|
||||
function VehicleBar:ApplyConfig(config)
|
||||
ButtonBar.ApplyConfig(self, config)
|
||||
|
||||
if not self.config.position.x then
|
||||
self:ClearSetPoint("CENTER", 120, 27)
|
||||
self:SavePosition()
|
||||
end
|
||||
|
||||
self:UpdateButtonLayout()
|
||||
end
|
||||
|
||||
function VehicleBar:OnEvent(event, arg1)
|
||||
if event == "UNIT_ENTERED_VEHICLE" then
|
||||
if arg1 == "player" then
|
||||
self:UpdateButtonVisibility()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function VehicleBar:UpdateButtonVisibility()
|
||||
if IsVehicleAimAngleAdjustable() then
|
||||
_G["VehicleMenuBarPitchUpButton"]:Show()
|
||||
_G["VehicleMenuBarPitchDownButton"]:Show()
|
||||
else
|
||||
_G["VehicleMenuBarPitchUpButton"]:Hide()
|
||||
_G["VehicleMenuBarPitchDownButton"]:Hide()
|
||||
end
|
||||
|
||||
if CanExitVehicle() then
|
||||
_G["VehicleMenuBarLeaveButton"]:Show()
|
||||
else
|
||||
_G["VehicleMenuBarLeaveButton"]:Hide()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,642 @@
|
||||
--- **AceAddon-3.0** provides a template for creating addon objects.
|
||||
-- It'll provide you with a set of callback functions that allow you to simplify the loading
|
||||
-- process of your addon.\\
|
||||
-- Callbacks provided are:\\
|
||||
-- * **OnInitialize**, which is called directly after the addon is fully loaded.
|
||||
-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
|
||||
-- * **OnDisable**, which is only called when your addon is manually being disabled.
|
||||
-- @usage
|
||||
-- -- A small (but complete) addon, that doesn't do anything,
|
||||
-- -- but shows usage of the callbacks.
|
||||
-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
|
||||
--
|
||||
-- function MyAddon:OnInitialize()
|
||||
-- -- do init tasks here, like loading the Saved Variables,
|
||||
-- -- or setting up slash commands.
|
||||
-- end
|
||||
--
|
||||
-- function MyAddon:OnEnable()
|
||||
-- -- Do more initialization here, that really enables the use of your addon.
|
||||
-- -- Register Events, Hook functions, Create Frames, Get information from
|
||||
-- -- the game that wasn't available in OnInitialize
|
||||
-- end
|
||||
--
|
||||
-- function MyAddon:OnDisable()
|
||||
-- -- Unhook, Unregister Events, Hide frames that you created.
|
||||
-- -- You would probably only use an OnDisable if you want to
|
||||
-- -- build a "standby" mode, or be able to toggle modules on/off.
|
||||
-- end
|
||||
-- @class file
|
||||
-- @name AceAddon-3.0.lua
|
||||
-- @release $Id: AceAddon-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
|
||||
|
||||
local MAJOR, MINOR = "AceAddon-3.0", 5
|
||||
local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceAddon then return end -- No Upgrade needed.
|
||||
|
||||
AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
|
||||
AceAddon.addons = AceAddon.addons or {} -- addons in general
|
||||
AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
|
||||
AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
|
||||
AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
|
||||
AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
|
||||
|
||||
-- Lua APIs
|
||||
local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
|
||||
local fmt, tostring = string.format, tostring
|
||||
local select, pairs, next, type, unpack = select, pairs, next, type, unpack
|
||||
local loadstring, assert, error = loadstring, assert, error
|
||||
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
|
||||
|
||||
--[[
|
||||
xpcall safecall implementation
|
||||
]]
|
||||
local xpcall = xpcall
|
||||
|
||||
local function errorhandler(err)
|
||||
return geterrorhandler()(err)
|
||||
end
|
||||
|
||||
local function CreateDispatcher(argCount)
|
||||
local code = [[
|
||||
local xpcall, eh = ...
|
||||
local method, ARGS
|
||||
local function call() return method(ARGS) end
|
||||
|
||||
local function dispatch(func, ...)
|
||||
method = func
|
||||
if not method then return end
|
||||
ARGS = ...
|
||||
return xpcall(call, eh)
|
||||
end
|
||||
|
||||
return dispatch
|
||||
]]
|
||||
|
||||
local ARGS = {}
|
||||
for i = 1, argCount do ARGS[i] = "arg"..i end
|
||||
code = code:gsub("ARGS", tconcat(ARGS, ", "))
|
||||
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
|
||||
end
|
||||
|
||||
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
|
||||
local dispatcher = CreateDispatcher(argCount)
|
||||
rawset(self, argCount, dispatcher)
|
||||
return dispatcher
|
||||
end})
|
||||
Dispatchers[0] = function(func)
|
||||
return xpcall(func, errorhandler)
|
||||
end
|
||||
|
||||
local function safecall(func, ...)
|
||||
-- we check to see if the func is passed is actually a function here and don't error when it isn't
|
||||
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
|
||||
-- present execution should continue without hinderance
|
||||
if type(func) == "function" then
|
||||
return Dispatchers[select('#', ...)](func, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- local functions that will be implemented further down
|
||||
local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
|
||||
|
||||
-- used in the addon metatable
|
||||
local function addontostring( self ) return self.name end
|
||||
|
||||
--- Create a new AceAddon-3.0 addon.
|
||||
-- Any libraries you specified will be embeded, and the addon will be scheduled for
|
||||
-- its OnInitialize and OnEnable callbacks.
|
||||
-- The final addon object, with all libraries embeded, will be returned.
|
||||
-- @paramsig [object ,]name[, lib, ...]
|
||||
-- @param object Table to use as a base for the addon (optional)
|
||||
-- @param name Name of the addon object to create
|
||||
-- @param lib List of libraries to embed into the addon
|
||||
-- @usage
|
||||
-- -- Create a simple addon object
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
|
||||
--
|
||||
-- -- Create a Addon object based on the table of a frame
|
||||
-- local MyFrame = CreateFrame("Frame")
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
|
||||
function AceAddon:NewAddon(objectorname, ...)
|
||||
local object,name
|
||||
local i=1
|
||||
if type(objectorname)=="table" then
|
||||
object=objectorname
|
||||
name=...
|
||||
i=2
|
||||
else
|
||||
name=objectorname
|
||||
end
|
||||
if type(name)~="string" then
|
||||
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
|
||||
end
|
||||
if self.addons[name] then
|
||||
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
|
||||
end
|
||||
|
||||
object = object or {}
|
||||
object.name = name
|
||||
|
||||
local addonmeta = {}
|
||||
local oldmeta = getmetatable(object)
|
||||
if oldmeta then
|
||||
for k, v in pairs(oldmeta) do addonmeta[k] = v end
|
||||
end
|
||||
addonmeta.__tostring = addontostring
|
||||
|
||||
setmetatable( object, addonmeta )
|
||||
self.addons[name] = object
|
||||
object.modules = {}
|
||||
object.defaultModuleLibraries = {}
|
||||
Embed( object ) -- embed NewModule, GetModule methods
|
||||
self:EmbedLibraries(object, select(i,...))
|
||||
|
||||
-- add to queue of addons to be initialized upon ADDON_LOADED
|
||||
tinsert(self.initializequeue, object)
|
||||
return object
|
||||
end
|
||||
|
||||
|
||||
--- Get the addon object by its name from the internal AceAddon registry.
|
||||
-- Throws an error if the addon object cannot be found (except if silent is set).
|
||||
-- @param name unique name of the addon object
|
||||
-- @param silent if true, the addon is optional, silently return nil if its not found
|
||||
-- @usage
|
||||
-- -- Get the Addon
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
function AceAddon:GetAddon(name, silent)
|
||||
if not silent and not self.addons[name] then
|
||||
error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
|
||||
end
|
||||
return self.addons[name]
|
||||
end
|
||||
|
||||
-- - Embed a list of libraries into the specified addon.
|
||||
-- This function will try to embed all of the listed libraries into the addon
|
||||
-- and error if a single one fails.
|
||||
--
|
||||
-- **Note:** This function is for internal use by :NewAddon/:NewModule
|
||||
-- @paramsig addon, [lib, ...]
|
||||
-- @param addon addon object to embed the libs in
|
||||
-- @param lib List of libraries to embed into the addon
|
||||
function AceAddon:EmbedLibraries(addon, ...)
|
||||
for i=1,select("#", ... ) do
|
||||
local libname = select(i, ...)
|
||||
self:EmbedLibrary(addon, libname, false, 4)
|
||||
end
|
||||
end
|
||||
|
||||
-- - Embed a library into the addon object.
|
||||
-- This function will check if the specified library is registered with LibStub
|
||||
-- and if it has a :Embed function to call. It'll error if any of those conditions
|
||||
-- fails.
|
||||
--
|
||||
-- **Note:** This function is for internal use by :EmbedLibraries
|
||||
-- @paramsig addon, libname[, silent[, offset]]
|
||||
-- @param addon addon object to embed the library in
|
||||
-- @param libname name of the library to embed
|
||||
-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
|
||||
-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
|
||||
function AceAddon:EmbedLibrary(addon, libname, silent, offset)
|
||||
local lib = LibStub:GetLibrary(libname, true)
|
||||
if not lib and not silent then
|
||||
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
|
||||
elseif lib and type(lib.Embed) == "function" then
|
||||
lib:Embed(addon)
|
||||
tinsert(self.embeds[addon], libname)
|
||||
return true
|
||||
elseif lib then
|
||||
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
|
||||
end
|
||||
end
|
||||
|
||||
--- Return the specified module from an addon object.
|
||||
-- Throws an error if the addon object cannot be found (except if silent is set)
|
||||
-- @name //addon//:GetModule
|
||||
-- @paramsig name[, silent]
|
||||
-- @param name unique name of the module
|
||||
-- @param silent if true, the module is optional, silently return nil if its not found (optional)
|
||||
-- @usage
|
||||
-- -- Get the Addon
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- -- Get the Module
|
||||
-- MyModule = MyAddon:GetModule("MyModule")
|
||||
function GetModule(self, name, silent)
|
||||
if not self.modules[name] and not silent then
|
||||
error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
|
||||
end
|
||||
return self.modules[name]
|
||||
end
|
||||
|
||||
local function IsModuleTrue(self) return true end
|
||||
|
||||
--- Create a new module for the addon.
|
||||
-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
|
||||
-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
|
||||
-- an addon object.
|
||||
-- @name //addon//:NewModule
|
||||
-- @paramsig name[, prototype|lib[, lib, ...]]
|
||||
-- @param name unique name of the module
|
||||
-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
|
||||
-- @param lib List of libraries to embed into the addon
|
||||
-- @usage
|
||||
-- -- Create a module with some embeded libraries
|
||||
-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
|
||||
--
|
||||
-- -- Create a module with a prototype
|
||||
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
|
||||
-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
|
||||
function NewModule(self, name, prototype, ...)
|
||||
if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
|
||||
if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
|
||||
|
||||
if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
|
||||
|
||||
-- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
|
||||
-- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
|
||||
local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
|
||||
|
||||
module.IsModule = IsModuleTrue
|
||||
module:SetEnabledState(self.defaultModuleState)
|
||||
module.moduleName = name
|
||||
|
||||
if type(prototype) == "string" then
|
||||
AceAddon:EmbedLibraries(module, prototype, ...)
|
||||
else
|
||||
AceAddon:EmbedLibraries(module, ...)
|
||||
end
|
||||
AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
|
||||
|
||||
if not prototype or type(prototype) == "string" then
|
||||
prototype = self.defaultModulePrototype or nil
|
||||
end
|
||||
|
||||
if type(prototype) == "table" then
|
||||
local mt = getmetatable(module)
|
||||
mt.__index = prototype
|
||||
setmetatable(module, mt) -- More of a Base class type feel.
|
||||
end
|
||||
|
||||
safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
|
||||
self.modules[name] = module
|
||||
|
||||
return module
|
||||
end
|
||||
|
||||
--- Returns the real name of the addon or module, without any prefix.
|
||||
-- @name //addon//:GetName
|
||||
-- @paramsig
|
||||
-- @usage
|
||||
-- print(MyAddon:GetName())
|
||||
-- -- prints "MyAddon"
|
||||
function GetName(self)
|
||||
return self.moduleName or self.name
|
||||
end
|
||||
|
||||
--- Enables the Addon, if possible, return true or false depending on success.
|
||||
-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
|
||||
-- and enabling all modules of the addon (unless explicitly disabled).\\
|
||||
-- :Enable() also sets the internal `enableState` variable to true
|
||||
-- @name //addon//:Enable
|
||||
-- @paramsig
|
||||
-- @usage
|
||||
-- -- Enable MyModule
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- MyModule = MyAddon:GetModule("MyModule")
|
||||
-- MyModule:Enable()
|
||||
function Enable(self)
|
||||
self:SetEnabledState(true)
|
||||
return AceAddon:EnableAddon(self)
|
||||
end
|
||||
|
||||
--- Disables the Addon, if possible, return true or false depending on success.
|
||||
-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
|
||||
-- and disabling all modules of the addon.\\
|
||||
-- :Disable() also sets the internal `enableState` variable to false
|
||||
-- @name //addon//:Disable
|
||||
-- @paramsig
|
||||
-- @usage
|
||||
-- -- Disable MyAddon
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- MyAddon:Disable()
|
||||
function Disable(self)
|
||||
self:SetEnabledState(false)
|
||||
return AceAddon:DisableAddon(self)
|
||||
end
|
||||
|
||||
--- Enables the Module, if possible, return true or false depending on success.
|
||||
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
|
||||
-- @name //addon//:EnableModule
|
||||
-- @paramsig name
|
||||
-- @usage
|
||||
-- -- Enable MyModule using :GetModule
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- MyModule = MyAddon:GetModule("MyModule")
|
||||
-- MyModule:Enable()
|
||||
--
|
||||
-- -- Enable MyModule using the short-hand
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- MyAddon:EnableModule("MyModule")
|
||||
function EnableModule(self, name)
|
||||
local module = self:GetModule( name )
|
||||
return module:Enable()
|
||||
end
|
||||
|
||||
--- Disables the Module, if possible, return true or false depending on success.
|
||||
-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
|
||||
-- @name //addon//:DisableModule
|
||||
-- @paramsig name
|
||||
-- @usage
|
||||
-- -- Disable MyModule using :GetModule
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- MyModule = MyAddon:GetModule("MyModule")
|
||||
-- MyModule:Disable()
|
||||
--
|
||||
-- -- Disable MyModule using the short-hand
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
|
||||
-- MyAddon:DisableModule("MyModule")
|
||||
function DisableModule(self, name)
|
||||
local module = self:GetModule( name )
|
||||
return module:Disable()
|
||||
end
|
||||
|
||||
--- Set the default libraries to be mixed into all modules created by this object.
|
||||
-- Note that you can only change the default module libraries before any module is created.
|
||||
-- @name //addon//:SetDefaultModuleLibraries
|
||||
-- @paramsig lib[, lib, ...]
|
||||
-- @param lib List of libraries to embed into the addon
|
||||
-- @usage
|
||||
-- -- Create the addon object
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
|
||||
-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
|
||||
-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
|
||||
-- -- Create a module
|
||||
-- MyModule = MyAddon:NewModule("MyModule")
|
||||
function SetDefaultModuleLibraries(self, ...)
|
||||
if next(self.modules) then
|
||||
error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
|
||||
end
|
||||
self.defaultModuleLibraries = {...}
|
||||
end
|
||||
|
||||
--- Set the default state in which new modules are being created.
|
||||
-- Note that you can only change the default state before any module is created.
|
||||
-- @name //addon//:SetDefaultModuleState
|
||||
-- @paramsig state
|
||||
-- @param state Default state for new modules, true for enabled, false for disabled
|
||||
-- @usage
|
||||
-- -- Create the addon object
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
|
||||
-- -- Set the default state to "disabled"
|
||||
-- MyAddon:SetDefaultModuleState(false)
|
||||
-- -- Create a module and explicilty enable it
|
||||
-- MyModule = MyAddon:NewModule("MyModule")
|
||||
-- MyModule:Enable()
|
||||
function SetDefaultModuleState(self, state)
|
||||
if next(self.modules) then
|
||||
error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
|
||||
end
|
||||
self.defaultModuleState = state
|
||||
end
|
||||
|
||||
--- Set the default prototype to use for new modules on creation.
|
||||
-- Note that you can only change the default prototype before any module is created.
|
||||
-- @name //addon//:SetDefaultModulePrototype
|
||||
-- @paramsig prototype
|
||||
-- @param prototype Default prototype for the new modules (table)
|
||||
-- @usage
|
||||
-- -- Define a prototype
|
||||
-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
|
||||
-- -- Set the default prototype
|
||||
-- MyAddon:SetDefaultModulePrototype(prototype)
|
||||
-- -- Create a module and explicitly Enable it
|
||||
-- MyModule = MyAddon:NewModule("MyModule")
|
||||
-- MyModule:Enable()
|
||||
-- -- should print "OnEnable called!" now
|
||||
-- @see NewModule
|
||||
function SetDefaultModulePrototype(self, prototype)
|
||||
if next(self.modules) then
|
||||
error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
|
||||
end
|
||||
if type(prototype) ~= "table" then
|
||||
error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
|
||||
end
|
||||
self.defaultModulePrototype = prototype
|
||||
end
|
||||
|
||||
--- Set the state of an addon or module
|
||||
-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
|
||||
-- @name //addon//:SetEnabledState
|
||||
-- @paramsig state
|
||||
-- @param state the state of an addon or module (enabled=true, disabled=false)
|
||||
function SetEnabledState(self, state)
|
||||
self.enabledState = state
|
||||
end
|
||||
|
||||
|
||||
--- Return an iterator of all modules associated to the addon.
|
||||
-- @name //addon//:IterateModules
|
||||
-- @paramsig
|
||||
-- @usage
|
||||
-- -- Enable all modules
|
||||
-- for name, module in MyAddon:IterateModules() do
|
||||
-- module:Enable()
|
||||
-- end
|
||||
local function IterateModules(self) return pairs(self.modules) end
|
||||
|
||||
-- Returns an iterator of all embeds in the addon
|
||||
-- @name //addon//:IterateEmbeds
|
||||
-- @paramsig
|
||||
local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
|
||||
|
||||
--- Query the enabledState of an addon.
|
||||
-- @name //addon//:IsEnabled
|
||||
-- @paramsig
|
||||
-- @usage
|
||||
-- if MyAddon:IsEnabled() then
|
||||
-- MyAddon:Disable()
|
||||
-- end
|
||||
local function IsEnabled(self) return self.enabledState end
|
||||
local mixins = {
|
||||
NewModule = NewModule,
|
||||
GetModule = GetModule,
|
||||
Enable = Enable,
|
||||
Disable = Disable,
|
||||
EnableModule = EnableModule,
|
||||
DisableModule = DisableModule,
|
||||
IsEnabled = IsEnabled,
|
||||
SetDefaultModuleLibraries = SetDefaultModuleLibraries,
|
||||
SetDefaultModuleState = SetDefaultModuleState,
|
||||
SetDefaultModulePrototype = SetDefaultModulePrototype,
|
||||
SetEnabledState = SetEnabledState,
|
||||
IterateModules = IterateModules,
|
||||
IterateEmbeds = IterateEmbeds,
|
||||
GetName = GetName,
|
||||
}
|
||||
local function IsModule(self) return false end
|
||||
local pmixins = {
|
||||
defaultModuleState = true,
|
||||
enabledState = true,
|
||||
IsModule = IsModule,
|
||||
}
|
||||
-- Embed( target )
|
||||
-- target (object) - target object to embed aceaddon in
|
||||
--
|
||||
-- this is a local function specifically since it's meant to be only called internally
|
||||
function Embed(target)
|
||||
for k, v in pairs(mixins) do
|
||||
target[k] = v
|
||||
end
|
||||
for k, v in pairs(pmixins) do
|
||||
target[k] = target[k] or v
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- - Initialize the addon after creation.
|
||||
-- This function is only used internally during the ADDON_LOADED event
|
||||
-- It will call the **OnInitialize** function on the addon object (if present),
|
||||
-- and the **OnEmbedInitialize** function on all embeded libraries.
|
||||
--
|
||||
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
|
||||
-- @param addon addon object to intialize
|
||||
function AceAddon:InitializeAddon(addon)
|
||||
safecall(addon.OnInitialize, addon)
|
||||
|
||||
local embeds = self.embeds[addon]
|
||||
for i = 1, #embeds do
|
||||
local lib = LibStub:GetLibrary(embeds[i], true)
|
||||
if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
|
||||
end
|
||||
|
||||
-- we don't call InitializeAddon on modules specifically, this is handled
|
||||
-- from the event handler and only done _once_
|
||||
end
|
||||
|
||||
-- - Enable the addon after creation.
|
||||
-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
|
||||
-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
|
||||
-- It will call the **OnEnable** function on the addon object (if present),
|
||||
-- and the **OnEmbedEnable** function on all embeded libraries.\\
|
||||
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
|
||||
--
|
||||
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
|
||||
-- Use :Enable on the addon itself instead.
|
||||
-- @param addon addon object to enable
|
||||
function AceAddon:EnableAddon(addon)
|
||||
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
|
||||
if self.statuses[addon.name] or not addon.enabledState then return false end
|
||||
|
||||
-- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
|
||||
self.statuses[addon.name] = true
|
||||
|
||||
safecall(addon.OnEnable, addon)
|
||||
|
||||
-- make sure we're still enabled before continueing
|
||||
if self.statuses[addon.name] then
|
||||
local embeds = self.embeds[addon]
|
||||
for i = 1, #embeds do
|
||||
local lib = LibStub:GetLibrary(embeds[i], true)
|
||||
if lib then safecall(lib.OnEmbedEnable, lib, addon) end
|
||||
end
|
||||
|
||||
-- enable possible modules.
|
||||
for name, module in pairs(addon.modules) do
|
||||
self:EnableAddon(module)
|
||||
end
|
||||
end
|
||||
return self.statuses[addon.name] -- return true if we're disabled
|
||||
end
|
||||
|
||||
-- - Disable the addon
|
||||
-- Note: This function is only used internally.
|
||||
-- It will call the **OnDisable** function on the addon object (if present),
|
||||
-- and the **OnEmbedDisable** function on all embeded libraries.\\
|
||||
-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
|
||||
--
|
||||
-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
|
||||
-- Use :Disable on the addon itself instead.
|
||||
-- @param addon addon object to enable
|
||||
function AceAddon:DisableAddon(addon)
|
||||
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
|
||||
if not self.statuses[addon.name] then return false end
|
||||
|
||||
-- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
|
||||
self.statuses[addon.name] = false
|
||||
|
||||
safecall( addon.OnDisable, addon )
|
||||
|
||||
-- make sure we're still disabling...
|
||||
if not self.statuses[addon.name] then
|
||||
local embeds = self.embeds[addon]
|
||||
for i = 1, #embeds do
|
||||
local lib = LibStub:GetLibrary(embeds[i], true)
|
||||
if lib then safecall(lib.OnEmbedDisable, lib, addon) end
|
||||
end
|
||||
-- disable possible modules.
|
||||
for name, module in pairs(addon.modules) do
|
||||
self:DisableAddon(module)
|
||||
end
|
||||
end
|
||||
|
||||
return not self.statuses[addon.name] -- return true if we're disabled
|
||||
end
|
||||
|
||||
--- Get an iterator over all registered addons.
|
||||
-- @usage
|
||||
-- -- Print a list of all installed AceAddon's
|
||||
-- for name, addon in AceAddon:IterateAddons() do
|
||||
-- print("Addon: " .. name)
|
||||
-- end
|
||||
function AceAddon:IterateAddons() return pairs(self.addons) end
|
||||
|
||||
--- Get an iterator over the internal status registry.
|
||||
-- @usage
|
||||
-- -- Print a list of all enabled addons
|
||||
-- for name, status in AceAddon:IterateAddonStatus() do
|
||||
-- if status then
|
||||
-- print("EnabledAddon: " .. name)
|
||||
-- end
|
||||
-- end
|
||||
function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
|
||||
|
||||
-- Following Iterators are deprecated, and their addon specific versions should be used
|
||||
-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
|
||||
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
|
||||
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
|
||||
|
||||
-- Event Handling
|
||||
local function onEvent(this, event, arg1)
|
||||
if event == "ADDON_LOADED" or event == "PLAYER_LOGIN" then
|
||||
-- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
|
||||
while(#AceAddon.initializequeue > 0) do
|
||||
local addon = tremove(AceAddon.initializequeue, 1)
|
||||
-- this might be an issue with recursion - TODO: validate
|
||||
if event == "ADDON_LOADED" then addon.baseName = arg1 end
|
||||
AceAddon:InitializeAddon(addon)
|
||||
tinsert(AceAddon.enablequeue, addon)
|
||||
end
|
||||
|
||||
if IsLoggedIn() then
|
||||
while(#AceAddon.enablequeue > 0) do
|
||||
local addon = tremove(AceAddon.enablequeue, 1)
|
||||
AceAddon:EnableAddon(addon)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AceAddon.frame:RegisterEvent("ADDON_LOADED")
|
||||
AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
|
||||
AceAddon.frame:SetScript("OnEvent", onEvent)
|
||||
|
||||
-- upgrade embeded
|
||||
for name, addon in pairs(AceAddon.addons) do
|
||||
Embed(addon)
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceAddon-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,57 @@
|
||||
--- AceConfig-3.0 wrapper library.
|
||||
-- Provides an API to register an options table with the config registry,
|
||||
-- as well as associate it with a slash command.
|
||||
-- @class file
|
||||
-- @name AceConfig-3.0
|
||||
-- @release $Id: AceConfig-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
|
||||
|
||||
--[[
|
||||
AceConfig-3.0
|
||||
|
||||
Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
|
||||
|
||||
]]
|
||||
|
||||
local MAJOR, MINOR = "AceConfig-3.0", 2
|
||||
local AceConfig = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceConfig then return end
|
||||
|
||||
local cfgreg = LibStub("AceConfigRegistry-3.0")
|
||||
local cfgcmd = LibStub("AceConfigCmd-3.0")
|
||||
local cfgdlg = LibStub("AceConfigDialog-3.0")
|
||||
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local pcall, error, type, pairs = pcall, error, type, pairs
|
||||
|
||||
-- -------------------------------------------------------------------
|
||||
-- :RegisterOptionsTable(appName, options, slashcmd, persist)
|
||||
--
|
||||
-- - appName - (string) application name
|
||||
-- - options - table or function ref, see AceConfigRegistry
|
||||
-- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
|
||||
|
||||
--- Register a option table with the AceConfig registry.
|
||||
-- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly.
|
||||
-- @paramsig appName, options [, slashcmd]
|
||||
-- @param appName The application name for the config table.
|
||||
-- @param options The option table (or a function to generate one on demand)
|
||||
-- @param slashcmd A slash command to register for the option table, or a table of slash commands.
|
||||
-- @usage
|
||||
-- local AceConfig = LibStub("AceConfig-3.0")
|
||||
-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"})
|
||||
function AceConfig:RegisterOptionsTable(appName, options, slashcmd)
|
||||
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
|
||||
if not ok then error(msg, 2) end
|
||||
|
||||
if slashcmd then
|
||||
if type(slashcmd) == "table" then
|
||||
for _,cmd in pairs(slashcmd) do
|
||||
cfgcmd:CreateChatCommand(cmd, appName)
|
||||
end
|
||||
else
|
||||
cfgcmd:CreateChatCommand(slashcmd, appName)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/>
|
||||
<Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/>
|
||||
<Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/>
|
||||
<!--<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/>-->
|
||||
<Script file="AceConfig-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,787 @@
|
||||
--- AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames.
|
||||
-- @class file
|
||||
-- @name AceConfigCmd-3.0
|
||||
-- @release $Id: AceConfigCmd-3.0.lua 904 2009-12-13 11:56:37Z nevcairiel $
|
||||
|
||||
--[[
|
||||
AceConfigCmd-3.0
|
||||
|
||||
Handles commandline optionstable access
|
||||
|
||||
REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
|
||||
|
||||
]]
|
||||
|
||||
-- TODO: plugin args
|
||||
|
||||
|
||||
local MAJOR, MINOR = "AceConfigCmd-3.0", 12
|
||||
local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceConfigCmd then return end
|
||||
|
||||
AceConfigCmd.commands = AceConfigCmd.commands or {}
|
||||
local commands = AceConfigCmd.commands
|
||||
|
||||
local cfgreg = LibStub("AceConfigRegistry-3.0")
|
||||
local AceConsole -- LoD
|
||||
local AceConsoleName = "AceConsole-3.0"
|
||||
|
||||
-- Lua APIs
|
||||
local strsub, strsplit, strlower, strmatch, strtrim = string.sub, string.split, string.lower, string.match, string.trim
|
||||
local format, tonumber, tostring = string.format, tonumber, tostring
|
||||
local tsort, tinsert = table.sort, table.insert
|
||||
local select, pairs, next, type = select, pairs, next, type
|
||||
local error, assert = error, assert
|
||||
|
||||
-- WoW APIs
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: LibStub, SELECTED_CHAT_FRAME, DEFAULT_CHAT_FRAME
|
||||
|
||||
|
||||
local L = setmetatable({}, { -- TODO: replace with proper locale
|
||||
__index = function(self,k) return k end
|
||||
})
|
||||
|
||||
|
||||
|
||||
local function print(msg)
|
||||
(SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg)
|
||||
end
|
||||
|
||||
-- constants used by getparam() calls below
|
||||
|
||||
local handlertypes = {["table"]=true}
|
||||
local handlermsg = "expected a table"
|
||||
|
||||
local functypes = {["function"]=true, ["string"]=true}
|
||||
local funcmsg = "expected function or member name"
|
||||
|
||||
|
||||
-- pickfirstset() - picks the first non-nil value and returns it
|
||||
|
||||
local function pickfirstset(...)
|
||||
for i=1,select("#",...) do
|
||||
if select(i,...)~=nil then
|
||||
return select(i,...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- err() - produce real error() regarding malformed options tables etc
|
||||
|
||||
local function err(info,inputpos,msg )
|
||||
local cmdstr=" "..strsub(info.input, 1, inputpos-1)
|
||||
error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2)
|
||||
end
|
||||
|
||||
|
||||
-- usererr() - produce chatframe message regarding bad slash syntax etc
|
||||
|
||||
local function usererr(info,inputpos,msg )
|
||||
local cmdstr=strsub(info.input, 1, inputpos-1);
|
||||
print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table"))
|
||||
end
|
||||
|
||||
|
||||
-- callmethod() - call a given named method (e.g. "get", "set") with given arguments
|
||||
|
||||
local function callmethod(info, inputpos, tab, methodtype, ...)
|
||||
local method = info[methodtype]
|
||||
if not method then
|
||||
err(info, inputpos, "'"..methodtype.."': not set")
|
||||
end
|
||||
|
||||
info.arg = tab.arg
|
||||
info.option = tab
|
||||
info.type = tab.type
|
||||
|
||||
if type(method)=="function" then
|
||||
return method(info, ...)
|
||||
elseif type(method)=="string" then
|
||||
if type(info.handler[method])~="function" then
|
||||
err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
|
||||
end
|
||||
return info.handler[method](info.handler, info, ...)
|
||||
else
|
||||
assert(false) -- type should have already been checked on read
|
||||
end
|
||||
end
|
||||
|
||||
-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
|
||||
|
||||
local function callfunction(info, tab, methodtype, ...)
|
||||
local method = tab[methodtype]
|
||||
|
||||
info.arg = tab.arg
|
||||
info.option = tab
|
||||
info.type = tab.type
|
||||
|
||||
if type(method)=="function" then
|
||||
return method(info, ...)
|
||||
else
|
||||
assert(false) -- type should have already been checked on read
|
||||
end
|
||||
end
|
||||
|
||||
-- do_final() - do the final step (set/execute) along with validation and confirmation
|
||||
|
||||
local function do_final(info, inputpos, tab, methodtype, ...)
|
||||
if info.validate then
|
||||
local res = callmethod(info,inputpos,tab,"validate",...)
|
||||
if type(res)=="string" then
|
||||
usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
|
||||
return
|
||||
end
|
||||
end
|
||||
-- console ignores .confirm
|
||||
|
||||
callmethod(info,inputpos,tab,methodtype, ...)
|
||||
end
|
||||
|
||||
|
||||
-- getparam() - used by handle() to retreive and store "handler", "get", "set", etc
|
||||
|
||||
local function getparam(info, inputpos, tab, depth, paramname, types, errormsg)
|
||||
local old,oldat = info[paramname], info[paramname.."_at"]
|
||||
local val=tab[paramname]
|
||||
if val~=nil then
|
||||
if val==false then
|
||||
val=nil
|
||||
elseif not types[type(val)] then
|
||||
err(info, inputpos, "'" .. paramname.. "' - "..errormsg)
|
||||
end
|
||||
info[paramname] = val
|
||||
info[paramname.."_at"] = depth
|
||||
end
|
||||
return old,oldat
|
||||
end
|
||||
|
||||
|
||||
-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
|
||||
local dummytable={}
|
||||
|
||||
local function iterateargs(tab)
|
||||
if not tab.plugins then
|
||||
return pairs(tab.args)
|
||||
end
|
||||
|
||||
local argtabkey,argtab=next(tab.plugins)
|
||||
local v
|
||||
|
||||
return function(_, k)
|
||||
while argtab do
|
||||
k,v = next(argtab, k)
|
||||
if k then return k,v end
|
||||
if argtab==tab.args then
|
||||
argtab=nil
|
||||
else
|
||||
argtabkey,argtab = next(tab.plugins, argtabkey)
|
||||
if not argtabkey then
|
||||
argtab=tab.args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function checkhidden(info, inputpos, tab)
|
||||
if tab.cmdHidden~=nil then
|
||||
return tab.cmdHidden
|
||||
end
|
||||
local hidden = tab.hidden
|
||||
if type(hidden) == "function" or type(hidden) == "string" then
|
||||
info.hidden = hidden
|
||||
hidden = callmethod(info, inputpos, tab, 'hidden')
|
||||
info.hidden = nil
|
||||
end
|
||||
return hidden
|
||||
end
|
||||
|
||||
local function showhelp(info, inputpos, tab, depth, noHead)
|
||||
if not noHead then
|
||||
print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
|
||||
end
|
||||
|
||||
local sortTbl = {} -- [1..n]=name
|
||||
local refTbl = {} -- [name]=tableref
|
||||
|
||||
for k,v in iterateargs(tab) do
|
||||
if not refTbl[k] then -- a plugin overriding something in .args
|
||||
tinsert(sortTbl, k)
|
||||
refTbl[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
tsort(sortTbl, function(one, two)
|
||||
local o1 = refTbl[one].order or 100
|
||||
local o2 = refTbl[two].order or 100
|
||||
if type(o1) == "function" or type(o1) == "string" then
|
||||
info.order = o1
|
||||
info[#info+1] = one
|
||||
o1 = callmethod(info, inputpos, refTbl[one], "order")
|
||||
info[#info] = nil
|
||||
info.order = nil
|
||||
end
|
||||
if type(o2) == "function" or type(o1) == "string" then
|
||||
info.order = o2
|
||||
info[#info+1] = two
|
||||
o2 = callmethod(info, inputpos, refTbl[two], "order")
|
||||
info[#info] = nil
|
||||
info.order = nil
|
||||
end
|
||||
if o1<0 and o2<0 then return o1<o2 end
|
||||
if o2<0 then return true end
|
||||
if o1<0 then return false end
|
||||
if o1==o2 then return tostring(one)<tostring(two) end -- compare names
|
||||
return o1<o2
|
||||
end)
|
||||
|
||||
for i = 1, #sortTbl do
|
||||
local k = sortTbl[i]
|
||||
local v = refTbl[k]
|
||||
if not checkhidden(info, inputpos, v) then
|
||||
if v.type ~= "description" and v.type ~= "header" then
|
||||
-- recursively show all inline groups
|
||||
local name, desc = v.name, v.desc
|
||||
if type(name) == "function" then
|
||||
name = callfunction(info, v, 'name')
|
||||
end
|
||||
if type(desc) == "function" then
|
||||
desc = callfunction(info, v, 'desc')
|
||||
end
|
||||
if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then
|
||||
print(" "..(desc or name)..":")
|
||||
local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg)
|
||||
showhelp(info, inputpos, v, depth, true)
|
||||
info.handler,info.handler_at = oldhandler,oldhandler_at
|
||||
else
|
||||
local key = k:gsub(" ", "_")
|
||||
print(" |cffffff78"..key.."|r - "..(desc or name or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function keybindingValidateFunc(text)
|
||||
if text == nil or text == "NONE" then
|
||||
return nil
|
||||
end
|
||||
text = text:upper()
|
||||
local shift, ctrl, alt
|
||||
local modifier
|
||||
while true do
|
||||
if text == "-" then
|
||||
break
|
||||
end
|
||||
modifier, text = strsplit('-', text, 2)
|
||||
if text then
|
||||
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then
|
||||
return false
|
||||
end
|
||||
if modifier == "SHIFT" then
|
||||
if shift then
|
||||
return false
|
||||
end
|
||||
shift = true
|
||||
end
|
||||
if modifier == "CTRL" then
|
||||
if ctrl then
|
||||
return false
|
||||
end
|
||||
ctrl = true
|
||||
end
|
||||
if modifier == "ALT" then
|
||||
if alt then
|
||||
return false
|
||||
end
|
||||
alt = true
|
||||
end
|
||||
else
|
||||
text = modifier
|
||||
break
|
||||
end
|
||||
end
|
||||
if text == "" then
|
||||
return false
|
||||
end
|
||||
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then
|
||||
return false
|
||||
end
|
||||
local s = text
|
||||
if shift then
|
||||
s = "SHIFT-" .. s
|
||||
end
|
||||
if ctrl then
|
||||
s = "CTRL-" .. s
|
||||
end
|
||||
if alt then
|
||||
s = "ALT-" .. s
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
-- handle() - selfrecursing function that processes input->optiontable
|
||||
-- - depth - starts at 0
|
||||
-- - retfalse - return false rather than produce error if a match is not found (used by inlined groups)
|
||||
|
||||
local function handle(info, inputpos, tab, depth, retfalse)
|
||||
|
||||
if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Grab hold of handler,set,get,func,etc if set (and remember old ones)
|
||||
-- Note that we do NOT validate if method names are correct at this stage,
|
||||
-- the handler may change before they're actually used!
|
||||
|
||||
local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg)
|
||||
local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg)
|
||||
local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg)
|
||||
local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg)
|
||||
local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg)
|
||||
--local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg)
|
||||
|
||||
-------------------------------------------------------------------
|
||||
-- Act according to .type of this table
|
||||
|
||||
if tab.type=="group" then
|
||||
------------ group --------------------------------------------
|
||||
|
||||
if type(tab.args)~="table" then err(info, inputpos) end
|
||||
if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end
|
||||
|
||||
-- grab next arg from input
|
||||
local _,nextpos,arg = (info.input):find(" *([^ ]+) *", inputpos)
|
||||
if not arg then
|
||||
showhelp(info, inputpos, tab, depth)
|
||||
return
|
||||
end
|
||||
nextpos=nextpos+1
|
||||
|
||||
-- loop .args and try to find a key with a matching name
|
||||
for k,v in iterateargs(tab) do
|
||||
if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
|
||||
|
||||
-- is this child an inline group? if so, traverse into it
|
||||
if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then
|
||||
info[depth+1] = k
|
||||
if handle(info, inputpos, v, depth+1, true)==false then
|
||||
info[depth+1] = nil
|
||||
-- wasn't found in there, but that's ok, we just keep looking down here
|
||||
else
|
||||
return -- done, name was found in inline group
|
||||
end
|
||||
-- matching name and not a inline group
|
||||
elseif strlower(arg)==strlower(k:gsub(" ", "_")) then
|
||||
info[depth+1] = k
|
||||
return handle(info,nextpos,v,depth+1)
|
||||
end
|
||||
end
|
||||
|
||||
-- no match
|
||||
if retfalse then
|
||||
-- restore old infotable members and return false to indicate failure
|
||||
info.handler,info.handler_at = oldhandler,oldhandler_at
|
||||
info.set,info.set_at = oldset,oldset_at
|
||||
info.get,info.get_at = oldget,oldget_at
|
||||
info.func,info.func_at = oldfunc,oldfunc_at
|
||||
info.validate,info.validate_at = oldvalidate,oldvalidate_at
|
||||
--info.confirm,info.confirm_at = oldconfirm,oldconfirm_at
|
||||
return false
|
||||
end
|
||||
|
||||
-- couldn't find the command, display error
|
||||
usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"])
|
||||
return
|
||||
end
|
||||
|
||||
local str = strsub(info.input,inputpos);
|
||||
|
||||
if tab.type=="execute" then
|
||||
------------ execute --------------------------------------------
|
||||
do_final(info, inputpos, tab, "func")
|
||||
|
||||
|
||||
|
||||
elseif tab.type=="input" then
|
||||
------------ input --------------------------------------------
|
||||
|
||||
local res = true
|
||||
if tab.pattern then
|
||||
if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
|
||||
if not strmatch(str, tab.pattern) then
|
||||
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", str)
|
||||
|
||||
|
||||
|
||||
elseif tab.type=="toggle" then
|
||||
------------ toggle --------------------------------------------
|
||||
local b
|
||||
local str = strtrim(strlower(str))
|
||||
if str=="" then
|
||||
b = callmethod(info, inputpos, tab, "get")
|
||||
|
||||
if tab.tristate then
|
||||
--cycle in true, nil, false order
|
||||
if b then
|
||||
b = nil
|
||||
elseif b == nil then
|
||||
b = false
|
||||
else
|
||||
b = true
|
||||
end
|
||||
else
|
||||
b = not b
|
||||
end
|
||||
|
||||
elseif str==L["on"] then
|
||||
b = true
|
||||
elseif str==L["off"] then
|
||||
b = false
|
||||
elseif tab.tristate and str==L["default"] then
|
||||
b = nil
|
||||
else
|
||||
if tab.tristate then
|
||||
usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str))
|
||||
else
|
||||
usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str))
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", b)
|
||||
|
||||
|
||||
elseif tab.type=="range" then
|
||||
------------ range --------------------------------------------
|
||||
local val = tonumber(str)
|
||||
if not val then
|
||||
usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
|
||||
return
|
||||
end
|
||||
if type(info.step)=="number" then
|
||||
val = val- (val % info.step)
|
||||
end
|
||||
if type(info.min)=="number" and val<info.min then
|
||||
usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) )
|
||||
return
|
||||
end
|
||||
if type(info.max)=="number" and val>info.max then
|
||||
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) )
|
||||
return
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", val)
|
||||
|
||||
|
||||
elseif tab.type=="select" then
|
||||
------------ select ------------------------------------
|
||||
local str = strtrim(strlower(str))
|
||||
|
||||
local values = tab.values
|
||||
if type(values) == "function" or type(values) == "string" then
|
||||
info.values = values
|
||||
values = callmethod(info, inputpos, tab, "values")
|
||||
info.values = nil
|
||||
end
|
||||
|
||||
if str == "" then
|
||||
local b = callmethod(info, inputpos, tab, "get")
|
||||
local fmt = "|cffffff78- [%s]|r %s"
|
||||
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
|
||||
print(L["Options for |cffffff78"..info[#info].."|r:"])
|
||||
for k, v in pairs(values) do
|
||||
if b == k then
|
||||
print(fmt_sel:format(k, v))
|
||||
else
|
||||
print(fmt:format(k, v))
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local ok
|
||||
for k,v in pairs(values) do
|
||||
if strlower(k)==str then
|
||||
str = k -- overwrite with key (in case of case mismatches)
|
||||
ok = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not ok then
|
||||
usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
|
||||
return
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", str)
|
||||
|
||||
elseif tab.type=="multiselect" then
|
||||
------------ multiselect -------------------------------------------
|
||||
local str = strtrim(strlower(str))
|
||||
|
||||
local values = tab.values
|
||||
if type(values) == "function" or type(values) == "string" then
|
||||
info.values = values
|
||||
values = callmethod(info, inputpos, tab, "values")
|
||||
info.values = nil
|
||||
end
|
||||
|
||||
if str == "" then
|
||||
local fmt = "|cffffff78- [%s]|r %s"
|
||||
local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r"
|
||||
print(L["Options for |cffffff78"..info[#info].."|r (multiple possible):"])
|
||||
for k, v in pairs(values) do
|
||||
if callmethod(info, inputpos, tab, "get", k) then
|
||||
print(fmt_sel:format(k, v))
|
||||
else
|
||||
print(fmt:format(k, v))
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
--build a table of the selections, checking that they exist
|
||||
--parse for =on =off =default in the process
|
||||
--table will be key = true for options that should toggle, key = [on|off|default] for options to be set
|
||||
local sels = {}
|
||||
for v in str:gmatch("[^ ]+") do
|
||||
--parse option=on etc
|
||||
local opt, val = v:match('(.+)=(.+)')
|
||||
--get option if toggling
|
||||
if not opt then
|
||||
opt = v
|
||||
end
|
||||
|
||||
--check that the opt is valid
|
||||
local ok
|
||||
for k,v in pairs(values) do
|
||||
if strlower(k)==opt then
|
||||
opt = k -- overwrite with key (in case of case mismatches)
|
||||
ok = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not ok then
|
||||
usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
|
||||
return
|
||||
end
|
||||
|
||||
--check that if val was supplied it is valid
|
||||
if val then
|
||||
if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then
|
||||
--val is valid insert it
|
||||
sels[opt] = val
|
||||
else
|
||||
if tab.tristate then
|
||||
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val))
|
||||
else
|
||||
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
|
||||
end
|
||||
return
|
||||
end
|
||||
else
|
||||
-- no val supplied, toggle
|
||||
sels[opt] = true
|
||||
end
|
||||
end
|
||||
|
||||
for opt, val in pairs(sels) do
|
||||
local newval
|
||||
|
||||
if (val == true) then
|
||||
--toggle the option
|
||||
local b = callmethod(info, inputpos, tab, "get", opt)
|
||||
|
||||
if tab.tristate then
|
||||
--cycle in true, nil, false order
|
||||
if b then
|
||||
b = nil
|
||||
elseif b == nil then
|
||||
b = false
|
||||
else
|
||||
b = true
|
||||
end
|
||||
else
|
||||
b = not b
|
||||
end
|
||||
newval = b
|
||||
else
|
||||
--set the option as specified
|
||||
if val==L["on"] then
|
||||
newval = true
|
||||
elseif val==L["off"] then
|
||||
newval = false
|
||||
elseif val==L["default"] then
|
||||
newval = nil
|
||||
end
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", opt, newval)
|
||||
end
|
||||
|
||||
|
||||
elseif tab.type=="color" then
|
||||
------------ color --------------------------------------------
|
||||
local str = strtrim(strlower(str))
|
||||
if str == "" then
|
||||
--TODO: Show current value
|
||||
return
|
||||
end
|
||||
|
||||
local r, g, b, a
|
||||
|
||||
if tab.hasAlpha then
|
||||
if str:len() == 8 and str:find("^%x*$") then
|
||||
--parse a hex string
|
||||
r,g,b,a = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255, tonumber(str:sub(7, 8), 16) / 255
|
||||
else
|
||||
--parse seperate values
|
||||
r,g,b,a = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$")
|
||||
r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a)
|
||||
end
|
||||
if not (r and g and b and a) then
|
||||
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str))
|
||||
return
|
||||
end
|
||||
|
||||
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then
|
||||
--values are valid
|
||||
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then
|
||||
--values are valid 0..255, convert to 0..1
|
||||
r = r / 255
|
||||
g = g / 255
|
||||
b = b / 255
|
||||
a = a / 255
|
||||
else
|
||||
--values are invalid
|
||||
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str))
|
||||
end
|
||||
else
|
||||
a = 1.0
|
||||
if str:len() == 6 and str:find("^%x*$") then
|
||||
--parse a hex string
|
||||
r,g,b = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255
|
||||
else
|
||||
--parse seperate values
|
||||
r,g,b = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+)$")
|
||||
r,g,b = tonumber(r), tonumber(g), tonumber(b)
|
||||
end
|
||||
if not (r and g and b) then
|
||||
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str))
|
||||
return
|
||||
end
|
||||
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then
|
||||
--values are valid
|
||||
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
|
||||
--values are valid 0..255, convert to 0..1
|
||||
r = r / 255
|
||||
g = g / 255
|
||||
b = b / 255
|
||||
else
|
||||
--values are invalid
|
||||
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str))
|
||||
end
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", r,g,b,a)
|
||||
|
||||
elseif tab.type=="keybinding" then
|
||||
------------ keybinding --------------------------------------------
|
||||
local str = strtrim(strlower(str))
|
||||
if str == "" then
|
||||
--TODO: Show current value
|
||||
return
|
||||
end
|
||||
local value = keybindingValidateFunc(str:upper())
|
||||
if value == false then
|
||||
usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str))
|
||||
return
|
||||
end
|
||||
|
||||
do_final(info, inputpos, tab, "set", value)
|
||||
|
||||
elseif tab.type=="description" then
|
||||
------------ description --------------------
|
||||
-- ignore description, GUI config only
|
||||
else
|
||||
err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'")
|
||||
end
|
||||
end
|
||||
|
||||
--- Handle the chat command.
|
||||
-- This is usually called from a chat command handler to parse the command input as operations on an aceoptions table.\\
|
||||
-- AceConfigCmd uses this function internally when a slash command is registered with `:CreateChatCommand`
|
||||
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
|
||||
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
||||
-- @param input The commandline input (as given by the WoW handler, i.e. without the command itself)
|
||||
-- @usage
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0")
|
||||
-- -- Use AceConsole-3.0 to register a Chat Command
|
||||
-- MyAddon:RegisterChatCommand("mychat", "ChatCommand")
|
||||
--
|
||||
-- -- Show the GUI if no input is supplied, otherwise handle the chat input.
|
||||
-- function MyAddon:ChatCommand(input)
|
||||
-- -- Assuming "MyOptions" is the appName of a valid options table
|
||||
-- if not input or input:trim() == "" then
|
||||
-- LibStub("AceConfigDialog-3.0"):Open("MyOptions")
|
||||
-- else
|
||||
-- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input)
|
||||
-- end
|
||||
-- end
|
||||
function AceConfigCmd:HandleCommand(slashcmd, appName, input)
|
||||
|
||||
local optgetter = cfgreg:GetOptionsTable(appName)
|
||||
if not optgetter then
|
||||
error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2)
|
||||
end
|
||||
local options = assert( optgetter("cmd", MAJOR) )
|
||||
|
||||
local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
|
||||
[0] = slashcmd,
|
||||
appName = appName,
|
||||
options = options,
|
||||
input = input,
|
||||
self = self,
|
||||
handler = self,
|
||||
uiType = "cmd",
|
||||
uiName = MAJOR,
|
||||
}
|
||||
|
||||
handle(info, 1, options, 0) -- (info, inputpos, table, depth)
|
||||
end
|
||||
|
||||
--- Utility function to create a slash command handler.
|
||||
-- Also registers tab completion with AceTab
|
||||
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
|
||||
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
||||
function AceConfigCmd:CreateChatCommand(slashcmd, appName)
|
||||
if not AceConsole then
|
||||
AceConsole = LibStub(AceConsoleName)
|
||||
end
|
||||
if AceConsole.RegisterChatCommand(self, slashcmd, function(input)
|
||||
AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable
|
||||
end,
|
||||
true) then -- succesfully registered so lets get the command -> app table in
|
||||
commands[slashcmd] = appName
|
||||
end
|
||||
end
|
||||
|
||||
--- Utility function that returns the options table that belongs to a slashcommand.
|
||||
-- Designed to be used for the AceTab interface.
|
||||
-- @param slashcmd The slash command WITHOUT leading slash (only used for error output)
|
||||
-- @return The options table associated with the slash command (or nil if the slash command was not registered)
|
||||
function AceConfigCmd:GetChatCommandOptions(slashcmd)
|
||||
return commands[slashcmd]
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceConfigCmd-3.0.lua"/>
|
||||
</Ui>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceConfigDialog-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,346 @@
|
||||
--- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
|
||||
-- Options tables can be registered as raw tables, OR as function refs that return a table.\\
|
||||
-- Such functions receive three arguments: "uiType", "uiName", "appName". \\
|
||||
-- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
|
||||
-- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\
|
||||
-- * The **appName** field is the options table name as given at registration time \\
|
||||
--
|
||||
-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
|
||||
-- @class file
|
||||
-- @name AceConfigRegistry-3.0
|
||||
-- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $
|
||||
local MAJOR, MINOR = "AceConfigRegistry-3.0", 12
|
||||
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceConfigRegistry then return end
|
||||
|
||||
AceConfigRegistry.tables = AceConfigRegistry.tables or {}
|
||||
|
||||
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
|
||||
|
||||
if not AceConfigRegistry.callbacks then
|
||||
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
|
||||
end
|
||||
|
||||
-- Lua APIs
|
||||
local tinsert, tconcat = table.insert, table.concat
|
||||
local strfind, strmatch = string.find, string.match
|
||||
local type, tostring, select, pairs = type, tostring, select, pairs
|
||||
local error, assert = error, assert
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- Validating options table consistency:
|
||||
|
||||
|
||||
AceConfigRegistry.validated = {
|
||||
-- list of options table names ran through :ValidateOptionsTable automatically.
|
||||
-- CLEARED ON PURPOSE, since newer versions may have newer validators
|
||||
cmd = {},
|
||||
dropdown = {},
|
||||
dialog = {},
|
||||
}
|
||||
|
||||
|
||||
|
||||
local function err(msg, errlvl, ...)
|
||||
local t = {}
|
||||
for i=select("#",...),1,-1 do
|
||||
tinsert(t, (select(i, ...)))
|
||||
end
|
||||
error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
|
||||
end
|
||||
|
||||
|
||||
local isstring={["string"]=true, _="string"}
|
||||
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
|
||||
local istable={["table"]=true, _="table"}
|
||||
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
|
||||
local optstring={["nil"]=true,["string"]=true, _="string"}
|
||||
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
|
||||
local optnumber={["nil"]=true,["number"]=true, _="number"}
|
||||
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
|
||||
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
|
||||
local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
|
||||
local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
|
||||
local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
|
||||
local opttable={["nil"]=true,["table"]=true, _="table"}
|
||||
local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
|
||||
local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
|
||||
|
||||
local basekeys={
|
||||
type=isstring,
|
||||
name=isstringfunc,
|
||||
desc=optstringfunc,
|
||||
descStyle=optstring,
|
||||
order=optmethodnumber,
|
||||
validate=optmethodfalse,
|
||||
confirm=optmethodbool,
|
||||
confirmText=optstring,
|
||||
disabled=optmethodbool,
|
||||
hidden=optmethodbool,
|
||||
guiHidden=optmethodbool,
|
||||
dialogHidden=optmethodbool,
|
||||
dropdownHidden=optmethodbool,
|
||||
cmdHidden=optmethodbool,
|
||||
icon=optstringfunc,
|
||||
iconCoords=optmethodtable,
|
||||
handler=opttable,
|
||||
get=optmethodfalse,
|
||||
set=optmethodfalse,
|
||||
func=optmethodfalse,
|
||||
arg={["*"]=true},
|
||||
width=optstring,
|
||||
}
|
||||
|
||||
local typedkeys={
|
||||
header={},
|
||||
description={
|
||||
image=optstringfunc,
|
||||
imageCoords=optmethodtable,
|
||||
imageHeight=optnumber,
|
||||
imageWidth=optnumber,
|
||||
fontSize=optstringfunc,
|
||||
},
|
||||
group={
|
||||
args=istable,
|
||||
plugins=opttable,
|
||||
inline=optbool,
|
||||
cmdInline=optbool,
|
||||
guiInline=optbool,
|
||||
dropdownInline=optbool,
|
||||
dialogInline=optbool,
|
||||
childGroups=optstring,
|
||||
},
|
||||
execute={
|
||||
image=optstringfunc,
|
||||
imageCoords=optmethodtable,
|
||||
imageHeight=optnumber,
|
||||
imageWidth=optnumber,
|
||||
},
|
||||
input={
|
||||
pattern=optstring,
|
||||
usage=optstring,
|
||||
control=optstring,
|
||||
dialogControl=optstring,
|
||||
dropdownControl=optstring,
|
||||
multiline=optboolnumber,
|
||||
},
|
||||
toggle={
|
||||
tristate=optbool,
|
||||
image=optstringfunc,
|
||||
imageCoords=optmethodtable,
|
||||
},
|
||||
tristate={
|
||||
},
|
||||
range={
|
||||
min=optnumber,
|
||||
softMin=optnumber,
|
||||
max=optnumber,
|
||||
softMax=optnumber,
|
||||
step=optnumber,
|
||||
bigStep=optnumber,
|
||||
isPercent=optbool,
|
||||
},
|
||||
select={
|
||||
values=ismethodtable,
|
||||
style={
|
||||
["nil"]=true,
|
||||
["string"]={dropdown=true,radio=true},
|
||||
_="string: 'dropdown' or 'radio'"
|
||||
},
|
||||
control=optstring,
|
||||
dialogControl=optstring,
|
||||
dropdownControl=optstring,
|
||||
},
|
||||
multiselect={
|
||||
values=ismethodtable,
|
||||
style=optstring,
|
||||
tristate=optbool,
|
||||
control=optstring,
|
||||
dialogControl=optstring,
|
||||
dropdownControl=optstring,
|
||||
},
|
||||
color={
|
||||
hasAlpha=optbool,
|
||||
},
|
||||
keybinding={
|
||||
-- TODO
|
||||
},
|
||||
}
|
||||
|
||||
local function validateKey(k,errlvl,...)
|
||||
errlvl=(errlvl or 0)+1
|
||||
if type(k)~="string" then
|
||||
err("["..tostring(k).."] - key is not a string", errlvl,...)
|
||||
end
|
||||
if strfind(k, "[%c\127]") then
|
||||
err("["..tostring(k).."] - key name contained control characters", errlvl,...)
|
||||
end
|
||||
end
|
||||
|
||||
local function validateVal(v, oktypes, errlvl,...)
|
||||
errlvl=(errlvl or 0)+1
|
||||
local isok=oktypes[type(v)] or oktypes["*"]
|
||||
|
||||
if not isok then
|
||||
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
|
||||
end
|
||||
if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
|
||||
if not isok[v] then
|
||||
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function validate(options,errlvl,...)
|
||||
errlvl=(errlvl or 0)+1
|
||||
-- basic consistency
|
||||
if type(options)~="table" then
|
||||
err(": expected a table, got a "..type(options), errlvl,...)
|
||||
end
|
||||
if type(options.type)~="string" then
|
||||
err(".type: expected a string, got a "..type(options.type), errlvl,...)
|
||||
end
|
||||
|
||||
-- get type and 'typedkeys' member
|
||||
local tk = typedkeys[options.type]
|
||||
if not tk then
|
||||
err(".type: unknown type '"..options.type.."'", errlvl,...)
|
||||
end
|
||||
|
||||
-- make sure that all options[] are known parameters
|
||||
for k,v in pairs(options) do
|
||||
if not (tk[k] or basekeys[k]) then
|
||||
err(": unknown parameter", errlvl,tostring(k),...)
|
||||
end
|
||||
end
|
||||
|
||||
-- verify that required params are there, and that everything is the right type
|
||||
for k,oktypes in pairs(basekeys) do
|
||||
validateVal(options[k], oktypes, errlvl,k,...)
|
||||
end
|
||||
for k,oktypes in pairs(tk) do
|
||||
validateVal(options[k], oktypes, errlvl,k,...)
|
||||
end
|
||||
|
||||
-- extra logic for groups
|
||||
if options.type=="group" then
|
||||
for k,v in pairs(options.args) do
|
||||
validateKey(k,errlvl,"args",...)
|
||||
validate(v, errlvl,k,"args",...)
|
||||
end
|
||||
if options.plugins then
|
||||
for plugname,plugin in pairs(options.plugins) do
|
||||
if type(plugin)~="table" then
|
||||
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
|
||||
end
|
||||
for k,v in pairs(plugin) do
|
||||
validateKey(k,errlvl,tostring(plugname),"plugins",...)
|
||||
validate(v, errlvl,k,tostring(plugname),"plugins",...)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Validates basic structure and integrity of an options table \\
|
||||
-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
|
||||
-- @param options The table to be validated
|
||||
-- @param name The name of the table to be validated (shown in any error message)
|
||||
-- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
|
||||
function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
|
||||
errlvl=(errlvl or 0)+1
|
||||
name = name or "Optionstable"
|
||||
if not options.name then
|
||||
options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
|
||||
end
|
||||
validate(options,errlvl,name)
|
||||
end
|
||||
|
||||
--- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
|
||||
-- You should call this function if your options table changed from any outside event, like a game event
|
||||
-- or a timer.
|
||||
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
||||
function AceConfigRegistry:NotifyChange(appName)
|
||||
if not AceConfigRegistry.tables[appName] then return end
|
||||
AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
|
||||
end
|
||||
|
||||
-- -------------------------------------------------------------------
|
||||
-- Registering and retreiving options tables:
|
||||
|
||||
|
||||
-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
|
||||
|
||||
local function validateGetterArgs(uiType, uiName, errlvl)
|
||||
errlvl=(errlvl or 0)+2
|
||||
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
|
||||
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
|
||||
end
|
||||
if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
|
||||
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
|
||||
end
|
||||
end
|
||||
|
||||
--- Register an options table with the config registry.
|
||||
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
||||
-- @param options The options table, OR a function reference that generates it on demand. \\
|
||||
-- See the top of the page for info on arguments passed to such functions.
|
||||
function AceConfigRegistry:RegisterOptionsTable(appName, options)
|
||||
if type(options)=="table" then
|
||||
if options.type~="group" then -- quick sanity checker
|
||||
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
|
||||
end
|
||||
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
|
||||
errlvl=(errlvl or 0)+1
|
||||
validateGetterArgs(uiType, uiName, errlvl)
|
||||
if not AceConfigRegistry.validated[uiType][appName] then
|
||||
AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
|
||||
AceConfigRegistry.validated[uiType][appName] = true
|
||||
end
|
||||
return options
|
||||
end
|
||||
elseif type(options)=="function" then
|
||||
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
|
||||
errlvl=(errlvl or 0)+1
|
||||
validateGetterArgs(uiType, uiName, errlvl)
|
||||
local tab = assert(options(uiType, uiName, appName))
|
||||
if not AceConfigRegistry.validated[uiType][appName] then
|
||||
AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
|
||||
AceConfigRegistry.validated[uiType][appName] = true
|
||||
end
|
||||
return tab
|
||||
end
|
||||
else
|
||||
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns an iterator of ["appName"]=funcref pairs
|
||||
function AceConfigRegistry:IterateOptionsTables()
|
||||
return pairs(AceConfigRegistry.tables)
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- Query the registry for a specific options table.
|
||||
-- If only appName is given, a function is returned which you
|
||||
-- can call with (uiType,uiName) to get the table.\\
|
||||
-- If uiType&uiName are given, the table is returned.
|
||||
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
||||
-- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
|
||||
-- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
|
||||
function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
|
||||
local f = AceConfigRegistry.tables[appName]
|
||||
if not f then
|
||||
return nil
|
||||
end
|
||||
|
||||
if uiType then
|
||||
return f(uiType,uiName,1) -- get the table for us
|
||||
else
|
||||
return f -- return the function
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceConfigRegistry-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,250 @@
|
||||
--- **AceConsole-3.0** provides registration facilities for slash commands.
|
||||
-- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
|
||||
-- to your addons individual needs.
|
||||
--
|
||||
-- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
|
||||
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
|
||||
-- and can be accessed directly, without having to explicitly call AceConsole itself.\\
|
||||
-- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
|
||||
-- make into AceConsole.
|
||||
-- @class file
|
||||
-- @name AceConsole-3.0
|
||||
-- @release $Id: AceConsole-3.0.lua 878 2009-11-02 18:51:58Z nevcairiel $
|
||||
local MAJOR,MINOR = "AceConsole-3.0", 7
|
||||
|
||||
local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceConsole then return end -- No upgrade needed
|
||||
|
||||
AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
|
||||
AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
|
||||
AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
|
||||
|
||||
-- Lua APIs
|
||||
local tconcat, tostring, select = table.concat, tostring, select
|
||||
local type, pairs, error = type, pairs, error
|
||||
local format, strfind, strsub = string.format, string.find, string.sub
|
||||
local max = math.max
|
||||
|
||||
-- WoW APIs
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
|
||||
|
||||
local tmp={}
|
||||
local function Print(self,frame,...)
|
||||
local n=0
|
||||
if self ~= AceConsole then
|
||||
n=n+1
|
||||
tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
|
||||
end
|
||||
for i=1, select("#", ...) do
|
||||
n=n+1
|
||||
tmp[n] = tostring(select(i, ...))
|
||||
end
|
||||
frame:AddMessage( tconcat(tmp," ",1,n) )
|
||||
end
|
||||
|
||||
--- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
|
||||
-- @paramsig [chatframe ,] ...
|
||||
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
|
||||
-- @param ... List of any values to be printed
|
||||
function AceConsole:Print(...)
|
||||
local frame = ...
|
||||
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
|
||||
return Print(self, frame, select(2,...))
|
||||
else
|
||||
return Print(self, DEFAULT_CHAT_FRAME, ...)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
|
||||
-- @paramsig [chatframe ,] "format"[, ...]
|
||||
-- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
|
||||
-- @param format Format string - same syntax as standard Lua format()
|
||||
-- @param ... Arguments to the format string
|
||||
function AceConsole:Printf(...)
|
||||
local frame = ...
|
||||
if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
|
||||
return Print(self, frame, format(select(2,...)))
|
||||
else
|
||||
return Print(self, DEFAULT_CHAT_FRAME, format(...))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- Register a simple chat command
|
||||
-- @param command Chat command to be registered WITHOUT leading "/"
|
||||
-- @param func Function to call when the slash command is being used (funcref or methodname)
|
||||
-- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
|
||||
function AceConsole:RegisterChatCommand( command, func, persist )
|
||||
if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
|
||||
|
||||
if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
|
||||
|
||||
local name = "ACECONSOLE_"..command:upper()
|
||||
|
||||
if type( func ) == "string" then
|
||||
SlashCmdList[name] = function(input, editBox)
|
||||
self[func](self, input, editBox)
|
||||
end
|
||||
else
|
||||
SlashCmdList[name] = func
|
||||
end
|
||||
_G["SLASH_"..name.."1"] = "/"..command:lower()
|
||||
AceConsole.commands[command] = name
|
||||
-- non-persisting commands are registered for enabling disabling
|
||||
if not persist then
|
||||
if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
|
||||
AceConsole.weakcommands[self][command] = func
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Unregister a chatcommand
|
||||
-- @param command Chat command to be unregistered WITHOUT leading "/"
|
||||
function AceConsole:UnregisterChatCommand( command )
|
||||
local name = AceConsole.commands[command]
|
||||
if name then
|
||||
SlashCmdList[name] = nil
|
||||
_G["SLASH_" .. name .. "1"] = nil
|
||||
hash_SlashCmdList["/" .. command:upper()] = nil
|
||||
AceConsole.commands[command] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- Get an iterator over all Chat Commands registered with AceConsole
|
||||
-- @return Iterator (pairs) over all commands
|
||||
function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
|
||||
|
||||
|
||||
local function nils(n, ...)
|
||||
if n>1 then
|
||||
return nil, nils(n-1, ...)
|
||||
elseif n==1 then
|
||||
return nil, ...
|
||||
else
|
||||
return ...
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Retreive one or more space-separated arguments from a string.
|
||||
-- Treats quoted strings and itemlinks as non-spaced.
|
||||
-- @param string The raw argument string
|
||||
-- @param numargs How many arguments to get (default 1)
|
||||
-- @param startpos Where in the string to start scanning (default 1)
|
||||
-- @return Returns arg1, arg2, ..., nextposition\\
|
||||
-- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
|
||||
function AceConsole:GetArgs(str, numargs, startpos)
|
||||
numargs = numargs or 1
|
||||
startpos = max(startpos or 1, 1)
|
||||
|
||||
local pos=startpos
|
||||
|
||||
-- find start of new arg
|
||||
pos = strfind(str, "[^ ]", pos)
|
||||
if not pos then -- whoops, end of string
|
||||
return nils(numargs, 1e9)
|
||||
end
|
||||
|
||||
if numargs<1 then
|
||||
return pos
|
||||
end
|
||||
|
||||
-- quoted or space separated? find out which pattern to use
|
||||
local delim_or_pipe
|
||||
local ch = strsub(str, pos, pos)
|
||||
if ch=='"' then
|
||||
pos = pos + 1
|
||||
delim_or_pipe='([|"])'
|
||||
elseif ch=="'" then
|
||||
pos = pos + 1
|
||||
delim_or_pipe="([|'])"
|
||||
else
|
||||
delim_or_pipe="([| ])"
|
||||
end
|
||||
|
||||
startpos = pos
|
||||
|
||||
while true do
|
||||
-- find delimiter or hyperlink
|
||||
local ch,_
|
||||
pos,_,ch = strfind(str, delim_or_pipe, pos)
|
||||
|
||||
if not pos then break end
|
||||
|
||||
if ch=="|" then
|
||||
-- some kind of escape
|
||||
|
||||
if strsub(str,pos,pos+1)=="|H" then
|
||||
-- It's a |H....|hhyper link!|h
|
||||
pos=strfind(str, "|h", pos+2) -- first |h
|
||||
if not pos then break end
|
||||
|
||||
pos=strfind(str, "|h", pos+2) -- second |h
|
||||
if not pos then break end
|
||||
elseif strsub(str,pos, pos+1) == "|T" then
|
||||
-- It's a |T....|t texture
|
||||
pos=strfind(str, "|t", pos+2)
|
||||
if not pos then break end
|
||||
end
|
||||
|
||||
pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
|
||||
|
||||
else
|
||||
-- found delimiter, done with this arg
|
||||
return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
|
||||
return strsub(str, startpos), nils(numargs-1, 1e9)
|
||||
end
|
||||
|
||||
|
||||
--- embedding and embed handling
|
||||
|
||||
local mixins = {
|
||||
"Print",
|
||||
"Printf",
|
||||
"RegisterChatCommand",
|
||||
"UnregisterChatCommand",
|
||||
"GetArgs",
|
||||
}
|
||||
|
||||
-- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
|
||||
-- @param target target object to embed AceBucket in
|
||||
function AceConsole:Embed( target )
|
||||
for k, v in pairs( mixins ) do
|
||||
target[v] = self[v]
|
||||
end
|
||||
self.embeds[target] = true
|
||||
return target
|
||||
end
|
||||
|
||||
function AceConsole:OnEmbedEnable( target )
|
||||
if AceConsole.weakcommands[target] then
|
||||
for command, func in pairs( AceConsole.weakcommands[target] ) do
|
||||
target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceConsole:OnEmbedDisable( target )
|
||||
if AceConsole.weakcommands[target] then
|
||||
for command, func in pairs( AceConsole.weakcommands[target] ) do
|
||||
target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for addon in pairs(AceConsole.embeds) do
|
||||
AceConsole:Embed(addon)
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceConsole-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,728 @@
|
||||
--- **AceDB-3.0** manages the SavedVariables of your addon.
|
||||
-- It offers profile management, smart defaults and namespaces for modules.\\
|
||||
-- Data can be saved in different data-types, depending on its intended usage.
|
||||
-- The most common data-type is the `profile` type, which allows the user to choose
|
||||
-- the active profile, and manage the profiles of all of his characters.\\
|
||||
-- The following data types are available:
|
||||
-- * **char** Character-specific data. Every character has its own database.
|
||||
-- * **realm** Realm-specific data. All of the players characters on the same realm share this database.
|
||||
-- * **class** Class-specific data. All of the players characters of the same class share this database.
|
||||
-- * **race** Race-specific data. All of the players characters of the same race share this database.
|
||||
-- * **faction** Faction-specific data. All of the players characters of the same faction share this database.
|
||||
-- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database.
|
||||
-- * **global** Global Data. All characters on the same account share this database.
|
||||
-- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used.
|
||||
--
|
||||
-- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions
|
||||
-- of the DBObjectLib listed here. \\
|
||||
-- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note
|
||||
-- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that,
|
||||
-- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases.
|
||||
--
|
||||
-- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]].
|
||||
--
|
||||
-- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs.
|
||||
--
|
||||
-- @usage
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample")
|
||||
--
|
||||
-- -- declare defaults to be used in the DB
|
||||
-- local defaults = {
|
||||
-- profile = {
|
||||
-- setting = true,
|
||||
-- }
|
||||
-- }
|
||||
--
|
||||
-- function MyAddon:OnInitialize()
|
||||
-- -- Assuming the .toc says ## SavedVariables: MyAddonDB
|
||||
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
|
||||
-- end
|
||||
-- @class file
|
||||
-- @name AceDB-3.0.lua
|
||||
-- @release $Id: AceDB-3.0.lua 914 2010-03-08 12:09:22Z nevcairiel $
|
||||
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 20
|
||||
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
|
||||
|
||||
if not AceDB then return end -- No upgrade needed
|
||||
|
||||
-- Lua APIs
|
||||
local type, pairs, next, error = type, pairs, next, error
|
||||
local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
|
||||
|
||||
-- WoW APIs
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: LibStub
|
||||
|
||||
AceDB.db_registry = AceDB.db_registry or {}
|
||||
AceDB.frame = AceDB.frame or CreateFrame("Frame")
|
||||
|
||||
local CallbackHandler
|
||||
local CallbackDummy = { Fire = function() end }
|
||||
|
||||
local DBObjectLib = {}
|
||||
|
||||
--[[-------------------------------------------------------------------------
|
||||
AceDB Utility Functions
|
||||
---------------------------------------------------------------------------]]
|
||||
|
||||
-- Simple shallow copy for copying defaults
|
||||
local function copyTable(src, dest)
|
||||
if type(dest) ~= "table" then dest = {} end
|
||||
if type(src) == "table" then
|
||||
for k,v in pairs(src) do
|
||||
if type(v) == "table" then
|
||||
-- try to index the key first so that the metatable creates the defaults, if set, and use that table
|
||||
v = copyTable(v, dest[k])
|
||||
end
|
||||
dest[k] = v
|
||||
end
|
||||
end
|
||||
return dest
|
||||
end
|
||||
|
||||
-- Called to add defaults to a section of the database
|
||||
--
|
||||
-- When a ["*"] default section is indexed with a new key, a table is returned
|
||||
-- and set in the host table. These tables must be cleaned up by removeDefaults
|
||||
-- in order to ensure we don't write empty default tables.
|
||||
local function copyDefaults(dest, src)
|
||||
-- this happens if some value in the SV overwrites our default value with a non-table
|
||||
--if type(dest) ~= "table" then return end
|
||||
for k, v in pairs(src) do
|
||||
if k == "*" or k == "**" then
|
||||
if type(v) == "table" then
|
||||
-- This is a metatable used for table defaults
|
||||
local mt = {
|
||||
-- This handles the lookup and creation of new subtables
|
||||
__index = function(t,k)
|
||||
if k == nil then return nil end
|
||||
local tbl = {}
|
||||
copyDefaults(tbl, v)
|
||||
rawset(t, k, tbl)
|
||||
return tbl
|
||||
end,
|
||||
}
|
||||
setmetatable(dest, mt)
|
||||
-- handle already existing tables in the SV
|
||||
for dk, dv in pairs(dest) do
|
||||
if not rawget(src, dk) and type(dv) == "table" then
|
||||
copyDefaults(dv, v)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Values are not tables, so this is just a simple return
|
||||
local mt = {__index = function(t,k) return k~=nil and v or nil end}
|
||||
setmetatable(dest, mt)
|
||||
end
|
||||
elseif type(v) == "table" then
|
||||
if not rawget(dest, k) then rawset(dest, k, {}) end
|
||||
if type(dest[k]) == "table" then
|
||||
copyDefaults(dest[k], v)
|
||||
if src['**'] then
|
||||
copyDefaults(dest[k], src['**'])
|
||||
end
|
||||
end
|
||||
else
|
||||
if rawget(dest, k) == nil then
|
||||
rawset(dest, k, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Called to remove all defaults in the default table from the database
|
||||
local function removeDefaults(db, defaults, blocker)
|
||||
-- remove all metatables from the db, so we don't accidentally create new sub-tables through them
|
||||
setmetatable(db, nil)
|
||||
-- loop through the defaults and remove their content
|
||||
for k,v in pairs(defaults) do
|
||||
if k == "*" or k == "**" then
|
||||
if type(v) == "table" then
|
||||
-- Loop through all the actual k,v pairs and remove
|
||||
for key, value in pairs(db) do
|
||||
if type(value) == "table" then
|
||||
-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
|
||||
if defaults[key] == nil and (not blocker or blocker[key] == nil) then
|
||||
removeDefaults(value, v)
|
||||
-- if the table is empty afterwards, remove it
|
||||
if next(value) == nil then
|
||||
db[key] = nil
|
||||
end
|
||||
-- if it was specified, only strip ** content, but block values which were set in the key table
|
||||
elseif k == "**" then
|
||||
removeDefaults(value, v, defaults[key])
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif k == "*" then
|
||||
-- check for non-table default
|
||||
for key, value in pairs(db) do
|
||||
if defaults[key] == nil and v == value then
|
||||
db[key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif type(v) == "table" and type(db[k]) == "table" then
|
||||
-- if a blocker was set, dive into it, to allow multi-level defaults
|
||||
removeDefaults(db[k], v, blocker and blocker[k])
|
||||
if next(db[k]) == nil then
|
||||
db[k] = nil
|
||||
end
|
||||
else
|
||||
-- check if the current value matches the default, and that its not blocked by another defaults table
|
||||
if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
|
||||
db[k] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This is called when a table section is first accessed, to set up the defaults
|
||||
local function initSection(db, section, svstore, key, defaults)
|
||||
local sv = rawget(db, "sv")
|
||||
|
||||
local tableCreated
|
||||
if not sv[svstore] then sv[svstore] = {} end
|
||||
if not sv[svstore][key] then
|
||||
sv[svstore][key] = {}
|
||||
tableCreated = true
|
||||
end
|
||||
|
||||
local tbl = sv[svstore][key]
|
||||
|
||||
if defaults then
|
||||
copyDefaults(tbl, defaults)
|
||||
end
|
||||
rawset(db, section, tbl)
|
||||
|
||||
return tableCreated, tbl
|
||||
end
|
||||
|
||||
-- Metatable to handle the dynamic creation of sections and copying of sections.
|
||||
local dbmt = {
|
||||
__index = function(t, section)
|
||||
local keys = rawget(t, "keys")
|
||||
local key = keys[section]
|
||||
if key then
|
||||
local defaultTbl = rawget(t, "defaults")
|
||||
local defaults = defaultTbl and defaultTbl[section]
|
||||
|
||||
if section == "profile" then
|
||||
local new = initSection(t, section, "profiles", key, defaults)
|
||||
if new then
|
||||
-- Callback: OnNewProfile, database, newProfileKey
|
||||
t.callbacks:Fire("OnNewProfile", t, key)
|
||||
end
|
||||
elseif section == "profiles" then
|
||||
local sv = rawget(t, "sv")
|
||||
if not sv.profiles then sv.profiles = {} end
|
||||
rawset(t, "profiles", sv.profiles)
|
||||
elseif section == "global" then
|
||||
local sv = rawget(t, "sv")
|
||||
if not sv.global then sv.global = {} end
|
||||
if defaults then
|
||||
copyDefaults(sv.global, defaults)
|
||||
end
|
||||
rawset(t, section, sv.global)
|
||||
else
|
||||
initSection(t, section, section, key, defaults)
|
||||
end
|
||||
end
|
||||
|
||||
return rawget(t, section)
|
||||
end
|
||||
}
|
||||
|
||||
local function validateDefaults(defaults, keyTbl, offset)
|
||||
if not defaults then return end
|
||||
offset = offset or 0
|
||||
for k in pairs(defaults) do
|
||||
if not keyTbl[k] or k == "profiles" then
|
||||
error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local preserve_keys = {
|
||||
["callbacks"] = true,
|
||||
["RegisterCallback"] = true,
|
||||
["UnregisterCallback"] = true,
|
||||
["UnregisterAllCallbacks"] = true,
|
||||
["children"] = true,
|
||||
}
|
||||
|
||||
local realmKey = GetRealmName()
|
||||
local charKey = UnitName("player") .. " - " .. realmKey
|
||||
local _, classKey = UnitClass("player")
|
||||
local _, raceKey = UnitRace("player")
|
||||
local factionKey = UnitFactionGroup("player")
|
||||
local factionrealmKey = factionKey .. " - " .. realmKey
|
||||
-- Actual database initialization function
|
||||
local function initdb(sv, defaults, defaultProfile, olddb, parent)
|
||||
-- Generate the database keys for each section
|
||||
|
||||
-- map "true" to our "Default" profile
|
||||
if defaultProfile == true then defaultProfile = "Default" end
|
||||
|
||||
local profileKey
|
||||
if not parent then
|
||||
-- Make a container for profile keys
|
||||
if not sv.profileKeys then sv.profileKeys = {} end
|
||||
|
||||
-- Try to get the profile selected from the char db
|
||||
profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
|
||||
|
||||
-- save the selected profile for later
|
||||
sv.profileKeys[charKey] = profileKey
|
||||
else
|
||||
-- Use the profile of the parents DB
|
||||
profileKey = parent.keys.profile or defaultProfile or charKey
|
||||
|
||||
-- clear the profileKeys in the DB, namespaces don't need to store them
|
||||
sv.profileKeys = nil
|
||||
end
|
||||
|
||||
-- This table contains keys that enable the dynamic creation
|
||||
-- of each section of the table. The 'global' and 'profiles'
|
||||
-- have a key of true, since they are handled in a special case
|
||||
local keyTbl= {
|
||||
["char"] = charKey,
|
||||
["realm"] = realmKey,
|
||||
["class"] = classKey,
|
||||
["race"] = raceKey,
|
||||
["faction"] = factionKey,
|
||||
["factionrealm"] = factionrealmKey,
|
||||
["profile"] = profileKey,
|
||||
["global"] = true,
|
||||
["profiles"] = true,
|
||||
}
|
||||
|
||||
validateDefaults(defaults, keyTbl, 1)
|
||||
|
||||
-- This allows us to use this function to reset an entire database
|
||||
-- Clear out the old database
|
||||
if olddb then
|
||||
for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
|
||||
end
|
||||
|
||||
-- Give this database the metatable so it initializes dynamically
|
||||
local db = setmetatable(olddb or {}, dbmt)
|
||||
|
||||
if not rawget(db, "callbacks") then
|
||||
-- try to load CallbackHandler-1.0 if it loaded after our library
|
||||
if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
|
||||
db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
|
||||
end
|
||||
|
||||
-- Copy methods locally into the database object, to avoid hitting
|
||||
-- the metatable when calling methods
|
||||
|
||||
if not parent then
|
||||
for name, func in pairs(DBObjectLib) do
|
||||
db[name] = func
|
||||
end
|
||||
else
|
||||
-- hack this one in
|
||||
db.RegisterDefaults = DBObjectLib.RegisterDefaults
|
||||
db.ResetProfile = DBObjectLib.ResetProfile
|
||||
end
|
||||
|
||||
-- Set some properties in the database object
|
||||
db.profiles = sv.profiles
|
||||
db.keys = keyTbl
|
||||
db.sv = sv
|
||||
--db.sv_name = name
|
||||
db.defaults = defaults
|
||||
db.parent = parent
|
||||
|
||||
-- store the DB in the registry
|
||||
AceDB.db_registry[db] = true
|
||||
|
||||
return db
|
||||
end
|
||||
|
||||
-- handle PLAYER_LOGOUT
|
||||
-- strip all defaults from all databases
|
||||
-- and cleans up empty sections
|
||||
local function logoutHandler(frame, event)
|
||||
if event == "PLAYER_LOGOUT" then
|
||||
for db in pairs(AceDB.db_registry) do
|
||||
db.callbacks:Fire("OnDatabaseShutdown", db)
|
||||
db:RegisterDefaults(nil)
|
||||
|
||||
-- cleanup sections that are empty without defaults
|
||||
local sv = rawget(db, "sv")
|
||||
for section in pairs(db.keys) do
|
||||
if rawget(sv, section) then
|
||||
-- global is special, all other sections have sub-entrys
|
||||
-- also don't delete empty profiles on main dbs, only on namespaces
|
||||
if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then
|
||||
for key in pairs(sv[section]) do
|
||||
if not next(sv[section][key]) then
|
||||
sv[section][key] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if not next(sv[section]) then
|
||||
sv[section] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
|
||||
AceDB.frame:SetScript("OnEvent", logoutHandler)
|
||||
|
||||
|
||||
--[[-------------------------------------------------------------------------
|
||||
AceDB Object Method Definitions
|
||||
---------------------------------------------------------------------------]]
|
||||
|
||||
--- Sets the defaults table for the given database object by clearing any
|
||||
-- that are currently set, and then setting the new defaults.
|
||||
-- @param defaults A table of defaults for this database
|
||||
function DBObjectLib:RegisterDefaults(defaults)
|
||||
if defaults and type(defaults) ~= "table" then
|
||||
error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
|
||||
end
|
||||
|
||||
validateDefaults(defaults, self.keys)
|
||||
|
||||
-- Remove any currently set defaults
|
||||
if self.defaults then
|
||||
for section,key in pairs(self.keys) do
|
||||
if self.defaults[section] and rawget(self, section) then
|
||||
removeDefaults(self[section], self.defaults[section])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the DBObject.defaults table
|
||||
self.defaults = defaults
|
||||
|
||||
-- Copy in any defaults, only touching those sections already created
|
||||
if defaults then
|
||||
for section,key in pairs(self.keys) do
|
||||
if defaults[section] and rawget(self, section) then
|
||||
copyDefaults(self[section], defaults[section])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Changes the profile of the database and all of it's namespaces to the
|
||||
-- supplied named profile
|
||||
-- @param name The name of the profile to set as the current profile
|
||||
function DBObjectLib:SetProfile(name)
|
||||
if type(name) ~= "string" then
|
||||
error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
|
||||
end
|
||||
|
||||
-- changing to the same profile, dont do anything
|
||||
if name == self.keys.profile then return end
|
||||
|
||||
local oldProfile = self.profile
|
||||
local defaults = self.defaults and self.defaults.profile
|
||||
|
||||
-- Callback: OnProfileShutdown, database
|
||||
self.callbacks:Fire("OnProfileShutdown", self)
|
||||
|
||||
if oldProfile and defaults then
|
||||
-- Remove the defaults from the old profile
|
||||
removeDefaults(oldProfile, defaults)
|
||||
end
|
||||
|
||||
self.profile = nil
|
||||
self.keys["profile"] = name
|
||||
|
||||
-- if the storage exists, save the new profile
|
||||
-- this won't exist on namespaces.
|
||||
if self.sv.profileKeys then
|
||||
self.sv.profileKeys[charKey] = name
|
||||
end
|
||||
|
||||
-- populate to child namespaces
|
||||
if self.children then
|
||||
for _, db in pairs(self.children) do
|
||||
DBObjectLib.SetProfile(db, name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Callback: OnProfileChanged, database, newProfileKey
|
||||
self.callbacks:Fire("OnProfileChanged", self, name)
|
||||
end
|
||||
|
||||
--- Returns a table with the names of the existing profiles in the database.
|
||||
-- You can optionally supply a table to re-use for this purpose.
|
||||
-- @param tbl A table to store the profile names in (optional)
|
||||
function DBObjectLib:GetProfiles(tbl)
|
||||
if tbl and type(tbl) ~= "table" then
|
||||
error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
|
||||
end
|
||||
|
||||
-- Clear the container table
|
||||
if tbl then
|
||||
for k,v in pairs(tbl) do tbl[k] = nil end
|
||||
else
|
||||
tbl = {}
|
||||
end
|
||||
|
||||
local curProfile = self.keys.profile
|
||||
|
||||
local i = 0
|
||||
for profileKey in pairs(self.profiles) do
|
||||
i = i + 1
|
||||
tbl[i] = profileKey
|
||||
if curProfile and profileKey == curProfile then curProfile = nil end
|
||||
end
|
||||
|
||||
-- Add the current profile, if it hasn't been created yet
|
||||
if curProfile then
|
||||
i = i + 1
|
||||
tbl[i] = curProfile
|
||||
end
|
||||
|
||||
return tbl, i
|
||||
end
|
||||
|
||||
--- Returns the current profile name used by the database
|
||||
function DBObjectLib:GetCurrentProfile()
|
||||
return self.keys.profile
|
||||
end
|
||||
|
||||
--- Deletes a named profile. This profile must not be the active profile.
|
||||
-- @param name The name of the profile to be deleted
|
||||
-- @param silent If true, do not raise an error when the profile does not exist
|
||||
function DBObjectLib:DeleteProfile(name, silent)
|
||||
if type(name) ~= "string" then
|
||||
error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
|
||||
end
|
||||
|
||||
if self.keys.profile == name then
|
||||
error("Cannot delete the active profile in an AceDBObject.", 2)
|
||||
end
|
||||
|
||||
if not rawget(self.sv.profiles, name) and not silent then
|
||||
error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
|
||||
end
|
||||
|
||||
self.sv.profiles[name] = nil
|
||||
|
||||
-- populate to child namespaces
|
||||
if self.children then
|
||||
for _, db in pairs(self.children) do
|
||||
DBObjectLib.DeleteProfile(db, name, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Callback: OnProfileDeleted, database, profileKey
|
||||
self.callbacks:Fire("OnProfileDeleted", self, name)
|
||||
end
|
||||
|
||||
--- Copies a named profile into the current profile, overwriting any conflicting
|
||||
-- settings.
|
||||
-- @param name The name of the profile to be copied into the current profile
|
||||
-- @param silent If true, do not raise an error when the profile does not exist
|
||||
function DBObjectLib:CopyProfile(name, silent)
|
||||
if type(name) ~= "string" then
|
||||
error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
|
||||
end
|
||||
|
||||
if name == self.keys.profile then
|
||||
error("Cannot have the same source and destination profiles.", 2)
|
||||
end
|
||||
|
||||
if not rawget(self.sv.profiles, name) and not silent then
|
||||
error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
|
||||
end
|
||||
|
||||
-- Reset the profile before copying
|
||||
DBObjectLib.ResetProfile(self, nil, true)
|
||||
|
||||
local profile = self.profile
|
||||
local source = self.sv.profiles[name]
|
||||
|
||||
copyTable(source, profile)
|
||||
|
||||
-- populate to child namespaces
|
||||
if self.children then
|
||||
for _, db in pairs(self.children) do
|
||||
DBObjectLib.CopyProfile(db, name, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- Callback: OnProfileCopied, database, sourceProfileKey
|
||||
self.callbacks:Fire("OnProfileCopied", self, name)
|
||||
end
|
||||
|
||||
--- Resets the current profile to the default values (if specified).
|
||||
-- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object
|
||||
-- @param noCallbacks if set to true, won't fire the OnProfileReset callback
|
||||
function DBObjectLib:ResetProfile(noChildren, noCallbacks)
|
||||
local profile = self.profile
|
||||
|
||||
for k,v in pairs(profile) do
|
||||
profile[k] = nil
|
||||
end
|
||||
|
||||
local defaults = self.defaults and self.defaults.profile
|
||||
if defaults then
|
||||
copyDefaults(profile, defaults)
|
||||
end
|
||||
|
||||
-- populate to child namespaces
|
||||
if self.children and not noChildren then
|
||||
for _, db in pairs(self.children) do
|
||||
DBObjectLib.ResetProfile(db, nil, noCallbacks)
|
||||
end
|
||||
end
|
||||
|
||||
-- Callback: OnProfileReset, database
|
||||
if not noCallbacks then
|
||||
self.callbacks:Fire("OnProfileReset", self)
|
||||
end
|
||||
end
|
||||
|
||||
--- Resets the entire database, using the string defaultProfile as the new default
|
||||
-- profile.
|
||||
-- @param defaultProfile The profile name to use as the default
|
||||
function DBObjectLib:ResetDB(defaultProfile)
|
||||
if defaultProfile and type(defaultProfile) ~= "string" then
|
||||
error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
|
||||
end
|
||||
|
||||
local sv = self.sv
|
||||
for k,v in pairs(sv) do
|
||||
sv[k] = nil
|
||||
end
|
||||
|
||||
local parent = self.parent
|
||||
|
||||
initdb(sv, self.defaults, defaultProfile, self)
|
||||
|
||||
-- fix the child namespaces
|
||||
if self.children then
|
||||
if not sv.namespaces then sv.namespaces = {} end
|
||||
for name, db in pairs(self.children) do
|
||||
if not sv.namespaces[name] then sv.namespaces[name] = {} end
|
||||
initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
|
||||
end
|
||||
end
|
||||
|
||||
-- Callback: OnDatabaseReset, database
|
||||
self.callbacks:Fire("OnDatabaseReset", self)
|
||||
-- Callback: OnProfileChanged, database, profileKey
|
||||
self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a new database namespace, directly tied to the database. This
|
||||
-- is a full scale database in it's own rights other than the fact that
|
||||
-- it cannot control its profile individually
|
||||
-- @param name The name of the new namespace
|
||||
-- @param defaults A table of values to use as defaults
|
||||
function DBObjectLib:RegisterNamespace(name, defaults)
|
||||
if type(name) ~= "string" then
|
||||
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
|
||||
end
|
||||
if defaults and type(defaults) ~= "table" then
|
||||
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
|
||||
end
|
||||
if self.children and self.children[name] then
|
||||
error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
|
||||
end
|
||||
|
||||
local sv = self.sv
|
||||
if not sv.namespaces then sv.namespaces = {} end
|
||||
if not sv.namespaces[name] then
|
||||
sv.namespaces[name] = {}
|
||||
end
|
||||
|
||||
local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
|
||||
|
||||
if not self.children then self.children = {} end
|
||||
self.children[name] = newDB
|
||||
return newDB
|
||||
end
|
||||
|
||||
--- Returns an already existing namespace from the database object.
|
||||
-- @param name The name of the new namespace
|
||||
-- @param silent if true, the addon is optional, silently return nil if its not found
|
||||
-- @usage
|
||||
-- local namespace = self.db:GetNamespace('namespace')
|
||||
-- @return the namespace object if found
|
||||
function DBObjectLib:GetNamespace(name, silent)
|
||||
if type(name) ~= "string" then
|
||||
error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2)
|
||||
end
|
||||
if not silent and not (self.children and self.children[name]) then
|
||||
error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2)
|
||||
end
|
||||
if not self.children then self.children = {} end
|
||||
return self.children[name]
|
||||
end
|
||||
|
||||
--[[-------------------------------------------------------------------------
|
||||
AceDB Exposed Methods
|
||||
---------------------------------------------------------------------------]]
|
||||
|
||||
--- Creates a new database object that can be used to handle database settings and profiles.
|
||||
-- By default, an empty DB is created, using a character specific profile.
|
||||
--
|
||||
-- You can override the default profile used by passing any profile name as the third argument,
|
||||
-- or by passing //true// as the third argument to use a globally shared profile called "Default".
|
||||
--
|
||||
-- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char"
|
||||
-- will use a profile named "char", and not a character-specific profile.
|
||||
-- @param tbl The name of variable, or table to use for the database
|
||||
-- @param defaults A table of database defaults
|
||||
-- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default.
|
||||
-- You can also pass //true// to use a shared global profile called "Default".
|
||||
-- @usage
|
||||
-- -- Create an empty DB using a character-specific default profile.
|
||||
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB")
|
||||
-- @usage
|
||||
-- -- Create a DB using defaults and using a shared default profile
|
||||
-- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true)
|
||||
function AceDB:New(tbl, defaults, defaultProfile)
|
||||
if type(tbl) == "string" then
|
||||
local name = tbl
|
||||
tbl = _G[name]
|
||||
if not tbl then
|
||||
tbl = {}
|
||||
_G[name] = tbl
|
||||
end
|
||||
end
|
||||
|
||||
if type(tbl) ~= "table" then
|
||||
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
|
||||
end
|
||||
|
||||
if defaults and type(defaults) ~= "table" then
|
||||
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
|
||||
end
|
||||
|
||||
if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then
|
||||
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2)
|
||||
end
|
||||
|
||||
return initdb(tbl, defaults, defaultProfile)
|
||||
end
|
||||
|
||||
-- upgrade existing databases
|
||||
for db in pairs(AceDB.db_registry) do
|
||||
if not db.parent then
|
||||
for name,func in pairs(DBObjectLib) do
|
||||
db[name] = func
|
||||
end
|
||||
else
|
||||
db.RegisterDefaults = DBObjectLib.RegisterDefaults
|
||||
db.ResetProfile = DBObjectLib.ResetProfile
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceDB-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,420 @@
|
||||
--- AceDBOptions-3.0 provides a universal AceConfig options screen for managing AceDB-3.0 profiles.
|
||||
-- @class file
|
||||
-- @name AceDBOptions-3.0
|
||||
-- @release $Id: AceDBOptions-3.0.lua 938 2010-06-13 07:21:38Z nevcairiel $
|
||||
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 12
|
||||
local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR)
|
||||
|
||||
if not AceDBOptions then return end -- No upgrade needed
|
||||
|
||||
-- Lua APIs
|
||||
local pairs, next = pairs, next
|
||||
|
||||
-- WoW APIs
|
||||
local UnitClass = UnitClass
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: NORMAL_FONT_COLOR_CODE, FONT_COLOR_CODE_CLOSE
|
||||
|
||||
AceDBOptions.optionTables = AceDBOptions.optionTables or {}
|
||||
AceDBOptions.handlers = AceDBOptions.handlers or {}
|
||||
|
||||
--[[
|
||||
Localization of AceDBOptions-3.0
|
||||
]]
|
||||
|
||||
local L = {
|
||||
default = "Default",
|
||||
intro = "You can change the active database profile, so you can have different settings for every character.",
|
||||
reset_desc = "Reset the current profile back to its default values, in case your configuration is broken, or you simply want to start over.",
|
||||
reset = "Reset Profile",
|
||||
reset_sub = "Reset the current profile to the default",
|
||||
choose_desc = "You can either create a new profile by entering a name in the editbox, or choose one of the already existing profiles.",
|
||||
new = "New",
|
||||
new_sub = "Create a new empty profile.",
|
||||
choose = "Existing Profiles",
|
||||
choose_sub = "Select one of your currently available profiles.",
|
||||
copy_desc = "Copy the settings from one existing profile into the currently active profile.",
|
||||
copy = "Copy From",
|
||||
delete_desc = "Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.",
|
||||
delete = "Delete a Profile",
|
||||
delete_sub = "Deletes a profile from the database.",
|
||||
delete_confirm = "Are you sure you want to delete the selected profile?",
|
||||
profiles = "Profiles",
|
||||
profiles_sub = "Manage Profiles",
|
||||
current = "Current Profile:",
|
||||
}
|
||||
|
||||
local LOCALE = GetLocale()
|
||||
if LOCALE == "deDE" then
|
||||
L["default"] = "Standard"
|
||||
L["intro"] = "Hier kannst du das aktive Datenbankprofile \195\164ndern, damit du verschiedene Einstellungen f\195\188r jeden Charakter erstellen kannst, wodurch eine sehr flexible Konfiguration m\195\182glich wird."
|
||||
L["reset_desc"] = "Setzt das momentane Profil auf Standardwerte zur\195\188ck, f\195\188r den Fall das mit der Konfiguration etwas schief lief oder weil du einfach neu starten willst."
|
||||
L["reset"] = "Profil zur\195\188cksetzen"
|
||||
L["reset_sub"] = "Das aktuelle Profil auf Standard zur\195\188cksetzen."
|
||||
L["choose_desc"] = "Du kannst ein neues Profil erstellen, indem du einen neuen Namen in der Eingabebox 'Neu' eingibst, oder w\195\164hle eines der vorhandenen Profile aus."
|
||||
L["new"] = "Neu"
|
||||
L["new_sub"] = "Ein neues Profil erstellen."
|
||||
L["choose"] = "Vorhandene Profile"
|
||||
L["choose_sub"] = "W\195\164hlt ein bereits vorhandenes Profil aus."
|
||||
L["copy_desc"] = "Kopiere die Einstellungen von einem vorhandenen Profil in das aktive Profil."
|
||||
L["copy"] = "Kopieren von..."
|
||||
L["delete_desc"] = "L\195\182sche vorhandene oder unbenutzte Profile aus der Datenbank um Platz zu sparen und um die SavedVariables Datei 'sauber' zu halten."
|
||||
L["delete"] = "Profil l\195\182schen"
|
||||
L["delete_sub"] = "L\195\182scht ein Profil aus der Datenbank."
|
||||
L["delete_confirm"] = "Willst du das ausgew\195\164hlte Profil wirklich l\195\182schen?"
|
||||
L["profiles"] = "Profile"
|
||||
L["profiles_sub"] = "Profile verwalten"
|
||||
--L["current"] = "Current Profile:"
|
||||
elseif LOCALE == "frFR" then
|
||||
L["default"] = "D\195\169faut"
|
||||
L["intro"] = "Vous pouvez changer le profil actuel afin d'avoir des param\195\168tres diff\195\169rents pour chaque personnage, permettant ainsi d'avoir une configuration tr\195\168s flexible."
|
||||
L["reset_desc"] = "R\195\169initialise le profil actuel au cas o\195\185 votre configuration est corrompue ou si vous voulez tout simplement faire table rase."
|
||||
L["reset"] = "R\195\169initialiser le profil"
|
||||
L["reset_sub"] = "R\195\169initialise le profil actuel avec les param\195\168tres par d\195\169faut."
|
||||
L["choose_desc"] = "Vous pouvez cr\195\169er un nouveau profil en entrant un nouveau nom dans la bo\195\174te de saisie, ou en choississant un des profils d\195\169j\195\160 existants."
|
||||
L["new"] = "Nouveau"
|
||||
L["new_sub"] = "Cr\195\169\195\169e un nouveau profil vierge."
|
||||
L["choose"] = "Profils existants"
|
||||
L["choose_sub"] = "Permet de choisir un des profils d\195\169j\195\160 disponibles."
|
||||
L["copy_desc"] = "Copie les param\195\168tres d'un profil d\195\169j\195\160 existant dans le profil actuellement actif."
|
||||
L["copy"] = "Copier \195\160 partir de"
|
||||
L["delete_desc"] = "Supprime les profils existants inutilis\195\169s de la base de donn\195\169es afin de gagner de la place et de nettoyer le fichier SavedVariables."
|
||||
L["delete"] = "Supprimer un profil"
|
||||
L["delete_sub"] = "Supprime un profil de la base de donn\195\169es."
|
||||
L["delete_confirm"] = "Etes-vous s\195\187r de vouloir supprimer le profil s\195\169lectionn\195\169 ?"
|
||||
L["profiles"] = "Profils"
|
||||
L["profiles_sub"] = "Gestion des profils"
|
||||
--L["current"] = "Current Profile:"
|
||||
elseif LOCALE == "koKR" then
|
||||
L["default"] = "기본값"
|
||||
L["intro"] = "모든 캐릭터의 다양한 설정과 사용중인 데이터베이스 프로필, 어느것이던지 매우 다루기 쉽게 바꿀수 있습니다."
|
||||
L["reset_desc"] = "단순히 다시 새롭게 구성을 원하는 경우, 현재 프로필을 기본값으로 초기화 합니다."
|
||||
L["reset"] = "프로필 초기화"
|
||||
L["reset_sub"] = "현재의 프로필을 기본값으로 초기화 합니다"
|
||||
L["choose_desc"] = "새로운 이름을 입력하거나, 이미 있는 프로필중 하나를 선택하여 새로운 프로필을 만들 수 있습니다."
|
||||
L["new"] = "새로운 프로필"
|
||||
L["new_sub"] = "새로운 프로필을 만듭니다."
|
||||
L["choose"] = "프로필 선택"
|
||||
L["choose_sub"] = "당신이 현재 이용할수 있는 프로필을 선택합니다."
|
||||
L["copy_desc"] = "현재 사용중인 프로필에, 선택한 프로필의 설정을 복사합니다."
|
||||
L["copy"] = "복사"
|
||||
L["delete_desc"] = "데이터베이스에 사용중이거나 저장된 프로파일 삭제로 SavedVariables 파일의 정리와 공간 절약이 됩니다."
|
||||
L["delete"] = "프로필 삭제"
|
||||
L["delete_sub"] = "데이터베이스의 프로필을 삭제합니다."
|
||||
L["delete_confirm"] = "정말로 선택한 프로필의 삭제를 원하십니까?"
|
||||
L["profiles"] = "프로필"
|
||||
L["profiles_sub"] = "프로필 설정"
|
||||
--L["current"] = "Current Profile:"
|
||||
elseif LOCALE == "esES" or LOCALE == "esMX" then
|
||||
L["default"] = "Por defecto"
|
||||
L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones."
|
||||
L["reset_desc"] = "Reinicia el perfil actual a los valores por defectos, en caso de que se haya estropeado la configuración o quieras volver a empezar de nuevo."
|
||||
L["reset"] = "Reiniciar Perfil"
|
||||
L["reset_sub"] = "Reinicar el perfil actual al de por defecto"
|
||||
L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes."
|
||||
L["new"] = "Nuevo"
|
||||
L["new_sub"] = "Crear un nuevo perfil vacio."
|
||||
L["choose"] = "Perfiles existentes"
|
||||
L["choose_sub"] = "Selecciona uno de los perfiles disponibles."
|
||||
L["copy_desc"] = "Copia los ajustes de un perfil existente al perfil actual."
|
||||
L["copy"] = "Copiar de"
|
||||
L["delete_desc"] = "Borra los perfiles existentes y sin uso de la base de datos para ganar espacio y limpiar el archivo SavedVariables."
|
||||
L["delete"] = "Borrar un Perfil"
|
||||
L["delete_sub"] = "Borra un perfil de la base de datos."
|
||||
L["delete_confirm"] = "¿Estas seguro que quieres borrar el perfil seleccionado?"
|
||||
L["profiles"] = "Perfiles"
|
||||
L["profiles_sub"] = "Manejar Perfiles"
|
||||
--L["current"] = "Current Profile:"
|
||||
elseif LOCALE == "zhTW" then
|
||||
L["default"] = "預設"
|
||||
L["intro"] = "你可以選擇一個活動的資料設定檔,這樣你的每個角色就可以擁有不同的設定值,可以給你的插件設定帶來極大的靈活性。"
|
||||
L["reset_desc"] = "將當前的設定檔恢復到它的預設值,用於你的設定檔損壞,或者你只是想重來的情況。"
|
||||
L["reset"] = "重置設定檔"
|
||||
L["reset_sub"] = "將當前的設定檔恢復為預設值"
|
||||
L["choose_desc"] = "你可以通過在文本框內輸入一個名字創立一個新的設定檔,也可以選擇一個已經存在的設定檔。"
|
||||
L["new"] = "新建"
|
||||
L["new_sub"] = "新建一個空的設定檔。"
|
||||
L["choose"] = "現有的設定檔"
|
||||
L["choose_sub"] = "從當前可用的設定檔裏面選擇一個。"
|
||||
L["copy_desc"] = "從當前某個已保存的設定檔複製到當前正使用的設定檔。"
|
||||
L["copy"] = "複製自"
|
||||
L["delete_desc"] = "從資料庫裏刪除不再使用的設定檔,以節省空間,並且清理SavedVariables檔。"
|
||||
L["delete"] = "刪除一個設定檔"
|
||||
L["delete_sub"] = "從資料庫裏刪除一個設定檔。"
|
||||
L["delete_confirm"] = "你確定要刪除所選擇的設定檔嗎?"
|
||||
L["profiles"] = "設定檔"
|
||||
L["profiles_sub"] = "管理設定檔"
|
||||
--L["current"] = "Current Profile:"
|
||||
elseif LOCALE == "zhCN" then
|
||||
L["default"] = "默认"
|
||||
L["intro"] = "你可以选择一个活动的数据配置文件,这样你的每个角色就可以拥有不同的设置值,可以给你的插件配置带来极大的灵活性。"
|
||||
L["reset_desc"] = "将当前的配置文件恢复到它的默认值,用于你的配置文件损坏,或者你只是想重来的情况。"
|
||||
L["reset"] = "重置配置文件"
|
||||
L["reset_sub"] = "将当前的配置文件恢复为默认值"
|
||||
L["choose_desc"] = "你可以通过在文本框内输入一个名字创立一个新的配置文件,也可以选择一个已经存在的配置文件。"
|
||||
L["new"] = "新建"
|
||||
L["new_sub"] = "新建一个空的配置文件。"
|
||||
L["choose"] = "现有的配置文件"
|
||||
L["choose_sub"] = "从当前可用的配置文件里面选择一个。"
|
||||
L["copy_desc"] = "从当前某个已保存的配置文件复制到当前正使用的配置文件。"
|
||||
L["copy"] = "复制自"
|
||||
L["delete_desc"] = "从数据库里删除不再使用的配置文件,以节省空间,并且清理SavedVariables文件。"
|
||||
L["delete"] = "删除一个配置文件"
|
||||
L["delete_sub"] = "从数据库里删除一个配置文件。"
|
||||
L["delete_confirm"] = "你确定要删除所选择的配置文件么?"
|
||||
L["profiles"] = "配置文件"
|
||||
L["profiles_sub"] = "管理配置文件"
|
||||
--L["current"] = "Current Profile:"
|
||||
elseif LOCALE == "ruRU" then
|
||||
L["default"] = "По умолчанию"
|
||||
L["intro"] = "Изменяя активный профиль, вы можете задать различные настройки модификаций для каждого персонажа."
|
||||
L["reset_desc"] = "Если ваша конфигурации испорчена или если вы хотите настроить всё заново - сбросьте текущий профиль на стандартные значения."
|
||||
L["reset"] = "Сброс профиля"
|
||||
L["reset_sub"] = "Сброс текущего профиля на стандартный"
|
||||
L["choose_desc"] = "Вы можете создать новый профиль, введя название в поле ввода, или выбрать один из уже существующих профилей."
|
||||
L["new"] = "Новый"
|
||||
L["new_sub"] = "Создать новый чистый профиль"
|
||||
L["choose"] = "Существующие профили"
|
||||
L["choose_sub"] = "Выбор одиного из уже доступных профилей"
|
||||
L["copy_desc"] = "Скопировать настройки из выбранного профиля в активный."
|
||||
L["copy"] = "Скопировать из"
|
||||
L["delete_desc"] = "Удалить существующий и неиспользуемый профиль из БД для сохранения места, и очистить SavedVariables файл."
|
||||
L["delete"] = "Удалить профиль"
|
||||
L["delete_sub"] = "Удаление профиля из БД"
|
||||
L["delete_confirm"] = "Вы уверены, что вы хотите удалить выбранный профиль?"
|
||||
L["profiles"] = "Профили"
|
||||
L["profiles_sub"] = "Управление профилями"
|
||||
--L["current"] = "Current Profile:"
|
||||
end
|
||||
|
||||
local defaultProfiles
|
||||
local tmpprofiles = {}
|
||||
|
||||
-- Get a list of available profiles for the specified database.
|
||||
-- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below.
|
||||
-- @param db The db object to retrieve the profiles from
|
||||
-- @param common If true, getProfileList will add the default profiles to the return list, even if they have not been created yet
|
||||
-- @param nocurrent If true, then getProfileList will not display the current profile in the list
|
||||
-- @return Hashtable of all profiles with the internal name as keys and the display name as value.
|
||||
local function getProfileList(db, common, nocurrent)
|
||||
local profiles = {}
|
||||
|
||||
-- copy existing profiles into the table
|
||||
local currentProfile = db:GetCurrentProfile()
|
||||
for i,v in pairs(db:GetProfiles(tmpprofiles)) do
|
||||
if not (nocurrent and v == currentProfile) then
|
||||
profiles[v] = v
|
||||
end
|
||||
end
|
||||
|
||||
-- add our default profiles to choose from ( or rename existing profiles)
|
||||
for k,v in pairs(defaultProfiles) do
|
||||
if (common or profiles[k]) and not (nocurrent and k == currentProfile) then
|
||||
profiles[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return profiles
|
||||
end
|
||||
|
||||
--[[
|
||||
OptionsHandlerPrototype
|
||||
prototype class for handling the options in a sane way
|
||||
]]
|
||||
local OptionsHandlerPrototype = {}
|
||||
|
||||
--[[ Reset the profile ]]
|
||||
function OptionsHandlerPrototype:Reset()
|
||||
self.db:ResetProfile()
|
||||
end
|
||||
|
||||
--[[ Set the profile to value ]]
|
||||
function OptionsHandlerPrototype:SetProfile(info, value)
|
||||
self.db:SetProfile(value)
|
||||
end
|
||||
|
||||
--[[ returns the currently active profile ]]
|
||||
function OptionsHandlerPrototype:GetCurrentProfile()
|
||||
return self.db:GetCurrentProfile()
|
||||
end
|
||||
|
||||
--[[
|
||||
List all active profiles
|
||||
you can control the output with the .arg variable
|
||||
currently four modes are supported
|
||||
|
||||
(empty) - return all available profiles
|
||||
"nocurrent" - returns all available profiles except the currently active profile
|
||||
"common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default")
|
||||
"both" - common except the active profile
|
||||
]]
|
||||
function OptionsHandlerPrototype:ListProfiles(info)
|
||||
local arg = info.arg
|
||||
local profiles
|
||||
if arg == "common" and not self.noDefaultProfiles then
|
||||
profiles = getProfileList(self.db, true, nil)
|
||||
elseif arg == "nocurrent" then
|
||||
profiles = getProfileList(self.db, nil, true)
|
||||
elseif arg == "both" then -- currently not used
|
||||
profiles = getProfileList(self.db, (not self.noDefaultProfiles) and true, true)
|
||||
else
|
||||
profiles = getProfileList(self.db)
|
||||
end
|
||||
|
||||
return profiles
|
||||
end
|
||||
|
||||
function OptionsHandlerPrototype:HasNoProfiles(info)
|
||||
local profiles = self:ListProfiles(info)
|
||||
return ((not next(profiles)) and true or false)
|
||||
end
|
||||
|
||||
--[[ Copy a profile ]]
|
||||
function OptionsHandlerPrototype:CopyProfile(info, value)
|
||||
self.db:CopyProfile(value)
|
||||
end
|
||||
|
||||
--[[ Delete a profile from the db ]]
|
||||
function OptionsHandlerPrototype:DeleteProfile(info, value)
|
||||
self.db:DeleteProfile(value)
|
||||
end
|
||||
|
||||
--[[ fill defaultProfiles with some generic values ]]
|
||||
local function generateDefaultProfiles(db)
|
||||
defaultProfiles = {
|
||||
["Default"] = L["default"],
|
||||
[db.keys.char] = db.keys.char,
|
||||
[db.keys.realm] = db.keys.realm,
|
||||
[db.keys.class] = UnitClass("player")
|
||||
}
|
||||
end
|
||||
|
||||
--[[ create and return a handler object for the db, or upgrade it if it already existed ]]
|
||||
local function getOptionsHandler(db, noDefaultProfiles)
|
||||
if not defaultProfiles then
|
||||
generateDefaultProfiles(db)
|
||||
end
|
||||
|
||||
local handler = AceDBOptions.handlers[db] or { db = db, noDefaultProfiles = noDefaultProfiles }
|
||||
|
||||
for k,v in pairs(OptionsHandlerPrototype) do
|
||||
handler[k] = v
|
||||
end
|
||||
|
||||
AceDBOptions.handlers[db] = handler
|
||||
return handler
|
||||
end
|
||||
|
||||
--[[
|
||||
the real options table
|
||||
]]
|
||||
local optionsTable = {
|
||||
desc = {
|
||||
order = 1,
|
||||
type = "description",
|
||||
name = L["intro"] .. "\n",
|
||||
},
|
||||
descreset = {
|
||||
order = 9,
|
||||
type = "description",
|
||||
name = L["reset_desc"],
|
||||
},
|
||||
reset = {
|
||||
order = 10,
|
||||
type = "execute",
|
||||
name = L["reset"],
|
||||
desc = L["reset_sub"],
|
||||
func = "Reset",
|
||||
},
|
||||
current = {
|
||||
order = 11,
|
||||
type = "description",
|
||||
name = function(info) return L["current"] .. " " .. NORMAL_FONT_COLOR_CODE .. info.handler:GetCurrentProfile() .. FONT_COLOR_CODE_CLOSE end,
|
||||
width = "default",
|
||||
},
|
||||
choosedesc = {
|
||||
order = 20,
|
||||
type = "description",
|
||||
name = "\n" .. L["choose_desc"],
|
||||
},
|
||||
new = {
|
||||
name = L["new"],
|
||||
desc = L["new_sub"],
|
||||
type = "input",
|
||||
order = 30,
|
||||
get = false,
|
||||
set = "SetProfile",
|
||||
},
|
||||
choose = {
|
||||
name = L["choose"],
|
||||
desc = L["choose_sub"],
|
||||
type = "select",
|
||||
order = 40,
|
||||
get = "GetCurrentProfile",
|
||||
set = "SetProfile",
|
||||
values = "ListProfiles",
|
||||
arg = "common",
|
||||
},
|
||||
copydesc = {
|
||||
order = 50,
|
||||
type = "description",
|
||||
name = "\n" .. L["copy_desc"],
|
||||
},
|
||||
copyfrom = {
|
||||
order = 60,
|
||||
type = "select",
|
||||
name = L["copy"],
|
||||
desc = L["copy_desc"],
|
||||
get = false,
|
||||
set = "CopyProfile",
|
||||
values = "ListProfiles",
|
||||
disabled = "HasNoProfiles",
|
||||
arg = "nocurrent",
|
||||
},
|
||||
deldesc = {
|
||||
order = 70,
|
||||
type = "description",
|
||||
name = "\n" .. L["delete_desc"],
|
||||
},
|
||||
delete = {
|
||||
order = 80,
|
||||
type = "select",
|
||||
name = L["delete"],
|
||||
desc = L["delete_sub"],
|
||||
get = false,
|
||||
set = "DeleteProfile",
|
||||
values = "ListProfiles",
|
||||
disabled = "HasNoProfiles",
|
||||
arg = "nocurrent",
|
||||
confirm = true,
|
||||
confirmText = L["delete_confirm"],
|
||||
},
|
||||
}
|
||||
|
||||
--- Get/Create a option table that you can use in your addon to control the profiles of AceDB-3.0.
|
||||
-- @param db The database object to create the options table for.
|
||||
-- @return The options table to be used in AceConfig-3.0
|
||||
-- @usage
|
||||
-- -- Assuming `options` is your top-level options table and `self.db` is your database:
|
||||
-- options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
|
||||
function AceDBOptions:GetOptionsTable(db, noDefaultProfiles)
|
||||
local tbl = AceDBOptions.optionTables[db] or {
|
||||
type = "group",
|
||||
name = L["profiles"],
|
||||
desc = L["profiles_sub"],
|
||||
}
|
||||
|
||||
tbl.handler = getOptionsHandler(db, noDefaultProfiles)
|
||||
tbl.args = optionsTable
|
||||
|
||||
AceDBOptions.optionTables[db] = tbl
|
||||
return tbl
|
||||
end
|
||||
|
||||
-- upgrade existing tables
|
||||
for db,tbl in pairs(AceDBOptions.optionTables) do
|
||||
tbl.handler = getOptionsHandler(db)
|
||||
tbl.args = optionsTable
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceDBOptions-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,126 @@
|
||||
--- AceEvent-3.0 provides event registration and secure dispatching.
|
||||
-- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around
|
||||
-- CallbackHandler, and dispatches all game events or addon message to the registrees.
|
||||
--
|
||||
-- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent:Embed(MyAddon) or by
|
||||
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
|
||||
-- and can be accessed directly, without having to explicitly call AceEvent itself.\\
|
||||
-- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you
|
||||
-- make into AceEvent.
|
||||
-- @class file
|
||||
-- @name AceEvent-3.0
|
||||
-- @release $Id: AceEvent-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
|
||||
local MAJOR, MINOR = "AceEvent-3.0", 3
|
||||
local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceEvent then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs = pairs
|
||||
|
||||
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
|
||||
|
||||
AceEvent.frame = AceEvent.frame or CreateFrame("Frame", "AceEvent30Frame") -- our event frame
|
||||
AceEvent.embeds = AceEvent.embeds or {} -- what objects embed this lib
|
||||
|
||||
-- APIs and registry for blizzard events, using CallbackHandler lib
|
||||
if not AceEvent.events then
|
||||
AceEvent.events = CallbackHandler:New(AceEvent,
|
||||
"RegisterEvent", "UnregisterEvent", "UnregisterAllEvents")
|
||||
end
|
||||
|
||||
function AceEvent.events:OnUsed(target, eventname)
|
||||
AceEvent.frame:RegisterEvent(eventname)
|
||||
end
|
||||
|
||||
function AceEvent.events:OnUnused(target, eventname)
|
||||
AceEvent.frame:UnregisterEvent(eventname)
|
||||
end
|
||||
|
||||
|
||||
-- APIs and registry for IPC messages, using CallbackHandler lib
|
||||
if not AceEvent.messages then
|
||||
AceEvent.messages = CallbackHandler:New(AceEvent,
|
||||
"RegisterMessage", "UnregisterMessage", "UnregisterAllMessages"
|
||||
)
|
||||
AceEvent.SendMessage = AceEvent.messages.Fire
|
||||
end
|
||||
|
||||
--- embedding and embed handling
|
||||
local mixins = {
|
||||
"RegisterEvent", "UnregisterEvent",
|
||||
"RegisterMessage", "UnregisterMessage",
|
||||
"SendMessage",
|
||||
"UnregisterAllEvents", "UnregisterAllMessages",
|
||||
}
|
||||
|
||||
--- Register for a Blizzard Event.
|
||||
-- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument.
|
||||
-- Any arguments to the event will be passed on after that.
|
||||
-- @name AceEvent:RegisterEvent
|
||||
-- @class function
|
||||
-- @paramsig event[, callback [, arg]]
|
||||
-- @param event The event to register for
|
||||
-- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name)
|
||||
-- @param arg An optional argument to pass to the callback function
|
||||
|
||||
--- Unregister an event.
|
||||
-- @name AceEvent:UnregisterEvent
|
||||
-- @class function
|
||||
-- @paramsig event
|
||||
-- @param event The event to unregister
|
||||
|
||||
--- Register for a custom AceEvent-internal message.
|
||||
-- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument.
|
||||
-- Any arguments to the event will be passed on after that.
|
||||
-- @name AceEvent:RegisterMessage
|
||||
-- @class function
|
||||
-- @paramsig message[, callback [, arg]]
|
||||
-- @param message The message to register for
|
||||
-- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name)
|
||||
-- @param arg An optional argument to pass to the callback function
|
||||
|
||||
--- Unregister a message
|
||||
-- @name AceEvent:UnregisterMessage
|
||||
-- @class function
|
||||
-- @paramsig message
|
||||
-- @param message The message to unregister
|
||||
|
||||
--- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message.
|
||||
-- @name AceEvent:SendMessage
|
||||
-- @class function
|
||||
-- @paramsig message, ...
|
||||
-- @param message The message to send
|
||||
-- @param ... Any arguments to the message
|
||||
|
||||
|
||||
-- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
|
||||
-- @param target target object to embed AceEvent in
|
||||
function AceEvent:Embed(target)
|
||||
for k, v in pairs(mixins) do
|
||||
target[v] = self[v]
|
||||
end
|
||||
self.embeds[target] = true
|
||||
return target
|
||||
end
|
||||
|
||||
-- AceEvent:OnEmbedDisable( target )
|
||||
-- target (object) - target object that is being disabled
|
||||
--
|
||||
-- Unregister all events messages etc when the target disables.
|
||||
-- this method should be called by the target manually or by an addon framework
|
||||
function AceEvent:OnEmbedDisable(target)
|
||||
target:UnregisterAllEvents()
|
||||
target:UnregisterAllMessages()
|
||||
end
|
||||
|
||||
-- Script to fire blizzard events into the event listeners
|
||||
local events = AceEvent.events
|
||||
AceEvent.frame:SetScript("OnEvent", function(this, event, ...)
|
||||
events:Fire(event, ...)
|
||||
end)
|
||||
|
||||
--- Finally: upgrade our old embeds
|
||||
for target, v in pairs(AceEvent.embeds) do
|
||||
AceEvent:Embed(target)
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceEvent-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,805 @@
|
||||
--- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs.
|
||||
-- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself
|
||||
-- to create any custom GUI. There are more extensive examples in the test suite in the Ace3
|
||||
-- stand-alone distribution.
|
||||
--
|
||||
-- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly,
|
||||
-- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool
|
||||
-- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we"ll
|
||||
-- implement a proper API to modify it.
|
||||
-- @usage
|
||||
-- local AceGUI = LibStub("AceGUI-3.0")
|
||||
-- -- Create a container frame
|
||||
-- local f = AceGUI:Create("Frame")
|
||||
-- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end)
|
||||
-- f:SetTitle("AceGUI-3.0 Example")
|
||||
-- f:SetStatusText("Status Bar")
|
||||
-- f:SetLayout("Flow")
|
||||
-- -- Create a button
|
||||
-- local btn = AceGUI:Create("Button")
|
||||
-- btn:SetWidth(170)
|
||||
-- btn:SetText("Button !")
|
||||
-- btn:SetCallback("OnClick", function() print("Click!") end)
|
||||
-- -- Add the button to the container
|
||||
-- f:AddChild(btn)
|
||||
-- @class file
|
||||
-- @name AceGUI-3.0
|
||||
-- @release $Id: AceGUI-3.0.lua 924 2010-05-13 15:12:20Z nevcairiel $
|
||||
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 33
|
||||
local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
|
||||
|
||||
if not AceGUI then return end -- No upgrade needed
|
||||
|
||||
-- Lua APIs
|
||||
local tconcat, tremove, tinsert = table.concat, table.remove, table.insert
|
||||
local select, pairs, next, type = select, pairs, next, type
|
||||
local error, assert, loadstring = error, assert, loadstring
|
||||
local setmetatable, rawget, rawset = setmetatable, rawget, rawset
|
||||
local math_max = math.max
|
||||
|
||||
-- WoW APIs
|
||||
local UIParent = UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: geterrorhandler, LibStub
|
||||
|
||||
--local con = LibStub("AceConsole-3.0",true)
|
||||
|
||||
AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
|
||||
AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
|
||||
AceGUI.WidgetBase = AceGUI.WidgetBase or {}
|
||||
AceGUI.WidgetContainerBase = AceGUI.WidgetContainerBase or {}
|
||||
AceGUI.WidgetVersions = AceGUI.WidgetVersions or {}
|
||||
|
||||
-- local upvalues
|
||||
local WidgetRegistry = AceGUI.WidgetRegistry
|
||||
local LayoutRegistry = AceGUI.LayoutRegistry
|
||||
local WidgetVersions = AceGUI.WidgetVersions
|
||||
|
||||
--[[
|
||||
xpcall safecall implementation
|
||||
]]
|
||||
local xpcall = xpcall
|
||||
|
||||
local function errorhandler(err)
|
||||
return geterrorhandler()(err)
|
||||
end
|
||||
|
||||
local function CreateDispatcher(argCount)
|
||||
local code = [[
|
||||
local xpcall, eh = ...
|
||||
local method, ARGS
|
||||
local function call() return method(ARGS) end
|
||||
|
||||
local function dispatch(func, ...)
|
||||
method = func
|
||||
if not method then return end
|
||||
ARGS = ...
|
||||
return xpcall(call, eh)
|
||||
end
|
||||
|
||||
return dispatch
|
||||
]]
|
||||
|
||||
local ARGS = {}
|
||||
for i = 1, argCount do ARGS[i] = "arg"..i end
|
||||
code = code:gsub("ARGS", tconcat(ARGS, ", "))
|
||||
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
|
||||
end
|
||||
|
||||
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
|
||||
local dispatcher = CreateDispatcher(argCount)
|
||||
rawset(self, argCount, dispatcher)
|
||||
return dispatcher
|
||||
end})
|
||||
Dispatchers[0] = function(func)
|
||||
return xpcall(func, errorhandler)
|
||||
end
|
||||
|
||||
local function safecall(func, ...)
|
||||
return Dispatchers[select("#", ...)](func, ...)
|
||||
end
|
||||
|
||||
-- Recycling functions
|
||||
local newWidget, delWidget
|
||||
do
|
||||
-- Version Upgrade in Minor 29
|
||||
-- Internal Storage of the objects changed, from an array table
|
||||
-- to a hash table, and additionally we introduced versioning on
|
||||
-- the widgets which would discard all widgets from a pre-29 version
|
||||
-- anyway, so we just clear the storage now, and don't try to
|
||||
-- convert the storage tables to the new format.
|
||||
-- This should generally not cause *many* widgets to end up in trash,
|
||||
-- since once dialogs are opened, all addons should be loaded already
|
||||
-- and AceGUI should be on the latest version available on the users
|
||||
-- setup.
|
||||
-- -- nevcairiel - Nov 2nd, 2009
|
||||
if oldminor and oldminor < 29 and AceGUI.objPools then
|
||||
AceGUI.objPools = nil
|
||||
end
|
||||
|
||||
AceGUI.objPools = AceGUI.objPools or {}
|
||||
local objPools = AceGUI.objPools
|
||||
--Returns a new instance, if none are available either returns a new table or calls the given contructor
|
||||
function newWidget(type)
|
||||
if not WidgetRegistry[type] then
|
||||
error("Attempt to instantiate unknown widget type", 2)
|
||||
end
|
||||
|
||||
if not objPools[type] then
|
||||
objPools[type] = {}
|
||||
end
|
||||
|
||||
local newObj = next(objPools[type])
|
||||
if not newObj then
|
||||
newObj = WidgetRegistry[type]()
|
||||
newObj.AceGUIWidgetVersion = WidgetVersions[type]
|
||||
else
|
||||
objPools[type][newObj] = nil
|
||||
-- if the widget is older then the latest, don't even try to reuse it
|
||||
-- just forget about it, and grab a new one.
|
||||
if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[type] then
|
||||
return newWidget(type)
|
||||
end
|
||||
end
|
||||
return newObj
|
||||
end
|
||||
-- Releases an instance to the Pool
|
||||
function delWidget(obj,type)
|
||||
if not objPools[type] then
|
||||
objPools[type] = {}
|
||||
end
|
||||
if objPools[type][obj] then
|
||||
error("Attempt to Release Widget that is already released", 2)
|
||||
end
|
||||
objPools[type][obj] = true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-------------------
|
||||
-- API Functions --
|
||||
-------------------
|
||||
|
||||
-- Gets a widget Object
|
||||
|
||||
--- Create a new Widget of the given type.
|
||||
-- This function will instantiate a new widget (or use one from the widget pool), and call the
|
||||
-- OnAcquire function on it, before returning.
|
||||
-- @param type The type of the widget.
|
||||
-- @return The newly created widget.
|
||||
function AceGUI:Create(type)
|
||||
if WidgetRegistry[type] then
|
||||
local widget = newWidget(type)
|
||||
|
||||
if rawget(widget, "Acquire") then
|
||||
widget.OnAcquire = widget.Acquire
|
||||
widget.Acquire = nil
|
||||
elseif rawget(widget, "Aquire") then
|
||||
widget.OnAcquire = widget.Aquire
|
||||
widget.Aquire = nil
|
||||
end
|
||||
|
||||
if rawget(widget, "Release") then
|
||||
widget.OnRelease = rawget(widget, "Release")
|
||||
widget.Release = nil
|
||||
end
|
||||
|
||||
if widget.OnAcquire then
|
||||
widget:OnAcquire()
|
||||
else
|
||||
error(("Widget type %s doesn't supply an OnAcquire Function"):format(type))
|
||||
end
|
||||
-- Set the default Layout ("List")
|
||||
safecall(widget.SetLayout, widget, "List")
|
||||
safecall(widget.ResumeLayout, widget)
|
||||
return widget
|
||||
end
|
||||
end
|
||||
|
||||
--- Releases a widget Object.
|
||||
-- This function calls OnRelease on the widget and places it back in the widget pool.
|
||||
-- Any data on the widget is being erased, and the widget will be hidden.\\
|
||||
-- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well.
|
||||
-- @param widget The widget to release
|
||||
function AceGUI:Release(widget)
|
||||
safecall(widget.PauseLayout, widget)
|
||||
widget:Fire("OnRelease")
|
||||
safecall(widget.ReleaseChildren, widget)
|
||||
|
||||
if widget.OnRelease then
|
||||
widget:OnRelease()
|
||||
-- else
|
||||
-- error(("Widget type %s doesn't supply an OnRelease Function"):format(widget.type))
|
||||
end
|
||||
for k in pairs(widget.userdata) do
|
||||
widget.userdata[k] = nil
|
||||
end
|
||||
for k in pairs(widget.events) do
|
||||
widget.events[k] = nil
|
||||
end
|
||||
widget.width = nil
|
||||
widget.relWidth = nil
|
||||
widget.height = nil
|
||||
widget.relHeight = nil
|
||||
widget.noAutoHeight = nil
|
||||
widget.frame:ClearAllPoints()
|
||||
widget.frame:Hide()
|
||||
widget.frame:SetParent(UIParent)
|
||||
widget.frame.width = nil
|
||||
widget.frame.height = nil
|
||||
if widget.content then
|
||||
widget.content.width = nil
|
||||
widget.content.height = nil
|
||||
end
|
||||
delWidget(widget, widget.type)
|
||||
end
|
||||
|
||||
-----------
|
||||
-- Focus --
|
||||
-----------
|
||||
|
||||
|
||||
--- Called when a widget has taken focus.
|
||||
-- e.g. Dropdowns opening, Editboxes gaining kb focus
|
||||
-- @param widget The widget that should be focused
|
||||
function AceGUI:SetFocus(widget)
|
||||
if self.FocusedWidget and self.FocusedWidget ~= widget then
|
||||
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
|
||||
end
|
||||
self.FocusedWidget = widget
|
||||
end
|
||||
|
||||
|
||||
--- Called when something has happened that could cause widgets with focus to drop it
|
||||
-- e.g. titlebar of a frame being clicked
|
||||
function AceGUI:ClearFocus()
|
||||
if self.FocusedWidget then
|
||||
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget)
|
||||
self.FocusedWidget = nil
|
||||
end
|
||||
end
|
||||
|
||||
-------------
|
||||
-- Widgets --
|
||||
-------------
|
||||
--[[
|
||||
Widgets must provide the following functions
|
||||
OnAcquire() - Called when the object is acquired, should set everything to a default hidden state
|
||||
|
||||
And the following members
|
||||
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
|
||||
type - the type of the object, same as the name given to :RegisterWidget()
|
||||
|
||||
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
|
||||
It will be cleared automatically when a widget is released
|
||||
Placing values directly into a widget object should be avoided
|
||||
|
||||
If the Widget can act as a container for other Widgets the following
|
||||
content - frame or derivitive that children will be anchored to
|
||||
|
||||
The Widget can supply the following Optional Members
|
||||
:OnRelease() - Called when the object is Released, should remove any additional anchors and clear any data
|
||||
:OnWidthSet(width) - Called when the width of the widget is changed
|
||||
:OnHeightSet(height) - Called when the height of the widget is changed
|
||||
Widgets should not use the OnSizeChanged events of thier frame or content members, use these methods instead
|
||||
AceGUI already sets a handler to the event
|
||||
:LayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the
|
||||
area used for controls. These can be nil if the layout used the existing size to layout the controls.
|
||||
|
||||
]]
|
||||
|
||||
--------------------------
|
||||
-- Widget Base Template --
|
||||
--------------------------
|
||||
do
|
||||
local WidgetBase = AceGUI.WidgetBase
|
||||
|
||||
WidgetBase.SetParent = function(self, parent)
|
||||
local frame = self.frame
|
||||
frame:SetParent(nil)
|
||||
frame:SetParent(parent.content)
|
||||
self.parent = parent
|
||||
end
|
||||
|
||||
WidgetBase.SetCallback = function(self, name, func)
|
||||
if type(func) == "function" then
|
||||
self.events[name] = func
|
||||
end
|
||||
end
|
||||
|
||||
WidgetBase.Fire = function(self, name, ...)
|
||||
if self.events[name] then
|
||||
local success, ret = safecall(self.events[name], self, name, ...)
|
||||
if success then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
WidgetBase.SetWidth = function(self, width)
|
||||
self.frame:SetWidth(width)
|
||||
self.frame.width = width
|
||||
if self.OnWidthSet then
|
||||
self:OnWidthSet(width)
|
||||
end
|
||||
end
|
||||
|
||||
WidgetBase.SetRelativeWidth = function(self, width)
|
||||
if width <= 0 or width > 1 then
|
||||
error(":SetRelativeWidth(width): Invalid relative width.", 2)
|
||||
end
|
||||
self.relWidth = width
|
||||
self.width = "relative"
|
||||
end
|
||||
|
||||
WidgetBase.SetHeight = function(self, height)
|
||||
self.frame:SetHeight(height)
|
||||
self.frame.height = height
|
||||
if self.OnHeightSet then
|
||||
self:OnHeightSet(height)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ WidgetBase.SetRelativeHeight = function(self, height)
|
||||
if height <= 0 or height > 1 then
|
||||
error(":SetRelativeHeight(height): Invalid relative height.", 2)
|
||||
end
|
||||
self.relHeight = height
|
||||
self.height = "relative"
|
||||
end ]]
|
||||
|
||||
WidgetBase.IsVisible = function(self)
|
||||
return self.frame:IsVisible()
|
||||
end
|
||||
|
||||
WidgetBase.IsShown= function(self)
|
||||
return self.frame:IsShown()
|
||||
end
|
||||
|
||||
WidgetBase.Release = function(self)
|
||||
AceGUI:Release(self)
|
||||
end
|
||||
|
||||
WidgetBase.SetPoint = function(self, ...)
|
||||
return self.frame:SetPoint(...)
|
||||
end
|
||||
|
||||
WidgetBase.ClearAllPoints = function(self)
|
||||
return self.frame:ClearAllPoints()
|
||||
end
|
||||
|
||||
WidgetBase.GetNumPoints = function(self)
|
||||
return self.frame:GetNumPoints()
|
||||
end
|
||||
|
||||
WidgetBase.GetPoint = function(self, ...)
|
||||
return self.frame:GetPoint(...)
|
||||
end
|
||||
|
||||
WidgetBase.GetUserDataTable = function(self)
|
||||
return self.userdata
|
||||
end
|
||||
|
||||
WidgetBase.SetUserData = function(self, key, value)
|
||||
self.userdata[key] = value
|
||||
end
|
||||
|
||||
WidgetBase.GetUserData = function(self, key)
|
||||
return self.userdata[key]
|
||||
end
|
||||
|
||||
WidgetBase.IsFullHeight = function(self)
|
||||
return self.height == "fill"
|
||||
end
|
||||
|
||||
WidgetBase.SetFullHeight = function(self, isFull)
|
||||
if isFull then
|
||||
self.height = "fill"
|
||||
else
|
||||
self.height = nil
|
||||
end
|
||||
end
|
||||
|
||||
WidgetBase.IsFullWidth = function(self)
|
||||
return self.width == "fill"
|
||||
end
|
||||
|
||||
WidgetBase.SetFullWidth = function(self, isFull)
|
||||
if isFull then
|
||||
self.width = "fill"
|
||||
else
|
||||
self.width = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- local function LayoutOnUpdate(this)
|
||||
-- this:SetScript("OnUpdate",nil)
|
||||
-- this.obj:PerformLayout()
|
||||
-- end
|
||||
|
||||
local WidgetContainerBase = AceGUI.WidgetContainerBase
|
||||
|
||||
WidgetContainerBase.PauseLayout = function(self)
|
||||
self.LayoutPaused = true
|
||||
end
|
||||
|
||||
WidgetContainerBase.ResumeLayout = function(self)
|
||||
self.LayoutPaused = nil
|
||||
end
|
||||
|
||||
WidgetContainerBase.PerformLayout = function(self)
|
||||
if self.LayoutPaused then
|
||||
return
|
||||
end
|
||||
safecall(self.LayoutFunc, self.content, self.children)
|
||||
end
|
||||
|
||||
--call this function to layout, makes sure layed out objects get a frame to get sizes etc
|
||||
WidgetContainerBase.DoLayout = function(self)
|
||||
self:PerformLayout()
|
||||
-- if not self.parent then
|
||||
-- self.frame:SetScript("OnUpdate", LayoutOnUpdate)
|
||||
-- end
|
||||
end
|
||||
|
||||
WidgetContainerBase.AddChild = function(self, child, beforeWidget)
|
||||
if beforeWidget then
|
||||
local siblingIndex = 1
|
||||
for _, widget in pairs(self.children) do
|
||||
if widget == beforeWidget then
|
||||
break
|
||||
end
|
||||
siblingIndex = siblingIndex + 1
|
||||
end
|
||||
tinsert(self.children, siblingIndex, child)
|
||||
else
|
||||
tinsert(self.children, child)
|
||||
end
|
||||
child:SetParent(self)
|
||||
child.frame:Show()
|
||||
self:DoLayout()
|
||||
end
|
||||
|
||||
WidgetContainerBase.AddChildren = function(self, ...)
|
||||
for i = 1, select("#", ...) do
|
||||
local child = select(i, ...)
|
||||
tinsert(self.children, child)
|
||||
child:SetParent(self)
|
||||
child.frame:Show()
|
||||
end
|
||||
self:DoLayout()
|
||||
end
|
||||
|
||||
WidgetContainerBase.ReleaseChildren = function(self)
|
||||
local children = self.children
|
||||
for i = 1,#children do
|
||||
AceGUI:Release(children[i])
|
||||
children[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
WidgetContainerBase.SetLayout = function(self, Layout)
|
||||
self.LayoutFunc = AceGUI:GetLayout(Layout)
|
||||
end
|
||||
|
||||
WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust)
|
||||
if adjust then
|
||||
self.noAutoHeight = nil
|
||||
else
|
||||
self.noAutoHeight = true
|
||||
end
|
||||
end
|
||||
|
||||
local function FrameResize(this)
|
||||
local self = this.obj
|
||||
if this:GetWidth() and this:GetHeight() then
|
||||
if self.OnWidthSet then
|
||||
self:OnWidthSet(this:GetWidth())
|
||||
end
|
||||
if self.OnHeightSet then
|
||||
self:OnHeightSet(this:GetHeight())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ContentResize(this)
|
||||
if this:GetWidth() and this:GetHeight() then
|
||||
this.width = this:GetWidth()
|
||||
this.height = this:GetHeight()
|
||||
this.obj:DoLayout()
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(WidgetContainerBase, {__index=WidgetBase})
|
||||
|
||||
--One of these function should be called on each Widget Instance as part of its creation process
|
||||
|
||||
--- Register a widget-class as a container for newly created widgets.
|
||||
-- @param widget The widget class
|
||||
function AceGUI:RegisterAsContainer(widget)
|
||||
widget.children = {}
|
||||
widget.userdata = {}
|
||||
widget.events = {}
|
||||
widget.base = WidgetContainerBase
|
||||
widget.content.obj = widget
|
||||
widget.frame.obj = widget
|
||||
widget.content:SetScript("OnSizeChanged", ContentResize)
|
||||
widget.frame:SetScript("OnSizeChanged", FrameResize)
|
||||
setmetatable(widget, {__index = WidgetContainerBase})
|
||||
widget:SetLayout("List")
|
||||
return widget
|
||||
end
|
||||
|
||||
--- Register a widget-class as a widget.
|
||||
-- @param widget The widget class
|
||||
function AceGUI:RegisterAsWidget(widget)
|
||||
widget.userdata = {}
|
||||
widget.events = {}
|
||||
widget.base = WidgetBase
|
||||
widget.frame.obj = widget
|
||||
widget.frame:SetScript("OnSizeChanged", FrameResize)
|
||||
setmetatable(widget, {__index = WidgetBase})
|
||||
return widget
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
------------------
|
||||
-- Widget API --
|
||||
------------------
|
||||
|
||||
--- Registers a widget Constructor, this function returns a new instance of the Widget
|
||||
-- @param Name The name of the widget
|
||||
-- @param Constructor The widget constructor function
|
||||
-- @param Version The version of the widget
|
||||
function AceGUI:RegisterWidgetType(Name, Constructor, Version)
|
||||
assert(type(Constructor) == "function")
|
||||
assert(type(Version) == "number")
|
||||
|
||||
local oldVersion = WidgetVersions[Name]
|
||||
if oldVersion and oldVersion >= Version then return end
|
||||
|
||||
WidgetVersions[Name] = Version
|
||||
WidgetRegistry[Name] = Constructor
|
||||
end
|
||||
|
||||
--- Registers a Layout Function
|
||||
-- @param Name The name of the layout
|
||||
-- @param LayoutFunc Reference to the layout function
|
||||
function AceGUI:RegisterLayout(Name, LayoutFunc)
|
||||
assert(type(LayoutFunc) == "function")
|
||||
if type(Name) == "string" then
|
||||
Name = Name:upper()
|
||||
end
|
||||
LayoutRegistry[Name] = LayoutFunc
|
||||
end
|
||||
|
||||
--- Get a Layout Function from the registry
|
||||
-- @param Name The name of the layout
|
||||
function AceGUI:GetLayout(Name)
|
||||
if type(Name) == "string" then
|
||||
Name = Name:upper()
|
||||
end
|
||||
return LayoutRegistry[Name]
|
||||
end
|
||||
|
||||
AceGUI.counts = AceGUI.counts or {}
|
||||
|
||||
--- A type-based counter to count the number of widgets created.
|
||||
-- This is used by widgets that require a named frame, e.g. when a Blizzard
|
||||
-- Template requires it.
|
||||
-- @param type The widget type
|
||||
function AceGUI:GetNextWidgetNum(type)
|
||||
if not self.counts[type] then
|
||||
self.counts[type] = 0
|
||||
end
|
||||
self.counts[type] = self.counts[type] + 1
|
||||
return self.counts[type]
|
||||
end
|
||||
|
||||
--- Return the number of created widgets for this type.
|
||||
-- In contrast to GetNextWidgetNum, the number is not incremented.
|
||||
-- @param type The widget type
|
||||
function AceGUI:GetWidgetCount(type)
|
||||
return self.counts[type] or 0
|
||||
end
|
||||
|
||||
--- Return the version of the currently registered widget type.
|
||||
-- @param type The widget type
|
||||
function AceGUI:GetWidgetVersion(type)
|
||||
return WidgetVersions[type]
|
||||
end
|
||||
|
||||
-------------
|
||||
-- Layouts --
|
||||
-------------
|
||||
|
||||
--[[
|
||||
A Layout is a func that takes 2 parameters
|
||||
content - the frame that widgets will be placed inside
|
||||
children - a table containing the widgets to layout
|
||||
]]
|
||||
|
||||
-- Very simple Layout, Children are stacked on top of each other down the left side
|
||||
AceGUI:RegisterLayout("List",
|
||||
function(content, children)
|
||||
local height = 0
|
||||
local width = content.width or content:GetWidth() or 0
|
||||
for i = 1, #children do
|
||||
local child = children[i]
|
||||
|
||||
local frame = child.frame
|
||||
frame:ClearAllPoints()
|
||||
frame:Show()
|
||||
if i == 1 then
|
||||
frame:SetPoint("TOPLEFT", content)
|
||||
else
|
||||
frame:SetPoint("TOPLEFT", children[i-1].frame, "BOTTOMLEFT")
|
||||
end
|
||||
|
||||
if child.width == "fill" then
|
||||
child:SetWidth(width)
|
||||
frame:SetPoint("RIGHT", content)
|
||||
|
||||
if child.DoLayout then
|
||||
child:DoLayout()
|
||||
end
|
||||
elseif child.width == "relative" then
|
||||
child:SetWidth(width * child.relWidth)
|
||||
|
||||
if child.DoLayout then
|
||||
child:DoLayout()
|
||||
end
|
||||
end
|
||||
|
||||
height = height + (frame.height or frame:GetHeight() or 0)
|
||||
end
|
||||
safecall(content.obj.LayoutFinished, content.obj, nil, height)
|
||||
end)
|
||||
|
||||
-- A single control fills the whole content area
|
||||
AceGUI:RegisterLayout("Fill",
|
||||
function(content, children)
|
||||
if children[1] then
|
||||
children[1]:SetWidth(content:GetWidth() or 0)
|
||||
children[1]:SetHeight(content:GetHeight() or 0)
|
||||
children[1].frame:SetAllPoints(content)
|
||||
children[1].frame:Show()
|
||||
safecall(content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight())
|
||||
end
|
||||
end)
|
||||
|
||||
AceGUI:RegisterLayout("Flow",
|
||||
function(content, children)
|
||||
--used height so far
|
||||
local height = 0
|
||||
--width used in the current row
|
||||
local usedwidth = 0
|
||||
--height of the current row
|
||||
local rowheight = 0
|
||||
local rowoffset = 0
|
||||
local lastrowoffset
|
||||
|
||||
local width = content.width or content:GetWidth() or 0
|
||||
|
||||
--control at the start of the row
|
||||
local rowstart
|
||||
local rowstartoffset
|
||||
local lastrowstart
|
||||
local isfullheight
|
||||
|
||||
local frameoffset
|
||||
local lastframeoffset
|
||||
local oversize
|
||||
for i = 1, #children do
|
||||
local child = children[i]
|
||||
oversize = nil
|
||||
local frame = child.frame
|
||||
local frameheight = frame.height or frame:GetHeight() or 0
|
||||
local framewidth = frame.width or frame:GetWidth() or 0
|
||||
lastframeoffset = frameoffset
|
||||
-- HACK: Why did we set a frameoffset of (frameheight / 2) ?
|
||||
-- That was moving all widgets half the widgets size down, is that intended?
|
||||
-- Actually, it seems to be neccessary for many cases, we'll leave it in for now.
|
||||
-- If widgets seem to anchor weirdly with this, provide a valid alignoffset for them.
|
||||
-- TODO: Investigate moar!
|
||||
frameoffset = child.alignoffset or (frameheight / 2)
|
||||
|
||||
if child.width == "relative" then
|
||||
framewidth = width * child.relWidth
|
||||
end
|
||||
|
||||
frame:Show()
|
||||
frame:ClearAllPoints()
|
||||
if i == 1 then
|
||||
-- anchor the first control to the top left
|
||||
frame:SetPoint("TOPLEFT", content)
|
||||
rowheight = frameheight
|
||||
rowoffset = frameoffset
|
||||
rowstart = frame
|
||||
rowstartoffset = frameoffset
|
||||
usedwidth = framewidth
|
||||
if usedwidth > width then
|
||||
oversize = true
|
||||
end
|
||||
else
|
||||
-- if there isn't available width for the control start a new row
|
||||
-- if a control is "fill" it will be on a row of its own full width
|
||||
if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then
|
||||
if isfullheight then
|
||||
-- a previous row has already filled the entire height, there's nothing we can usefully do anymore
|
||||
-- (maybe error/warn about this?)
|
||||
break
|
||||
end
|
||||
--anchor the previous row, we will now know its height and offset
|
||||
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
|
||||
height = height + rowheight + 3
|
||||
--save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it
|
||||
rowstart = frame
|
||||
rowstartoffset = frameoffset
|
||||
rowheight = frameheight
|
||||
rowoffset = frameoffset
|
||||
usedwidth = framewidth
|
||||
if usedwidth > width then
|
||||
oversize = true
|
||||
end
|
||||
-- put the control on the current row, adding it to the width and checking if the height needs to be increased
|
||||
else
|
||||
--handles cases where the new height is higher than either control because of the offsets
|
||||
--math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset)
|
||||
|
||||
--offset is always the larger of the two offsets
|
||||
rowoffset = math_max(rowoffset, frameoffset)
|
||||
rowheight = math_max(rowheight, rowoffset + (frameheight / 2))
|
||||
|
||||
frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT", 0, frameoffset - lastframeoffset)
|
||||
usedwidth = framewidth + usedwidth
|
||||
end
|
||||
end
|
||||
|
||||
if child.width == "fill" then
|
||||
child:SetWidth(width)
|
||||
frame:SetPoint("RIGHT", content)
|
||||
|
||||
usedwidth = 0
|
||||
rowstart = frame
|
||||
rowstartoffset = frameoffset
|
||||
|
||||
if child.DoLayout then
|
||||
child:DoLayout()
|
||||
end
|
||||
rowheight = frame.height or frame:GetHeight() or 0
|
||||
rowoffset = child.alignoffset or (rowheight / 2)
|
||||
rowstartoffset = rowoffset
|
||||
elseif child.width == "relative" then
|
||||
child:SetWidth(width * child.relWidth)
|
||||
|
||||
if child.DoLayout then
|
||||
child:DoLayout()
|
||||
end
|
||||
elseif oversize then
|
||||
if width > 1 then
|
||||
frame:SetPoint("RIGHT", content)
|
||||
end
|
||||
end
|
||||
|
||||
if child.height == "fill" then
|
||||
frame:SetPoint("BOTTOM", content)
|
||||
isfullheight = true
|
||||
end
|
||||
end
|
||||
|
||||
--anchor the last row, if its full height needs a special case since its height has just been changed by the anchor
|
||||
if isfullheight then
|
||||
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height)
|
||||
elseif rowstart then
|
||||
rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3))
|
||||
end
|
||||
|
||||
height = height + rowheight + 3
|
||||
safecall(content.obj.LayoutFinished, content.obj, nil, height)
|
||||
end)
|
||||
@@ -0,0 +1,28 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceGUI-3.0.lua"/>
|
||||
<!-- Container -->
|
||||
<Script file="widgets\AceGUIContainer-BlizOptionsGroup.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-DropDownGroup.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-Frame.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-InlineGroup.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-ScrollFrame.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-SimpleGroup.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-TabGroup.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-TreeGroup.lua"/>
|
||||
<Script file="widgets\AceGUIContainer-Window.lua"/>
|
||||
<!-- Widgets -->
|
||||
<Script file="widgets\AceGUIWidget-Button.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-CheckBox.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-ColorPicker.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-DropDown.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-DropDown-Items.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-EditBox.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-Heading.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-Icon.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-InteractiveLabel.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-Keybinding.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-Label.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-MultiLineEditBox.lua"/>
|
||||
<Script file="widgets\AceGUIWidget-Slider.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,133 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
BlizOptionsGroup Container
|
||||
Simple container widget for the integration of AceGUI into the Blizzard Interface Options
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "BlizOptionsGroup", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs = pairs
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
|
||||
local function OnShow(frame)
|
||||
frame.obj:Fire("OnShow")
|
||||
end
|
||||
|
||||
local function OnHide(frame)
|
||||
frame.obj:Fire("OnHide")
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Support functions
|
||||
-------------------------------------------------------------------------------]]
|
||||
|
||||
local function okay(frame)
|
||||
frame.obj:Fire("okay")
|
||||
end
|
||||
|
||||
local function cancel(frame)
|
||||
frame.obj:Fire("cancel")
|
||||
end
|
||||
|
||||
local function defaults(frame)
|
||||
frame.obj:Fire("defaults")
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self:SetName()
|
||||
self:SetTitle()
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["OnWidthSet"] = function(self, width)
|
||||
local content = self.content
|
||||
local contentwidth = width - 63
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
end,
|
||||
|
||||
["OnHeightSet"] = function(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - 26
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end,
|
||||
|
||||
["SetName"] = function(self, name, parent)
|
||||
self.frame.name = name
|
||||
self.frame.parent = parent
|
||||
end,
|
||||
|
||||
["SetTitle"] = function(self, title)
|
||||
local content = self.content
|
||||
content:ClearAllPoints()
|
||||
if not title or title == "" then
|
||||
content:SetPoint("TOPLEFT", 10, -10)
|
||||
self.label:SetText("")
|
||||
else
|
||||
content:SetPoint("TOPLEFT", 10, -40)
|
||||
self.label:SetText(title)
|
||||
end
|
||||
content:SetPoint("BOTTOMRIGHT", -10, 10)
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame")
|
||||
frame:Hide()
|
||||
|
||||
-- support functions for the Blizzard Interface Options
|
||||
frame.okay = okay
|
||||
frame.cancel = cancel
|
||||
frame.defaults = defaults
|
||||
|
||||
frame:SetScript("OnHide", OnHide)
|
||||
frame:SetScript("OnShow", OnShow)
|
||||
|
||||
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
|
||||
label:SetPoint("TOPLEFT", 10, -15)
|
||||
label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
|
||||
label:SetJustifyH("LEFT")
|
||||
label:SetJustifyV("TOP")
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame", nil, frame)
|
||||
content:SetPoint("TOPLEFT", 10, -10)
|
||||
content:SetPoint("BOTTOMRIGHT", -10, 10)
|
||||
|
||||
local widget = {
|
||||
label = label,
|
||||
frame = frame,
|
||||
content = content,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsContainer(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,178 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local assert, pairs, type = assert, pairs, type
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
--[[
|
||||
Selection Group controls all have an interface to select a group for thier contents
|
||||
None of them will auto size to thier contents, and should usually be used with a scrollframe
|
||||
unless you know that the controls will fit inside
|
||||
]]
|
||||
|
||||
--------------------------
|
||||
-- Dropdown Group --
|
||||
--------------------------
|
||||
--[[
|
||||
Events :
|
||||
OnGroupSelected
|
||||
|
||||
]]
|
||||
do
|
||||
local Type = "DropdownGroup"
|
||||
local Version = 13
|
||||
|
||||
local function OnAcquire(self)
|
||||
self.dropdown:SetText("")
|
||||
self:SetDropdownWidth(200)
|
||||
self:SetTitle("")
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self.dropdown.list = nil
|
||||
self.status = nil
|
||||
for k in pairs(self.localstatus) do
|
||||
self.localstatus[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local PaneBackdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 5, bottom = 3 }
|
||||
}
|
||||
|
||||
local function SetTitle(self,title)
|
||||
self.titletext:SetText(title)
|
||||
self.dropdown.frame:ClearAllPoints()
|
||||
if title and title ~= "" then
|
||||
self.dropdown.frame:SetPoint("TOPRIGHT", self.frame, "TOPRIGHT", -2, 0)
|
||||
else
|
||||
self.dropdown.frame:SetPoint("TOPLEFT", self.frame, "TOPLEFT", -1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function SelectedGroup(self,event,value)
|
||||
local group = self.parentgroup
|
||||
local status = group.status or group.localstatus
|
||||
status.selected = value
|
||||
self.parentgroup:Fire("OnGroupSelected", value)
|
||||
end
|
||||
|
||||
local function SetGroupList(self,list)
|
||||
self.dropdown:SetList(list)
|
||||
end
|
||||
|
||||
-- called to set an external table to store status in
|
||||
local function SetStatusTable(self, status)
|
||||
assert(type(status) == "table")
|
||||
self.status = status
|
||||
end
|
||||
|
||||
local function SetGroup(self,group)
|
||||
self.dropdown:SetValue(group)
|
||||
local status = self.status or self.localstatus
|
||||
status.selected = group
|
||||
self:Fire("OnGroupSelected", group)
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
local contentwidth = width - 26
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
end
|
||||
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - 63
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end
|
||||
|
||||
local function LayoutFinished(self, width, height)
|
||||
self:SetHeight((height or 0) + 63)
|
||||
end
|
||||
|
||||
local function SetDropdownWidth(self, width)
|
||||
self.dropdown:SetWidth(width)
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame")
|
||||
local self = {}
|
||||
self.type = Type
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
|
||||
self.SetTitle = SetTitle
|
||||
self.SetGroupList = SetGroupList
|
||||
self.SetGroup = SetGroup
|
||||
self.SetStatusTable = SetStatusTable
|
||||
self.SetDropdownWidth = SetDropdownWidth
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
self.LayoutFinished = LayoutFinished
|
||||
|
||||
self.localstatus = {}
|
||||
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
|
||||
frame:SetHeight(100)
|
||||
frame:SetWidth(100)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
local titletext = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
titletext:SetPoint("TOPLEFT", frame, "TOPLEFT", 4, -5)
|
||||
titletext:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -4, -5)
|
||||
titletext:SetJustifyH("LEFT")
|
||||
titletext:SetHeight(18)
|
||||
self.titletext = titletext
|
||||
|
||||
local dropdown = AceGUI:Create("Dropdown")
|
||||
self.dropdown = dropdown
|
||||
dropdown.frame:SetParent(frame)
|
||||
dropdown.frame:SetFrameLevel(dropdown.frame:GetFrameLevel() + 2)
|
||||
dropdown.parentgroup = self
|
||||
dropdown:SetCallback("OnValueChanged",SelectedGroup)
|
||||
dropdown.frame:SetPoint("TOPLEFT",frame,"TOPLEFT", -1, 0)
|
||||
dropdown.frame:Show()
|
||||
dropdown:SetLabel("")
|
||||
|
||||
local border = CreateFrame("Frame",nil,frame)
|
||||
self.border = border
|
||||
border:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-26)
|
||||
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,3)
|
||||
|
||||
border:SetBackdrop(PaneBackdrop)
|
||||
border:SetBackdropColor(0.1,0.1,0.1,0.5)
|
||||
border:SetBackdropBorderColor(0.4,0.4,0.4)
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame",nil,border)
|
||||
self.content = content
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT",border,"TOPLEFT",10,-10)
|
||||
content:SetPoint("BOTTOMRIGHT",border,"BOTTOMRIGHT",-10,10)
|
||||
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,288 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Frame Container
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "Frame", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs, assert, type = pairs, assert, type
|
||||
local wipe = table.wipe
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: CLOSE
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Button_OnClick(frame)
|
||||
PlaySound("gsTitleOptionExit")
|
||||
frame.obj:Hide()
|
||||
end
|
||||
|
||||
local function Frame_OnClose(frame)
|
||||
frame.obj:Fire("OnClose")
|
||||
end
|
||||
|
||||
local function Frame_OnMouseDown(frame)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function Title_OnMouseDown(frame)
|
||||
frame:GetParent():StartMoving()
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function MoverSizer_OnMouseUp(mover)
|
||||
local frame = mover:GetParent()
|
||||
frame:StopMovingOrSizing()
|
||||
local self = frame.obj
|
||||
local status = self.status or self.localstatus
|
||||
status.width = frame:GetWidth()
|
||||
status.height = frame:GetHeight()
|
||||
status.top = frame:GetTop()
|
||||
status.left = frame:GetLeft()
|
||||
end
|
||||
|
||||
local function SizerSE_OnMouseDown(frame)
|
||||
frame:GetParent():StartSizing("BOTTOMRIGHT")
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function SizerS_OnMouseDown(frame)
|
||||
frame:GetParent():StartSizing("BOTTOM")
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function SizerE_OnMouseDown(frame)
|
||||
frame:GetParent():StartSizing("RIGHT")
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self.frame:SetParent(UIParent)
|
||||
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
self:SetTitle()
|
||||
self:SetStatusText()
|
||||
self:ApplyStatus()
|
||||
self:Show()
|
||||
end,
|
||||
|
||||
["OnRelease"] = function(self)
|
||||
self.status = nil
|
||||
wipe(self.localstatus)
|
||||
end,
|
||||
|
||||
["OnWidthSet"] = function(self, width)
|
||||
local content = self.content
|
||||
local contentwidth = width - 34
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
end,
|
||||
|
||||
["OnHeightSet"] = function(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - 57
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end,
|
||||
|
||||
["SetTitle"] = function(self, title)
|
||||
self.titletext:SetText(title)
|
||||
end,
|
||||
|
||||
["SetStatusText"] = function(self, text)
|
||||
self.statustext:SetText(text)
|
||||
end,
|
||||
|
||||
["Hide"] = function(self)
|
||||
self.frame:Hide()
|
||||
end,
|
||||
|
||||
["Show"] = function(self)
|
||||
self.frame:Show()
|
||||
end,
|
||||
|
||||
-- called to set an external table to store status in
|
||||
["SetStatusTable"] = function(self, status)
|
||||
assert(type(status) == "table")
|
||||
self.status = status
|
||||
self:ApplyStatus()
|
||||
end,
|
||||
|
||||
["ApplyStatus"] = function(self)
|
||||
local status = self.status or self.localstatus
|
||||
local frame = self.frame
|
||||
self:SetWidth(status.width or 700)
|
||||
self:SetHeight(status.height or 500)
|
||||
frame:ClearAllPoints()
|
||||
if status.top and status.left then
|
||||
frame:SetPoint("TOP", UIParent, "BOTTOM", 0, status.top)
|
||||
frame:SetPoint("LEFT", UIParent, "LEFT", status.left, 0)
|
||||
else
|
||||
frame:SetPoint("CENTER")
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local FrameBackdrop = {
|
||||
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
|
||||
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
||||
tile = true, tileSize = 32, edgeSize = 32,
|
||||
insets = { left = 8, right = 8, top = 8, bottom = 8 }
|
||||
}
|
||||
|
||||
local PaneBackdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 5, bottom = 3 }
|
||||
}
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:SetMovable(true)
|
||||
frame:SetResizable(true)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
frame:SetBackdrop(FrameBackdrop)
|
||||
frame:SetBackdropColor(0, 0, 0, 1)
|
||||
frame:SetMinResize(400, 200)
|
||||
frame:SetToplevel(true)
|
||||
frame:SetScript("OnHide", Frame_OnClose)
|
||||
frame:SetScript("OnMouseDown", Frame_OnMouseDown)
|
||||
|
||||
local closebutton = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
|
||||
closebutton:SetScript("OnClick", Button_OnClick)
|
||||
closebutton:SetPoint("BOTTOMRIGHT", -27, 17)
|
||||
closebutton:SetHeight(20)
|
||||
closebutton:SetWidth(100)
|
||||
closebutton:SetText(CLOSE)
|
||||
|
||||
local statusbg = CreateFrame("Frame", nil, frame)
|
||||
statusbg:SetPoint("BOTTOMLEFT", 15, 15)
|
||||
statusbg:SetPoint("BOTTOMRIGHT", -132, 15)
|
||||
statusbg:SetHeight(24)
|
||||
statusbg:SetBackdrop(PaneBackdrop)
|
||||
statusbg:SetBackdropColor(0.1,0.1,0.1)
|
||||
statusbg:SetBackdropBorderColor(0.4,0.4,0.4)
|
||||
|
||||
local statustext = statusbg:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
statustext:SetPoint("TOPLEFT", 7, -2)
|
||||
statustext:SetPoint("BOTTOMRIGHT", -7, 2)
|
||||
statustext:SetHeight(20)
|
||||
statustext:SetJustifyH("LEFT")
|
||||
statustext:SetText("")
|
||||
|
||||
local titlebg = frame:CreateTexture(nil, "OVERLAY")
|
||||
titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
|
||||
titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
|
||||
titlebg:SetPoint("TOP", 0, 12)
|
||||
titlebg:SetWidth(100)
|
||||
titlebg:SetHeight(40)
|
||||
|
||||
local title = CreateFrame("Frame", nil, frame)
|
||||
title:EnableMouse(true)
|
||||
title:SetScript("OnMouseDown", Title_OnMouseDown)
|
||||
title:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
|
||||
title:SetAllPoints(titlebg)
|
||||
|
||||
local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||||
titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
|
||||
|
||||
local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
|
||||
titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
|
||||
titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
|
||||
titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
|
||||
titlebg_l:SetWidth(30)
|
||||
titlebg_l:SetHeight(40)
|
||||
|
||||
local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
|
||||
titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
|
||||
titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
|
||||
titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
|
||||
titlebg_r:SetWidth(30)
|
||||
titlebg_r:SetHeight(40)
|
||||
|
||||
local sizer_se = CreateFrame("Frame", nil, frame)
|
||||
sizer_se:SetPoint("BOTTOMRIGHT")
|
||||
sizer_se:SetWidth(25)
|
||||
sizer_se:SetHeight(25)
|
||||
sizer_se:EnableMouse()
|
||||
sizer_se:SetScript("OnMouseDown",SizerSE_OnMouseDown)
|
||||
sizer_se:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
|
||||
|
||||
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
|
||||
line1:SetWidth(14)
|
||||
line1:SetHeight(14)
|
||||
line1:SetPoint("BOTTOMRIGHT", -8, 8)
|
||||
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
local x = 0.1 * 14/17
|
||||
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
|
||||
|
||||
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
|
||||
line2:SetWidth(8)
|
||||
line2:SetHeight(8)
|
||||
line2:SetPoint("BOTTOMRIGHT", -8, 8)
|
||||
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
local x = 0.1 * 8/17
|
||||
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
|
||||
|
||||
local sizer_s = CreateFrame("Frame", nil, frame)
|
||||
sizer_s:SetPoint("BOTTOMRIGHT", -25, 0)
|
||||
sizer_s:SetPoint("BOTTOMLEFT")
|
||||
sizer_s:SetHeight(25)
|
||||
sizer_s:EnableMouse(true)
|
||||
sizer_s:SetScript("OnMouseDown", SizerS_OnMouseDown)
|
||||
sizer_s:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
|
||||
|
||||
local sizer_e = CreateFrame("Frame", nil, frame)
|
||||
sizer_e:SetPoint("BOTTOMRIGHT", 0, 25)
|
||||
sizer_e:SetPoint("TOPRIGHT")
|
||||
sizer_e:SetWidth(25)
|
||||
sizer_e:EnableMouse(true)
|
||||
sizer_e:SetScript("OnMouseDown", SizerE_OnMouseDown)
|
||||
sizer_e:SetScript("OnMouseUp", MoverSizer_OnMouseUp)
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame", nil, frame)
|
||||
content:SetPoint("TOPLEFT", 17, -27)
|
||||
content:SetPoint("BOTTOMRIGHT", -17, 40)
|
||||
|
||||
local widget = {
|
||||
localstatus = {},
|
||||
titletext = titletext,
|
||||
statustext = statustext,
|
||||
content = content,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
closebutton.obj = widget
|
||||
|
||||
return AceGUI:RegisterAsContainer(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,138 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-------------
|
||||
-- Widgets --
|
||||
-------------
|
||||
--[[
|
||||
Widgets must provide the following functions
|
||||
Acquire() - Called when the object is aquired, should set everything to a default hidden state
|
||||
Release() - Called when the object is Released, should remove any anchors and hide the Widget
|
||||
|
||||
And the following members
|
||||
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
|
||||
type - the type of the object, same as the name given to :RegisterWidget()
|
||||
|
||||
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
|
||||
It will be cleared automatically when a widget is released
|
||||
Placing values directly into a widget object should be avoided
|
||||
|
||||
If the Widget can act as a container for other Widgets the following
|
||||
content - frame or derivitive that children will be anchored to
|
||||
|
||||
The Widget can supply the following Optional Members
|
||||
|
||||
|
||||
]]
|
||||
|
||||
--------------------------
|
||||
-- Inline Group --
|
||||
--------------------------
|
||||
--[[
|
||||
This is a simple grouping container, no selection
|
||||
It will resize automatically to the height of the controls added to it
|
||||
]]
|
||||
|
||||
do
|
||||
local Type = "InlineGroup"
|
||||
local Version = 6
|
||||
|
||||
local function OnAcquire(self)
|
||||
self:SetWidth(300)
|
||||
self:SetHeight(100)
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
local PaneBackdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 5, bottom = 3 }
|
||||
}
|
||||
|
||||
local function SetTitle(self,title)
|
||||
self.titletext:SetText(title)
|
||||
end
|
||||
|
||||
|
||||
local function LayoutFinished(self, width, height)
|
||||
if self.noAutoHeight then return end
|
||||
self:SetHeight((height or 0) + 40)
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
local contentwidth = width - 20
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
end
|
||||
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - 20
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local self = {}
|
||||
self.type = Type
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
self.SetTitle = SetTitle
|
||||
self.frame = frame
|
||||
self.LayoutFinished = LayoutFinished
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
|
||||
frame.obj = self
|
||||
|
||||
frame:SetHeight(100)
|
||||
frame:SetWidth(100)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
|
||||
titletext:SetPoint("TOPLEFT",frame,"TOPLEFT",14,0)
|
||||
titletext:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-14,0)
|
||||
titletext:SetJustifyH("LEFT")
|
||||
titletext:SetHeight(18)
|
||||
|
||||
self.titletext = titletext
|
||||
|
||||
local border = CreateFrame("Frame",nil,frame)
|
||||
self.border = border
|
||||
border:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-17)
|
||||
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-1,3)
|
||||
|
||||
border:SetBackdrop(PaneBackdrop)
|
||||
border:SetBackdropColor(0.1,0.1,0.1,0.5)
|
||||
border:SetBackdropBorderColor(0.4,0.4,0.4)
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame",nil,border)
|
||||
self.content = content
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT",border,"TOPLEFT",10,-10)
|
||||
content:SetPoint("BOTTOMRIGHT",border,"BOTTOMRIGHT",-10,10)
|
||||
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,241 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local pairs, assert, type = pairs, assert, type
|
||||
local min, max, floor = math.min, math.max, math.floor
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
|
||||
-------------
|
||||
-- Widgets --
|
||||
-------------
|
||||
--[[
|
||||
Widgets must provide the following functions
|
||||
Acquire() - Called when the object is aquired, should set everything to a default hidden state
|
||||
Release() - Called when the object is Released, should remove any anchors and hide the Widget
|
||||
|
||||
And the following members
|
||||
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
|
||||
type - the type of the object, same as the name given to :RegisterWidget()
|
||||
|
||||
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
|
||||
It will be cleared automatically when a widget is released
|
||||
Placing values directly into a widget object should be avoided
|
||||
|
||||
If the Widget can act as a container for other Widgets the following
|
||||
content - frame or derivitive that children will be anchored to
|
||||
|
||||
The Widget can supply the following Optional Members
|
||||
|
||||
|
||||
]]
|
||||
|
||||
--------------------------
|
||||
-- Scroll Frame --
|
||||
--------------------------
|
||||
do
|
||||
local Type = "ScrollFrame"
|
||||
local Version = 9
|
||||
|
||||
local function OnAcquire(self)
|
||||
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self.status = nil
|
||||
-- do SetScroll after niling status, but before clearing localstatus
|
||||
-- so the scroll value isnt populated back into status, but not kept in localstatus either
|
||||
self:SetScroll(0)
|
||||
for k in pairs(self.localstatus) do
|
||||
self.localstatus[k] = nil
|
||||
end
|
||||
self.scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,0)
|
||||
self.scrollbar:Hide()
|
||||
self.scrollBarShown = nil
|
||||
self.content.height, self.content.width = nil, nil
|
||||
end
|
||||
|
||||
local function SetScroll(self, value)
|
||||
local status = self.status or self.localstatus
|
||||
local viewheight = self.scrollframe:GetHeight()
|
||||
local height = self.content:GetHeight()
|
||||
local offset
|
||||
|
||||
if viewheight > height then
|
||||
offset = 0
|
||||
else
|
||||
offset = floor((height - viewheight) / 1000.0 * value)
|
||||
end
|
||||
self.content:ClearAllPoints()
|
||||
self.content:SetPoint("TOPLEFT", self.scrollframe, "TOPLEFT", 0, offset)
|
||||
self.content:SetPoint("TOPRIGHT", self.scrollframe, "TOPRIGHT", 0, offset)
|
||||
status.offset = offset
|
||||
status.scrollvalue = value
|
||||
end
|
||||
|
||||
local function MoveScroll(self, value)
|
||||
local status = self.status or self.localstatus
|
||||
local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
|
||||
|
||||
if height > viewheight then
|
||||
self.scrollbar:Hide()
|
||||
else
|
||||
self.scrollbar:Show()
|
||||
local diff = height - viewheight
|
||||
local delta = 1
|
||||
if value < 0 then
|
||||
delta = -1
|
||||
end
|
||||
self.scrollbar:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function FixScroll(self)
|
||||
if self.updateLock then return end
|
||||
self.updateLock = true
|
||||
local status = self.status or self.localstatus
|
||||
local height, viewheight = self.scrollframe:GetHeight(), self.content:GetHeight()
|
||||
local offset = status.offset or 0
|
||||
local curvalue = self.scrollbar:GetValue()
|
||||
if viewheight < height then
|
||||
if self.scrollBarShown then
|
||||
self.scrollBarShown = nil
|
||||
self.scrollbar:Hide()
|
||||
self.scrollbar:SetValue(0)
|
||||
self.scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,0)
|
||||
self:DoLayout()
|
||||
end
|
||||
else
|
||||
if not self.scrollBarShown then
|
||||
self.scrollBarShown = true
|
||||
self.scrollbar:Show()
|
||||
self.scrollframe:SetPoint("BOTTOMRIGHT", self.frame,"BOTTOMRIGHT",-20,0)
|
||||
self:DoLayout()
|
||||
end
|
||||
local value = (offset / (viewheight - height) * 1000)
|
||||
if value > 1000 then value = 1000 end
|
||||
self.scrollbar:SetValue(value)
|
||||
self:SetScroll(value)
|
||||
if value < 1000 then
|
||||
self.content:ClearAllPoints()
|
||||
self.content:SetPoint("TOPLEFT", self.scrollframe, "TOPLEFT", 0, offset)
|
||||
self.content:SetPoint("TOPRIGHT", self.scrollframe, "TOPRIGHT", 0, offset)
|
||||
status.offset = offset
|
||||
end
|
||||
end
|
||||
self.updateLock = nil
|
||||
end
|
||||
|
||||
local function OnMouseWheel(this, value)
|
||||
this.obj:MoveScroll(value)
|
||||
end
|
||||
|
||||
local function OnScrollValueChanged(this, value)
|
||||
this.obj:SetScroll(value)
|
||||
end
|
||||
|
||||
local function FixScrollOnUpdate(this)
|
||||
this:SetScript("OnUpdate", nil)
|
||||
this.obj:FixScroll()
|
||||
end
|
||||
|
||||
local function OnSizeChanged(this)
|
||||
this:SetScript("OnUpdate", FixScrollOnUpdate)
|
||||
end
|
||||
|
||||
local function LayoutFinished(self, width, height)
|
||||
self.content:SetHeight(height or 0 + 20)
|
||||
self.scrollframe:SetScript("OnUpdate", FixScrollOnUpdate)
|
||||
end
|
||||
|
||||
-- called to set an external table to store status in
|
||||
local function SetStatusTable(self, status)
|
||||
assert(type(status) == "table")
|
||||
self.status = status
|
||||
if not status.scrollvalue then
|
||||
status.scrollvalue = 0
|
||||
end
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
content.width = width
|
||||
end
|
||||
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
content.height = height
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
local self = {}
|
||||
self.type = Type
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
|
||||
self.MoveScroll = MoveScroll
|
||||
self.FixScroll = FixScroll
|
||||
self.SetScroll = SetScroll
|
||||
self.LayoutFinished = LayoutFinished
|
||||
self.SetStatusTable = SetStatusTable
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
|
||||
self.localstatus = {}
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
|
||||
--Container Support
|
||||
local scrollframe = CreateFrame("ScrollFrame", nil, frame)
|
||||
scrollframe.obj = self
|
||||
scrollframe:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, 0)
|
||||
scrollframe:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", 0, 0)
|
||||
scrollframe:EnableMouseWheel(true)
|
||||
scrollframe:SetScript("OnMouseWheel", OnMouseWheel)
|
||||
scrollframe:SetScript("OnSizeChanged", OnSizeChanged)
|
||||
self.scrollframe = scrollframe
|
||||
|
||||
local content = CreateFrame("Frame", nil, scrollframe)
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT", scrollframe, "TOPLEFT", 0, 0)
|
||||
content:SetPoint("TOPRIGHT", scrollframe, "TOPRIGHT", 0, 0)
|
||||
content:SetHeight(400)
|
||||
self.content = content
|
||||
scrollframe:SetScrollChild(content)
|
||||
|
||||
local num = AceGUI:GetNextWidgetNum(Type)
|
||||
local name = ("AceConfigDialogScrollFrame%dScrollBar"):format(num)
|
||||
local scrollbar = CreateFrame("Slider", name, scrollframe, "UIPanelScrollBarTemplate")
|
||||
scrollbar.obj = self
|
||||
scrollbar:SetPoint("TOPLEFT", scrollframe, "TOPRIGHT", 4, -16)
|
||||
scrollbar:SetPoint("BOTTOMLEFT", scrollframe, "BOTTOMRIGHT", 4, 16)
|
||||
scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
|
||||
scrollbar:SetMinMaxValues(0, 1000)
|
||||
scrollbar:SetValueStep(1)
|
||||
scrollbar:SetValue(0)
|
||||
scrollbar:SetWidth(16)
|
||||
scrollbar:Hide()
|
||||
self.scrollbar = scrollbar
|
||||
|
||||
local scrollbg = scrollbar:CreateTexture(nil, "BACKGROUND")
|
||||
scrollbg:SetAllPoints(scrollbar)
|
||||
scrollbg:SetTexture(0, 0, 0, 0.4)
|
||||
|
||||
self.localstatus.scrollvalue = 0
|
||||
|
||||
--self:FixScroll()
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
--AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-------------
|
||||
-- Widgets --
|
||||
-------------
|
||||
--[[
|
||||
Widgets must provide the following functions
|
||||
Acquire() - Called when the object is aquired, should set everything to a default hidden state
|
||||
Release() - Called when the object is Released, should remove any anchors and hide the Widget
|
||||
|
||||
And the following members
|
||||
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
|
||||
type - the type of the object, same as the name given to :RegisterWidget()
|
||||
|
||||
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
|
||||
It will be cleared automatically when a widget is released
|
||||
Placing values directly into a widget object should be avoided
|
||||
|
||||
If the Widget can act as a container for other Widgets the following
|
||||
content - frame or derivitive that children will be anchored to
|
||||
|
||||
The Widget can supply the following Optional Members
|
||||
|
||||
|
||||
]]
|
||||
|
||||
--------------------------
|
||||
-- Simple Group --
|
||||
--------------------------
|
||||
--[[
|
||||
This is a simple grouping container, no selection, no borders
|
||||
It will resize automatically to the height of the controls added to it
|
||||
]]
|
||||
|
||||
do
|
||||
local Type = "SimpleGroup"
|
||||
local Version = 5
|
||||
|
||||
local function OnAcquire(self)
|
||||
self:SetWidth(300)
|
||||
self:SetHeight(100)
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
local function LayoutFinished(self, width, height)
|
||||
if self.noAutoHeight then return end
|
||||
self:SetHeight(height or 0)
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
content:SetWidth(width)
|
||||
content.width = width
|
||||
end
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
content:SetHeight(height)
|
||||
content.height = height
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local self = {}
|
||||
self.type = Type
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
self.frame = frame
|
||||
self.LayoutFinished = LayoutFinished
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
|
||||
frame.obj = self
|
||||
|
||||
frame:SetHeight(100)
|
||||
frame:SetWidth(100)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame",nil,frame)
|
||||
self.content = content
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
|
||||
content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
|
||||
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,389 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local pairs, ipairs, assert, type = pairs, ipairs, assert, type
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: PanelTemplates_TabResize, PanelTemplates_SetDisabledTabState, PanelTemplates_SelectTab, PanelTemplates_DeselectTab
|
||||
|
||||
-------------
|
||||
-- Widgets --
|
||||
-------------
|
||||
--[[
|
||||
Widgets must provide the following functions
|
||||
Acquire() - Called when the object is aquired, should set everything to a default hidden state
|
||||
Release() - Called when the object is Released, should remove any anchors and hide the Widget
|
||||
|
||||
And the following members
|
||||
frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes
|
||||
type - the type of the object, same as the name given to :RegisterWidget()
|
||||
|
||||
Widgets contain a table called userdata, this is a safe place to store data associated with the wigdet
|
||||
It will be cleared automatically when a widget is released
|
||||
Placing values directly into a widget object should be avoided
|
||||
|
||||
If the Widget can act as a container for other Widgets the following
|
||||
content - frame or derivitive that children will be anchored to
|
||||
|
||||
The Widget can supply the following Optional Members
|
||||
|
||||
|
||||
]]
|
||||
|
||||
--------------------------
|
||||
-- Tab Group --
|
||||
--------------------------
|
||||
|
||||
do
|
||||
local Type = "TabGroup"
|
||||
local Version = 25
|
||||
|
||||
local PaneBackdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 5, bottom = 3 }
|
||||
}
|
||||
|
||||
local function OnAcquire(self)
|
||||
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self.status = nil
|
||||
for k in pairs(self.localstatus) do
|
||||
self.localstatus[k] = nil
|
||||
end
|
||||
self.tablist = nil
|
||||
for _, tab in pairs(self.tabs) do
|
||||
tab:Hide()
|
||||
end
|
||||
self:SetTitle()
|
||||
end
|
||||
|
||||
local function Tab_SetText(self, text)
|
||||
self:_SetText(text)
|
||||
local width = self.obj.frame.width or self.obj.frame:GetWidth() or 0
|
||||
PanelTemplates_TabResize(self, 0, nil, width)
|
||||
end
|
||||
|
||||
local function UpdateTabLook(self)
|
||||
if self.disabled then
|
||||
PanelTemplates_SetDisabledTabState(self)
|
||||
elseif self.selected then
|
||||
PanelTemplates_SelectTab(self)
|
||||
else
|
||||
PanelTemplates_DeselectTab(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function Tab_SetSelected(self, selected)
|
||||
self.selected = selected
|
||||
UpdateTabLook(self)
|
||||
end
|
||||
|
||||
local function Tab_OnClick(self)
|
||||
if not (self.selected or self.disabled) then
|
||||
PlaySound("igCharacterInfoTab")
|
||||
self.obj:SelectTab(self.value)
|
||||
end
|
||||
end
|
||||
|
||||
local function Tab_SetDisabled(self, disabled)
|
||||
self.disabled = disabled
|
||||
UpdateTabLook(self)
|
||||
end
|
||||
|
||||
local function Tab_OnEnter(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnTabEnter", self.tabs[this.id].value, this)
|
||||
end
|
||||
|
||||
local function Tab_OnLeave(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnTabLeave", self.tabs[this.id].value, this)
|
||||
end
|
||||
|
||||
local function Tab_OnShow(this)
|
||||
_G[this:GetName().."HighlightTexture"]:SetWidth(this:GetTextWidth() + 30)
|
||||
end
|
||||
|
||||
local function CreateTab(self, id)
|
||||
local tabname = "AceGUITabGroup"..self.num.."Tab"..id
|
||||
local tab = CreateFrame("Button",tabname,self.border,"OptionsFrameTabButtonTemplate")
|
||||
tab.obj = self
|
||||
tab.id = id
|
||||
|
||||
tab.text = _G[tabname .. "Text"]
|
||||
tab.text:ClearAllPoints()
|
||||
tab.text:SetPoint("LEFT", tab, "LEFT", 14, -3)
|
||||
tab.text:SetPoint("RIGHT", tab, "RIGHT", -12, -3)
|
||||
|
||||
tab:SetScript("OnClick",Tab_OnClick)
|
||||
tab:SetScript("OnEnter",Tab_OnEnter)
|
||||
tab:SetScript("OnLeave",Tab_OnLeave)
|
||||
tab:SetScript("OnShow", Tab_OnShow)
|
||||
|
||||
tab._SetText = tab.SetText
|
||||
tab.SetText = Tab_SetText
|
||||
tab.SetSelected = Tab_SetSelected
|
||||
tab.SetDisabled = Tab_SetDisabled
|
||||
|
||||
return tab
|
||||
end
|
||||
|
||||
local function SetTitle(self, text)
|
||||
self.titletext:SetText(text or "")
|
||||
if text and text ~= "" then
|
||||
self.alignoffset = 25
|
||||
else
|
||||
self.alignoffset = 18
|
||||
end
|
||||
self:BuildTabs()
|
||||
end
|
||||
|
||||
-- called to set an external table to store status in
|
||||
local function SetStatusTable(self, status)
|
||||
assert(type(status) == "table")
|
||||
self.status = status
|
||||
end
|
||||
|
||||
local function SelectTab(self, value)
|
||||
local status = self.status or self.localstatus
|
||||
|
||||
local found
|
||||
for i, v in ipairs(self.tabs) do
|
||||
if v.value == value then
|
||||
v:SetSelected(true)
|
||||
found = true
|
||||
else
|
||||
v:SetSelected(false)
|
||||
end
|
||||
end
|
||||
status.selected = value
|
||||
if found then
|
||||
self:Fire("OnGroupSelected",value)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetTabs(self, tabs)
|
||||
self.tablist = tabs
|
||||
self:BuildTabs()
|
||||
end
|
||||
|
||||
|
||||
local widths = {}
|
||||
local rowwidths = {}
|
||||
local rowends = {}
|
||||
local function BuildTabs(self)
|
||||
local hastitle = (self.titletext:GetText() and self.titletext:GetText() ~= "")
|
||||
local status = self.status or self.localstatus
|
||||
local tablist = self.tablist
|
||||
local tabs = self.tabs
|
||||
|
||||
if not tablist then return end
|
||||
|
||||
local width = self.frame.width or self.frame:GetWidth() or 0
|
||||
|
||||
for i = #widths, 1, -1 do
|
||||
widths[i] = nil
|
||||
end
|
||||
for i = #rowwidths, 1, -1 do
|
||||
rowwidths[i] = nil
|
||||
end
|
||||
for i = #rowends, 1, -1 do
|
||||
rowends[i] = nil
|
||||
end
|
||||
|
||||
--Place Text into tabs and get thier initial width
|
||||
for i, v in ipairs(tablist) do
|
||||
local tab = tabs[i]
|
||||
if not tab then
|
||||
tab = self:CreateTab(i)
|
||||
tabs[i] = tab
|
||||
end
|
||||
|
||||
tab:Show()
|
||||
tab:SetText(v.text)
|
||||
tab:SetDisabled(v.disabled)
|
||||
tab.value = v.value
|
||||
|
||||
widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text
|
||||
end
|
||||
|
||||
for i = (#tablist)+1, #tabs, 1 do
|
||||
tabs[i]:Hide()
|
||||
end
|
||||
|
||||
--First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout
|
||||
local numtabs = #tablist
|
||||
local numrows = 1
|
||||
local usedwidth = 0
|
||||
|
||||
for i = 1, #tablist do
|
||||
--If this is not the first tab of a row and there isn't room for it
|
||||
if usedwidth ~= 0 and (width - usedwidth - widths[i]) < 0 then
|
||||
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
|
||||
rowends[numrows] = i - 1
|
||||
numrows = numrows + 1
|
||||
usedwidth = 0
|
||||
end
|
||||
usedwidth = usedwidth + widths[i]
|
||||
end
|
||||
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px
|
||||
rowends[numrows] = #tablist
|
||||
|
||||
--Fix for single tabs being left on the last row, move a tab from the row above if applicable
|
||||
if numrows > 1 then
|
||||
--if the last row has only one tab
|
||||
if rowends[numrows-1] == numtabs-1 then
|
||||
--if there are more than 2 tabs in the 2nd last row
|
||||
if (numrows == 2 and rowends[numrows-1] > 2) or (rowends[numrows] - rowends[numrows-1] > 2) then
|
||||
--move 1 tab from the second last row to the last, if there is enough space
|
||||
if (rowwidths[numrows] + widths[numtabs-1]) <= width then
|
||||
rowends[numrows-1] = rowends[numrows-1] - 1
|
||||
rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1]
|
||||
rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--anchor the rows as defined and resize tabs to fill thier row
|
||||
local starttab = 1
|
||||
for row, endtab in ipairs(rowends) do
|
||||
local first = true
|
||||
for tabno = starttab, endtab do
|
||||
local tab = tabs[tabno]
|
||||
tab:ClearAllPoints()
|
||||
if first then
|
||||
tab:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 0, -(hastitle and 14 or 7)-(row-1)*20 )
|
||||
first = false
|
||||
else
|
||||
tab:SetPoint("LEFT", tabs[tabno-1], "RIGHT", -10, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- equal padding for each tab to fill the available width,
|
||||
-- if the used space is above 75% already
|
||||
local padding = 0
|
||||
if not (numrows == 1 and rowwidths[1] < width*0.75) then
|
||||
padding = (width - rowwidths[row]) / (endtab - starttab+1)
|
||||
end
|
||||
|
||||
for i = starttab, endtab do
|
||||
PanelTemplates_TabResize(tabs[i], padding + 4, nil, width)
|
||||
end
|
||||
starttab = endtab + 1
|
||||
end
|
||||
|
||||
self.borderoffset = (hastitle and 17 or 10)+((numrows)*20)
|
||||
self.border:SetPoint("TOPLEFT",self.frame,"TOPLEFT",1,-self.borderoffset)
|
||||
end
|
||||
|
||||
local function BuildTabsOnUpdate(this)
|
||||
BuildTabs(this.obj)
|
||||
this:SetScript("OnUpdate", nil)
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
local contentwidth = width - 60
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
BuildTabs(self)
|
||||
self.frame:SetScript("OnUpdate", BuildTabsOnUpdate)
|
||||
end
|
||||
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - (self.borderoffset + 23)
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end
|
||||
|
||||
local function LayoutFinished(self, width, height)
|
||||
if self.noAutoHeight then return end
|
||||
self:SetHeight((height or 0) + (self.borderoffset + 23))
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local self = {}
|
||||
self.type = Type
|
||||
|
||||
self.num = AceGUI:GetNextWidgetNum(Type)
|
||||
|
||||
self.localstatus = {}
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
self.SetTitle = SetTitle
|
||||
self.CreateTab = CreateTab
|
||||
self.SelectTab = SelectTab
|
||||
self.BuildTabs = BuildTabs
|
||||
self.SetStatusTable = SetStatusTable
|
||||
self.SetTabs = SetTabs
|
||||
self.LayoutFinished = LayoutFinished
|
||||
self.frame = frame
|
||||
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
|
||||
frame.obj = self
|
||||
|
||||
frame:SetHeight(100)
|
||||
frame:SetWidth(100)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
self.alignoffset = 18
|
||||
|
||||
local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
|
||||
titletext:SetPoint("TOPLEFT",frame,"TOPLEFT",14,0)
|
||||
titletext:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-14,0)
|
||||
titletext:SetJustifyH("LEFT")
|
||||
titletext:SetHeight(18)
|
||||
titletext:SetText("")
|
||||
|
||||
self.titletext = titletext
|
||||
|
||||
local border = CreateFrame("Frame",nil,frame)
|
||||
self.border = border
|
||||
self.borderoffset = 27
|
||||
border:SetPoint("TOPLEFT",frame,"TOPLEFT",1,-27)
|
||||
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-1,3)
|
||||
|
||||
border:SetBackdrop(PaneBackdrop)
|
||||
border:SetBackdropColor(0.1,0.1,0.1,0.5)
|
||||
border:SetBackdropBorderColor(0.4,0.4,0.4)
|
||||
|
||||
self.tabs = {}
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame",nil,border)
|
||||
self.content = content
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT",border,"TOPLEFT",10,-7)
|
||||
content:SetPoint("BOTTOMRIGHT",border,"BOTTOMRIGHT",-10,7)
|
||||
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,746 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local next, pairs, ipairs, assert, type = next, pairs, ipairs, assert, type
|
||||
local math_min, math_max, floor = math.min, math.max, floor
|
||||
local select, tremove, unpack = select, table.remove, unpack
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: GameTooltip, FONT_COLOR_CODE_CLOSE
|
||||
|
||||
-- Recycling functions
|
||||
local new, del
|
||||
do
|
||||
local pool = setmetatable({},{__mode='k'})
|
||||
function new()
|
||||
local t = next(pool)
|
||||
if t then
|
||||
pool[t] = nil
|
||||
return t
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
function del(t)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
pool[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
--------------
|
||||
-- TreeView --
|
||||
--------------
|
||||
|
||||
do
|
||||
local Type = "TreeGroup"
|
||||
local Version = 23
|
||||
|
||||
local DEFAULT_TREE_WIDTH = 175
|
||||
local DEFAULT_TREE_SIZABLE = true
|
||||
|
||||
local PaneBackdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 5, bottom = 3 }
|
||||
}
|
||||
|
||||
local DraggerBackdrop = {
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = nil,
|
||||
tile = true, tileSize = 16, edgeSize = 0,
|
||||
insets = { left = 3, right = 3, top = 7, bottom = 7 }
|
||||
}
|
||||
|
||||
local function OnAcquire(self)
|
||||
self:SetTreeWidth(DEFAULT_TREE_WIDTH,DEFAULT_TREE_SIZABLE)
|
||||
self:EnableButtonTooltips(true)
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self.status = nil
|
||||
for k, v in pairs(self.localstatus) do
|
||||
if k == "groups" then
|
||||
for k2 in pairs(v) do
|
||||
v[k2] = nil
|
||||
end
|
||||
else
|
||||
self.localstatus[k] = nil
|
||||
end
|
||||
end
|
||||
self.localstatus.scrollvalue = 0
|
||||
self.localstatus.treewidth = DEFAULT_TREE_WIDTH
|
||||
self.localstatus.treesizable = DEFAULT_TREE_SIZABLE
|
||||
end
|
||||
|
||||
local function GetButtonParents(line)
|
||||
local parent = line.parent
|
||||
if parent and parent.value then
|
||||
return parent.value, GetButtonParents(parent)
|
||||
end
|
||||
end
|
||||
|
||||
local function GetButtonUniqueValue(line)
|
||||
local parent = line.parent
|
||||
if parent and parent.value then
|
||||
return GetButtonUniqueValue(parent).."\001"..line.value
|
||||
else
|
||||
return line.value
|
||||
end
|
||||
end
|
||||
|
||||
local function ButtonOnClick(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnClick",this.uniquevalue, this.selected)
|
||||
if not this.selected then
|
||||
self:SetSelected(this.uniquevalue)
|
||||
this.selected = true
|
||||
this:LockHighlight()
|
||||
self:RefreshTree()
|
||||
end
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function ExpandOnClick(this)
|
||||
local button = this.button
|
||||
local self = button.obj
|
||||
local status = (self.status or self.localstatus).groups
|
||||
status[button.uniquevalue] = not status[button.uniquevalue]
|
||||
self:RefreshTree()
|
||||
end
|
||||
|
||||
local function ButtonOnDoubleClick(button)
|
||||
local self = button.obj
|
||||
local status = self.status or self.localstatus
|
||||
local status = (self.status or self.localstatus).groups
|
||||
status[button.uniquevalue] = not status[button.uniquevalue]
|
||||
self:RefreshTree()
|
||||
end
|
||||
|
||||
local function EnableButtonTooltips(self, enable)
|
||||
self.enabletooltips = enable
|
||||
end
|
||||
|
||||
local function Button_OnEnter(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnButtonEnter", this.uniquevalue, this)
|
||||
|
||||
if self.enabletooltips then
|
||||
GameTooltip:SetOwner(this, "ANCHOR_NONE")
|
||||
GameTooltip:SetPoint("LEFT",this,"RIGHT")
|
||||
GameTooltip:SetText(this.text:GetText() or "", 1, .82, 0, 1)
|
||||
|
||||
GameTooltip:Show()
|
||||
end
|
||||
end
|
||||
|
||||
local function Button_OnLeave(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnButtonLeave", this.uniquevalue, this)
|
||||
|
||||
if self.enabletooltips then
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local buttoncount = 1
|
||||
local function CreateButton(self)
|
||||
local button = CreateFrame("Button",("AceGUI30TreeButton%d"):format(buttoncount),self.treeframe, "OptionsListButtonTemplate")
|
||||
buttoncount = buttoncount + 1
|
||||
button.obj = self
|
||||
|
||||
local icon = button:CreateTexture(nil, "OVERLAY")
|
||||
icon:SetWidth(14)
|
||||
icon:SetHeight(14)
|
||||
button.icon = icon
|
||||
|
||||
button:SetScript("OnClick",ButtonOnClick)
|
||||
button:SetScript("OnDoubleClick", ButtonOnDoubleClick)
|
||||
button:SetScript("OnEnter",Button_OnEnter)
|
||||
button:SetScript("OnLeave",Button_OnLeave)
|
||||
|
||||
button.toggle.button = button
|
||||
button.toggle:SetScript("OnClick",ExpandOnClick)
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
local function UpdateButton(button, treeline, selected, canExpand, isExpanded)
|
||||
local self = button.obj
|
||||
local toggle = button.toggle
|
||||
local frame = self.frame
|
||||
local text = treeline.text or ""
|
||||
local icon = treeline.icon
|
||||
local iconCoords = treeline.iconCoords
|
||||
local level = treeline.level
|
||||
local value = treeline.value
|
||||
local uniquevalue = treeline.uniquevalue
|
||||
local disabled = treeline.disabled
|
||||
|
||||
button.treeline = treeline
|
||||
button.value = value
|
||||
button.uniquevalue = uniquevalue
|
||||
if selected then
|
||||
button:LockHighlight()
|
||||
button.selected = true
|
||||
else
|
||||
button:UnlockHighlight()
|
||||
button.selected = false
|
||||
end
|
||||
local normalTexture = button:GetNormalTexture()
|
||||
local line = button.line
|
||||
button.level = level
|
||||
if ( level == 1 ) then
|
||||
button:SetNormalFontObject("GameFontNormal")
|
||||
button:SetHighlightFontObject("GameFontHighlight")
|
||||
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2)
|
||||
else
|
||||
button:SetNormalFontObject("GameFontHighlightSmall")
|
||||
button:SetHighlightFontObject("GameFontHighlightSmall")
|
||||
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2)
|
||||
end
|
||||
|
||||
if disabled then
|
||||
button:EnableMouse(false)
|
||||
button.text:SetText("|cff808080"..text..FONT_COLOR_CODE_CLOSE)
|
||||
else
|
||||
button.text:SetText(text)
|
||||
button:EnableMouse(true)
|
||||
end
|
||||
|
||||
if icon then
|
||||
button.icon:SetTexture(icon)
|
||||
button.icon:SetPoint("LEFT", button, "LEFT", 8 * level, (level == 1) and 0 or 1)
|
||||
else
|
||||
button.icon:SetTexture(nil)
|
||||
end
|
||||
|
||||
if iconCoords then
|
||||
button.icon:SetTexCoord(unpack(iconCoords))
|
||||
else
|
||||
button.icon:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
|
||||
if canExpand then
|
||||
if not isExpanded then
|
||||
toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP")
|
||||
toggle:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-DOWN")
|
||||
else
|
||||
toggle:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-UP")
|
||||
toggle:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-DOWN")
|
||||
end
|
||||
toggle:Show()
|
||||
else
|
||||
toggle:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function OnScrollValueChanged(this, value)
|
||||
if this.obj.noupdate then return end
|
||||
local self = this.obj
|
||||
local status = self.status or self.localstatus
|
||||
status.scrollvalue = value
|
||||
self:RefreshTree()
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
-- called to set an external table to store status in
|
||||
local function SetStatusTable(self, status)
|
||||
assert(type(status) == "table")
|
||||
self.status = status
|
||||
if not status.groups then
|
||||
status.groups = {}
|
||||
end
|
||||
if not status.scrollvalue then
|
||||
status.scrollvalue = 0
|
||||
end
|
||||
if not status.treewidth then
|
||||
status.treewidth = DEFAULT_TREE_WIDTH
|
||||
end
|
||||
if not status.treesizable then
|
||||
status.treesizable = DEFAULT_TREE_SIZABLE
|
||||
end
|
||||
self:SetTreeWidth(status.treewidth,status.treesizable)
|
||||
self:RefreshTree()
|
||||
end
|
||||
|
||||
--sets the tree to be displayed
|
||||
--[[
|
||||
example tree
|
||||
|
||||
Alpha
|
||||
Bravo
|
||||
-Charlie
|
||||
-Delta
|
||||
-Echo
|
||||
Foxtrot
|
||||
|
||||
tree = {
|
||||
{
|
||||
value = "A",
|
||||
text = "Alpha"
|
||||
},
|
||||
{
|
||||
value = "B",
|
||||
text = "Bravo",
|
||||
children = {
|
||||
{
|
||||
value = "C",
|
||||
text = "Charlie"
|
||||
},
|
||||
{
|
||||
value = "D",
|
||||
text = "Delta"
|
||||
children = {
|
||||
{
|
||||
value = "E",
|
||||
text = "Echo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
value = "F",
|
||||
text = "Foxtrot"
|
||||
},
|
||||
}
|
||||
]]
|
||||
local function SetTree(self, tree, filter)
|
||||
self.filter = filter
|
||||
if tree then
|
||||
assert(type(tree) == "table")
|
||||
end
|
||||
self.tree = tree
|
||||
self:RefreshTree()
|
||||
end
|
||||
|
||||
local function ShouldDisplayLevel(tree)
|
||||
local result = false
|
||||
for k, v in ipairs(tree) do
|
||||
if v.children == nil and v.visible ~= false then
|
||||
result = true
|
||||
elseif v.children then
|
||||
result = result or ShouldDisplayLevel(v.children)
|
||||
end
|
||||
if result then return result end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function addLine(self, v, tree, level, parent)
|
||||
local line = new()
|
||||
line.value = v.value
|
||||
line.text = v.text
|
||||
line.icon = v.icon
|
||||
line.iconCoords = v.iconCoords
|
||||
line.disabled = v.disabled
|
||||
line.tree = tree
|
||||
line.level = level
|
||||
line.parent = parent
|
||||
line.visible = v.visible
|
||||
line.uniquevalue = GetButtonUniqueValue(line)
|
||||
if v.children then
|
||||
line.hasChildren = true
|
||||
else
|
||||
line.hasChildren = nil
|
||||
end
|
||||
self.lines[#self.lines+1] = line
|
||||
return line
|
||||
end
|
||||
|
||||
local function BuildLevel(self, tree, level, parent)
|
||||
local groups = (self.status or self.localstatus).groups
|
||||
local hasChildren = self.hasChildren
|
||||
|
||||
for i, v in ipairs(tree) do
|
||||
if v.children then
|
||||
if not self.filter or ShouldDisplayLevel(v.children) then
|
||||
local line = addLine(self, v, tree, level, parent)
|
||||
if groups[line.uniquevalue] then
|
||||
self:BuildLevel(v.children, level+1, line)
|
||||
end
|
||||
end
|
||||
elseif v.visible ~= false or not self.filter then
|
||||
addLine(self, v, tree, level, parent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--fire an update after one frame to catch the treeframes height
|
||||
local function FirstFrameUpdate(this)
|
||||
local self = this.obj
|
||||
this:SetScript("OnUpdate",nil)
|
||||
self:RefreshTree()
|
||||
end
|
||||
|
||||
local function ResizeUpdate(this)
|
||||
this.obj:RefreshTree()
|
||||
end
|
||||
|
||||
local function RefreshTree(self)
|
||||
local buttons = self.buttons
|
||||
local lines = self.lines
|
||||
|
||||
for i, v in ipairs(buttons) do
|
||||
v:Hide()
|
||||
end
|
||||
while lines[1] do
|
||||
local t = tremove(lines)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
del(t)
|
||||
end
|
||||
|
||||
if not self.tree then return end
|
||||
--Build the list of visible entries from the tree and status tables
|
||||
local status = self.status or self.localstatus
|
||||
local groupstatus = status.groups
|
||||
local tree = self.tree
|
||||
|
||||
local treeframe = self.treeframe
|
||||
|
||||
self:BuildLevel(tree, 1)
|
||||
|
||||
local numlines = #lines
|
||||
|
||||
local maxlines = (floor(((self.treeframe:GetHeight()or 0) - 20 ) / 18))
|
||||
|
||||
local first, last
|
||||
|
||||
if numlines <= maxlines then
|
||||
--the whole tree fits in the frame
|
||||
status.scrollvalue = 0
|
||||
self:ShowScroll(false)
|
||||
first, last = 1, numlines
|
||||
else
|
||||
self:ShowScroll(true)
|
||||
--scrolling will be needed
|
||||
self.noupdate = true
|
||||
self.scrollbar:SetMinMaxValues(0, numlines - maxlines)
|
||||
--check if we are scrolled down too far
|
||||
if numlines - status.scrollvalue < maxlines then
|
||||
status.scrollvalue = numlines - maxlines
|
||||
self.scrollbar:SetValue(status.scrollvalue)
|
||||
end
|
||||
self.noupdate = nil
|
||||
first, last = status.scrollvalue+1, status.scrollvalue + maxlines
|
||||
end
|
||||
|
||||
local buttonnum = 1
|
||||
for i = first, last do
|
||||
local line = lines[i]
|
||||
local button = buttons[buttonnum]
|
||||
if not button then
|
||||
button = self:CreateButton()
|
||||
|
||||
buttons[buttonnum] = button
|
||||
button:SetParent(treeframe)
|
||||
button:SetFrameLevel(treeframe:GetFrameLevel()+1)
|
||||
button:ClearAllPoints()
|
||||
if i == 1 then
|
||||
if self.showscroll then
|
||||
button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
|
||||
button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10)
|
||||
else
|
||||
button:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
|
||||
button:SetPoint("TOPLEFT", self.treeframe, "TOPLEFT", 0, -10)
|
||||
end
|
||||
else
|
||||
button:SetPoint("TOPRIGHT", buttons[buttonnum-1], "BOTTOMRIGHT",0,0)
|
||||
button:SetPoint("TOPLEFT", buttons[buttonnum-1], "BOTTOMLEFT",0,0)
|
||||
end
|
||||
end
|
||||
|
||||
UpdateButton(button, line, status.selected == line.uniquevalue, line.hasChildren, groupstatus[line.uniquevalue] )
|
||||
button:Show()
|
||||
buttonnum = buttonnum + 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function SetSelected(self, value)
|
||||
local status = self.status or self.localstatus
|
||||
if status.selected ~= value then
|
||||
status.selected = value
|
||||
self:Fire("OnGroupSelected", value)
|
||||
end
|
||||
end
|
||||
|
||||
local function BuildUniqueValue(...)
|
||||
local n = select('#', ...)
|
||||
if n == 1 then
|
||||
return ...
|
||||
else
|
||||
return (...).."\001"..BuildUniqueValue(select(2,...))
|
||||
end
|
||||
end
|
||||
|
||||
local function Select(self, uniquevalue, ...)
|
||||
self.filter = false
|
||||
local status = self.status or self.localstatus
|
||||
local groups = status.groups
|
||||
for i = 1, select('#', ...) do
|
||||
groups[BuildUniqueValue(select(i, ...))] = true
|
||||
end
|
||||
status.selected = uniquevalue
|
||||
self:RefreshTree()
|
||||
self:Fire("OnGroupSelected", uniquevalue)
|
||||
end
|
||||
|
||||
local function SelectByPath(self, ...)
|
||||
self:Select(BuildUniqueValue(...), ...)
|
||||
end
|
||||
|
||||
--Selects a tree node by UniqueValue
|
||||
local function SelectByValue(self, uniquevalue)
|
||||
self:Select(uniquevalue, ("\001"):split(uniquevalue))
|
||||
end
|
||||
|
||||
|
||||
local function ShowScroll(self, show)
|
||||
self.showscroll = show
|
||||
if show then
|
||||
self.scrollbar:Show()
|
||||
if self.buttons[1] then
|
||||
self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",-22,-10)
|
||||
end
|
||||
else
|
||||
self.scrollbar:Hide()
|
||||
if self.buttons[1] then
|
||||
self.buttons[1]:SetPoint("TOPRIGHT", self.treeframe,"TOPRIGHT",0,-10)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
local treeframe = self.treeframe
|
||||
local status = self.status or self.localstatus
|
||||
status.fullwidth = width
|
||||
|
||||
local contentwidth = width - status.treewidth - 20
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
|
||||
local maxtreewidth = math_min(400, width - 50)
|
||||
|
||||
if maxtreewidth > 100 and status.treewidth > maxtreewidth then
|
||||
self:SetTreeWidth(maxtreewidth, status.treesizable)
|
||||
end
|
||||
treeframe:SetMaxResize(maxtreewidth,1600)
|
||||
end
|
||||
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - 20
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end
|
||||
|
||||
|
||||
local function TreeOnMouseWheel(this, delta)
|
||||
local self = this.obj
|
||||
if self.showscroll then
|
||||
local scrollbar = self.scrollbar
|
||||
local min, max = scrollbar:GetMinMaxValues()
|
||||
local value = scrollbar:GetValue()
|
||||
local newvalue = math_min(max,math_max(min,value - delta))
|
||||
if value ~= newvalue then
|
||||
scrollbar:SetValue(newvalue)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function SetTreeWidth(self, treewidth, resizable)
|
||||
if not resizable then
|
||||
if type(treewidth) == 'number' then
|
||||
resizable = false
|
||||
elseif type(treewidth) == 'boolean' then
|
||||
resizable = treewidth
|
||||
treewidth = DEFAULT_TREE_WIDTH
|
||||
else
|
||||
resizable = false
|
||||
treewidth = DEFAULT_TREE_WIDTH
|
||||
end
|
||||
end
|
||||
self.treeframe:SetWidth(treewidth)
|
||||
self.dragger:EnableMouse(resizable)
|
||||
|
||||
local status = self.status or self.localstatus
|
||||
status.treewidth = treewidth
|
||||
status.treesizable = resizable
|
||||
|
||||
-- recalculate the content width
|
||||
if status.fullwidth then
|
||||
self:OnWidthSet(status.fullwidth)
|
||||
end
|
||||
end
|
||||
|
||||
local function draggerLeave(this)
|
||||
this:SetBackdropColor(1, 1, 1, 0)
|
||||
end
|
||||
|
||||
local function draggerEnter(this)
|
||||
this:SetBackdropColor(1, 1, 1, 0.8)
|
||||
end
|
||||
|
||||
local function draggerDown(this)
|
||||
local treeframe = this:GetParent()
|
||||
treeframe:StartSizing("RIGHT")
|
||||
end
|
||||
|
||||
local function draggerUp(this)
|
||||
local treeframe = this:GetParent()
|
||||
local self = treeframe.obj
|
||||
local frame = treeframe:GetParent()
|
||||
treeframe:StopMovingOrSizing()
|
||||
--treeframe:SetScript("OnUpdate", nil)
|
||||
treeframe:SetUserPlaced(false)
|
||||
--Without this :GetHeight will get stuck on the current height, causing the tree contents to not resize
|
||||
treeframe:SetHeight(0)
|
||||
treeframe:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
|
||||
treeframe:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
|
||||
|
||||
local status = self.status or self.localstatus
|
||||
status.treewidth = treeframe:GetWidth()
|
||||
|
||||
treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth())
|
||||
-- recalculate the content width
|
||||
treeframe.obj:OnWidthSet(status.fullwidth)
|
||||
-- update the layout of the content
|
||||
treeframe.obj:DoLayout()
|
||||
end
|
||||
|
||||
local function LayoutFinished(self, width, height)
|
||||
if self.noAutoHeight then return end
|
||||
self:SetHeight((height or 0) + 20)
|
||||
end
|
||||
|
||||
local createdcount = 0
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local self = {}
|
||||
self.type = Type
|
||||
self.lines = {}
|
||||
self.levels = {}
|
||||
self.buttons = {}
|
||||
self.hasChildren = {}
|
||||
self.localstatus = {}
|
||||
self.localstatus.groups = {}
|
||||
self.filter = false
|
||||
|
||||
local treeframe = CreateFrame("Frame",nil,frame)
|
||||
treeframe.obj = self
|
||||
treeframe:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
|
||||
treeframe:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
|
||||
treeframe:SetWidth(DEFAULT_TREE_WIDTH)
|
||||
treeframe:SetScript("OnUpdate",FirstFrameUpdate)
|
||||
treeframe:SetScript("OnSizeChanged",ResizeUpdate)
|
||||
|
||||
treeframe:EnableMouseWheel(true)
|
||||
treeframe:SetScript("OnMouseWheel", TreeOnMouseWheel)
|
||||
treeframe:SetBackdrop(PaneBackdrop)
|
||||
treeframe:SetBackdropColor(0.1,0.1,0.1,0.5)
|
||||
treeframe:SetBackdropBorderColor(0.4,0.4,0.4)
|
||||
|
||||
treeframe:SetResizable(true)
|
||||
treeframe:SetMinResize(100, 1)
|
||||
treeframe:SetMaxResize(400,1600)
|
||||
local dragger = CreateFrame("Frame", nil, treeframe)
|
||||
dragger:SetWidth(8)
|
||||
dragger:SetPoint("TOP", treeframe, "TOPRIGHT")
|
||||
dragger:SetPoint("BOTTOM", treeframe, "BOTTOMRIGHT")
|
||||
dragger:SetBackdrop(DraggerBackdrop)
|
||||
dragger:SetBackdropColor(1, 1, 1, 0)
|
||||
dragger:SetScript("OnMouseDown", draggerDown)
|
||||
dragger:SetScript("OnMouseUp", draggerUp)
|
||||
dragger:SetScript("OnEnter", draggerEnter)
|
||||
dragger:SetScript("OnLeave", draggerLeave)
|
||||
|
||||
self.dragger = dragger
|
||||
self.treeframe = treeframe
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
|
||||
self.SetTree = SetTree
|
||||
self.SetTreeWidth = SetTreeWidth
|
||||
self.RefreshTree = RefreshTree
|
||||
self.SetStatusTable = SetStatusTable
|
||||
self.BuildLevel = BuildLevel
|
||||
self.CreateButton = CreateButton
|
||||
self.SetSelected = SetSelected
|
||||
self.ShowScroll = ShowScroll
|
||||
self.SetStatusTable = SetStatusTable
|
||||
self.Select = Select
|
||||
self.SelectByValue = SelectByValue
|
||||
self.SelectByPath = SelectByPath
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
self.EnableButtonTooltips = EnableButtonTooltips
|
||||
--self.Filter = Filter
|
||||
self.LayoutFinished = LayoutFinished
|
||||
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
|
||||
createdcount = createdcount + 1
|
||||
local scrollbar = CreateFrame("Slider",("AceConfigDialogTreeGroup%dScrollBar"):format(createdcount),treeframe,"UIPanelScrollBarTemplate")
|
||||
self.scrollbar = scrollbar
|
||||
local scrollbg = scrollbar:CreateTexture(nil,"BACKGROUND")
|
||||
scrollbg:SetAllPoints(scrollbar)
|
||||
scrollbg:SetTexture(0,0,0,0.4)
|
||||
scrollbar.obj = self
|
||||
self.noupdate = true
|
||||
scrollbar:SetPoint("TOPRIGHT",treeframe,"TOPRIGHT",-10,-26)
|
||||
scrollbar:SetPoint("BOTTOMRIGHT",treeframe,"BOTTOMRIGHT",-10,26)
|
||||
scrollbar:SetScript("OnValueChanged", OnScrollValueChanged)
|
||||
scrollbar:SetMinMaxValues(0,0)
|
||||
self.localstatus.scrollvalue = 0
|
||||
scrollbar:SetValueStep(1)
|
||||
scrollbar:SetValue(0)
|
||||
scrollbar:SetWidth(16)
|
||||
self.noupdate = nil
|
||||
|
||||
local border = CreateFrame("Frame",nil,frame)
|
||||
self.border = border
|
||||
border:SetPoint("TOPLEFT",treeframe,"TOPRIGHT", 0,0)
|
||||
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
|
||||
|
||||
border:SetBackdrop(PaneBackdrop)
|
||||
border:SetBackdropColor(0.1,0.1,0.1,0.5)
|
||||
border:SetBackdropBorderColor(0.4,0.4,0.4)
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame",nil,border)
|
||||
self.content = content
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT",border,"TOPLEFT",10,-10)
|
||||
content:SetPoint("BOTTOMRIGHT",border,"BOTTOMRIGHT",-10,10)
|
||||
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
--AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,331 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local pairs, assert, type = pairs, assert, type
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: GameFontNormal
|
||||
|
||||
----------------
|
||||
-- Main Frame --
|
||||
----------------
|
||||
--[[
|
||||
Events :
|
||||
OnClose
|
||||
|
||||
]]
|
||||
do
|
||||
local Type = "Window"
|
||||
local Version = 4
|
||||
|
||||
local function frameOnClose(this)
|
||||
this.obj:Fire("OnClose")
|
||||
end
|
||||
|
||||
local function closeOnClick(this)
|
||||
PlaySound("gsTitleOptionExit")
|
||||
this.obj:Hide()
|
||||
end
|
||||
|
||||
local function frameOnMouseDown(this)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function titleOnMouseDown(this)
|
||||
this:GetParent():StartMoving()
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function frameOnMouseUp(this)
|
||||
local frame = this:GetParent()
|
||||
frame:StopMovingOrSizing()
|
||||
local self = frame.obj
|
||||
local status = self.status or self.localstatus
|
||||
status.width = frame:GetWidth()
|
||||
status.height = frame:GetHeight()
|
||||
status.top = frame:GetTop()
|
||||
status.left = frame:GetLeft()
|
||||
end
|
||||
|
||||
local function sizerseOnMouseDown(this)
|
||||
this:GetParent():StartSizing("BOTTOMRIGHT")
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function sizersOnMouseDown(this)
|
||||
this:GetParent():StartSizing("BOTTOM")
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function sizereOnMouseDown(this)
|
||||
this:GetParent():StartSizing("RIGHT")
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function sizerOnMouseUp(this)
|
||||
this:GetParent():StopMovingOrSizing()
|
||||
end
|
||||
|
||||
local function SetTitle(self,title)
|
||||
self.titletext:SetText(title)
|
||||
end
|
||||
|
||||
local function SetStatusText(self,text)
|
||||
-- self.statustext:SetText(text)
|
||||
end
|
||||
|
||||
local function Hide(self)
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
local function Show(self)
|
||||
self.frame:Show()
|
||||
end
|
||||
|
||||
local function OnAcquire(self)
|
||||
self.frame:SetParent(UIParent)
|
||||
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
self:ApplyStatus()
|
||||
self:EnableResize(true)
|
||||
self:Show()
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.status = nil
|
||||
for k in pairs(self.localstatus) do
|
||||
self.localstatus[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- called to set an external table to store status in
|
||||
local function SetStatusTable(self, status)
|
||||
assert(type(status) == "table")
|
||||
self.status = status
|
||||
self:ApplyStatus()
|
||||
end
|
||||
|
||||
local function ApplyStatus(self)
|
||||
local status = self.status or self.localstatus
|
||||
local frame = self.frame
|
||||
self:SetWidth(status.width or 700)
|
||||
self:SetHeight(status.height or 500)
|
||||
if status.top and status.left then
|
||||
frame:SetPoint("TOP",UIParent,"BOTTOM",0,status.top)
|
||||
frame:SetPoint("LEFT",UIParent,"LEFT",status.left,0)
|
||||
else
|
||||
frame:SetPoint("CENTER",UIParent,"CENTER")
|
||||
end
|
||||
end
|
||||
|
||||
local function OnWidthSet(self, width)
|
||||
local content = self.content
|
||||
local contentwidth = width - 34
|
||||
if contentwidth < 0 then
|
||||
contentwidth = 0
|
||||
end
|
||||
content:SetWidth(contentwidth)
|
||||
content.width = contentwidth
|
||||
end
|
||||
|
||||
|
||||
local function OnHeightSet(self, height)
|
||||
local content = self.content
|
||||
local contentheight = height - 57
|
||||
if contentheight < 0 then
|
||||
contentheight = 0
|
||||
end
|
||||
content:SetHeight(contentheight)
|
||||
content.height = contentheight
|
||||
end
|
||||
|
||||
local function EnableResize(self, state)
|
||||
local func = state and "Show" or "Hide"
|
||||
self.sizer_se[func](self.sizer_se)
|
||||
self.sizer_s[func](self.sizer_s)
|
||||
self.sizer_e[func](self.sizer_e)
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local self = {}
|
||||
self.type = "Window"
|
||||
|
||||
self.Hide = Hide
|
||||
self.Show = Show
|
||||
self.SetTitle = SetTitle
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
self.SetStatusText = SetStatusText
|
||||
self.SetStatusTable = SetStatusTable
|
||||
self.ApplyStatus = ApplyStatus
|
||||
self.OnWidthSet = OnWidthSet
|
||||
self.OnHeightSet = OnHeightSet
|
||||
self.EnableResize = EnableResize
|
||||
|
||||
self.localstatus = {}
|
||||
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
frame:SetWidth(700)
|
||||
frame:SetHeight(500)
|
||||
frame:SetPoint("CENTER",UIParent,"CENTER",0,0)
|
||||
frame:EnableMouse()
|
||||
frame:SetMovable(true)
|
||||
frame:SetResizable(true)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
frame:SetScript("OnMouseDown", frameOnMouseDown)
|
||||
|
||||
frame:SetScript("OnHide",frameOnClose)
|
||||
frame:SetMinResize(240,240)
|
||||
frame:SetToplevel(true)
|
||||
|
||||
local titlebg = frame:CreateTexture(nil, "BACKGROUND")
|
||||
titlebg:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Title-Background]])
|
||||
titlebg:SetPoint("TOPLEFT", 9, -6)
|
||||
titlebg:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", -28, -24)
|
||||
|
||||
local dialogbg = frame:CreateTexture(nil, "BACKGROUND")
|
||||
dialogbg:SetTexture([[Interface\Tooltips\UI-Tooltip-Background]])
|
||||
dialogbg:SetPoint("TOPLEFT", 8, -24)
|
||||
dialogbg:SetPoint("BOTTOMRIGHT", -6, 8)
|
||||
dialogbg:SetVertexColor(0, 0, 0, .75)
|
||||
|
||||
local topleft = frame:CreateTexture(nil, "BORDER")
|
||||
topleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
topleft:SetWidth(64)
|
||||
topleft:SetHeight(64)
|
||||
topleft:SetPoint("TOPLEFT")
|
||||
topleft:SetTexCoord(0.501953125, 0.625, 0, 1)
|
||||
|
||||
local topright = frame:CreateTexture(nil, "BORDER")
|
||||
topright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
topright:SetWidth(64)
|
||||
topright:SetHeight(64)
|
||||
topright:SetPoint("TOPRIGHT")
|
||||
topright:SetTexCoord(0.625, 0.75, 0, 1)
|
||||
|
||||
local top = frame:CreateTexture(nil, "BORDER")
|
||||
top:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
top:SetHeight(64)
|
||||
top:SetPoint("TOPLEFT", topleft, "TOPRIGHT")
|
||||
top:SetPoint("TOPRIGHT", topright, "TOPLEFT")
|
||||
top:SetTexCoord(0.25, 0.369140625, 0, 1)
|
||||
|
||||
local bottomleft = frame:CreateTexture(nil, "BORDER")
|
||||
bottomleft:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
bottomleft:SetWidth(64)
|
||||
bottomleft:SetHeight(64)
|
||||
bottomleft:SetPoint("BOTTOMLEFT")
|
||||
bottomleft:SetTexCoord(0.751953125, 0.875, 0, 1)
|
||||
|
||||
local bottomright = frame:CreateTexture(nil, "BORDER")
|
||||
bottomright:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
bottomright:SetWidth(64)
|
||||
bottomright:SetHeight(64)
|
||||
bottomright:SetPoint("BOTTOMRIGHT")
|
||||
bottomright:SetTexCoord(0.875, 1, 0, 1)
|
||||
|
||||
local bottom = frame:CreateTexture(nil, "BORDER")
|
||||
bottom:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
bottom:SetHeight(64)
|
||||
bottom:SetPoint("BOTTOMLEFT", bottomleft, "BOTTOMRIGHT")
|
||||
bottom:SetPoint("BOTTOMRIGHT", bottomright, "BOTTOMLEFT")
|
||||
bottom:SetTexCoord(0.376953125, 0.498046875, 0, 1)
|
||||
|
||||
local left = frame:CreateTexture(nil, "BORDER")
|
||||
left:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
left:SetWidth(64)
|
||||
left:SetPoint("TOPLEFT", topleft, "BOTTOMLEFT")
|
||||
left:SetPoint("BOTTOMLEFT", bottomleft, "TOPLEFT")
|
||||
left:SetTexCoord(0.001953125, 0.125, 0, 1)
|
||||
|
||||
local right = frame:CreateTexture(nil, "BORDER")
|
||||
right:SetTexture([[Interface\PaperDollInfoFrame\UI-GearManager-Border]])
|
||||
right:SetWidth(64)
|
||||
right:SetPoint("TOPRIGHT", topright, "BOTTOMRIGHT")
|
||||
right:SetPoint("BOTTOMRIGHT", bottomright, "TOPRIGHT")
|
||||
right:SetTexCoord(0.1171875, 0.2421875, 0, 1)
|
||||
|
||||
local close = CreateFrame("Button", nil, frame, "UIPanelCloseButton")
|
||||
close:SetPoint("TOPRIGHT", 2, 1)
|
||||
close:SetScript("OnClick", closeOnClick)
|
||||
self.closebutton = close
|
||||
close.obj = self
|
||||
|
||||
local titletext = frame:CreateFontString(nil, "ARTWORK")
|
||||
titletext:SetFontObject(GameFontNormal)
|
||||
titletext:SetPoint("TOPLEFT", 12, -8)
|
||||
titletext:SetPoint("TOPRIGHT", -32, -8)
|
||||
self.titletext = titletext
|
||||
|
||||
local title = CreateFrame("Button", nil, frame)
|
||||
title:SetPoint("TOPLEFT", titlebg)
|
||||
title:SetPoint("BOTTOMRIGHT", titlebg)
|
||||
title:EnableMouse()
|
||||
title:SetScript("OnMouseDown",titleOnMouseDown)
|
||||
title:SetScript("OnMouseUp", frameOnMouseUp)
|
||||
self.title = title
|
||||
|
||||
local sizer_se = CreateFrame("Frame",nil,frame)
|
||||
sizer_se:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
|
||||
sizer_se:SetWidth(25)
|
||||
sizer_se:SetHeight(25)
|
||||
sizer_se:EnableMouse()
|
||||
sizer_se:SetScript("OnMouseDown",sizerseOnMouseDown)
|
||||
sizer_se:SetScript("OnMouseUp", sizerOnMouseUp)
|
||||
self.sizer_se = sizer_se
|
||||
|
||||
local line1 = sizer_se:CreateTexture(nil, "BACKGROUND")
|
||||
self.line1 = line1
|
||||
line1:SetWidth(14)
|
||||
line1:SetHeight(14)
|
||||
line1:SetPoint("BOTTOMRIGHT", -8, 8)
|
||||
line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
local x = 0.1 * 14/17
|
||||
line1:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
|
||||
|
||||
local line2 = sizer_se:CreateTexture(nil, "BACKGROUND")
|
||||
self.line2 = line2
|
||||
line2:SetWidth(8)
|
||||
line2:SetHeight(8)
|
||||
line2:SetPoint("BOTTOMRIGHT", -8, 8)
|
||||
line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
local x = 0.1 * 8/17
|
||||
line2:SetTexCoord(0.05 - x, 0.5, 0.05, 0.5 + x, 0.05, 0.5 - x, 0.5 + x, 0.5)
|
||||
|
||||
local sizer_s = CreateFrame("Frame",nil,frame)
|
||||
sizer_s:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-25,0)
|
||||
sizer_s:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
|
||||
sizer_s:SetHeight(25)
|
||||
sizer_s:EnableMouse()
|
||||
sizer_s:SetScript("OnMouseDown",sizersOnMouseDown)
|
||||
sizer_s:SetScript("OnMouseUp", sizerOnMouseUp)
|
||||
self.sizer_s = sizer_s
|
||||
|
||||
local sizer_e = CreateFrame("Frame",nil,frame)
|
||||
sizer_e:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,25)
|
||||
sizer_e:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
|
||||
sizer_e:SetWidth(25)
|
||||
sizer_e:EnableMouse()
|
||||
sizer_e:SetScript("OnMouseDown",sizereOnMouseDown)
|
||||
sizer_e:SetScript("OnMouseUp", sizerOnMouseUp)
|
||||
self.sizer_e = sizer_e
|
||||
|
||||
--Container Support
|
||||
local content = CreateFrame("Frame",nil,frame)
|
||||
self.content = content
|
||||
content.obj = self
|
||||
content:SetPoint("TOPLEFT",frame,"TOPLEFT",12,-32)
|
||||
content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-12,13)
|
||||
|
||||
AceGUI:RegisterAsContainer(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,92 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Button Widget
|
||||
Graphical Button.
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "Button", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs = pairs
|
||||
|
||||
-- WoW APIs
|
||||
local _G = _G
|
||||
local PlaySound, CreateFrame, UIParent = PlaySound, CreateFrame, UIParent
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Button_OnClick(frame, ...)
|
||||
PlaySound("igMainMenuOption")
|
||||
frame.obj:Fire("OnClick", ...)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function Control_OnEnter(frame)
|
||||
frame.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(frame)
|
||||
frame.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
-- restore default values
|
||||
self:SetHeight(24)
|
||||
self:SetWidth(200)
|
||||
self:SetDisabled(false)
|
||||
self:SetText()
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["SetText"] = function(self, text)
|
||||
self.text:SetText(text)
|
||||
end,
|
||||
|
||||
["SetDisabled"] = function(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.frame:Disable()
|
||||
else
|
||||
self.frame:Enable()
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local name = "AceGUI30Button" .. AceGUI:GetNextWidgetNum(Type)
|
||||
local frame = CreateFrame("Button", name, UIParent, "UIPanelButtonTemplate2")
|
||||
frame:Hide()
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:SetScript("OnClick", Button_OnClick)
|
||||
frame:SetScript("OnEnter", Control_OnEnter)
|
||||
frame:SetScript("OnLeave", Control_OnLeave)
|
||||
|
||||
local text = frame:GetFontString()
|
||||
text:ClearAllPoints()
|
||||
text:SetPoint("TOPLEFT", 15, -1)
|
||||
text:SetPoint("BOTTOMRIGHT", -15, 1)
|
||||
text:SetJustifyV("MIDDLE")
|
||||
|
||||
local widget = {
|
||||
text = text,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,285 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Checkbox Widget
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "CheckBox", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local select, pairs = select, pairs
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: SetDesaturation, GameFontHighlight
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Control_OnEnter(frame)
|
||||
frame.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(frame)
|
||||
frame.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function CheckBox_OnMouseDown(frame)
|
||||
local self = frame.obj
|
||||
if not self.disabled then
|
||||
self.text:SetPoint("LEFT", self.checkbg, "RIGHT", 1, -1)
|
||||
end
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function CheckBox_OnMouseUp(frame)
|
||||
local self = frame.obj
|
||||
if not self.disabled then
|
||||
self:ToggleChecked()
|
||||
|
||||
if self.checked then
|
||||
PlaySound("igMainMenuOptionCheckBoxOn")
|
||||
else -- for both nil and false (tristate)
|
||||
PlaySound("igMainMenuOptionCheckBoxOff")
|
||||
end
|
||||
|
||||
self:Fire("OnValueChanged", self.checked)
|
||||
self.text:SetPoint("LEFT", self.checkbg, "RIGHT")
|
||||
end
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Support functions
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function AlignImage(self)
|
||||
local img = self.image:GetTexture()
|
||||
self.text:ClearAllPoints()
|
||||
if not img then
|
||||
self.text:SetPoint("LEFT", self.checkbg, "RIGHT")
|
||||
self.text:SetPoint("RIGHT")
|
||||
else
|
||||
self.text:SetPoint("LEFT", self.image,"RIGHT", 1, 0)
|
||||
self.text:SetPoint("RIGHT")
|
||||
end
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self:SetType()
|
||||
self:SetValue(false)
|
||||
self:SetTriState(nil)
|
||||
-- height is calculated from the width and required space for the description
|
||||
self:SetWidth(200)
|
||||
self:SetImage()
|
||||
self:SetDisabled(nil)
|
||||
self:SetDescription(nil)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["OnWidthSet"] = function(self, width)
|
||||
if self.desc then
|
||||
self.desc:SetWidth(width - 30)
|
||||
if self.desc:GetText() and self.desc:GetText() ~= "" then
|
||||
self:SetHeight(28 + self.desc:GetHeight())
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
["SetDisabled"] = function(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.frame:Disable()
|
||||
self.text:SetTextColor(0.5, 0.5, 0.5)
|
||||
SetDesaturation(self.check, true)
|
||||
else
|
||||
self.frame:Enable()
|
||||
self.text:SetTextColor(1, 1, 1)
|
||||
if self.tristate and self.checked == nil then
|
||||
SetDesaturation(self.check, true)
|
||||
else
|
||||
SetDesaturation(self.check, false)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
["SetValue"] = function(self,value)
|
||||
local check = self.check
|
||||
self.checked = value
|
||||
if value then
|
||||
SetDesaturation(self.check, false)
|
||||
self.check:Show()
|
||||
else
|
||||
--Nil is the unknown tristate value
|
||||
if self.tristate and value == nil then
|
||||
SetDesaturation(self.check, true)
|
||||
self.check:Show()
|
||||
else
|
||||
SetDesaturation(self.check, false)
|
||||
self.check:Hide()
|
||||
end
|
||||
end
|
||||
self:SetDisabled(self.disabled)
|
||||
end,
|
||||
|
||||
["GetValue"] = function(self)
|
||||
return self.checked
|
||||
end,
|
||||
|
||||
["SetTriState"] = function(self, enabled)
|
||||
self.tristate = enabled
|
||||
self:SetValue(self:GetValue())
|
||||
end,
|
||||
|
||||
["SetType"] = function(self, type)
|
||||
local checkbg = self.checkbg
|
||||
local check = self.check
|
||||
local highlight = self.highlight
|
||||
|
||||
local size
|
||||
if type == "radio" then
|
||||
size = 16
|
||||
checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
|
||||
checkbg:SetTexCoord(0, 0.25, 0, 1)
|
||||
check:SetTexture("Interface\\Buttons\\UI-RadioButton")
|
||||
check:SetTexCoord(0.25, 0.5, 0, 1)
|
||||
check:SetBlendMode("ADD")
|
||||
highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
|
||||
highlight:SetTexCoord(0.5, 0.75, 0, 1)
|
||||
else
|
||||
size = 24
|
||||
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
|
||||
checkbg:SetTexCoord(0, 1, 0, 1)
|
||||
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
||||
check:SetTexCoord(0, 1, 0, 1)
|
||||
check:SetBlendMode("BLEND")
|
||||
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
|
||||
highlight:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
checkbg:SetHeight(size)
|
||||
checkbg:SetWidth(size)
|
||||
end,
|
||||
|
||||
["ToggleChecked"] = function(self)
|
||||
local value = self:GetValue()
|
||||
if self.tristate then
|
||||
--cycle in true, nil, false order
|
||||
if value then
|
||||
self:SetValue(nil)
|
||||
elseif value == nil then
|
||||
self:SetValue(false)
|
||||
else
|
||||
self:SetValue(true)
|
||||
end
|
||||
else
|
||||
self:SetValue(not self:GetValue())
|
||||
end
|
||||
end,
|
||||
|
||||
["SetLabel"] = function(self, label)
|
||||
self.text:SetText(label)
|
||||
end,
|
||||
|
||||
["SetDescription"] = function(self, desc)
|
||||
if desc then
|
||||
if not self.desc then
|
||||
local desc = self.frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
|
||||
desc:ClearAllPoints()
|
||||
desc:SetPoint("TOPLEFT", self.checkbg, "TOPRIGHT", 5, -21)
|
||||
desc:SetWidth(self.frame.width - 30)
|
||||
desc:SetJustifyH("LEFT")
|
||||
desc:SetJustifyV("TOP")
|
||||
self.desc = desc
|
||||
end
|
||||
self.desc:Show()
|
||||
--self.text:SetFontObject(GameFontNormal)
|
||||
self.desc:SetText(desc)
|
||||
self:SetHeight(28 + self.desc:GetHeight())
|
||||
else
|
||||
if self.desc then
|
||||
self.desc:SetText("")
|
||||
self.desc:Hide()
|
||||
end
|
||||
--self.text:SetFontObject(GameFontHighlight)
|
||||
self:SetHeight(24)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetImage"] = function(self, path, ...)
|
||||
local image = self.image
|
||||
image:SetTexture(path)
|
||||
|
||||
if image:GetTexture() then
|
||||
local n = select("#", ...)
|
||||
if n == 4 or n == 8 then
|
||||
image:SetTexCoord(...)
|
||||
else
|
||||
image:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
end
|
||||
AlignImage(self)
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Button", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:SetScript("OnEnter", Control_OnEnter)
|
||||
frame:SetScript("OnLeave", Control_OnLeave)
|
||||
frame:SetScript("OnMouseDown", CheckBox_OnMouseDown)
|
||||
frame:SetScript("OnMouseUp", CheckBox_OnMouseUp)
|
||||
|
||||
local checkbg = frame:CreateTexture(nil, "ARTWORK")
|
||||
checkbg:SetWidth(24)
|
||||
checkbg:SetHeight(24)
|
||||
checkbg:SetPoint("TOPLEFT")
|
||||
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
|
||||
|
||||
local check = frame:CreateTexture(nil, "OVERLAY")
|
||||
check:SetAllPoints(checkbg)
|
||||
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
||||
|
||||
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
|
||||
text:SetJustifyH("LEFT")
|
||||
text:SetHeight(18)
|
||||
text:SetPoint("LEFT", checkbg, "RIGHT")
|
||||
text:SetPoint("RIGHT")
|
||||
|
||||
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
|
||||
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
|
||||
highlight:SetBlendMode("ADD")
|
||||
highlight:SetAllPoints(checkbg)
|
||||
|
||||
local image = frame:CreateTexture(nil, "OVERLAY")
|
||||
image:SetHeight(16)
|
||||
image:SetWidth(16)
|
||||
image:SetPoint("LEFT", checkbg, "RIGHT", 1, 0)
|
||||
|
||||
local widget = {
|
||||
checkbg = checkbg,
|
||||
check = check,
|
||||
text = text,
|
||||
highlight = highlight,
|
||||
image = image,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,186 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
ColorPicker Widget
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "ColorPicker", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs = pairs
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: ShowUIPanel, HideUIPanel, ColorPickerFrame, OpacitySliderFrame
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Support functions
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function ColorCallback(self, r, g, b, a, isAlpha)
|
||||
if not self.HasAlpha then
|
||||
a = 1
|
||||
end
|
||||
self:SetColor(r, g, b, a)
|
||||
if ColorPickerFrame:IsVisible() then
|
||||
--colorpicker is still open
|
||||
self:Fire("OnValueChanged", r, g, b, a)
|
||||
else
|
||||
--colorpicker is closed, color callback is first, ignore it,
|
||||
--alpha callback is the final call after it closes so confirm now
|
||||
if isAlpha then
|
||||
self:Fire("OnValueConfirmed", r, g, b, a)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Control_OnEnter(frame)
|
||||
frame.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(frame)
|
||||
frame.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function ColorSwatch_OnClick(frame)
|
||||
HideUIPanel(ColorPickerFrame)
|
||||
local self = frame.obj
|
||||
if not self.disabled then
|
||||
ColorPickerFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
ColorPickerFrame.func = function()
|
||||
local r, g, b = ColorPickerFrame:GetColorRGB()
|
||||
local a = 1 - OpacitySliderFrame:GetValue()
|
||||
ColorCallback(self, r, g, b, a)
|
||||
end
|
||||
|
||||
ColorPickerFrame.hasOpacity = self.HasAlpha
|
||||
ColorPickerFrame.opacityFunc = function()
|
||||
local r, g, b = ColorPickerFrame:GetColorRGB()
|
||||
local a = 1 - OpacitySliderFrame:GetValue()
|
||||
ColorCallback(self, r, g, b, a, true)
|
||||
end
|
||||
|
||||
local r, g, b, a = self.r, self.g, self.b, self.a
|
||||
if self.HasAlpha then
|
||||
ColorPickerFrame.opacity = 1 - (a or 0)
|
||||
end
|
||||
ColorPickerFrame:SetColorRGB(r, g, b)
|
||||
|
||||
ColorPickerFrame.cancelFunc = function()
|
||||
ColorCallback(self, r, g, b, a, true)
|
||||
end
|
||||
|
||||
ShowUIPanel(ColorPickerFrame)
|
||||
end
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self:SetHeight(24)
|
||||
self:SetWidth(200)
|
||||
self:SetHasAlpha(false)
|
||||
self:SetColor(0, 0, 0, 1)
|
||||
self:SetDisabled(nil)
|
||||
self:SetLabel(nil)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["SetLabel"] = function(self, text)
|
||||
self.text:SetText(text)
|
||||
end,
|
||||
|
||||
["SetColor"] = function(self, r, g, b, a)
|
||||
self.r = r
|
||||
self.g = g
|
||||
self.b = b
|
||||
self.a = a or 1
|
||||
self.colorSwatch:SetVertexColor(r, g, b, a)
|
||||
end,
|
||||
|
||||
["SetHasAlpha"] = function(self, HasAlpha)
|
||||
self.HasAlpha = HasAlpha
|
||||
end,
|
||||
|
||||
["SetDisabled"] = function(self, disabled)
|
||||
self.disabled = disabled
|
||||
if self.disabled then
|
||||
self.frame:Disable()
|
||||
self.text:SetTextColor(0.5, 0.5, 0.5)
|
||||
else
|
||||
self.frame:Enable()
|
||||
self.text:SetTextColor(1, 1, 1)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Button", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:SetScript("OnEnter", Control_OnEnter)
|
||||
frame:SetScript("OnLeave", Control_OnLeave)
|
||||
frame:SetScript("OnClick", ColorSwatch_OnClick)
|
||||
|
||||
local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
|
||||
colorSwatch:SetWidth(19)
|
||||
colorSwatch:SetHeight(19)
|
||||
colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
|
||||
colorSwatch:SetPoint("LEFT")
|
||||
|
||||
local texture = frame:CreateTexture(nil, "BACKGROUND")
|
||||
texture:SetWidth(16)
|
||||
texture:SetHeight(16)
|
||||
texture:SetTexture(1, 1, 1)
|
||||
texture:SetPoint("CENTER", colorSwatch)
|
||||
texture:Show()
|
||||
|
||||
local checkers = frame:CreateTexture(nil, "BACKGROUND")
|
||||
checkers:SetWidth(14)
|
||||
checkers:SetHeight(14)
|
||||
checkers:SetTexture("Tileset\\Generic\\Checkers")
|
||||
checkers:SetTexCoord(.25, 0, 0.5, .25)
|
||||
checkers:SetDesaturated(true)
|
||||
checkers:SetVertexColor(1, 1, 1, 0.75)
|
||||
checkers:SetPoint("CENTER", colorSwatch)
|
||||
checkers:Show()
|
||||
|
||||
local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
|
||||
text:SetHeight(24)
|
||||
text:SetJustifyH("LEFT")
|
||||
text:SetTextColor(1, 1, 1)
|
||||
text:SetPoint("LEFT", colorSwatch, "RIGHT", 2, 0)
|
||||
text:SetPoint("RIGHT")
|
||||
|
||||
--local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
|
||||
--highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
|
||||
--highlight:SetBlendMode("ADD")
|
||||
--highlight:SetAllPoints(frame)
|
||||
|
||||
local widget = {
|
||||
colorSwatch = colorSwatch,
|
||||
text = text,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,465 @@
|
||||
--[[ $Id: AceGUIWidget-DropDown-Items.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]--
|
||||
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local select, assert = select, assert
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame = CreateFrame
|
||||
|
||||
local function fixlevels(parent,...)
|
||||
local i = 1
|
||||
local child = select(i, ...)
|
||||
while child do
|
||||
child:SetFrameLevel(parent:GetFrameLevel()+1)
|
||||
fixlevels(child, child:GetChildren())
|
||||
i = i + 1
|
||||
child = select(i, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local function fixstrata(strata, parent, ...)
|
||||
local i = 1
|
||||
local child = select(i, ...)
|
||||
parent:SetFrameStrata(strata)
|
||||
while child do
|
||||
fixstrata(strata, child, child:GetChildren())
|
||||
i = i + 1
|
||||
child = select(i, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- ItemBase is the base "class" for all dropdown items.
|
||||
-- Each item has to use ItemBase.Create(widgetType) to
|
||||
-- create an initial 'self' value.
|
||||
-- ItemBase will add common functions and ui event handlers.
|
||||
-- Be sure to keep basic usage when you override functions.
|
||||
|
||||
local ItemBase = {
|
||||
-- NOTE: The ItemBase version is added to each item's version number
|
||||
-- to ensure proper updates on ItemBase changes.
|
||||
-- Use at least 1000er steps.
|
||||
version = 1000,
|
||||
counter = 0,
|
||||
}
|
||||
|
||||
function ItemBase.Frame_OnEnter(this)
|
||||
local self = this.obj
|
||||
|
||||
if self.useHighlight then
|
||||
self.highlight:Show()
|
||||
end
|
||||
self:Fire("OnEnter")
|
||||
|
||||
if self.specialOnEnter then
|
||||
self.specialOnEnter(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ItemBase.Frame_OnLeave(this)
|
||||
local self = this.obj
|
||||
|
||||
self.highlight:Hide()
|
||||
self:Fire("OnLeave")
|
||||
|
||||
if self.specialOnLeave then
|
||||
self.specialOnLeave(self)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported, AceGUI callback
|
||||
function ItemBase.OnAcquire(self)
|
||||
self.frame:SetToplevel(true)
|
||||
self.frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
end
|
||||
|
||||
-- exported, AceGUI callback
|
||||
function ItemBase.OnRelease(self)
|
||||
self:SetDisabled(false)
|
||||
self.pullout = nil
|
||||
self.frame:SetParent(nil)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
-- exported
|
||||
-- NOTE: this is called by a Dropdown-Pullout.
|
||||
-- Do not call this method directly
|
||||
function ItemBase.SetPullout(self, pullout)
|
||||
self.pullout = pullout
|
||||
|
||||
self.frame:SetParent(nil)
|
||||
self.frame:SetParent(pullout.itemFrame)
|
||||
self.parent = pullout.itemFrame
|
||||
fixlevels(pullout.itemFrame, pullout.itemFrame:GetChildren())
|
||||
end
|
||||
|
||||
-- exported
|
||||
function ItemBase.SetText(self, text)
|
||||
self.text:SetText(text or "")
|
||||
end
|
||||
|
||||
-- exported
|
||||
function ItemBase.GetText(self)
|
||||
return self.text:GetText()
|
||||
end
|
||||
|
||||
-- exported
|
||||
function ItemBase.SetPoint(self, ...)
|
||||
self.frame:SetPoint(...)
|
||||
end
|
||||
|
||||
-- exported
|
||||
function ItemBase.Show(self)
|
||||
self.frame:Show()
|
||||
end
|
||||
|
||||
-- exported
|
||||
function ItemBase.Hide(self)
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
-- exported
|
||||
function ItemBase.SetDisabled(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.useHighlight = false
|
||||
self.text:SetTextColor(.5, .5, .5)
|
||||
else
|
||||
self.useHighlight = true
|
||||
self.text:SetTextColor(1, 1, 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
-- NOTE: this is called by a Dropdown-Pullout.
|
||||
-- Do not call this method directly
|
||||
function ItemBase.SetOnLeave(self, func)
|
||||
self.specialOnLeave = func
|
||||
end
|
||||
|
||||
-- exported
|
||||
-- NOTE: this is called by a Dropdown-Pullout.
|
||||
-- Do not call this method directly
|
||||
function ItemBase.SetOnEnter(self, func)
|
||||
self.specialOnEnter = func
|
||||
end
|
||||
|
||||
function ItemBase.Create(type)
|
||||
-- NOTE: Most of the following code is copied from AceGUI-3.0/Dropdown widget
|
||||
local count = AceGUI:GetNextWidgetNum(type)
|
||||
local frame = CreateFrame("Button", "AceGUI30DropDownItem"..count)
|
||||
local self = {}
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
self.type = type
|
||||
|
||||
self.useHighlight = true
|
||||
|
||||
frame:SetHeight(17)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
local text = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
|
||||
text:SetTextColor(1,1,1)
|
||||
text:SetJustifyH("LEFT")
|
||||
text:SetPoint("TOPLEFT",frame,"TOPLEFT",18,0)
|
||||
text:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-8,0)
|
||||
self.text = text
|
||||
|
||||
local highlight = frame:CreateTexture(nil, "OVERLAY")
|
||||
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
|
||||
highlight:SetBlendMode("ADD")
|
||||
highlight:SetHeight(14)
|
||||
highlight:ClearAllPoints()
|
||||
highlight:SetPoint("RIGHT",frame,"RIGHT",-3,0)
|
||||
highlight:SetPoint("LEFT",frame,"LEFT",5,0)
|
||||
highlight:Hide()
|
||||
self.highlight = highlight
|
||||
|
||||
local check = frame:CreateTexture("OVERLAY")
|
||||
check:SetWidth(16)
|
||||
check:SetHeight(16)
|
||||
check:SetPoint("LEFT",frame,"LEFT",3,-1)
|
||||
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
|
||||
check:Hide()
|
||||
self.check = check
|
||||
|
||||
local sub = frame:CreateTexture("OVERLAY")
|
||||
sub:SetWidth(16)
|
||||
sub:SetHeight(16)
|
||||
sub:SetPoint("RIGHT",frame,"RIGHT",-3,-1)
|
||||
sub:SetTexture("Interface\\ChatFrame\\ChatFrameExpandArrow")
|
||||
sub:Hide()
|
||||
self.sub = sub
|
||||
|
||||
frame:SetScript("OnEnter", ItemBase.Frame_OnEnter)
|
||||
frame:SetScript("OnLeave", ItemBase.Frame_OnLeave)
|
||||
|
||||
self.OnAcquire = ItemBase.OnAcquire
|
||||
self.OnRelease = ItemBase.OnRelease
|
||||
|
||||
self.SetPullout = ItemBase.SetPullout
|
||||
self.GetText = ItemBase.GetText
|
||||
self.SetText = ItemBase.SetText
|
||||
self.SetDisabled = ItemBase.SetDisabled
|
||||
|
||||
self.SetPoint = ItemBase.SetPoint
|
||||
self.Show = ItemBase.Show
|
||||
self.Hide = ItemBase.Hide
|
||||
|
||||
self.SetOnLeave = ItemBase.SetOnLeave
|
||||
self.SetOnEnter = ItemBase.SetOnEnter
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--[[
|
||||
Template for items:
|
||||
|
||||
-- Item:
|
||||
--
|
||||
do
|
||||
local widgetType = "Dropdown-Item-"
|
||||
local widgetVersion = 1
|
||||
|
||||
local function Constructor()
|
||||
local self = ItemBase.Create(widgetType)
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
|
||||
end
|
||||
--]]
|
||||
|
||||
-- Item: Header
|
||||
-- A single text entry.
|
||||
-- Special: Different text color and no highlight
|
||||
do
|
||||
local widgetType = "Dropdown-Item-Header"
|
||||
local widgetVersion = 1
|
||||
|
||||
local function OnEnter(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnEnter")
|
||||
|
||||
if self.specialOnEnter then
|
||||
self.specialOnEnter(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnLeave(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnLeave")
|
||||
|
||||
if self.specialOnLeave then
|
||||
self.specialOnLeave(self)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported, override
|
||||
local function SetDisabled(self, disabled)
|
||||
ItemBase.SetDisabled(self, disabled)
|
||||
if not disabled then
|
||||
self.text:SetTextColor(1, 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local self = ItemBase.Create(widgetType)
|
||||
|
||||
self.SetDisabled = SetDisabled
|
||||
|
||||
self.frame:SetScript("OnEnter", OnEnter)
|
||||
self.frame:SetScript("OnLeave", OnLeave)
|
||||
|
||||
self.text:SetTextColor(1, 1, 0)
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
|
||||
end
|
||||
|
||||
-- Item: Execute
|
||||
-- A simple button
|
||||
do
|
||||
local widgetType = "Dropdown-Item-Execute"
|
||||
local widgetVersion = 1
|
||||
|
||||
local function Frame_OnClick(this, button)
|
||||
local self = this.obj
|
||||
if self.disabled then return end
|
||||
self:Fire("OnClick")
|
||||
if self.pullout then
|
||||
self.pullout:Close()
|
||||
end
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local self = ItemBase.Create(widgetType)
|
||||
|
||||
self.frame:SetScript("OnClick", Frame_OnClick)
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
|
||||
end
|
||||
|
||||
-- Item: Toggle
|
||||
-- Some sort of checkbox for dropdown menus.
|
||||
-- Does not close the pullout on click.
|
||||
do
|
||||
local widgetType = "Dropdown-Item-Toggle"
|
||||
local widgetVersion = 3
|
||||
|
||||
local function UpdateToggle(self)
|
||||
if self.value then
|
||||
self.check:Show()
|
||||
else
|
||||
self.check:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
ItemBase.OnRelease(self)
|
||||
self:SetValue(nil)
|
||||
end
|
||||
|
||||
local function Frame_OnClick(this, button)
|
||||
local self = this.obj
|
||||
if self.disabled then return end
|
||||
self.value = not self.value
|
||||
if self.value then
|
||||
PlaySound("igMainMenuOptionCheckBoxOn")
|
||||
else
|
||||
PlaySound("igMainMenuOptionCheckBoxOff")
|
||||
end
|
||||
UpdateToggle(self)
|
||||
self:Fire("OnValueChanged", self.value)
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetValue(self, value)
|
||||
self.value = value
|
||||
UpdateToggle(self)
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function GetValue(self)
|
||||
return self.value
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local self = ItemBase.Create(widgetType)
|
||||
|
||||
self.frame:SetScript("OnClick", Frame_OnClick)
|
||||
|
||||
self.SetValue = SetValue
|
||||
self.GetValue = GetValue
|
||||
self.OnRelease = OnRelease
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
|
||||
end
|
||||
|
||||
-- Item: Menu
|
||||
-- Shows a submenu on mouse over
|
||||
-- Does not close the pullout on click
|
||||
do
|
||||
local widgetType = "Dropdown-Item-Menu"
|
||||
local widgetVersion = 2
|
||||
|
||||
local function OnEnter(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnEnter")
|
||||
|
||||
if self.specialOnEnter then
|
||||
self.specialOnEnter(self)
|
||||
end
|
||||
|
||||
self.highlight:Show()
|
||||
|
||||
if not self.disabled and self.submenu then
|
||||
self.submenu:Open("TOPLEFT", self.frame, "TOPRIGHT", self.pullout:GetRightBorderWidth(), 0, self.frame:GetFrameLevel() + 100)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnHide(this)
|
||||
local self = this.obj
|
||||
if self.submenu then
|
||||
self.submenu:Close()
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetMenu(self, menu)
|
||||
assert(menu.type == "Dropdown-Pullout")
|
||||
self.submenu = menu
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function CloseMenu(self)
|
||||
self.submenu:Close()
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local self = ItemBase.Create(widgetType)
|
||||
|
||||
self.sub:Show()
|
||||
|
||||
self.frame:SetScript("OnEnter", OnEnter)
|
||||
self.frame:SetScript("OnHide", OnHide)
|
||||
|
||||
self.SetMenu = SetMenu
|
||||
self.CloseMenu = CloseMenu
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
|
||||
end
|
||||
|
||||
-- Item: Separator
|
||||
-- A single line to separate items
|
||||
do
|
||||
local widgetType = "Dropdown-Item-Separator"
|
||||
local widgetVersion = 1
|
||||
|
||||
-- exported, override
|
||||
local function SetDisabled(self, disabled)
|
||||
ItemBase.SetDisabled(self, disabled)
|
||||
self.useHighlight = false
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local self = ItemBase.Create(widgetType)
|
||||
|
||||
self.SetDisabled = SetDisabled
|
||||
|
||||
local line = self.frame:CreateTexture(nil, "OVERLAY")
|
||||
line:SetHeight(1)
|
||||
line:SetTexture(.5, .5, .5)
|
||||
line:SetPoint("LEFT", self.frame, "LEFT", 10, 0)
|
||||
line:SetPoint("RIGHT", self.frame, "RIGHT", -10, 0)
|
||||
|
||||
self.text:Hide()
|
||||
|
||||
self.useHighlight = false
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion + ItemBase.version)
|
||||
end
|
||||
@@ -0,0 +1,707 @@
|
||||
--[[ $Id: AceGUIWidget-DropDown.lua 916 2010-03-15 12:24:36Z nevcairiel $ ]]--
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local min, max, floor = math.min, math.max, math.floor
|
||||
local select, pairs, ipairs = select, pairs, ipairs
|
||||
local tsort = table.sort
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local UIParent, CreateFrame = UIParent, CreateFrame
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: CLOSE
|
||||
|
||||
local function fixlevels(parent,...)
|
||||
local i = 1
|
||||
local child = select(i, ...)
|
||||
while child do
|
||||
child:SetFrameLevel(parent:GetFrameLevel()+1)
|
||||
fixlevels(child, child:GetChildren())
|
||||
i = i + 1
|
||||
child = select(i, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local function fixstrata(strata, parent, ...)
|
||||
local i = 1
|
||||
local child = select(i, ...)
|
||||
parent:SetFrameStrata(strata)
|
||||
while child do
|
||||
fixstrata(strata, child, child:GetChildren())
|
||||
i = i + 1
|
||||
child = select(i, ...)
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
local widgetType = "Dropdown-Pullout"
|
||||
local widgetVersion = 3
|
||||
|
||||
--[[ Static data ]]--
|
||||
|
||||
local backdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
|
||||
edgeSize = 32,
|
||||
tileSize = 32,
|
||||
tile = true,
|
||||
insets = { left = 11, right = 12, top = 12, bottom = 11 },
|
||||
}
|
||||
local sliderBackdrop = {
|
||||
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
|
||||
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 8,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
}
|
||||
|
||||
local defaultWidth = 200
|
||||
local defaultMaxHeight = 600
|
||||
|
||||
--[[ UI Event Handlers ]]--
|
||||
|
||||
-- HACK: This should be no part of the pullout, but there
|
||||
-- is no other 'clean' way to response to any item-OnEnter
|
||||
-- Used to close Submenus when an other item is entered
|
||||
local function OnEnter(item)
|
||||
local self = item.pullout
|
||||
for k, v in ipairs(self.items) do
|
||||
if v.CloseMenu and v ~= item then
|
||||
v:CloseMenu()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- See the note in Constructor() for each scroll related function
|
||||
local function OnMouseWheel(this, value)
|
||||
this.obj:MoveScroll(value)
|
||||
end
|
||||
|
||||
local function OnScrollValueChanged(this, value)
|
||||
this.obj:SetScroll(value)
|
||||
end
|
||||
|
||||
local function OnSizeChanged(this)
|
||||
this.obj:FixScroll()
|
||||
end
|
||||
|
||||
--[[ Exported methods ]]--
|
||||
|
||||
-- exported
|
||||
local function SetScroll(self, value)
|
||||
local status = self.scrollStatus
|
||||
local frame, child = self.scrollFrame, self.itemFrame
|
||||
local height, viewheight = frame:GetHeight(), child:GetHeight()
|
||||
|
||||
local offset
|
||||
if height > viewheight then
|
||||
offset = 0
|
||||
else
|
||||
offset = floor((viewheight - height) / 1000 * value)
|
||||
end
|
||||
child:ClearAllPoints()
|
||||
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
|
||||
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", self.slider:IsShown() and -12 or 0, offset)
|
||||
status.offset = offset
|
||||
status.scrollvalue = value
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function MoveScroll(self, value)
|
||||
local status = self.scrollStatus
|
||||
local frame, child = self.scrollFrame, self.itemFrame
|
||||
local height, viewheight = frame:GetHeight(), child:GetHeight()
|
||||
|
||||
if height > viewheight then
|
||||
self.slider:Hide()
|
||||
else
|
||||
self.slider:Show()
|
||||
local diff = height - viewheight
|
||||
local delta = 1
|
||||
if value < 0 then
|
||||
delta = -1
|
||||
end
|
||||
self.slider:SetValue(min(max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function FixScroll(self)
|
||||
local status = self.scrollStatus
|
||||
local frame, child = self.scrollFrame, self.itemFrame
|
||||
local height, viewheight = frame:GetHeight(), child:GetHeight()
|
||||
local offset = status.offset or 0
|
||||
|
||||
if viewheight < height then
|
||||
self.slider:Hide()
|
||||
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, offset)
|
||||
self.slider:SetValue(0)
|
||||
else
|
||||
self.slider:Show()
|
||||
local value = (offset / (viewheight - height) * 1000)
|
||||
if value > 1000 then value = 1000 end
|
||||
self.slider:SetValue(value)
|
||||
self:SetScroll(value)
|
||||
if value < 1000 then
|
||||
child:ClearAllPoints()
|
||||
child:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, offset)
|
||||
child:SetPoint("TOPRIGHT", frame, "TOPRIGHT", -12, offset)
|
||||
status.offset = offset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- exported, AceGUI callback
|
||||
local function OnAcquire(self)
|
||||
self.frame:SetParent(UIParent)
|
||||
--self.itemFrame:SetToplevel(true)
|
||||
end
|
||||
|
||||
-- exported, AceGUI callback
|
||||
local function OnRelease(self)
|
||||
self:Clear()
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function AddItem(self, item)
|
||||
self.items[#self.items + 1] = item
|
||||
|
||||
local h = #self.items * 16
|
||||
self.itemFrame:SetHeight(h)
|
||||
self.frame:SetHeight(min(h + 34, self.maxHeight)) -- +34: 20 for scrollFrame placement (10 offset) and +14 for item placement
|
||||
|
||||
item.frame:SetPoint("LEFT", self.itemFrame, "LEFT")
|
||||
item.frame:SetPoint("RIGHT", self.itemFrame, "RIGHT")
|
||||
|
||||
item:SetPullout(self)
|
||||
item:SetOnEnter(OnEnter)
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function Open(self, point, relFrame, relPoint, x, y)
|
||||
local items = self.items
|
||||
local frame = self.frame
|
||||
local itemFrame = self.itemFrame
|
||||
|
||||
frame:SetPoint(point, relFrame, relPoint, x, y)
|
||||
|
||||
|
||||
local height = 8
|
||||
for i, item in pairs(items) do
|
||||
if i == 1 then
|
||||
item:SetPoint("TOP", itemFrame, "TOP", 0, -2)
|
||||
else
|
||||
item:SetPoint("TOP", items[i-1].frame, "BOTTOM", 0, 1)
|
||||
end
|
||||
|
||||
item:Show()
|
||||
|
||||
height = height + 16
|
||||
end
|
||||
itemFrame:SetHeight(height)
|
||||
fixstrata("TOOLTIP", frame, frame:GetChildren())
|
||||
frame:Show()
|
||||
self:Fire("OnOpen")
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function Close(self)
|
||||
self.frame:Hide()
|
||||
self:Fire("OnClose")
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function Clear(self)
|
||||
local items = self.items
|
||||
for i, item in pairs(items) do
|
||||
AceGUI:Release(item)
|
||||
items[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function IterateItems(self)
|
||||
return ipairs(self.items)
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetHideOnLeave(self, val)
|
||||
self.hideOnLeave = val
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetMaxHeight(self, height)
|
||||
self.maxHeight = height or defaultMaxHeight
|
||||
if self.frame:GetHeight() > height then
|
||||
self.frame:SetHeight(height)
|
||||
elseif (self.itemFrame:GetHeight() + 34) < height then
|
||||
self.frame:SetHeight(self.itemFrame:GetHeight() + 34) -- see :AddItem
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function GetRightBorderWidth(self)
|
||||
return 6 + (self.slider:IsShown() and 12 or 0)
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function GetLeftBorderWidth(self)
|
||||
return 6
|
||||
end
|
||||
|
||||
--[[ Constructor ]]--
|
||||
|
||||
local function Constructor()
|
||||
local count = AceGUI:GetNextWidgetNum(widgetType)
|
||||
local frame = CreateFrame("Frame", "AceGUI30Pullout"..count, UIParent)
|
||||
local self = {}
|
||||
self.count = count
|
||||
self.type = widgetType
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
|
||||
self.OnAcquire = OnAcquire
|
||||
self.OnRelease = OnRelease
|
||||
|
||||
self.AddItem = AddItem
|
||||
self.Open = Open
|
||||
self.Close = Close
|
||||
self.Clear = Clear
|
||||
self.IterateItems = IterateItems
|
||||
self.SetHideOnLeave = SetHideOnLeave
|
||||
|
||||
self.SetScroll = SetScroll
|
||||
self.MoveScroll = MoveScroll
|
||||
self.FixScroll = FixScroll
|
||||
|
||||
self.SetMaxHeight = SetMaxHeight
|
||||
self.GetRightBorderWidth = GetRightBorderWidth
|
||||
self.GetLeftBorderWidth = GetLeftBorderWidth
|
||||
|
||||
self.items = {}
|
||||
|
||||
self.scrollStatus = {
|
||||
scrollvalue = 0,
|
||||
}
|
||||
|
||||
self.maxHeight = defaultMaxHeight
|
||||
|
||||
frame:SetBackdrop(backdrop)
|
||||
frame:SetBackdropColor(0, 0, 0)
|
||||
frame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
frame:SetClampedToScreen(true)
|
||||
frame:SetWidth(defaultWidth)
|
||||
frame:SetHeight(self.maxHeight)
|
||||
--frame:SetToplevel(true)
|
||||
|
||||
-- NOTE: The whole scroll frame code is copied from the AceGUI-3.0 widget ScrollFrame
|
||||
local scrollFrame = CreateFrame("ScrollFrame", nil, frame)
|
||||
local itemFrame = CreateFrame("Frame", nil, scrollFrame)
|
||||
|
||||
self.scrollFrame = scrollFrame
|
||||
self.itemFrame = itemFrame
|
||||
|
||||
scrollFrame.obj = self
|
||||
itemFrame.obj = self
|
||||
|
||||
local slider = CreateFrame("Slider", "AceGUI30PulloutScrollbar"..count, scrollFrame)
|
||||
slider:SetOrientation("VERTICAL")
|
||||
slider:SetHitRectInsets(0, 0, -10, 0)
|
||||
slider:SetBackdrop(sliderBackdrop)
|
||||
slider:SetWidth(8)
|
||||
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Vertical")
|
||||
slider:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
self.slider = slider
|
||||
slider.obj = self
|
||||
|
||||
scrollFrame:SetScrollChild(itemFrame)
|
||||
scrollFrame:SetPoint("TOPLEFT", frame, "TOPLEFT", 6, -12)
|
||||
scrollFrame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -6, 12)
|
||||
scrollFrame:EnableMouseWheel(true)
|
||||
scrollFrame:SetScript("OnMouseWheel", OnMouseWheel)
|
||||
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
|
||||
scrollFrame:SetToplevel(true)
|
||||
scrollFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
itemFrame:SetPoint("TOPLEFT", scrollFrame, "TOPLEFT", 0, 0)
|
||||
itemFrame:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", -12, 0)
|
||||
itemFrame:SetHeight(400)
|
||||
itemFrame:SetToplevel(true)
|
||||
itemFrame:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
|
||||
slider:SetPoint("TOPLEFT", scrollFrame, "TOPRIGHT", -16, 0)
|
||||
slider:SetPoint("BOTTOMLEFT", scrollFrame, "BOTTOMRIGHT", -16, 0)
|
||||
slider:SetScript("OnValueChanged", OnScrollValueChanged)
|
||||
slider:SetMinMaxValues(0, 1000)
|
||||
slider:SetValueStep(1)
|
||||
slider:SetValue(0)
|
||||
|
||||
scrollFrame:Show()
|
||||
itemFrame:Show()
|
||||
slider:Hide()
|
||||
|
||||
self:FixScroll()
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
|
||||
end
|
||||
|
||||
do
|
||||
local widgetType = "Dropdown"
|
||||
local widgetVersion = 22
|
||||
|
||||
--[[ Static data ]]--
|
||||
|
||||
--[[ UI event handler ]]--
|
||||
|
||||
local function Control_OnEnter(this)
|
||||
this.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(this)
|
||||
this.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function Dropdown_OnHide(this)
|
||||
local self = this.obj
|
||||
if self.open then
|
||||
self.pullout:Close()
|
||||
end
|
||||
end
|
||||
|
||||
local function Dropdown_TogglePullout(this)
|
||||
local self = this.obj
|
||||
PlaySound("igMainMenuOptionCheckBoxOn") -- missleading name, but the Blizzard code uses this sound
|
||||
if self.open then
|
||||
self.open = nil
|
||||
self.pullout:Close()
|
||||
AceGUI:ClearFocus()
|
||||
else
|
||||
self.open = true
|
||||
self.pullout:SetWidth(self.frame:GetWidth())
|
||||
self.pullout:Open("TOPLEFT", self.frame, "BOTTOMLEFT", 0, self.label:IsShown() and -2 or 0)
|
||||
AceGUI:SetFocus(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnPulloutOpen(this)
|
||||
local self = this.userdata.obj
|
||||
local value = self.value
|
||||
|
||||
if not self.multiselect then
|
||||
for i, item in this:IterateItems() do
|
||||
item:SetValue(item.userdata.value == value)
|
||||
end
|
||||
end
|
||||
|
||||
self.open = true
|
||||
end
|
||||
|
||||
local function OnPulloutClose(this)
|
||||
local self = this.userdata.obj
|
||||
self.open = nil
|
||||
self:Fire("OnClosed")
|
||||
end
|
||||
|
||||
local function ShowMultiText(self)
|
||||
local text
|
||||
for i, widget in self.pullout:IterateItems() do
|
||||
if widget.type == "Dropdown-Item-Toggle" then
|
||||
if widget:GetValue() then
|
||||
if text then
|
||||
text = text..", "..widget:GetText()
|
||||
else
|
||||
text = widget:GetText()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self:SetText(text)
|
||||
end
|
||||
|
||||
local function OnItemValueChanged(this, event, checked)
|
||||
local self = this.userdata.obj
|
||||
|
||||
if self.multiselect then
|
||||
self:Fire("OnValueChanged", this.userdata.value, checked)
|
||||
ShowMultiText(self)
|
||||
else
|
||||
if checked then
|
||||
self:SetValue(this.userdata.value)
|
||||
self:Fire("OnValueChanged", this.userdata.value)
|
||||
else
|
||||
this:SetValue(true)
|
||||
end
|
||||
if self.open then
|
||||
self.pullout:Close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Exported methods ]]--
|
||||
|
||||
-- exported, AceGUI callback
|
||||
local function OnAcquire(self)
|
||||
local pullout = AceGUI:Create("Dropdown-Pullout")
|
||||
self.pullout = pullout
|
||||
pullout.userdata.obj = self
|
||||
pullout:SetCallback("OnClose", OnPulloutClose)
|
||||
pullout:SetCallback("OnOpen", OnPulloutOpen)
|
||||
self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1)
|
||||
fixlevels(self.pullout.frame, self.pullout.frame:GetChildren())
|
||||
|
||||
self:SetHeight(44)
|
||||
self:SetWidth(200)
|
||||
end
|
||||
|
||||
-- exported, AceGUI callback
|
||||
local function OnRelease(self)
|
||||
if self.open then
|
||||
self.pullout:Close()
|
||||
end
|
||||
AceGUI:Release(self.pullout)
|
||||
self.pullout = nil
|
||||
|
||||
self:SetText("")
|
||||
self:SetLabel("")
|
||||
self:SetDisabled(false)
|
||||
self:SetMultiselect(false)
|
||||
|
||||
self.value = nil
|
||||
self.list = nil
|
||||
self.open = nil
|
||||
self.hasClose = nil
|
||||
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetDisabled(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.text:SetTextColor(0.5,0.5,0.5)
|
||||
self.button:Disable()
|
||||
self.label:SetTextColor(0.5,0.5,0.5)
|
||||
else
|
||||
self.button:Enable()
|
||||
self.label:SetTextColor(1,.82,0)
|
||||
self.text:SetTextColor(1,1,1)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function ClearFocus(self)
|
||||
if self.open then
|
||||
self.pullout:Close()
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetText(self, text)
|
||||
self.text:SetText(text or "")
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetLabel(self, text)
|
||||
if text and text ~= "" then
|
||||
self.label:SetText(text)
|
||||
self.label:Show()
|
||||
self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,-18)
|
||||
self.frame:SetHeight(44)
|
||||
else
|
||||
self.label:SetText("")
|
||||
self.label:Hide()
|
||||
self.dropdown:SetPoint("TOPLEFT",self.frame,"TOPLEFT",-15,0)
|
||||
self.frame:SetHeight(26)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetValue(self, value)
|
||||
if self.list then
|
||||
self:SetText(self.list[value] or "")
|
||||
end
|
||||
self.value = value
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function GetValue(self)
|
||||
return self.value
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetItemValue(self, item, value)
|
||||
if not self.multiselect then return end
|
||||
for i, widget in self.pullout:IterateItems() do
|
||||
if widget.userdata.value == item then
|
||||
if widget.SetValue then
|
||||
widget:SetValue(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
ShowMultiText(self)
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetItemDisabled(self, item, disabled)
|
||||
for i, widget in self.pullout:IterateItems() do
|
||||
if widget.userdata.value == item then
|
||||
widget:SetDisabled(disabled)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function AddListItem(self, value, text)
|
||||
local item = AceGUI:Create("Dropdown-Item-Toggle")
|
||||
item:SetText(text)
|
||||
item.userdata.obj = self
|
||||
item.userdata.value = value
|
||||
item:SetCallback("OnValueChanged", OnItemValueChanged)
|
||||
self.pullout:AddItem(item)
|
||||
end
|
||||
|
||||
local function AddCloseButton(self)
|
||||
if not self.hasClose then
|
||||
local close = AceGUI:Create("Dropdown-Item-Execute")
|
||||
close:SetText(CLOSE)
|
||||
self.pullout:AddItem(close)
|
||||
self.hasClose = true
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local sortlist = {}
|
||||
local function SetList(self, list)
|
||||
self.list = list
|
||||
self.pullout:Clear()
|
||||
self.hasClose = nil
|
||||
if not list then return end
|
||||
|
||||
for v in pairs(list) do
|
||||
sortlist[#sortlist + 1] = v
|
||||
end
|
||||
tsort(sortlist)
|
||||
|
||||
for i, value in pairs(sortlist) do
|
||||
AddListItem(self, value, list[value])
|
||||
sortlist[i] = nil
|
||||
end
|
||||
if self.multiselect then
|
||||
ShowMultiText(self)
|
||||
AddCloseButton(self)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function AddItem(self, value, text)
|
||||
if self.list then
|
||||
self.list[value] = text
|
||||
AddListItem(self, value, text)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function SetMultiselect(self, multi)
|
||||
self.multiselect = multi
|
||||
if multi then
|
||||
ShowMultiText(self)
|
||||
AddCloseButton(self)
|
||||
end
|
||||
end
|
||||
|
||||
-- exported
|
||||
local function GetMultiselect(self)
|
||||
return self.multiselect
|
||||
end
|
||||
|
||||
--[[ Constructor ]]--
|
||||
|
||||
local function Constructor()
|
||||
local count = AceGUI:GetNextWidgetNum(widgetType)
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
local dropdown = CreateFrame("Frame", "AceGUI30DropDown"..count, frame, "UIDropDownMenuTemplate")
|
||||
|
||||
local self = {}
|
||||
self.type = widgetType
|
||||
self.frame = frame
|
||||
self.dropdown = dropdown
|
||||
self.count = count
|
||||
frame.obj = self
|
||||
dropdown.obj = self
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
|
||||
self.ClearFocus = ClearFocus
|
||||
|
||||
self.SetText = SetText
|
||||
self.SetValue = SetValue
|
||||
self.GetValue = GetValue
|
||||
self.SetList = SetList
|
||||
self.SetLabel = SetLabel
|
||||
self.SetDisabled = SetDisabled
|
||||
self.AddItem = AddItem
|
||||
self.SetMultiselect = SetMultiselect
|
||||
self.GetMultiselect = GetMultiselect
|
||||
self.SetItemValue = SetItemValue
|
||||
self.SetItemDisabled = SetItemDisabled
|
||||
|
||||
self.alignoffset = 31
|
||||
|
||||
frame:SetHeight(44)
|
||||
frame:SetWidth(200)
|
||||
frame:SetScript("OnHide",Dropdown_OnHide)
|
||||
|
||||
dropdown:ClearAllPoints()
|
||||
dropdown:SetPoint("TOPLEFT",frame,"TOPLEFT",-15,0)
|
||||
dropdown:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",17,0)
|
||||
dropdown:SetScript("OnHide", nil)
|
||||
|
||||
local left = _G[dropdown:GetName() .. "Left"]
|
||||
local middle = _G[dropdown:GetName() .. "Middle"]
|
||||
local right = _G[dropdown:GetName() .. "Right"]
|
||||
|
||||
middle:ClearAllPoints()
|
||||
right:ClearAllPoints()
|
||||
|
||||
middle:SetPoint("LEFT", left, "RIGHT", 0, 0)
|
||||
middle:SetPoint("RIGHT", right, "LEFT", 0, 0)
|
||||
right:SetPoint("TOPRIGHT", dropdown, "TOPRIGHT", 0, 17)
|
||||
|
||||
local button = _G[dropdown:GetName() .. "Button"]
|
||||
self.button = button
|
||||
button.obj = self
|
||||
button:SetScript("OnEnter",Control_OnEnter)
|
||||
button:SetScript("OnLeave",Control_OnLeave)
|
||||
button:SetScript("OnClick",Dropdown_TogglePullout)
|
||||
|
||||
local text = _G[dropdown:GetName() .. "Text"]
|
||||
self.text = text
|
||||
text.obj = self
|
||||
text:ClearAllPoints()
|
||||
text:SetPoint("RIGHT", right, "RIGHT" ,-43, 2)
|
||||
text:SetPoint("LEFT", left, "LEFT", 25, 2)
|
||||
|
||||
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall")
|
||||
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
|
||||
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
|
||||
label:SetJustifyH("LEFT")
|
||||
label:SetHeight(18)
|
||||
label:Hide()
|
||||
self.label = label
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion)
|
||||
end
|
||||
@@ -0,0 +1,223 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
EditBox Widget
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "EditBox", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local tostring, pairs = tostring, pairs
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local GetCursorInfo, ClearCursor, GetSpellName = GetCursorInfo, ClearCursor, GetSpellName
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: AceGUIEditBoxInsertLink, ChatFontNormal, OKAY
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Support functions
|
||||
-------------------------------------------------------------------------------]]
|
||||
if not AceGUIEditBoxInsertLink then
|
||||
-- upgradeable hook
|
||||
hooksecurefunc("ChatEdit_InsertLink", function(...) return _G.AceGUIEditBoxInsertLink(...) end)
|
||||
end
|
||||
|
||||
function _G.AceGUIEditBoxInsertLink(text)
|
||||
for i = 1, AceGUI:GetWidgetCount(Type) do
|
||||
local editbox = _G["AceGUI-3.0EditBox"..i]
|
||||
if editbox and editbox:IsVisible() and editbox:HasFocus() then
|
||||
editbox:Insert(text)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ShowButton(self)
|
||||
if not self.disablebutton then
|
||||
self.button:Show()
|
||||
self.editbox:SetTextInsets(0, 20, 3, 3)
|
||||
end
|
||||
end
|
||||
|
||||
local function HideButton(self)
|
||||
self.button:Hide()
|
||||
self.editbox:SetTextInsets(0, 0, 3, 3)
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Control_OnEnter(frame)
|
||||
frame.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(frame)
|
||||
frame.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function EditBox_OnEscapePressed(frame)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function EditBox_OnEnterPressed(frame)
|
||||
local self = frame.obj
|
||||
local value = frame:GetText()
|
||||
local cancel = self:Fire("OnEnterPressed", value)
|
||||
if not cancel then
|
||||
PlaySound("igMainMenuOptionCheckBoxOn")
|
||||
HideButton(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function EditBox_OnReceiveDrag(frame)
|
||||
local self = frame.obj
|
||||
local type, id, info = GetCursorInfo()
|
||||
if type == "item" then
|
||||
self:SetText(info)
|
||||
self:Fire("OnEnterPressed", info)
|
||||
ClearCursor()
|
||||
elseif type == "spell" then
|
||||
local name, rank = GetSpellName(id, info)
|
||||
if rank and rank:match("%d") then
|
||||
name = name.."("..rank..")"
|
||||
end
|
||||
self:SetText(name)
|
||||
self:Fire("OnEnterPressed", name)
|
||||
ClearCursor()
|
||||
end
|
||||
HideButton(self)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local function EditBox_OnTextChanged(frame)
|
||||
local self = frame.obj
|
||||
local value = frame:GetText()
|
||||
if tostring(value) ~= tostring(self.lasttext) then
|
||||
self:Fire("OnTextChanged", value)
|
||||
self.lasttext = value
|
||||
ShowButton(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function Button_OnClick(frame)
|
||||
local editbox = frame.obj.editbox
|
||||
editbox:ClearFocus()
|
||||
EditBox_OnEnterPressed(editbox)
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
-- height is controlled by SetLabel
|
||||
self:SetWidth(200)
|
||||
self:SetDisabled(false)
|
||||
self:SetLabel()
|
||||
self:SetText()
|
||||
self:DisableButton(false)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["SetDisabled"] = function(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.editbox:EnableMouse(false)
|
||||
self.editbox:ClearFocus()
|
||||
self.editbox:SetTextColor(0.5,0.5,0.5)
|
||||
self.label:SetTextColor(0.5,0.5,0.5)
|
||||
else
|
||||
self.editbox:EnableMouse(true)
|
||||
self.editbox:SetTextColor(1,1,1)
|
||||
self.label:SetTextColor(1,.82,0)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetText"] = function(self, text)
|
||||
self.lasttext = text or ""
|
||||
self.editbox:SetText(text or "")
|
||||
self.editbox:SetCursorPosition(0)
|
||||
HideButton(self)
|
||||
end,
|
||||
|
||||
["SetLabel"] = function(self, text)
|
||||
if text and text ~= "" then
|
||||
self.label:SetText(text)
|
||||
self.label:Show()
|
||||
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
|
||||
self:SetHeight(44)
|
||||
self.alignoffset = 30
|
||||
else
|
||||
self.label:SetText("")
|
||||
self.label:Hide()
|
||||
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
|
||||
self:SetHeight(26)
|
||||
self.alignoffset = 12
|
||||
end
|
||||
end,
|
||||
|
||||
["DisableButton"] = function(self, disabled)
|
||||
self.disablebutton = disabled
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local num = AceGUI:GetNextWidgetNum(Type)
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
local editbox = CreateFrame("EditBox", "AceGUI-3.0EditBox"..num, frame, "InputBoxTemplate")
|
||||
editbox:SetAutoFocus(false)
|
||||
editbox:SetFontObject(ChatFontNormal)
|
||||
editbox:SetScript("OnEnter", Control_OnEnter)
|
||||
editbox:SetScript("OnLeave", Control_OnLeave)
|
||||
editbox:SetScript("OnEscapePressed", EditBox_OnEscapePressed)
|
||||
editbox:SetScript("OnEnterPressed", EditBox_OnEnterPressed)
|
||||
editbox:SetScript("OnTextChanged", EditBox_OnTextChanged)
|
||||
editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
|
||||
editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
|
||||
editbox:SetTextInsets(0, 0, 3, 3)
|
||||
editbox:SetMaxLetters(256)
|
||||
editbox:SetPoint("BOTTOMLEFT", 6, 0)
|
||||
editbox:SetPoint("BOTTOMRIGHT")
|
||||
editbox:SetHeight(19)
|
||||
|
||||
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||
label:SetPoint("TOPLEFT", 0, -2)
|
||||
label:SetPoint("TOPRIGHT", 0, -2)
|
||||
label:SetJustifyH("LEFT")
|
||||
label:SetHeight(18)
|
||||
|
||||
local button = CreateFrame("Button", nil, editbox, "UIPanelButtonTemplate")
|
||||
button:SetWidth(40)
|
||||
button:SetHeight(20)
|
||||
button:SetPoint("RIGHT", -2, 0)
|
||||
button:SetText(OKAY)
|
||||
button:SetScript("OnClick", Button_OnClick)
|
||||
button:Hide()
|
||||
|
||||
local widget = {
|
||||
alignoffset = 30,
|
||||
editbox = editbox,
|
||||
label = label,
|
||||
button = button,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
editbox.obj, button.obj = widget, widget
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,78 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Heading Widget
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "Heading", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs = pairs
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self:SetText()
|
||||
self:SetFullWidth()
|
||||
self:SetHeight(18)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["SetText"] = function(self, text)
|
||||
self.label:SetText(text or "")
|
||||
if text and text ~= "" then
|
||||
self.left:SetPoint("RIGHT", self.label, "LEFT", -5, 0)
|
||||
self.right:Show()
|
||||
else
|
||||
self.left:SetPoint("RIGHT", -3, 0)
|
||||
self.right:Hide()
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontNormal")
|
||||
label:SetPoint("TOP")
|
||||
label:SetPoint("BOTTOM")
|
||||
label:SetJustifyH("CENTER")
|
||||
|
||||
local left = frame:CreateTexture(nil, "BACKGROUND")
|
||||
left:SetHeight(8)
|
||||
left:SetPoint("LEFT", 3, 0)
|
||||
left:SetPoint("RIGHT", label, "LEFT", -5, 0)
|
||||
left:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
left:SetTexCoord(0.81, 0.94, 0.5, 1)
|
||||
|
||||
local right = frame:CreateTexture(nil, "BACKGROUND")
|
||||
right:SetHeight(8)
|
||||
right:SetPoint("RIGHT", -3, 0)
|
||||
right:SetPoint("LEFT", label, "RIGHT", 5, 0)
|
||||
right:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
|
||||
right:SetTexCoord(0.81, 0.94, 0.5, 1)
|
||||
|
||||
local widget = {
|
||||
label = label,
|
||||
left = left,
|
||||
right = right,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,144 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Icon Widget
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "Icon", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local select, pairs = select, pairs
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Control_OnEnter(frame)
|
||||
frame.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(frame)
|
||||
frame.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function Button_OnClick(frame, button)
|
||||
frame.obj:Fire("OnClick", button)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self:SetHeight(110)
|
||||
self:SetWidth(110)
|
||||
self:SetLabel()
|
||||
self:SetImage(nil)
|
||||
self:SetImageSize(64, 64)
|
||||
self:SetDisabled(false)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["SetLabel"] = function(self, text)
|
||||
if text and text ~= "" then
|
||||
self.label:Show()
|
||||
self.label:SetText(text)
|
||||
self:SetHeight(self.image:GetHeight() + 25)
|
||||
else
|
||||
self.label:Hide()
|
||||
self:SetHeight(self.image:GetHeight() + 10)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetImage"] = function(self, path, ...)
|
||||
local image = self.image
|
||||
image:SetTexture(path)
|
||||
|
||||
if image:GetTexture() then
|
||||
local n = select("#", ...)
|
||||
if n == 4 or n == 8 then
|
||||
image:SetTexCoord(...)
|
||||
else
|
||||
image:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
["SetImageSize"] = function(self, width, height)
|
||||
self.image:SetWidth(width)
|
||||
self.image:SetHeight(height)
|
||||
--self.frame:SetWidth(width + 30)
|
||||
if self.label:IsShown() then
|
||||
self:SetHeight(height + 25)
|
||||
else
|
||||
self:SetHeight(height + 10)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetDisabled"] = function(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.frame:Disable()
|
||||
self.label:SetTextColor(0.5, 0.5, 0.5)
|
||||
self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5)
|
||||
else
|
||||
self.frame:Enable()
|
||||
self.label:SetTextColor(1, 1, 1)
|
||||
self.image:SetVertexColor(1, 1, 1)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Button", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:SetScript("OnEnter", Control_OnEnter)
|
||||
frame:SetScript("OnLeave", Control_OnLeave)
|
||||
frame:SetScript("OnClick", Button_OnClick)
|
||||
|
||||
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlight")
|
||||
label:SetPoint("BOTTOMLEFT")
|
||||
label:SetPoint("BOTTOMRIGHT")
|
||||
label:SetJustifyH("CENTER")
|
||||
label:SetJustifyV("TOP")
|
||||
label:SetHeight(18)
|
||||
|
||||
local image = frame:CreateTexture(nil, "BACKGROUND")
|
||||
image:SetWidth(64)
|
||||
image:SetHeight(64)
|
||||
image:SetPoint("TOP", 0, -5)
|
||||
|
||||
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
|
||||
highlight:SetAllPoints(image)
|
||||
highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
|
||||
highlight:SetTexCoord(0, 1, 0.23, 0.77)
|
||||
highlight:SetBlendMode("ADD")
|
||||
|
||||
local widget = {
|
||||
label = label,
|
||||
image = image,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
-- SetText is deprecated, but keep it around for a while. (say, to WoW 4.0)
|
||||
if (select(4, GetBuildInfo()) < 40000) then
|
||||
widget.SetText = widget.SetLabel
|
||||
else
|
||||
widget.SetText = function(self, ...) print("AceGUI-3.0-Icon: SetText is deprecated! Use SetLabel instead!"); self:SetLabel(...) end
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,101 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
InteractiveLabel Widget
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "InteractiveLabel", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local select, pairs = select, pairs
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: GameFontHighlightSmall
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Control_OnEnter(frame)
|
||||
frame.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(frame)
|
||||
frame.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function Label_OnClick(frame, button)
|
||||
frame.obj:Fire("OnClick", button)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
self:LabelOnAcquire()
|
||||
self:SetHighlight()
|
||||
self:SetHighlightTexCoord()
|
||||
self:SetDisabled(false)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["SetHighlight"] = function(self, ...)
|
||||
self.highlight:SetTexture(...)
|
||||
end,
|
||||
|
||||
["SetHighlightTexCoord"] = function(self, ...)
|
||||
local c = select("#", ...)
|
||||
if c == 4 or c == 8 then
|
||||
self.highlight:SetTexCoord(...)
|
||||
else
|
||||
self.highlight:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetDisabled"] = function(self,disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.frame:EnableMouse(false)
|
||||
self.label:SetTextColor(0.5, 0.5, 0.5)
|
||||
else
|
||||
self.frame:EnableMouse(true)
|
||||
self.label:SetTextColor(1, 1, 1)
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
-- create a Label type that we will hijack
|
||||
local label = AceGUI:Create("Label")
|
||||
|
||||
local frame = label.frame
|
||||
frame:EnableMouse(true)
|
||||
frame:SetScript("OnEnter", Control_OnEnter)
|
||||
frame:SetScript("OnLeave", Control_OnLeave)
|
||||
frame:SetScript("OnMouseDown", Label_OnClick)
|
||||
|
||||
local highlight = frame:CreateTexture(nil, "HIGHLIGHT")
|
||||
highlight:SetTexture(nil)
|
||||
highlight:SetAllPoints()
|
||||
highlight:SetBlendMode("ADD")
|
||||
|
||||
label.highlight = highlight
|
||||
label.type = Type
|
||||
label.LabelOnAcquire = label.OnAcquire
|
||||
for method, func in pairs(methods) do
|
||||
label[method] = func
|
||||
end
|
||||
|
||||
return label
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
|
||||
-- WoW APIs
|
||||
local IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown = IsShiftKeyDown, IsControlKeyDown, IsAltKeyDown
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: NOT_BOUND
|
||||
|
||||
--------------------------
|
||||
-- Keybinding --
|
||||
--------------------------
|
||||
|
||||
do
|
||||
local Type = "Keybinding"
|
||||
local Version = 13
|
||||
|
||||
local ControlBackdrop = {
|
||||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||||
tile = true, tileSize = 16, edgeSize = 16,
|
||||
insets = { left = 3, right = 3, top = 3, bottom = 3 }
|
||||
}
|
||||
|
||||
local function Control_OnEnter(this)
|
||||
this.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(this)
|
||||
this.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function keybindingMsgFixWidth(this)
|
||||
this:SetWidth(this.msg:GetWidth()+10)
|
||||
this:SetScript("OnUpdate",nil)
|
||||
end
|
||||
|
||||
local function Keybinding_OnClick(this, button)
|
||||
if button == "LeftButton" or button == "RightButton" then
|
||||
local self = this.obj
|
||||
if self.waitingForKey then
|
||||
this:EnableKeyboard(false)
|
||||
self.msgframe:Hide()
|
||||
this:UnlockHighlight()
|
||||
self.waitingForKey = nil
|
||||
else
|
||||
this:EnableKeyboard(true)
|
||||
self.msgframe:Show()
|
||||
this:LockHighlight()
|
||||
self.waitingForKey = true
|
||||
end
|
||||
end
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local ignoreKeys = nil
|
||||
local function Keybinding_OnKeyDown(this, key)
|
||||
local self = this.obj
|
||||
if self.waitingForKey then
|
||||
local keyPressed = key
|
||||
if keyPressed == "ESCAPE" then
|
||||
keyPressed = ""
|
||||
else
|
||||
if not ignoreKeys then
|
||||
ignoreKeys = {
|
||||
["BUTTON1"] = true, ["BUTTON2"] = true,
|
||||
["UNKNOWN"] = true,
|
||||
["LSHIFT"] = true, ["LCTRL"] = true, ["LALT"] = true,
|
||||
["RSHIFT"] = true, ["RCTRL"] = true, ["RALT"] = true,
|
||||
}
|
||||
end
|
||||
if ignoreKeys[keyPressed] then return end
|
||||
if IsShiftKeyDown() then
|
||||
keyPressed = "SHIFT-"..keyPressed
|
||||
end
|
||||
if IsControlKeyDown() then
|
||||
keyPressed = "CTRL-"..keyPressed
|
||||
end
|
||||
if IsAltKeyDown() then
|
||||
keyPressed = "ALT-"..keyPressed
|
||||
end
|
||||
end
|
||||
|
||||
this:EnableKeyboard(false)
|
||||
self.msgframe:Hide()
|
||||
this:UnlockHighlight()
|
||||
self.waitingForKey = nil
|
||||
|
||||
if not self.disabled then
|
||||
self:SetKey(keyPressed)
|
||||
self:Fire("OnKeyChanged",keyPressed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function Keybinding_OnMouseDown(this, button)
|
||||
if button == "LeftButton" or button == "RightButton" then
|
||||
return
|
||||
elseif button == "MiddleButton" then
|
||||
button = "BUTTON3"
|
||||
elseif button == "Button4" then
|
||||
button = "BUTTON4"
|
||||
elseif button == "Button5" then
|
||||
button = "BUTTON5"
|
||||
end
|
||||
Keybinding_OnKeyDown(this, button)
|
||||
end
|
||||
|
||||
local function OnAcquire(self)
|
||||
self:SetWidth(200)
|
||||
self:SetHeight(44)
|
||||
self:SetLabel("")
|
||||
self:SetKey("")
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self.waitingForKey = nil
|
||||
self.msgframe:Hide()
|
||||
self:SetDisabled(false)
|
||||
end
|
||||
|
||||
local function SetDisabled(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.button:Disable()
|
||||
self.label:SetTextColor(0.5,0.5,0.5)
|
||||
else
|
||||
self.button:Enable()
|
||||
self.label:SetTextColor(1,1,1)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetKey(self, key)
|
||||
if (key or "") == "" then
|
||||
self.button:SetText(NOT_BOUND)
|
||||
self.button:SetNormalFontObject("GameFontNormal")
|
||||
else
|
||||
self.button:SetText(key)
|
||||
self.button:SetNormalFontObject("GameFontHighlight")
|
||||
end
|
||||
end
|
||||
|
||||
local function SetLabel(self, label)
|
||||
self.label:SetText(label or "")
|
||||
if (label or "") == "" then
|
||||
self.alignoffset = nil
|
||||
self:SetHeight(24)
|
||||
else
|
||||
self.alignoffset = 30
|
||||
self:SetHeight(44)
|
||||
end
|
||||
end
|
||||
|
||||
local function Constructor()
|
||||
local num = AceGUI:GetNextWidgetNum(Type)
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
|
||||
local button = CreateFrame("Button","AceGUI-3.0 KeybindingButton"..num,frame,"UIPanelButtonTemplate2")
|
||||
|
||||
local self = {}
|
||||
self.type = Type
|
||||
self.num = num
|
||||
|
||||
local text = button:GetFontString()
|
||||
text:SetPoint("LEFT",button,"LEFT",7,0)
|
||||
text:SetPoint("RIGHT",button,"RIGHT",-7,0)
|
||||
|
||||
button:SetScript("OnClick",Keybinding_OnClick)
|
||||
button:SetScript("OnKeyDown",Keybinding_OnKeyDown)
|
||||
button:SetScript("OnEnter",Control_OnEnter)
|
||||
button:SetScript("OnLeave",Control_OnLeave)
|
||||
button:SetScript("OnMouseDown",Keybinding_OnMouseDown)
|
||||
button:RegisterForClicks("AnyDown")
|
||||
button:EnableMouse()
|
||||
|
||||
button:SetHeight(24)
|
||||
button:SetWidth(200)
|
||||
button:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT",0,0)
|
||||
button:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
|
||||
|
||||
frame:SetWidth(200)
|
||||
frame:SetHeight(44)
|
||||
|
||||
self.alignoffset = 30
|
||||
|
||||
self.button = button
|
||||
|
||||
local label = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
|
||||
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
|
||||
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
|
||||
label:SetJustifyH("CENTER")
|
||||
label:SetHeight(18)
|
||||
self.label = label
|
||||
|
||||
local msgframe = CreateFrame("Frame",nil,UIParent)
|
||||
msgframe:SetHeight(30)
|
||||
msgframe:SetBackdrop(ControlBackdrop)
|
||||
msgframe:SetBackdropColor(0,0,0)
|
||||
msgframe:SetFrameStrata("FULLSCREEN_DIALOG")
|
||||
msgframe:SetFrameLevel(1000)
|
||||
self.msgframe = msgframe
|
||||
local msg = msgframe:CreateFontString(nil,"OVERLAY","GameFontNormal")
|
||||
msg:SetText("Press a key to bind, ESC to clear the binding or click the button again to cancel")
|
||||
msgframe.msg = msg
|
||||
msg:SetPoint("TOPLEFT",msgframe,"TOPLEFT",5,-5)
|
||||
msgframe:SetScript("OnUpdate", keybindingMsgFixWidth)
|
||||
msgframe:SetPoint("BOTTOM",button,"TOP",0,0)
|
||||
msgframe:Hide()
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
self.SetLabel = SetLabel
|
||||
self.SetDisabled = SetDisabled
|
||||
self.SetKey = SetKey
|
||||
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
button.obj = self
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,162 @@
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Label Widget
|
||||
Displays text and optionally an icon.
|
||||
-------------------------------------------------------------------------------]]
|
||||
local Type, Version = "Label", 21
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local max, select, pairs = math.max, select, pairs
|
||||
|
||||
-- WoW APIs
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: GameFontHighlightSmall
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Support functions
|
||||
-------------------------------------------------------------------------------]]
|
||||
|
||||
local function UpdateImageAnchor(self)
|
||||
if self.resizing then return end
|
||||
local frame = self.frame
|
||||
local width = frame.width or frame:GetWidth() or 0
|
||||
local image = self.image
|
||||
local label = self.label
|
||||
local height
|
||||
|
||||
label:ClearAllPoints()
|
||||
image:ClearAllPoints()
|
||||
|
||||
if self.imageshown then
|
||||
local imagewidth = image:GetWidth()
|
||||
if (width - imagewidth) < 200 or (label:GetText() or "") == "" then
|
||||
-- image goes on top centered when less than 200 width for the text, or if there is no text
|
||||
image:SetPoint("TOP")
|
||||
label:SetPoint("TOP", image, "BOTTOM")
|
||||
label:SetPoint("LEFT")
|
||||
label:SetWidth(width)
|
||||
height = image:GetHeight() + label:GetHeight()
|
||||
else
|
||||
-- image on the left
|
||||
image:SetPoint("TOPLEFT")
|
||||
label:SetPoint("TOPLEFT", image, "TOPRIGHT", 4, 0)
|
||||
label:SetWidth(width - imagewidth - 4)
|
||||
height = max(image:GetHeight(), label:GetHeight())
|
||||
end
|
||||
else
|
||||
-- no image shown
|
||||
label:SetPoint("TOPLEFT")
|
||||
label:SetWidth(width)
|
||||
height = label:GetHeight()
|
||||
end
|
||||
|
||||
self.resizing = true
|
||||
frame:SetHeight(height)
|
||||
frame.height = height
|
||||
self.resizing = nil
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["OnAcquire"] = function(self)
|
||||
-- set the flag to stop constant size updates
|
||||
self.resizing = true
|
||||
-- height is set dynamically by the text and image size
|
||||
self:SetWidth(200)
|
||||
self:SetText()
|
||||
self:SetImage(nil)
|
||||
self:SetImageSize(16, 16)
|
||||
self:SetColor()
|
||||
self:SetFontObject()
|
||||
|
||||
-- reset the flag
|
||||
self.resizing = nil
|
||||
-- run the update explicitly
|
||||
UpdateImageAnchor(self)
|
||||
end,
|
||||
|
||||
-- ["OnRelease"] = nil,
|
||||
|
||||
["OnWidthSet"] = function(self, width)
|
||||
UpdateImageAnchor(self)
|
||||
end,
|
||||
|
||||
["SetText"] = function(self, text)
|
||||
self.label:SetText(text)
|
||||
UpdateImageAnchor(self)
|
||||
end,
|
||||
|
||||
["SetColor"] = function(self, r, g, b)
|
||||
if not (r and g and b) then
|
||||
r, g, b = 1, 1, 1
|
||||
end
|
||||
self.label:SetVertexColor(r, g, b)
|
||||
end,
|
||||
|
||||
["SetImage"] = function(self, path, ...)
|
||||
local image = self.image
|
||||
image:SetTexture(path)
|
||||
|
||||
if image:GetTexture() then
|
||||
self.imageshown = true
|
||||
local n = select("#", ...)
|
||||
if n == 4 or n == 8 then
|
||||
image:SetTexCoord(...)
|
||||
else
|
||||
image:SetTexCoord(0, 1, 0, 1)
|
||||
end
|
||||
else
|
||||
self.imageshown = nil
|
||||
end
|
||||
UpdateImageAnchor(self)
|
||||
end,
|
||||
|
||||
["SetFont"] = function(self, font, height, flags)
|
||||
self.label:SetFont(font, height, flags)
|
||||
end,
|
||||
|
||||
["SetFontObject"] = function(self, font)
|
||||
self:SetFont((font or GameFontHighlightSmall):GetFont())
|
||||
end,
|
||||
|
||||
["SetImageSize"] = function(self, width, height)
|
||||
self.image:SetWidth(width)
|
||||
self.image:SetHeight(height)
|
||||
UpdateImageAnchor(self)
|
||||
end,
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
local label = frame:CreateFontString(nil, "BACKGROUND", "GameFontHighlightSmall")
|
||||
label:SetJustifyH("LEFT")
|
||||
label:SetJustifyV("TOP")
|
||||
|
||||
local image = frame:CreateTexture(nil, "BACKGROUND")
|
||||
|
||||
-- create widget
|
||||
local widget = {
|
||||
label = label,
|
||||
image = image,
|
||||
frame = frame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
|
||||
return AceGUI:RegisterAsWidget(widget)
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,278 @@
|
||||
local Type, Version = "MultiLineEditBox", 20
|
||||
local AceGUI = LibStub and LibStub("AceGUI-3.0", true)
|
||||
if not AceGUI or (AceGUI:GetWidgetVersion(Type) or 0) >= Version then return end
|
||||
|
||||
-- Lua APIs
|
||||
local pairs = pairs
|
||||
|
||||
-- WoW APIs
|
||||
local GetCursorInfo, GetSpellName, ClearCursor = GetCursorInfo, GetSpellName, ClearCursor
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
local _G = _G
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: ACCEPT, ChatFontNormal
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Scripts
|
||||
-------------------------------------------------------------------------------]]
|
||||
local function OnClick(self) -- Button
|
||||
self = self.obj
|
||||
self.editBox:ClearFocus()
|
||||
if not self:Fire("OnEnterPressed", self.editBox:GetText()) then
|
||||
self.button:Disable()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnCursorChanged(self, _, y, _, cursorHeight) -- EditBox
|
||||
self, y = self.obj.scrollFrame, -y
|
||||
local offset = self:GetVerticalScroll()
|
||||
if y < offset then
|
||||
self:SetVerticalScroll(y)
|
||||
else
|
||||
y = y + cursorHeight - self:GetHeight()
|
||||
if y > offset then
|
||||
self:SetVerticalScroll(y)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnEditFocusLost(self) -- EditBox
|
||||
self:HighlightText(0, 0)
|
||||
end
|
||||
|
||||
local function OnEnter(self) -- EditBox / ScrollFrame
|
||||
self = self.obj
|
||||
if not self.entered then
|
||||
self.entered = true
|
||||
self:Fire("OnEnter")
|
||||
end
|
||||
end
|
||||
|
||||
local function OnLeave(self) -- EditBox / ScrollFrame
|
||||
self = self.obj
|
||||
if self.entered then
|
||||
self.entered = nil
|
||||
self:Fire("OnLeave")
|
||||
end
|
||||
end
|
||||
|
||||
local function OnMouseUp(self) -- ScrollFrame
|
||||
self = self.obj.editBox
|
||||
self:SetFocus()
|
||||
self:SetCursorPosition(self:GetNumLetters())
|
||||
end
|
||||
|
||||
local function OnReceiveDrag(self) -- EditBox / ScrollFrame
|
||||
local type, id, info = GetCursorInfo()
|
||||
if type == "spell" then
|
||||
info, id = GetSpellName(id, info)
|
||||
if id and id:match("%d") then
|
||||
info = info .. "(" .. id .. ")"
|
||||
end
|
||||
elseif type ~= "item" then
|
||||
return
|
||||
end
|
||||
ClearCursor()
|
||||
self = self.obj
|
||||
local editBox = self.editBox
|
||||
if not editBox:HasFocus() then
|
||||
editBox:SetFocus()
|
||||
editBox:SetCursorPosition(editBox:GetNumLetters())
|
||||
end
|
||||
editBox:Insert(info)
|
||||
self.button:Enable()
|
||||
end
|
||||
|
||||
local function OnSizeChanged(self, width, height) -- ScrollFrame
|
||||
self.obj.editBox:SetWidth(width)
|
||||
end
|
||||
|
||||
local function OnTextChanged(self, userInput) -- EditBox
|
||||
if userInput then
|
||||
self = self.obj
|
||||
self:Fire("OnTextChanged", self.editBox:GetText())
|
||||
self.button:Enable()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnTextSet(self) -- EditBox
|
||||
self:HighlightText(0, 0)
|
||||
self:SetCursorPosition(self:GetNumLetters())
|
||||
self:SetCursorPosition(0)
|
||||
self.obj.button:Disable()
|
||||
end
|
||||
|
||||
local function OnVerticalScroll(self, offset) -- ScrollFrame
|
||||
local editBox = self.obj.editBox
|
||||
editBox:SetHitRectInsets(0, 0, offset, editBox:GetHeight() - offset - self:GetHeight())
|
||||
end
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Methods
|
||||
-------------------------------------------------------------------------------]]
|
||||
local methods = {
|
||||
["GetText"] = function(self)
|
||||
return self.editBox:GetText()
|
||||
end,
|
||||
|
||||
["OnAcquire"] = function(self)
|
||||
self.editBox:SetText("")
|
||||
self:SetDisabled(false)
|
||||
self:SetWidth(200)
|
||||
self:SetNumLines()
|
||||
self.entered = nil
|
||||
end,
|
||||
|
||||
["OnRelease"] = function(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
end,
|
||||
|
||||
["SetDisabled"] = function(self, disabled)
|
||||
local editBox = self.editBox
|
||||
if disabled then
|
||||
editBox:ClearFocus()
|
||||
editBox:EnableMouse(false)
|
||||
editBox:SetTextColor(0.5, 0.5, 0.5)
|
||||
self.label:SetTextColor(0.5, 0.5, 0.5)
|
||||
self.scrollFrame:EnableMouse(false)
|
||||
self.button:Disable()
|
||||
else
|
||||
editBox:EnableMouse(true)
|
||||
editBox:SetTextColor(1, 1, 1)
|
||||
self.label:SetTextColor(1, 0.82, 0)
|
||||
self.scrollFrame:EnableMouse(true)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetLabel"] = function(self, text)
|
||||
if text and text ~= "" then
|
||||
self.label:SetText(text)
|
||||
if self.labelHeight ~= 10 then
|
||||
self.labelHeight = 10
|
||||
self.scrollBar:SetPoint("TOP", self.label, "BOTTOM", 0, -19)
|
||||
self:SetHeight(self.frame.height + 10)
|
||||
self.label:Show()
|
||||
end
|
||||
elseif self.labelHeight ~= 0 then
|
||||
self.labelHeight = 0
|
||||
self.label:Hide()
|
||||
self.scrollBar:SetPoint("TOP", self.frame, "TOP", 0, -23)
|
||||
self:SetHeight(self.frame.height - 10)
|
||||
end
|
||||
end,
|
||||
|
||||
["SetNumLines"] = function(self, value)
|
||||
if not value or value < 4 then
|
||||
value = 4
|
||||
end
|
||||
self:SetHeight(value * 14 + 41 + self.labelHeight)
|
||||
end,
|
||||
|
||||
["SetText"] = function(self, text)
|
||||
self.editBox:SetText(text)
|
||||
end
|
||||
}
|
||||
|
||||
--[[-----------------------------------------------------------------------------
|
||||
Constructor
|
||||
-------------------------------------------------------------------------------]]
|
||||
local backdrop = {
|
||||
bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
|
||||
edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], edgeSize = 16,
|
||||
insets = { left = 4, right = 3, top = 4, bottom = 3 }
|
||||
}
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame", nil, UIParent)
|
||||
frame:Hide()
|
||||
|
||||
local widgetNum = AceGUI:GetNextWidgetNum(Type)
|
||||
|
||||
local label = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||
label:SetPoint("TOPLEFT", frame, "TOPLEFT", 0, -4)
|
||||
label:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, -4)
|
||||
label:SetJustifyH("LEFT")
|
||||
label:SetText(ACCEPT)
|
||||
label:SetHeight(10)
|
||||
|
||||
local button = CreateFrame("Button", ("%s%dButton"):format(Type, widgetNum), frame, "UIPanelButtonTemplate2")
|
||||
button:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 0, 4)
|
||||
button:SetHeight(22)
|
||||
button:SetWidth(label:GetStringWidth() + 24)
|
||||
button:SetText(ACCEPT)
|
||||
button:SetScript("OnClick", OnClick)
|
||||
button:Disable()
|
||||
|
||||
local text = button:GetFontString()
|
||||
text:ClearAllPoints()
|
||||
text:SetPoint("TOPLEFT", button, "TOPLEFT", 5, -5)
|
||||
text:SetPoint("BOTTOMRIGHT", button, "BOTTOMRIGHT", -5, 1)
|
||||
text:SetJustifyV("MIDDLE")
|
||||
|
||||
local scrollBG = CreateFrame("Frame", nil, frame)
|
||||
scrollBG:SetBackdrop(backdrop)
|
||||
scrollBG:SetBackdropColor(0, 0, 0)
|
||||
scrollBG:SetBackdropBorderColor(0.4, 0.4, 0.4)
|
||||
|
||||
local scrollFrame = CreateFrame("ScrollFrame", ("%s%dScrollFrame"):format(Type, widgetNum), frame, "UIPanelScrollFrameTemplate")
|
||||
|
||||
local scrollBar = _G[scrollFrame:GetName() .. "ScrollBar"]
|
||||
scrollBar:ClearAllPoints()
|
||||
scrollBar:SetPoint("TOP", label, "BOTTOM", 0, -19)
|
||||
scrollBar:SetPoint("BOTTOM", button, "TOP", 0, 18)
|
||||
scrollBar:SetPoint("RIGHT", frame, "RIGHT")
|
||||
|
||||
scrollBG:SetPoint("TOPRIGHT", scrollBar, "TOPLEFT", 0, 19)
|
||||
scrollBG:SetPoint("BOTTOMLEFT", button, "TOPLEFT")
|
||||
|
||||
scrollFrame:SetPoint("TOPLEFT", scrollBG, "TOPLEFT", 5, -6)
|
||||
scrollFrame:SetPoint("BOTTOMRIGHT", scrollBG, "BOTTOMRIGHT", -4, 4)
|
||||
scrollFrame:SetScript("OnEnter", OnEnter)
|
||||
scrollFrame:SetScript("OnLeave", OnLeave)
|
||||
scrollFrame:SetScript("OnMouseUp", OnMouseUp)
|
||||
scrollFrame:SetScript("OnReceiveDrag", OnReceiveDrag)
|
||||
scrollFrame:SetScript("OnSizeChanged", OnSizeChanged)
|
||||
scrollFrame:HookScript("OnVerticalScroll", OnVerticalScroll)
|
||||
|
||||
local editBox = CreateFrame("EditBox", nil, scrollFrame)
|
||||
editBox:SetAllPoints()
|
||||
editBox:SetFontObject(ChatFontNormal)
|
||||
editBox:SetMultiLine(true)
|
||||
editBox:EnableMouse(true)
|
||||
editBox:SetAutoFocus(false)
|
||||
editBox:SetCountInvisibleLetters(false)
|
||||
editBox:SetScript("OnCursorChanged", OnCursorChanged)
|
||||
editBox:SetScript("OnEditFocusLost", OnEditFocusLost)
|
||||
editBox:SetScript("OnEnter", OnEnter)
|
||||
editBox:SetScript("OnEscapePressed", editBox.ClearFocus)
|
||||
editBox:SetScript("OnLeave", OnLeave)
|
||||
editBox:SetScript("OnMouseDown", OnReceiveDrag)
|
||||
editBox:SetScript("OnReceiveDrag", OnReceiveDrag)
|
||||
editBox:SetScript("OnTextChanged", OnTextChanged)
|
||||
editBox:SetScript("OnTextSet", OnTextSet)
|
||||
|
||||
scrollFrame:SetScrollChild(editBox)
|
||||
|
||||
local widget = {
|
||||
button = button,
|
||||
editBox = editBox,
|
||||
frame = frame,
|
||||
label = label,
|
||||
labelHeight = 10,
|
||||
scrollBar = scrollBar,
|
||||
scrollFrame = scrollFrame,
|
||||
type = Type
|
||||
}
|
||||
for method, func in pairs(methods) do
|
||||
widget[method] = func
|
||||
end
|
||||
button.obj, editBox.obj, scrollFrame.obj = widget, widget, widget
|
||||
|
||||
AceGUI:RegisterAsWidget(widget)
|
||||
return widget
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type, Constructor, Version)
|
||||
@@ -0,0 +1,285 @@
|
||||
local AceGUI = LibStub("AceGUI-3.0")
|
||||
|
||||
-- Lua APIs
|
||||
local min, max, floor = math.min, math.max, math.floor
|
||||
local tonumber = tonumber
|
||||
|
||||
-- WoW APIs
|
||||
local PlaySound = PlaySound
|
||||
local CreateFrame, UIParent = CreateFrame, UIParent
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: GameFontHighlightSmall
|
||||
|
||||
--------------------------
|
||||
-- Slider --
|
||||
--------------------------
|
||||
do
|
||||
local Type = "Slider"
|
||||
local Version = 11
|
||||
|
||||
local function OnAcquire(self)
|
||||
self:SetWidth(200)
|
||||
self:SetHeight(44)
|
||||
self:SetDisabled(false)
|
||||
self:SetIsPercent(nil)
|
||||
self:SetSliderValues(0,100,1)
|
||||
self:SetValue(0)
|
||||
end
|
||||
|
||||
local function OnRelease(self)
|
||||
self.frame:ClearAllPoints()
|
||||
self.frame:Hide()
|
||||
self.slider:EnableMouseWheel(false)
|
||||
self:SetDisabled(false)
|
||||
end
|
||||
|
||||
local function Control_OnEnter(this)
|
||||
this.obj:Fire("OnEnter")
|
||||
end
|
||||
|
||||
local function Control_OnLeave(this)
|
||||
this.obj:Fire("OnLeave")
|
||||
end
|
||||
|
||||
local function UpdateText(self)
|
||||
local value = self.value or 0
|
||||
if self.ispercent then
|
||||
self.editbox:SetText(("%s%%"):format(floor(value*1000+0.5)/10))
|
||||
else
|
||||
self.editbox:SetText(floor(value*100+0.5)/100)
|
||||
end
|
||||
end
|
||||
|
||||
local function UpdateLabels(self)
|
||||
local min, max = (self.min or 0), (self.max or 100)
|
||||
if self.ispercent then
|
||||
self.lowtext:SetFormattedText("%s%%",(min * 100))
|
||||
self.hightext:SetFormattedText("%s%%",(max * 100))
|
||||
else
|
||||
self.lowtext:SetText(min)
|
||||
self.hightext:SetText(max)
|
||||
end
|
||||
end
|
||||
|
||||
local function Slider_OnValueChanged(this)
|
||||
local self = this.obj
|
||||
if not this.setup then
|
||||
local newvalue
|
||||
newvalue = this:GetValue()
|
||||
if newvalue ~= self.value and not self.disabled then
|
||||
self.value = newvalue
|
||||
self:Fire("OnValueChanged", newvalue)
|
||||
end
|
||||
if self.value then
|
||||
local value = self.value
|
||||
UpdateText(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function Slider_OnMouseUp(this)
|
||||
local self = this.obj
|
||||
self:Fire("OnMouseUp",this:GetValue())
|
||||
end
|
||||
|
||||
local function Slider_OnMouseWheel(this, v)
|
||||
local self = this.obj
|
||||
if not self.disabled then
|
||||
local value = self.value
|
||||
if v > 0 then
|
||||
value = min(value + (self.step or 1),self.max)
|
||||
else
|
||||
value = max(value - (self.step or 1), self.min)
|
||||
end
|
||||
self.slider:SetValue(value)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetDisabled(self, disabled)
|
||||
self.disabled = disabled
|
||||
if disabled then
|
||||
self.slider:EnableMouse(false)
|
||||
self.label:SetTextColor(.5,.5,.5)
|
||||
self.hightext:SetTextColor(.5,.5,.5)
|
||||
self.lowtext:SetTextColor(.5,.5,.5)
|
||||
--self.valuetext:SetTextColor(.5,.5,.5)
|
||||
self.editbox:SetTextColor(.5,.5,.5)
|
||||
self.editbox:EnableMouse(false)
|
||||
self.editbox:ClearFocus()
|
||||
else
|
||||
self.slider:EnableMouse(true)
|
||||
self.label:SetTextColor(1,.82,0)
|
||||
self.hightext:SetTextColor(1,1,1)
|
||||
self.lowtext:SetTextColor(1,1,1)
|
||||
--self.valuetext:SetTextColor(1,1,1)
|
||||
self.editbox:SetTextColor(1,1,1)
|
||||
self.editbox:EnableMouse(true)
|
||||
end
|
||||
end
|
||||
|
||||
local function SetValue(self, value)
|
||||
self.slider.setup = true
|
||||
self.slider:SetValue(value)
|
||||
self.value = value
|
||||
UpdateText(self)
|
||||
self.slider.setup = nil
|
||||
end
|
||||
|
||||
local function SetLabel(self, text)
|
||||
self.label:SetText(text)
|
||||
end
|
||||
|
||||
local function SetSliderValues(self, min, max, step)
|
||||
local frame = self.slider
|
||||
frame.setup = true
|
||||
self.min = min
|
||||
self.max = max
|
||||
self.step = step
|
||||
frame:SetMinMaxValues(min or 0,max or 100)
|
||||
UpdateLabels(self)
|
||||
frame:SetValueStep(step or 1)
|
||||
if self.value then
|
||||
frame:SetValue(self.value)
|
||||
end
|
||||
frame.setup = nil
|
||||
end
|
||||
|
||||
local function EditBox_OnEscapePressed(this)
|
||||
this:ClearFocus()
|
||||
end
|
||||
|
||||
local function EditBox_OnEnterPressed(this)
|
||||
local self = this.obj
|
||||
local value = this:GetText()
|
||||
if self.ispercent then
|
||||
value = value:gsub('%%','')
|
||||
value = tonumber(value) / 100
|
||||
else
|
||||
value = tonumber(value)
|
||||
end
|
||||
|
||||
if value then
|
||||
PlaySound("igMainMenuOptionCheckBoxOn")
|
||||
self:Fire("OnValueChanged", value)
|
||||
self:Fire("OnMouseUp",value)
|
||||
end
|
||||
end
|
||||
|
||||
local function EditBox_OnEnter(this)
|
||||
this:SetBackdropBorderColor(0.5,0.5,0.5,1)
|
||||
end
|
||||
|
||||
local function EditBox_OnLeave(this)
|
||||
this:SetBackdropBorderColor(0.3,0.3,0.3,0.8)
|
||||
end
|
||||
|
||||
local function SetIsPercent(self, value)
|
||||
self.ispercent = value
|
||||
UpdateLabels(self)
|
||||
UpdateText(self)
|
||||
end
|
||||
|
||||
local function FrameOnMouseDown(this)
|
||||
this.obj.slider:EnableMouseWheel(true)
|
||||
AceGUI:ClearFocus()
|
||||
end
|
||||
|
||||
local SliderBackdrop = {
|
||||
bgFile = "Interface\\Buttons\\UI-SliderBar-Background",
|
||||
edgeFile = "Interface\\Buttons\\UI-SliderBar-Border",
|
||||
tile = true, tileSize = 8, edgeSize = 8,
|
||||
insets = { left = 3, right = 3, top = 6, bottom = 6 }
|
||||
}
|
||||
|
||||
local ManualBackdrop = {
|
||||
bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
|
||||
tile = true, edgeSize = 1, tileSize = 5,
|
||||
}
|
||||
|
||||
local function Constructor()
|
||||
local frame = CreateFrame("Frame",nil,UIParent)
|
||||
local self = {}
|
||||
self.type = Type
|
||||
|
||||
self.OnRelease = OnRelease
|
||||
self.OnAcquire = OnAcquire
|
||||
|
||||
self.frame = frame
|
||||
frame.obj = self
|
||||
|
||||
self.SetDisabled = SetDisabled
|
||||
self.SetValue = SetValue
|
||||
self.SetSliderValues = SetSliderValues
|
||||
self.SetLabel = SetLabel
|
||||
self.SetIsPercent = SetIsPercent
|
||||
|
||||
self.alignoffset = 25
|
||||
|
||||
frame:EnableMouse(true)
|
||||
frame:SetScript("OnMouseDown",FrameOnMouseDown)
|
||||
self.slider = CreateFrame("Slider",nil,frame)
|
||||
local slider = self.slider
|
||||
slider:SetScript("OnEnter",Control_OnEnter)
|
||||
slider:SetScript("OnLeave",Control_OnLeave)
|
||||
slider:SetScript("OnMouseUp", Slider_OnMouseUp)
|
||||
slider.obj = self
|
||||
slider:SetOrientation("HORIZONTAL")
|
||||
slider:SetHeight(15)
|
||||
slider:SetHitRectInsets(0,0,-10,0)
|
||||
slider:SetBackdrop(SliderBackdrop)
|
||||
--slider:EnableMouseWheel(true)
|
||||
slider:SetScript("OnMouseWheel", Slider_OnMouseWheel)
|
||||
|
||||
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
|
||||
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
|
||||
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
|
||||
label:SetJustifyH("CENTER")
|
||||
label:SetHeight(15)
|
||||
self.label = label
|
||||
|
||||
self.lowtext = slider:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall")
|
||||
self.lowtext:SetPoint("TOPLEFT",slider,"BOTTOMLEFT",2,3)
|
||||
|
||||
self.hightext = slider:CreateFontString(nil,"ARTWORK","GameFontHighlightSmall")
|
||||
self.hightext:SetPoint("TOPRIGHT",slider,"BOTTOMRIGHT",-2,3)
|
||||
|
||||
|
||||
local editbox = CreateFrame("EditBox",nil,frame)
|
||||
editbox:SetAutoFocus(false)
|
||||
editbox:SetFontObject(GameFontHighlightSmall)
|
||||
editbox:SetPoint("TOP",slider,"BOTTOM",0,0)
|
||||
editbox:SetHeight(14)
|
||||
editbox:SetWidth(70)
|
||||
editbox:SetJustifyH("CENTER")
|
||||
editbox:EnableMouse(true)
|
||||
editbox:SetScript("OnEscapePressed",EditBox_OnEscapePressed)
|
||||
editbox:SetScript("OnEnterPressed",EditBox_OnEnterPressed)
|
||||
editbox:SetScript("OnEnter",EditBox_OnEnter)
|
||||
editbox:SetScript("OnLeave",EditBox_OnLeave)
|
||||
editbox:SetBackdrop(ManualBackdrop)
|
||||
editbox:SetBackdropColor(0,0,0,0.5)
|
||||
editbox:SetBackdropBorderColor(0.3,0.3,0.30,0.80)
|
||||
self.editbox = editbox
|
||||
editbox.obj = self
|
||||
|
||||
slider:SetThumbTexture("Interface\\Buttons\\UI-SliderBar-Button-Horizontal")
|
||||
|
||||
frame:SetWidth(200)
|
||||
frame:SetHeight(44)
|
||||
slider:SetPoint("TOP",label,"BOTTOM",0,0)
|
||||
slider:SetPoint("LEFT",frame,"LEFT",3,0)
|
||||
slider:SetPoint("RIGHT",frame,"RIGHT",-3,0)
|
||||
|
||||
|
||||
slider:SetValue(self.value or 0)
|
||||
slider:SetScript("OnValueChanged",Slider_OnValueChanged)
|
||||
|
||||
AceGUI:RegisterAsWidget(self)
|
||||
return self
|
||||
end
|
||||
|
||||
AceGUI:RegisterWidgetType(Type,Constructor,Version)
|
||||
end
|
||||
@@ -0,0 +1,514 @@
|
||||
--- **AceHook-3.0** offers safe Hooking/Unhooking of functions, methods and frame scripts.
|
||||
-- Using AceHook-3.0 is recommended when you need to unhook your hooks again, so the hook chain isn't broken
|
||||
-- when you manually restore the original function.
|
||||
--
|
||||
-- **AceHook-3.0** can be embeded into your addon, either explicitly by calling AceHook:Embed(MyAddon) or by
|
||||
-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
|
||||
-- and can be accessed directly, without having to explicitly call AceHook itself.\\
|
||||
-- It is recommended to embed AceHook, otherwise you'll have to specify a custom `self` on all calls you
|
||||
-- make into AceHook.
|
||||
-- @class file
|
||||
-- @name AceHook-3.0
|
||||
-- @release $Id: AceHook-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $
|
||||
local ACEHOOK_MAJOR, ACEHOOK_MINOR = "AceHook-3.0", 5
|
||||
local AceHook, oldminor = LibStub:NewLibrary(ACEHOOK_MAJOR, ACEHOOK_MINOR)
|
||||
|
||||
if not AceHook then return end -- No upgrade needed
|
||||
|
||||
AceHook.embeded = AceHook.embeded or {}
|
||||
AceHook.registry = AceHook.registry or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end })
|
||||
AceHook.handlers = AceHook.handlers or {}
|
||||
AceHook.actives = AceHook.actives or {}
|
||||
AceHook.scripts = AceHook.scripts or {}
|
||||
AceHook.onceSecure = AceHook.onceSecure or {}
|
||||
AceHook.hooks = AceHook.hooks or {}
|
||||
|
||||
-- local upvalues
|
||||
local registry = AceHook.registry
|
||||
local handlers = AceHook.handlers
|
||||
local actives = AceHook.actives
|
||||
local scripts = AceHook.scripts
|
||||
local onceSecure = AceHook.onceSecure
|
||||
|
||||
-- Lua APIs
|
||||
local pairs, next, type = pairs, next, type
|
||||
local format = string.format
|
||||
local assert, error = assert, error
|
||||
|
||||
-- WoW APIs
|
||||
local issecurevariable, hooksecurefunc = issecurevariable, hooksecurefunc
|
||||
local _G = _G
|
||||
|
||||
-- functions for later definition
|
||||
local donothing, createHook, hook
|
||||
|
||||
local protectedScripts = {
|
||||
OnClick = true,
|
||||
}
|
||||
|
||||
-- upgrading of embeded is done at the bottom of the file
|
||||
|
||||
local mixins = {
|
||||
"Hook", "SecureHook",
|
||||
"HookScript", "SecureHookScript",
|
||||
"Unhook", "UnhookAll",
|
||||
"IsHooked",
|
||||
"RawHook", "RawHookScript"
|
||||
}
|
||||
|
||||
-- AceHook:Embed( target )
|
||||
-- target (object) - target object to embed AceHook in
|
||||
--
|
||||
-- Embeds AceEevent into the target object making the functions from the mixins list available on target:..
|
||||
function AceHook:Embed( target )
|
||||
for k, v in pairs( mixins ) do
|
||||
target[v] = self[v]
|
||||
end
|
||||
self.embeded[target] = true
|
||||
-- inject the hooks table safely
|
||||
target.hooks = target.hooks or {}
|
||||
return target
|
||||
end
|
||||
|
||||
-- AceHook:OnEmbedDisable( target )
|
||||
-- target (object) - target object that is being disabled
|
||||
--
|
||||
-- Unhooks all hooks when the target disables.
|
||||
-- this method should be called by the target manually or by an addon framework
|
||||
function AceHook:OnEmbedDisable( target )
|
||||
target:UnhookAll()
|
||||
end
|
||||
|
||||
function createHook(self, handler, orig, secure, failsafe)
|
||||
local uid
|
||||
local method = type(handler) == "string"
|
||||
if failsafe and not secure then
|
||||
-- failsafe hook creation
|
||||
uid = function(...)
|
||||
if actives[uid] then
|
||||
if method then
|
||||
self[handler](self, ...)
|
||||
else
|
||||
handler(...)
|
||||
end
|
||||
end
|
||||
return orig(...)
|
||||
end
|
||||
-- /failsafe hook
|
||||
else
|
||||
-- all other hooks
|
||||
uid = function(...)
|
||||
if actives[uid] then
|
||||
if method then
|
||||
return self[handler](self, ...)
|
||||
else
|
||||
return handler(...)
|
||||
end
|
||||
elseif not secure then -- backup on non secure
|
||||
return orig(...)
|
||||
end
|
||||
end
|
||||
-- /hook
|
||||
end
|
||||
return uid
|
||||
end
|
||||
|
||||
function donothing() end
|
||||
|
||||
function hook(self, obj, method, handler, script, secure, raw, forceSecure, usage)
|
||||
if not handler then handler = method end
|
||||
|
||||
-- These asserts make sure AceHooks's devs play by the rules.
|
||||
assert(not script or type(script) == "boolean")
|
||||
assert(not secure or type(secure) == "boolean")
|
||||
assert(not raw or type(raw) == "boolean")
|
||||
assert(not forceSecure or type(forceSecure) == "boolean")
|
||||
assert(usage)
|
||||
|
||||
-- Error checking Battery!
|
||||
if obj and type(obj) ~= "table" then
|
||||
error(format("%s: 'object' - nil or table expected got %s", usage, type(obj)), 3)
|
||||
end
|
||||
if type(method) ~= "string" then
|
||||
error(format("%s: 'method' - string expected got %s", usage, type(method)), 3)
|
||||
end
|
||||
if type(handler) ~= "string" and type(handler) ~= "function" then
|
||||
error(format("%s: 'handler' - nil, string, or function expected got %s", usage, type(handler)), 3)
|
||||
end
|
||||
if type(handler) == "string" and type(self[handler]) ~= "function" then
|
||||
error(format("%s: 'handler' - Handler specified does not exist at self[handler]", usage), 3)
|
||||
end
|
||||
if script then
|
||||
if not secure and obj:IsProtected() and protectedScripts[method] then
|
||||
error(format("Cannot hook secure script %q; Use SecureHookScript(obj, method, [handler]) instead.", method), 3)
|
||||
end
|
||||
if not obj or not obj.GetScript or not obj:HasScript(method) then
|
||||
error(format("%s: You can only hook a script on a frame object", usage), 3)
|
||||
end
|
||||
else
|
||||
local issecure
|
||||
if obj then
|
||||
issecure = onceSecure[obj] and onceSecure[obj][method] or issecurevariable(obj, method)
|
||||
else
|
||||
issecure = onceSecure[method] or issecurevariable(method)
|
||||
end
|
||||
if issecure then
|
||||
if forceSecure then
|
||||
if obj then
|
||||
onceSecure[obj] = onceSecure[obj] or {}
|
||||
onceSecure[obj][method] = true
|
||||
else
|
||||
onceSecure[method] = true
|
||||
end
|
||||
elseif not secure then
|
||||
error(format("%s: Attempt to hook secure function %s. Use `SecureHook' or add `true' to the argument list to override.", usage, method), 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local uid
|
||||
if obj then
|
||||
uid = registry[self][obj] and registry[self][obj][method]
|
||||
else
|
||||
uid = registry[self][method]
|
||||
end
|
||||
|
||||
if uid then
|
||||
if actives[uid] then
|
||||
-- Only two sane choices exist here. We either a) error 100% of the time or b) always unhook and then hook
|
||||
-- choice b would likely lead to odd debuging conditions or other mysteries so we're going with a.
|
||||
error(format("Attempting to rehook already active hook %s.", method))
|
||||
end
|
||||
|
||||
if handlers[uid] == handler then -- turn on a decative hook, note enclosures break this ability, small memory leak
|
||||
actives[uid] = true
|
||||
return
|
||||
elseif obj then -- is there any reason not to call unhook instead of doing the following several lines?
|
||||
if self.hooks and self.hooks[obj] then
|
||||
self.hooks[obj][method] = nil
|
||||
end
|
||||
registry[self][obj][method] = nil
|
||||
else
|
||||
if self.hooks then
|
||||
self.hooks[method] = nil
|
||||
end
|
||||
registry[self][method] = nil
|
||||
end
|
||||
handlers[uid], actives[uid], scripts[uid] = nil, nil, nil
|
||||
uid = nil
|
||||
end
|
||||
|
||||
local orig
|
||||
if script then
|
||||
orig = obj:GetScript(method) or donothing
|
||||
elseif obj then
|
||||
orig = obj[method]
|
||||
else
|
||||
orig = _G[method]
|
||||
end
|
||||
|
||||
if not orig then
|
||||
error(format("%s: Attempting to hook a non existing target", usage), 3)
|
||||
end
|
||||
|
||||
uid = createHook(self, handler, orig, secure, not (raw or secure))
|
||||
|
||||
if obj then
|
||||
self.hooks[obj] = self.hooks[obj] or {}
|
||||
registry[self][obj] = registry[self][obj] or {}
|
||||
registry[self][obj][method] = uid
|
||||
|
||||
if not secure then
|
||||
self.hooks[obj][method] = orig
|
||||
end
|
||||
|
||||
if script then
|
||||
-- If the script is empty before, HookScript will not work, so use SetScript instead
|
||||
-- This will make the hook insecure, but shouldnt matter, since it was empty before.
|
||||
-- It does not taint the full frame.
|
||||
if not secure or orig == donothing then
|
||||
obj:SetScript(method, uid)
|
||||
elseif secure then
|
||||
obj:HookScript(method, uid)
|
||||
end
|
||||
else
|
||||
if not secure then
|
||||
obj[method] = uid
|
||||
else
|
||||
hooksecurefunc(obj, method, uid)
|
||||
end
|
||||
end
|
||||
else
|
||||
registry[self][method] = uid
|
||||
|
||||
if not secure then
|
||||
_G[method] = uid
|
||||
self.hooks[method] = orig
|
||||
else
|
||||
hooksecurefunc(method, uid)
|
||||
end
|
||||
end
|
||||
|
||||
actives[uid], handlers[uid], scripts[uid] = true, handler, script and true or nil
|
||||
end
|
||||
|
||||
--- Hook a function or a method on an object.
|
||||
-- The hook created will be a "safe hook", that means that your handler will be called
|
||||
-- before the hooked function ("Pre-Hook"), and you don't have to call the original function yourself,
|
||||
-- however you cannot stop the execution of the function, or modify any of the arguments/return values.\\
|
||||
-- This type of hook is typically used if you need to know if some function got called, and don't want to modify it.
|
||||
-- @paramsig [object], method, [handler], [hookSecure]
|
||||
-- @param object The object to hook a method from
|
||||
-- @param method If object was specified, the name of the method, or the name of the function to hook.
|
||||
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
|
||||
-- @param hookSecure If true, AceHook will allow hooking of secure functions.
|
||||
-- @usage
|
||||
-- -- create an addon with AceHook embeded
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
|
||||
--
|
||||
-- function MyAddon:OnEnable()
|
||||
-- -- Hook ActionButton_UpdateHotkeys, overwriting the secure status
|
||||
-- self:Hook("ActionButton_UpdateHotkeys", true)
|
||||
-- end
|
||||
--
|
||||
-- function MyAddon:ActionButton_UpdateHotkeys(button, type)
|
||||
-- print(button:GetName() .. " is updating its HotKey")
|
||||
-- end
|
||||
function AceHook:Hook(object, method, handler, hookSecure)
|
||||
if type(object) == "string" then
|
||||
method, handler, hookSecure, object = object, method, handler, nil
|
||||
end
|
||||
|
||||
if handler == true then
|
||||
handler, hookSecure = nil, true
|
||||
end
|
||||
|
||||
hook(self, object, method, handler, false, false, false, hookSecure or false, "Usage: Hook([object], method, [handler], [hookSecure])")
|
||||
end
|
||||
|
||||
--- RawHook a function or a method on an object.
|
||||
-- The hook created will be a "raw hook", that means that your handler will completly replace
|
||||
-- the original function, and your handler has to call the original function (or not, depending on your intentions).\\
|
||||
-- The original function will be stored in `self.hooks[object][method]` or `self.hooks[functionName]` respectively.\\
|
||||
-- This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments
|
||||
-- or want to control execution of the original function.
|
||||
-- @paramsig [object], method, [handler], [hookSecure]
|
||||
-- @param object The object to hook a method from
|
||||
-- @param method If object was specified, the name of the method, or the name of the function to hook.
|
||||
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
|
||||
-- @param hookSecure If true, AceHook will allow hooking of secure functions.
|
||||
-- @usage
|
||||
-- -- create an addon with AceHook embeded
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
|
||||
--
|
||||
-- function MyAddon:OnEnable()
|
||||
-- -- Hook ActionButton_UpdateHotkeys, overwriting the secure status
|
||||
-- self:RawHook("ActionButton_UpdateHotkeys", true)
|
||||
-- end
|
||||
--
|
||||
-- function MyAddon:ActionButton_UpdateHotkeys(button, type)
|
||||
-- if button:GetName() == "MyButton" then
|
||||
-- -- do stuff here
|
||||
-- else
|
||||
-- self.hooks.ActionButton_UpdateHotkeys(button, type)
|
||||
-- end
|
||||
-- end
|
||||
function AceHook:RawHook(object, method, handler, hookSecure)
|
||||
if type(object) == "string" then
|
||||
method, handler, hookSecure, object = object, method, handler, nil
|
||||
end
|
||||
|
||||
if handler == true then
|
||||
handler, hookSecure = nil, true
|
||||
end
|
||||
|
||||
hook(self, object, method, handler, false, false, true, hookSecure or false, "Usage: RawHook([object], method, [handler], [hookSecure])")
|
||||
end
|
||||
|
||||
--- SecureHook a function or a method on an object.
|
||||
-- This function is a wrapper around the `hooksecurefunc` function in the WoW API. Using AceHook
|
||||
-- extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't
|
||||
-- required anymore, or the addon is being disabled.\\
|
||||
-- Secure Hooks should be used if the secure-status of the function is vital to its function,
|
||||
-- and taint would block execution. Secure Hooks are always called after the original function was called
|
||||
-- ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
|
||||
-- @paramsig [object], method, [handler]
|
||||
-- @param object The object to hook a method from
|
||||
-- @param method If object was specified, the name of the method, or the name of the function to hook.
|
||||
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked function)
|
||||
function AceHook:SecureHook(object, method, handler)
|
||||
if type(object) == "string" then
|
||||
method, handler, object = object, method, nil
|
||||
end
|
||||
|
||||
hook(self, object, method, handler, false, true, false, false, "Usage: SecureHook([object], method, [handler])")
|
||||
end
|
||||
|
||||
--- Hook a script handler on a frame.
|
||||
-- The hook created will be a "safe hook", that means that your handler will be called
|
||||
-- before the hooked script ("Pre-Hook"), and you don't have to call the original function yourself,
|
||||
-- however you cannot stop the execution of the function, or modify any of the arguments/return values.\\
|
||||
-- This is the frame script equivalent of the :Hook safe-hook. It would typically be used to be notified
|
||||
-- when a certain event happens to a frame.
|
||||
-- @paramsig frame, script, [handler]
|
||||
-- @param frame The Frame to hook the script on
|
||||
-- @param script The script to hook
|
||||
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
|
||||
-- @usage
|
||||
-- -- create an addon with AceHook embeded
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
|
||||
--
|
||||
-- function MyAddon:OnEnable()
|
||||
-- -- Hook the OnShow of FriendsFrame
|
||||
-- self:HookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
|
||||
-- end
|
||||
--
|
||||
-- function MyAddon:FriendsFrameOnShow(frame)
|
||||
-- print("The FriendsFrame was shown!")
|
||||
-- end
|
||||
function AceHook:HookScript(frame, script, handler)
|
||||
hook(self, frame, script, handler, true, false, false, false, "Usage: HookScript(object, method, [handler])")
|
||||
end
|
||||
|
||||
--- RawHook a script handler on a frame.
|
||||
-- The hook created will be a "raw hook", that means that your handler will completly replace
|
||||
-- the original script, and your handler has to call the original script (or not, depending on your intentions).\\
|
||||
-- The original script will be stored in `self.hooks[frame][script]`.\\
|
||||
-- This type of hook can be used for all purposes, and is usually the most common case when you need to modify arguments
|
||||
-- or want to control execution of the original script.
|
||||
-- @paramsig frame, script, [handler]
|
||||
-- @param frame The Frame to hook the script on
|
||||
-- @param script The script to hook
|
||||
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
|
||||
-- @usage
|
||||
-- -- create an addon with AceHook embeded
|
||||
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("HookDemo", "AceHook-3.0")
|
||||
--
|
||||
-- function MyAddon:OnEnable()
|
||||
-- -- Hook the OnShow of FriendsFrame
|
||||
-- self:RawHookScript(FriendsFrame, "OnShow", "FriendsFrameOnShow")
|
||||
-- end
|
||||
--
|
||||
-- function MyAddon:FriendsFrameOnShow(frame)
|
||||
-- -- Call the original function
|
||||
-- self.hooks[frame].OnShow(frame)
|
||||
-- -- Do our processing
|
||||
-- -- .. stuff
|
||||
-- end
|
||||
function AceHook:RawHookScript(frame, script, handler)
|
||||
hook(self, frame, script, handler, true, false, true, false, "Usage: RawHookScript(object, method, [handler])")
|
||||
end
|
||||
|
||||
--- SecureHook a script handler on a frame.
|
||||
-- This function is a wrapper around the `frame:HookScript` function in the WoW API. Using AceHook
|
||||
-- extends the functionality of secure hooks, and adds the ability to unhook once the hook isn't
|
||||
-- required anymore, or the addon is being disabled.\\
|
||||
-- Secure Hooks should be used if the secure-status of the function is vital to its function,
|
||||
-- and taint would block execution. Secure Hooks are always called after the original function was called
|
||||
-- ("Post Hook"), and you cannot modify the arguments, return values or control the execution.
|
||||
-- @paramsig frame, script, [handler]
|
||||
-- @param frame The Frame to hook the script on
|
||||
-- @param script The script to hook
|
||||
-- @param handler The handler for the hook, a funcref or a method name. (Defaults to the name of the hooked script)
|
||||
function AceHook:SecureHookScript(frame, script, handler)
|
||||
hook(self, frame, script, handler, true, true, false, false, "Usage: SecureHookScript(object, method, [handler])")
|
||||
end
|
||||
|
||||
--- Unhook from the specified function, method or script.
|
||||
-- @paramsig [obj], method
|
||||
-- @param obj The object or frame to unhook from
|
||||
-- @param method The name of the method, function or script to unhook from.
|
||||
function AceHook:Unhook(obj, method)
|
||||
local usage = "Usage: Unhook([obj], method)"
|
||||
if type(obj) == "string" then
|
||||
method, obj = obj, nil
|
||||
end
|
||||
|
||||
if obj and type(obj) ~= "table" then
|
||||
error(format("%s: 'obj' - expecting nil or table got %s", usage, type(obj)), 2)
|
||||
end
|
||||
if type(method) ~= "string" then
|
||||
error(format("%s: 'method' - expeting string got %s", usage, type(method)), 2)
|
||||
end
|
||||
|
||||
local uid
|
||||
if obj then
|
||||
uid = registry[self][obj] and registry[self][obj][method]
|
||||
else
|
||||
uid = registry[self][method]
|
||||
end
|
||||
|
||||
if not uid or not actives[uid] then
|
||||
-- Declining to error on an unneeded unhook since the end effect is the same and this would just be annoying.
|
||||
return false
|
||||
end
|
||||
|
||||
actives[uid], handlers[uid] = nil, nil
|
||||
|
||||
if obj then
|
||||
registry[self][obj][method] = nil
|
||||
registry[self][obj] = next(registry[self][obj]) and registry[self][obj] or nil
|
||||
|
||||
-- if the hook reference doesnt exist, then its a secure hook, just bail out and dont do any unhooking
|
||||
if not self.hooks[obj] or not self.hooks[obj][method] then return true end
|
||||
|
||||
if scripts[uid] and obj:GetScript(method) == uid then -- unhooks scripts
|
||||
obj:SetScript(method, self.hooks[obj][method] ~= donothing and self.hooks[obj][method] or nil)
|
||||
scripts[uid] = nil
|
||||
elseif obj and self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then -- unhooks methods
|
||||
obj[method] = self.hooks[obj][method]
|
||||
end
|
||||
|
||||
self.hooks[obj][method] = nil
|
||||
self.hooks[obj] = next(self.hooks[obj]) and self.hooks[obj] or nil
|
||||
else
|
||||
registry[self][method] = nil
|
||||
|
||||
-- if self.hooks[method] doesn't exist, then this is a SecureHook, just bail out
|
||||
if not self.hooks[method] then return true end
|
||||
|
||||
if self.hooks[method] and _G[method] == uid then -- unhooks functions
|
||||
_G[method] = self.hooks[method]
|
||||
end
|
||||
|
||||
self.hooks[method] = nil
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Unhook all existing hooks for this addon.
|
||||
function AceHook:UnhookAll()
|
||||
for key, value in pairs(registry[self]) do
|
||||
if type(key) == "table" then
|
||||
for method in pairs(value) do
|
||||
self:Unhook(key, method)
|
||||
end
|
||||
else
|
||||
self:Unhook(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Check if the specific function, method or script is already hooked.
|
||||
-- @paramsig [obj], method
|
||||
-- @param obj The object or frame to unhook from
|
||||
-- @param method The name of the method, function or script to unhook from.
|
||||
function AceHook:IsHooked(obj, method)
|
||||
-- we don't check if registry[self] exists, this is done by evil magicks in the metatable
|
||||
if type(obj) == "string" then
|
||||
if registry[self][obj] and actives[registry[self][obj]] then
|
||||
return true, handlers[registry[self][obj]]
|
||||
end
|
||||
else
|
||||
if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
|
||||
return true, handlers[registry[self][obj][method]]
|
||||
end
|
||||
end
|
||||
|
||||
return false, nil
|
||||
end
|
||||
|
||||
--- Upgrade our old embeded
|
||||
for target, v in pairs( AceHook.embeded ) do
|
||||
AceHook:Embed( target )
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceHook-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,136 @@
|
||||
--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
|
||||
-- @class file
|
||||
-- @name AceLocale-3.0
|
||||
-- @release $Id: AceLocale-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
|
||||
local MAJOR,MINOR = "AceLocale-3.0", 2
|
||||
|
||||
local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not AceLocale then return end -- no upgrade needed
|
||||
|
||||
-- Lua APIs
|
||||
local assert, tostring, error = assert, tostring, error
|
||||
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: GAME_LOCALE, geterrorhandler
|
||||
|
||||
local gameLocale = GetLocale()
|
||||
if gameLocale == "enGB" then
|
||||
gameLocale = "enUS"
|
||||
end
|
||||
|
||||
AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
|
||||
AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
|
||||
|
||||
-- This metatable is used on all tables returned from GetLocale
|
||||
local readmeta = {
|
||||
__index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
|
||||
rawset(self, key, key) -- only need to see the warning once, really
|
||||
geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
|
||||
return key
|
||||
end
|
||||
}
|
||||
|
||||
-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
|
||||
local readmetasilent = {
|
||||
__index = function(self, key) -- requesting totally unknown entries: return key
|
||||
rawset(self, key, key) -- only need to invoke this function once
|
||||
return key
|
||||
end
|
||||
}
|
||||
|
||||
-- Remember the locale table being registered right now (it gets set by :NewLocale())
|
||||
-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
|
||||
local registering
|
||||
|
||||
-- local assert false function
|
||||
local assertfalse = function() assert(false) end
|
||||
|
||||
-- This metatable proxy is used when registering nondefault locales
|
||||
local writeproxy = setmetatable({}, {
|
||||
__newindex = function(self, key, value)
|
||||
rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
|
||||
end,
|
||||
__index = assertfalse
|
||||
})
|
||||
|
||||
-- This metatable proxy is used when registering the default locale.
|
||||
-- It refuses to overwrite existing values
|
||||
-- Reason 1: Allows loading locales in any order
|
||||
-- Reason 2: If 2 modules have the same string, but only the first one to be
|
||||
-- loaded has a translation for the current locale, the translation
|
||||
-- doesn't get overwritten.
|
||||
--
|
||||
local writedefaultproxy = setmetatable({}, {
|
||||
__newindex = function(self, key, value)
|
||||
if not rawget(registering, key) then
|
||||
rawset(registering, key, value == true and key or value)
|
||||
end
|
||||
end,
|
||||
__index = assertfalse
|
||||
})
|
||||
|
||||
--- Register a new locale (or extend an existing one) for the specified application.
|
||||
-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
|
||||
-- game locale.
|
||||
-- @paramsig application, locale[, isDefault[, silent]]
|
||||
-- @param application Unique name of addon / module
|
||||
-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
|
||||
-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
|
||||
-- @param silent If true, the locale will not issue warnings for missing keys. Can only be set on the default locale.
|
||||
-- @usage
|
||||
-- -- enUS.lua
|
||||
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
|
||||
-- L["string1"] = true
|
||||
--
|
||||
-- -- deDE.lua
|
||||
-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
|
||||
-- if not L then return end
|
||||
-- L["string1"] = "Zeichenkette1"
|
||||
-- @return Locale Table to add localizations to, or nil if the current locale is not required.
|
||||
function AceLocale:NewLocale(application, locale, isDefault, silent)
|
||||
|
||||
if silent and not isDefault then
|
||||
error("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' can only be specified for the default locale", 2)
|
||||
end
|
||||
|
||||
-- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
|
||||
-- Ammo: I still think this is a bad idea, for instance an addon that checks for some ingame string will fail, just because some other addon
|
||||
-- gives the user the illusion that they can run in a different locale? Ditch this whole thing or allow a setting per 'application'. I'm of the
|
||||
-- opinion to remove this.
|
||||
local gameLocale = GAME_LOCALE or gameLocale
|
||||
|
||||
if locale ~= gameLocale and not isDefault then
|
||||
return -- nop, we don't need these translations
|
||||
end
|
||||
|
||||
local app = AceLocale.apps[application]
|
||||
|
||||
if not app then
|
||||
app = setmetatable({}, silent and readmetasilent or readmeta)
|
||||
AceLocale.apps[application] = app
|
||||
AceLocale.appnames[app] = application
|
||||
end
|
||||
|
||||
registering = app -- remember globally for writeproxy and writedefaultproxy
|
||||
|
||||
if isDefault then
|
||||
return writedefaultproxy
|
||||
end
|
||||
|
||||
return writeproxy
|
||||
end
|
||||
|
||||
--- Returns localizations for the current locale (or default locale if translations are missing).
|
||||
-- Errors if nothing is registered (spank developer, not just a missing translation)
|
||||
-- @param application Unique name of addon / module
|
||||
-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
|
||||
-- @return The locale table for the current language.
|
||||
function AceLocale:GetLocale(application, silent)
|
||||
if not silent and not AceLocale.apps[application] then
|
||||
error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
|
||||
end
|
||||
return AceLocale.apps[application]
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceLocale-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,240 @@
|
||||
--[[ $Id: CallbackHandler-1.0.lua 13 2009-12-06 21:56:53Z nevcairiel $ ]]
|
||||
local MAJOR, MINOR = "CallbackHandler-1.0", 5
|
||||
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not CallbackHandler then return end -- No upgrade needed
|
||||
|
||||
local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
|
||||
|
||||
-- Lua APIs
|
||||
local tconcat = table.concat
|
||||
local assert, error, loadstring = assert, error, loadstring
|
||||
local setmetatable, rawset, rawget = setmetatable, rawset, rawget
|
||||
local next, select, pairs, type, tostring = next, select, pairs, type, tostring
|
||||
|
||||
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
|
||||
-- List them here for Mikk's FindGlobals script
|
||||
-- GLOBALS: geterrorhandler
|
||||
|
||||
local xpcall = xpcall
|
||||
|
||||
local function errorhandler(err)
|
||||
return geterrorhandler()(err)
|
||||
end
|
||||
|
||||
local function CreateDispatcher(argCount)
|
||||
local code = [[
|
||||
local next, xpcall, eh = ...
|
||||
|
||||
local method, ARGS
|
||||
local function call() method(ARGS) end
|
||||
|
||||
local function dispatch(handlers, ...)
|
||||
local index
|
||||
index, method = next(handlers)
|
||||
if not method then return end
|
||||
local OLD_ARGS = ARGS
|
||||
ARGS = ...
|
||||
repeat
|
||||
xpcall(call, eh)
|
||||
index, method = next(handlers, index)
|
||||
until not method
|
||||
ARGS = OLD_ARGS
|
||||
end
|
||||
|
||||
return dispatch
|
||||
]]
|
||||
|
||||
local ARGS, OLD_ARGS = {}, {}
|
||||
for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
|
||||
code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
|
||||
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
|
||||
end
|
||||
|
||||
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
|
||||
local dispatcher = CreateDispatcher(argCount)
|
||||
rawset(self, argCount, dispatcher)
|
||||
return dispatcher
|
||||
end})
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
-- CallbackHandler:New
|
||||
--
|
||||
-- target - target object to embed public APIs in
|
||||
-- RegisterName - name of the callback registration API, default "RegisterCallback"
|
||||
-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
|
||||
-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
|
||||
|
||||
function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
|
||||
-- TODO: Remove this after beta has gone out
|
||||
assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
|
||||
|
||||
RegisterName = RegisterName or "RegisterCallback"
|
||||
UnregisterName = UnregisterName or "UnregisterCallback"
|
||||
if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
|
||||
UnregisterAllName = "UnregisterAllCallbacks"
|
||||
end
|
||||
|
||||
-- we declare all objects and exported APIs inside this closure to quickly gain access
|
||||
-- to e.g. function names, the "target" parameter, etc
|
||||
|
||||
|
||||
-- Create the registry object
|
||||
local events = setmetatable({}, meta)
|
||||
local registry = { recurse=0, events=events }
|
||||
|
||||
-- registry:Fire() - fires the given event/message into the registry
|
||||
function registry:Fire(eventname, ...)
|
||||
if not rawget(events, eventname) or not next(events[eventname]) then return end
|
||||
local oldrecurse = registry.recurse
|
||||
registry.recurse = oldrecurse + 1
|
||||
|
||||
Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
|
||||
|
||||
registry.recurse = oldrecurse
|
||||
|
||||
if registry.insertQueue and oldrecurse==0 then
|
||||
-- Something in one of our callbacks wanted to register more callbacks; they got queued
|
||||
for eventname,callbacks in pairs(registry.insertQueue) do
|
||||
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
|
||||
for self,func in pairs(callbacks) do
|
||||
events[eventname][self] = func
|
||||
-- fire OnUsed callback?
|
||||
if first and registry.OnUsed then
|
||||
registry.OnUsed(registry, target, eventname)
|
||||
first = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
registry.insertQueue = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Registration of a callback, handles:
|
||||
-- self["method"], leads to self["method"](self, ...)
|
||||
-- self with function ref, leads to functionref(...)
|
||||
-- "addonId" (instead of self) with function ref, leads to functionref(...)
|
||||
-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
|
||||
target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
|
||||
if type(eventname) ~= "string" then
|
||||
error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
|
||||
end
|
||||
|
||||
method = method or eventname
|
||||
|
||||
local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
|
||||
|
||||
if type(method) ~= "string" and type(method) ~= "function" then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
|
||||
end
|
||||
|
||||
local regfunc
|
||||
|
||||
if type(method) == "string" then
|
||||
-- self["method"] calling style
|
||||
if type(self) ~= "table" then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
|
||||
elseif self==target then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
|
||||
elseif type(self[method]) ~= "function" then
|
||||
error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
|
||||
end
|
||||
|
||||
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
|
||||
local arg=select(1,...)
|
||||
regfunc = function(...) self[method](self,arg,...) end
|
||||
else
|
||||
regfunc = function(...) self[method](self,...) end
|
||||
end
|
||||
else
|
||||
-- function ref with self=object or self="addonId"
|
||||
if type(self)~="table" and type(self)~="string" then
|
||||
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
|
||||
end
|
||||
|
||||
if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
|
||||
local arg=select(1,...)
|
||||
regfunc = function(...) method(arg,...) end
|
||||
else
|
||||
regfunc = method
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if events[eventname][self] or registry.recurse<1 then
|
||||
-- if registry.recurse<1 then
|
||||
-- we're overwriting an existing entry, or not currently recursing. just set it.
|
||||
events[eventname][self] = regfunc
|
||||
-- fire OnUsed callback?
|
||||
if registry.OnUsed and first then
|
||||
registry.OnUsed(registry, target, eventname)
|
||||
end
|
||||
else
|
||||
-- we're currently processing a callback in this registry, so delay the registration of this new entry!
|
||||
-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
|
||||
registry.insertQueue = registry.insertQueue or setmetatable({},meta)
|
||||
registry.insertQueue[eventname][self] = regfunc
|
||||
end
|
||||
end
|
||||
|
||||
-- Unregister a callback
|
||||
target[UnregisterName] = function(self, eventname)
|
||||
if not self or self==target then
|
||||
error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
|
||||
end
|
||||
if type(eventname) ~= "string" then
|
||||
error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
|
||||
end
|
||||
if rawget(events, eventname) and events[eventname][self] then
|
||||
events[eventname][self] = nil
|
||||
-- Fire OnUnused callback?
|
||||
if registry.OnUnused and not next(events[eventname]) then
|
||||
registry.OnUnused(registry, target, eventname)
|
||||
end
|
||||
end
|
||||
if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
|
||||
registry.insertQueue[eventname][self] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
|
||||
if UnregisterAllName then
|
||||
target[UnregisterAllName] = function(...)
|
||||
if select("#",...)<1 then
|
||||
error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
|
||||
end
|
||||
if select("#",...)==1 and ...==target then
|
||||
error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
|
||||
end
|
||||
|
||||
|
||||
for i=1,select("#",...) do
|
||||
local self = select(i,...)
|
||||
if registry.insertQueue then
|
||||
for eventname, callbacks in pairs(registry.insertQueue) do
|
||||
if callbacks[self] then
|
||||
callbacks[self] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
for eventname, callbacks in pairs(events) do
|
||||
if callbacks[self] then
|
||||
callbacks[self] = nil
|
||||
-- Fire OnUnused callback?
|
||||
if registry.OnUnused and not next(callbacks) then
|
||||
registry.OnUnused(registry, target, eventname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return registry
|
||||
end
|
||||
|
||||
|
||||
-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
|
||||
-- try to upgrade old implicit embeds since the system is selfcontained and
|
||||
-- relies on closures to work.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="CallbackHandler-1.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,263 @@
|
||||
--[[
|
||||
Name: DBIcon-1.0
|
||||
Revision: $Rev: 12 $
|
||||
Author(s): Rabbit (rabbit.magtheridon@gmail.com)
|
||||
Description: Allows addons to register to recieve a lightweight minimap icon as an alternative to more heavy LDB displays.
|
||||
Dependencies: LibStub
|
||||
License: GPL v2 or later.
|
||||
]]
|
||||
|
||||
--[[
|
||||
Copyright (C) 2008-2009 Rabbit
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
]]
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
-- DBIcon-1.0
|
||||
--
|
||||
-- Disclaimer: Most of this code was ripped from Barrel but fixed, streamlined
|
||||
-- and cleaned up a lot so that it no longer sucks.
|
||||
--
|
||||
|
||||
local DBICON10 = "LibDBIcon-1.0"
|
||||
local DBICON10_MINOR = tonumber(("$Rev: 12 $"):match("(%d+)"))
|
||||
if not LibStub then error(DBICON10 .. " requires LibStub.") end
|
||||
local ldb = LibStub("LibDataBroker-1.1", true)
|
||||
if not ldb then error(DBICON10 .. " requires LibDataBroker-1.1.") end
|
||||
local lib = LibStub:NewLibrary(DBICON10, DBICON10_MINOR)
|
||||
if not lib then return end
|
||||
|
||||
lib.disabled = lib.disabled or nil
|
||||
lib.objects = lib.objects or {}
|
||||
lib.callbackRegistered = lib.callbackRegistered or nil
|
||||
lib.notCreated = lib.notCreated or {}
|
||||
|
||||
function lib:IconCallback(event, name, key, value, dataobj)
|
||||
if lib.objects[name] then
|
||||
lib.objects[name].icon:SetTexture(dataobj.icon)
|
||||
end
|
||||
end
|
||||
if not lib.callbackRegistered then
|
||||
ldb.RegisterCallback(lib, "LibDataBroker_AttributeChanged__icon", "IconCallback")
|
||||
lib.callbackRegistered = true
|
||||
end
|
||||
|
||||
-- Tooltip code ripped from StatBlockCore by Funkydude
|
||||
local function getAnchors(frame)
|
||||
local x,y = frame:GetCenter()
|
||||
if not x or not y then return "TOPLEFT", "BOTTOMLEFT" end
|
||||
local hhalf = (x > UIParent:GetWidth()*2/3) and "RIGHT" or (x < UIParent:GetWidth()/3) and "LEFT" or ""
|
||||
local vhalf = (y > UIParent:GetHeight()/2) and "TOP" or "BOTTOM"
|
||||
return vhalf..hhalf, frame, (vhalf == "TOP" and "BOTTOM" or "TOP")..hhalf
|
||||
end
|
||||
|
||||
local function onEnter(self)
|
||||
if self.isMoving then return end
|
||||
local obj = self.dataObject
|
||||
if obj.OnTooltipShow then
|
||||
GameTooltip:SetOwner(self, "ANCHOR_NONE")
|
||||
GameTooltip:SetPoint(getAnchors(self))
|
||||
obj.OnTooltipShow(GameTooltip)
|
||||
GameTooltip:Show()
|
||||
elseif obj.OnEnter then
|
||||
obj.OnEnter(self)
|
||||
end
|
||||
end
|
||||
|
||||
local function onLeave(self)
|
||||
local obj = self.dataObject
|
||||
GameTooltip:Hide()
|
||||
if obj.OnLeave then obj.OnLeave(self) end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local minimapShapes = {
|
||||
["ROUND"] = {true, true, true, true},
|
||||
["SQUARE"] = {false, false, false, false},
|
||||
["CORNER-TOPLEFT"] = {true, false, false, false},
|
||||
["CORNER-TOPRIGHT"] = {false, false, true, false},
|
||||
["CORNER-BOTTOMLEFT"] = {false, true, false, false},
|
||||
["CORNER-BOTTOMRIGHT"] = {false, false, false, true},
|
||||
["SIDE-LEFT"] = {true, true, false, false},
|
||||
["SIDE-RIGHT"] = {false, false, true, true},
|
||||
["SIDE-TOP"] = {true, false, true, false},
|
||||
["SIDE-BOTTOM"] = {false, true, false, true},
|
||||
["TRICORNER-TOPLEFT"] = {true, true, true, false},
|
||||
["TRICORNER-TOPRIGHT"] = {true, false, true, true},
|
||||
["TRICORNER-BOTTOMLEFT"] = {true, true, false, true},
|
||||
["TRICORNER-BOTTOMRIGHT"] = {false, true, true, true},
|
||||
}
|
||||
|
||||
local function updatePosition(button)
|
||||
local angle = math.rad(button.db.minimapPos or 225)
|
||||
local x, y, q = math.cos(angle), math.sin(angle), 1
|
||||
if x < 0 then q = q + 1 end
|
||||
if y > 0 then q = q + 2 end
|
||||
local minimapShape = GetMinimapShape and GetMinimapShape() or "ROUND"
|
||||
local quadTable = minimapShapes[minimapShape]
|
||||
if quadTable[q] then
|
||||
x, y = x*80, y*80
|
||||
else
|
||||
local diagRadius = 103.13708498985 --math.sqrt(2*(80)^2)-10
|
||||
x = math.max(-80, math.min(x*diagRadius, 80))
|
||||
y = math.max(-80, math.min(y*diagRadius, 80))
|
||||
end
|
||||
button:SetPoint("CENTER", Minimap, "CENTER", x, y)
|
||||
end
|
||||
|
||||
local function onClick(self, b) if self.dataObject.OnClick then self.dataObject.OnClick(self, b) end end
|
||||
local function onMouseDown(self) self.icon:SetTexCoord(0, 1, 0, 1) end
|
||||
local function onMouseUp(self) self.icon:SetTexCoord(0.05, 0.95, 0.05, 0.95) end
|
||||
|
||||
local function onUpdate(self)
|
||||
local mx, my = Minimap:GetCenter()
|
||||
local px, py = GetCursorPosition()
|
||||
local scale = Minimap:GetEffectiveScale()
|
||||
px, py = px / scale, py / scale
|
||||
self.db.minimapPos = math.deg(math.atan2(py - my, px - mx)) % 360
|
||||
updatePosition(self)
|
||||
end
|
||||
|
||||
local function onDragStart(self)
|
||||
self:LockHighlight()
|
||||
self.icon:SetTexCoord(0, 1, 0, 1)
|
||||
self:SetScript("OnUpdate", onUpdate)
|
||||
self.isMoving = true
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
local function onDragStop(self)
|
||||
self:SetScript("OnUpdate", nil)
|
||||
self.icon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
|
||||
self:UnlockHighlight()
|
||||
self.isMoving = nil
|
||||
end
|
||||
|
||||
local function createButton(name, object, db)
|
||||
local button = CreateFrame("Button", "LibDBIcon10_"..name, Minimap)
|
||||
button.dataObject = object
|
||||
button.db = db
|
||||
button:SetFrameStrata("MEDIUM")
|
||||
button:SetWidth(31); button:SetHeight(31)
|
||||
button:SetFrameLevel(8)
|
||||
button:RegisterForClicks("anyUp")
|
||||
button:RegisterForDrag("LeftButton")
|
||||
button:SetHighlightTexture("Interface\\Minimap\\UI-Minimap-ZoomButton-Highlight")
|
||||
local overlay = button:CreateTexture(nil, "OVERLAY")
|
||||
overlay:SetWidth(53); overlay:SetHeight(53)
|
||||
overlay:SetTexture("Interface\\Minimap\\MiniMap-TrackingBorder")
|
||||
overlay:SetPoint("TOPLEFT")
|
||||
local icon = button:CreateTexture(nil, "BACKGROUND")
|
||||
icon:SetWidth(20); icon:SetHeight(20)
|
||||
icon:SetTexture(object.icon)
|
||||
icon:SetTexCoord(0.05, 0.95, 0.05, 0.95)
|
||||
icon:SetPoint("TOPLEFT", 7, -5)
|
||||
button.icon = icon
|
||||
|
||||
button:SetScript("OnEnter", onEnter)
|
||||
button:SetScript("OnLeave", onLeave)
|
||||
button:SetScript("OnClick", onClick)
|
||||
button:SetScript("OnDragStart", onDragStart)
|
||||
button:SetScript("OnDragStop", onDragStop)
|
||||
button:SetScript("OnMouseDown", onMouseDown)
|
||||
button:SetScript("OnMouseUp", onMouseUp)
|
||||
|
||||
lib.objects[name] = button
|
||||
|
||||
if lib.loggedIn then
|
||||
updatePosition(button)
|
||||
if not db.hide then button:Show()
|
||||
else button:Hide() end
|
||||
end
|
||||
end
|
||||
|
||||
-- We could use a metatable.__index on lib.objects, but then we'd create
|
||||
-- the icons when checking things like :IsRegistered, which is not necessary.
|
||||
local function check(name)
|
||||
if lib.notCreated[name] then
|
||||
createButton(name, lib.notCreated[name][1], lib.notCreated[name][2])
|
||||
lib.notCreated[name] = nil
|
||||
end
|
||||
end
|
||||
|
||||
lib.loggedIn = lib.loggedIn or false
|
||||
-- Wait a bit with the initial positioning to let any GetMinimapShape addons
|
||||
-- load up.
|
||||
if not lib.loggedIn then
|
||||
local f = CreateFrame("Frame")
|
||||
f:SetScript("OnEvent", function()
|
||||
for _, object in pairs(lib.objects) do
|
||||
updatePosition(object)
|
||||
if not lib.disabled and not object.db.hide then object:Show()
|
||||
else object:Hide() end
|
||||
end
|
||||
lib.loggedIn = true
|
||||
f:SetScript("OnEvent", nil)
|
||||
f = nil
|
||||
end)
|
||||
f:RegisterEvent("PLAYER_LOGIN")
|
||||
end
|
||||
|
||||
function lib:Register(name, object, db)
|
||||
if lib.disabled then return end
|
||||
if not object.icon then error("Can't register LDB objects without icons set!") end
|
||||
if lib.objects[name] or lib.notCreated[name] then error("Already registered, nubcake.") end
|
||||
if not db or not db.hide then
|
||||
createButton(name, object, db)
|
||||
else
|
||||
lib.notCreated[name] = {object, db}
|
||||
end
|
||||
end
|
||||
|
||||
function lib:Hide(name)
|
||||
if not lib.objects[name] then return end
|
||||
lib.objects[name]:Hide()
|
||||
end
|
||||
function lib:Show(name)
|
||||
if lib.disabled then return end
|
||||
check(name)
|
||||
lib.objects[name]:Show()
|
||||
updatePosition(lib.objects[name])
|
||||
end
|
||||
function lib:IsRegistered(name)
|
||||
return (lib.objects[name] or lib.notCreated[name]) and true or false
|
||||
end
|
||||
function lib:Refresh(name, db)
|
||||
if lib.disabled then return end
|
||||
check(name)
|
||||
local button = lib.objects[name]
|
||||
if db then button.db = db end
|
||||
updatePosition(button)
|
||||
end
|
||||
|
||||
function lib:EnableLibrary()
|
||||
lib.disabled = nil
|
||||
for name, object in pairs(lib.objects) do
|
||||
if not object.db or (object.db and not object.db.hide) then
|
||||
object:Show()
|
||||
updatePosition(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function lib:DisableLibrary()
|
||||
lib.disabled = true
|
||||
for name, object in pairs(lib.objects) do
|
||||
object:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
|
||||
assert(LibStub, "LibDataBroker-1.1 requires LibStub")
|
||||
assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
|
||||
|
||||
local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
|
||||
if not lib then return end
|
||||
oldminor = oldminor or 0
|
||||
|
||||
|
||||
lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
|
||||
lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
|
||||
local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
|
||||
|
||||
if oldminor < 2 then
|
||||
lib.domt = {
|
||||
__metatable = "access denied",
|
||||
__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
|
||||
}
|
||||
end
|
||||
|
||||
if oldminor < 3 then
|
||||
lib.domt.__newindex = function(self, key, value)
|
||||
if not attributestorage[self] then attributestorage[self] = {} end
|
||||
if attributestorage[self][key] == value then return end
|
||||
attributestorage[self][key] = value
|
||||
local name = namestorage[self]
|
||||
if not name then return end
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
|
||||
callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 2 then
|
||||
function lib:NewDataObject(name, dataobj)
|
||||
if self.proxystorage[name] then return end
|
||||
|
||||
if dataobj then
|
||||
assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
|
||||
self.attributestorage[dataobj] = {}
|
||||
for i,v in pairs(dataobj) do
|
||||
self.attributestorage[dataobj][i] = v
|
||||
dataobj[i] = nil
|
||||
end
|
||||
end
|
||||
dataobj = setmetatable(dataobj or {}, self.domt)
|
||||
self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
|
||||
self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
|
||||
return dataobj
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 1 then
|
||||
function lib:DataObjectIterator()
|
||||
return pairs(self.proxystorage)
|
||||
end
|
||||
|
||||
function lib:GetDataObjectByName(dataobjectname)
|
||||
return self.proxystorage[dataobjectname]
|
||||
end
|
||||
|
||||
function lib:GetNameByDataObject(dataobject)
|
||||
return self.namestorage[dataobject]
|
||||
end
|
||||
end
|
||||
|
||||
if oldminor < 4 then
|
||||
local next = pairs(attributestorage)
|
||||
function lib:pairs(dataobject_or_name)
|
||||
local t = type(dataobject_or_name)
|
||||
assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
|
||||
|
||||
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
|
||||
assert(attributestorage[dataobj], "Data object not found")
|
||||
|
||||
return next, attributestorage[dataobj], nil
|
||||
end
|
||||
|
||||
local ipairs_iter = ipairs(attributestorage)
|
||||
function lib:ipairs(dataobject_or_name)
|
||||
local t = type(dataobject_or_name)
|
||||
assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
|
||||
|
||||
local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
|
||||
assert(attributestorage[dataobj], "Data object not found")
|
||||
|
||||
return ipairs_iter, attributestorage[dataobj], 0
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,673 @@
|
||||
--[[
|
||||
Name: LibKeyBound-1.0
|
||||
Revision: $Rev: 95 $
|
||||
Author(s): Gello, Maul, Toadkiller, Tuller
|
||||
Website: http://www.wowace.com/wiki/LibKeyBound-1.0
|
||||
Documentation: http://www.wowace.com/wiki/LibKeyBound-1.0
|
||||
SVN: http://svn.wowace.com/wowace/trunk/LibKeyBound-1.0
|
||||
Description: An intuitive keybindings system: mouseover frame, click keys or buttons.
|
||||
Dependencies: CallbackHandler-1.0
|
||||
--]]
|
||||
|
||||
local MAJOR = 'LibKeyBound-1.0'
|
||||
local MINOR = tonumber(("$Revision: 95 $"):match("(%d+)")) + 90000
|
||||
|
||||
--[[
|
||||
LibKeyBound-1.0
|
||||
ClickBinder by Gello and TrinityBinder by Maul -> keyBound by Tuller -> LibKeyBound library by Toadkiller
|
||||
|
||||
Functions needed to implement
|
||||
button:GetHotkey() - returns the current hotkey assigned to the given button
|
||||
|
||||
Functions to implement if using a custom keybindings system:
|
||||
button:SetKey(key) - binds the given key to the given button
|
||||
button:FreeKey(key) - unbinds the given key from all other buttons
|
||||
button:ClearBindings() - removes all keys bound to the given button
|
||||
button:GetBindings() - returns a string listing all bindings of the given button
|
||||
button:GetActionName() - what we're binding to, used for printing
|
||||
--]]
|
||||
|
||||
local LibKeyBound, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not LibKeyBound then return end -- no upgrade needed
|
||||
|
||||
local _G = _G
|
||||
local NUM_MOUSE_BUTTONS = 31
|
||||
|
||||
-- CallbackHandler
|
||||
LibKeyBound.events = LibKeyBound.events or _G.LibStub('CallbackHandler-1.0'):New(LibKeyBound)
|
||||
|
||||
local L = LibKeyBoundLocale10
|
||||
LibKeyBound.L = L
|
||||
-- ToDo delete global LibKeyBoundLocale10 at some point
|
||||
LibKeyBound.Binder = LibKeyBound.Binder or {}
|
||||
|
||||
-- #NODOC
|
||||
function LibKeyBound:Initialize()
|
||||
do
|
||||
local f = CreateFrame('Frame', 'KeyboundDialog', UIParent)
|
||||
f:SetFrameStrata('DIALOG')
|
||||
f:SetToplevel(true)
|
||||
f:EnableMouse(true)
|
||||
f:SetClampedToScreen(true)
|
||||
f:SetWidth(360)
|
||||
f:SetHeight(140)
|
||||
f:SetBackdrop{
|
||||
bgFile='Interface\\DialogFrame\\UI-DialogBox-Background' ,
|
||||
edgeFile='Interface\\DialogFrame\\UI-DialogBox-Border',
|
||||
tile = true,
|
||||
insets = {left = 11, right = 12, top = 12, bottom = 11},
|
||||
tileSize = 32,
|
||||
edgeSize = 32,
|
||||
}
|
||||
f:SetPoint('TOP', 0, -24)
|
||||
f:Hide()
|
||||
f:SetScript('OnShow', function() PlaySound('igMainMenuOption') end)
|
||||
f:SetScript('OnHide', function() PlaySound('gsTitleOptionExit') end)
|
||||
|
||||
local tr = f:CreateTitleRegion()
|
||||
tr:SetAllPoints(f)
|
||||
|
||||
local header = f:CreateTexture(nil, 'ARTWORK')
|
||||
header:SetTexture('Interface\\DialogFrame\\UI-DialogBox-Header')
|
||||
header:SetWidth(256); header:SetHeight(64)
|
||||
header:SetPoint('TOP', 0, 12)
|
||||
|
||||
local title = f:CreateFontString('ARTWORK')
|
||||
title:SetFontObject('GameFontNormal')
|
||||
title:SetPoint('TOP', header, 'TOP', 0, -14)
|
||||
title:SetText(L.BindingMode)
|
||||
|
||||
local desc = f:CreateFontString('ARTWORK')
|
||||
desc:SetFontObject('GameFontHighlight')
|
||||
desc:SetJustifyV('TOP')
|
||||
desc:SetJustifyH('LEFT')
|
||||
desc:SetPoint('TOPLEFT', 18, -32)
|
||||
desc:SetPoint('BOTTOMRIGHT', -18, 48)
|
||||
desc:SetText(format(L.BindingsHelp, GetBindingText('ESCAPE', 'KEY_')))
|
||||
|
||||
-- Per character bindings checkbox
|
||||
local perChar = CreateFrame('CheckButton', 'KeyboundDialogCheck', f, 'OptionsCheckButtonTemplate')
|
||||
_G[perChar:GetName() .. 'Text']:SetText(CHARACTER_SPECIFIC_KEYBINDINGS)
|
||||
|
||||
perChar:SetScript('OnShow', function(self)
|
||||
self:SetChecked(GetCurrentBindingSet() == 2)
|
||||
end)
|
||||
|
||||
local current
|
||||
perChar:SetScript('OnClick', function(self)
|
||||
current = (perChar:GetChecked() and 2) or 1
|
||||
LoadBindings(current)
|
||||
end)
|
||||
|
||||
-- Okay bindings checkbox
|
||||
local okayBindings = CreateFrame('CheckButton', 'KeyboundDialogOkay', f, 'OptionsButtonTemplate')
|
||||
getglobal(okayBindings:GetName() .. 'Text'):SetText(OKAY)
|
||||
|
||||
okayBindings:SetScript('OnClick', function(self)
|
||||
current = (perChar:GetChecked() and 2) or 1
|
||||
if InCombatLockdown() then
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
else
|
||||
SaveBindings(current)
|
||||
LibKeyBound:Deactivate()
|
||||
end
|
||||
end)
|
||||
|
||||
okayBindings:SetScript('OnHide', function(self)
|
||||
current = (perChar:GetChecked() and 2) or 1
|
||||
if InCombatLockdown() then
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
else
|
||||
SaveBindings(current)
|
||||
end
|
||||
end)
|
||||
|
||||
okayBindings:SetScript('OnEvent', function(self, event)
|
||||
SaveBindings(current)
|
||||
self:UnregisterEvent(event)
|
||||
LibKeyBound:Deactivate()
|
||||
end)
|
||||
|
||||
-- Cancel bindings checkbox
|
||||
local cancelBindings = CreateFrame('CheckButton', 'KeyboundDialogCancel', f, 'OptionsButtonTemplate')
|
||||
getglobal(cancelBindings:GetName() .. 'Text'):SetText(CANCEL)
|
||||
|
||||
cancelBindings:SetScript('OnClick', function(self)
|
||||
if InCombatLockdown() then
|
||||
self:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
else
|
||||
LoadBindings(GetCurrentBindingSet())
|
||||
LibKeyBound:Deactivate()
|
||||
end
|
||||
end)
|
||||
|
||||
cancelBindings:SetScript('OnEvent', function(self, event)
|
||||
LoadBindings(GetCurrentBindingSet())
|
||||
self:UnregisterEvent(event)
|
||||
LibKeyBound:Deactivate()
|
||||
end)
|
||||
|
||||
--position buttons
|
||||
perChar:SetPoint('BOTTOMLEFT', 14, 32)
|
||||
cancelBindings:SetPoint('BOTTOMRIGHT', -14, 14)
|
||||
okayBindings:SetPoint('RIGHT', cancelBindings, 'LEFT')
|
||||
|
||||
self.dialog = f
|
||||
end
|
||||
|
||||
SlashCmdList['LibKeyBoundSlashCOMMAND'] = function() self:Toggle() end
|
||||
SLASH_LibKeyBoundSlashCOMMAND1 = '/libkeybound'
|
||||
SLASH_LibKeyBoundSlashCOMMAND2 = '/kb'
|
||||
SLASH_LibKeyBoundSlashCOMMAND3 = '/lkb'
|
||||
|
||||
LibKeyBound.initialized = true
|
||||
end
|
||||
|
||||
|
||||
-- Default color to indicate bindable frames in your mod.
|
||||
LibKeyBound.colorKeyBoundMode = LibKeyBound.colorKeyBoundMode or { 0, 1, 1, 0.5 }
|
||||
|
||||
--[[
|
||||
LibKeyBound:SetColorKeyBoundMode([r][, g][, b][, a])
|
||||
--]]
|
||||
--[[
|
||||
Arguments:
|
||||
number - red, default 0
|
||||
number - green, default 0
|
||||
number - blue, default 0
|
||||
number - alpha, default 1
|
||||
|
||||
Example:
|
||||
if (MyMod.keyBoundMode) then
|
||||
overlayFrame:SetBackdropColor(LibKeyBound:GetColorKeyBoundMode())
|
||||
end
|
||||
...
|
||||
local r, g, b, a = LibKeyBound:GetColorKeyBoundMode()
|
||||
|
||||
Notes:
|
||||
* Returns the color to use on your participating buttons during KeyBound Mode
|
||||
* Values are unpacked and ready to use as color arguments
|
||||
--]]
|
||||
function LibKeyBound:SetColorKeyBoundMode(r, g, b, a)
|
||||
r, g, b, a = r or 0, g or 0, b or 0, a or 1
|
||||
LibKeyBound.colorKeyBoundMode[1] = r
|
||||
LibKeyBound.colorKeyBoundMode[2] = g
|
||||
LibKeyBound.colorKeyBoundMode[3] = b
|
||||
LibKeyBound.colorKeyBoundMode[4] = a
|
||||
LibKeyBound.events:Fire('LIBKEYBOUND_MODE_COLOR_CHANGED')
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns:
|
||||
* number - red
|
||||
* number - green
|
||||
* number - blue
|
||||
* number - alpha
|
||||
|
||||
Example:
|
||||
if (MyMod.keyBoundMode) then
|
||||
overlayFrame:SetBackdropColor(LibKeyBound:GetColorKeyBoundMode())
|
||||
end
|
||||
...
|
||||
local r, g, b, a = LibKeyBound:GetColorKeyBoundMode()
|
||||
|
||||
Notes:
|
||||
* Returns the color to use on your participating buttons during KeyBound Mode
|
||||
* Values are unpacked and ready to use as color arguments
|
||||
--]]
|
||||
function LibKeyBound:GetColorKeyBoundMode()
|
||||
return unpack(LibKeyBound.colorKeyBoundMode)
|
||||
end
|
||||
|
||||
|
||||
function LibKeyBound:PLAYER_REGEN_ENABLED()
|
||||
if self.enabled then
|
||||
UIErrorsFrame:AddMessage(L.CombatBindingsEnabled, 1, 0.3, 0.3, 1, UIERRORS_HOLD_TIME)
|
||||
self.dialog:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound:PLAYER_REGEN_DISABLED()
|
||||
if self.enabled then
|
||||
self:Set(nil)
|
||||
UIErrorsFrame:AddMessage(L.CombatBindingsDisabled, 1, 0.3, 0.3, 1, UIERRORS_HOLD_TIME)
|
||||
self.dialog:Show()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Notes:
|
||||
* Switches KeyBound Mode between on and off
|
||||
|
||||
Example:
|
||||
local LibKeyBound = LibStub('LibKeyBound-1.0')
|
||||
LibKeyBound:Toggle()
|
||||
--]]
|
||||
function LibKeyBound:Toggle()
|
||||
if (LibKeyBound:IsShown()) then
|
||||
LibKeyBound:Deactivate()
|
||||
else
|
||||
LibKeyBound:Activate()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Notes:
|
||||
* Switches KeyBound Mode to on
|
||||
|
||||
Example:
|
||||
local LibKeyBound = LibStub('LibKeyBound-1.0')
|
||||
LibKeyBound:Activate()
|
||||
--]]
|
||||
function LibKeyBound:Activate()
|
||||
if not self:IsShown() then
|
||||
if InCombatLockdown() then
|
||||
UIErrorsFrame:AddMessage(L.CannotBindInCombat, 1, 0.3, 0.3, 1, UIERRORS_HOLD_TIME)
|
||||
else
|
||||
self.enabled = true
|
||||
if not self.frame then
|
||||
self.frame = LibKeyBound.Binder:Create()
|
||||
end
|
||||
self:Set(nil)
|
||||
self.dialog:Show()
|
||||
self.events:Fire('LIBKEYBOUND_ENABLED')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Notes:
|
||||
* Switches KeyBound Mode to off
|
||||
|
||||
Example:
|
||||
local LibKeyBound = LibStub('LibKeyBound-1.0')
|
||||
LibKeyBound:Deactivate()
|
||||
--]]
|
||||
function LibKeyBound:Deactivate()
|
||||
if self:IsShown() then
|
||||
self.enabled = nil
|
||||
self:Set(nil)
|
||||
self.dialog:Hide()
|
||||
|
||||
self.events:Fire('LIBKEYBOUND_DISABLED')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Returns:
|
||||
boolean - true if KeyBound Mode is currently on
|
||||
|
||||
Example:
|
||||
local LibKeyBound = LibStub('LibKeyBound-1.0')
|
||||
local isKeyBoundMode = LibKeyBound:IsShown()
|
||||
if (isKeyBoundMode) then
|
||||
-- Do something
|
||||
else
|
||||
-- Do another thing
|
||||
end
|
||||
|
||||
Notes:
|
||||
* Is KeyBound Mode currently on
|
||||
--]]
|
||||
function LibKeyBound:IsShown()
|
||||
return self.enabled
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Arguments:
|
||||
table - the button frame
|
||||
|
||||
Example:
|
||||
local button = this
|
||||
LibKeyBound:Set(button)
|
||||
|
||||
Notes:
|
||||
* Sets up button for keybinding
|
||||
* Call this in your OnEnter script for the button
|
||||
* Current bindings are shown in the tooltip
|
||||
* Primary binding is shown in green in the button text
|
||||
--]]
|
||||
function LibKeyBound:Set(button)
|
||||
local bindFrame = self.frame
|
||||
|
||||
if button and self:IsShown() and not InCombatLockdown() then
|
||||
bindFrame.button = button
|
||||
bindFrame:SetAllPoints(button)
|
||||
|
||||
bindFrame.text:SetFontObject('GameFontNormalLarge')
|
||||
bindFrame.text:SetText(button:GetHotkey())
|
||||
if bindFrame.text:GetStringWidth() > bindFrame:GetWidth() then
|
||||
bindFrame.text:SetFontObject('GameFontNormal')
|
||||
end
|
||||
bindFrame:Show()
|
||||
bindFrame:OnEnter()
|
||||
elseif bindFrame then
|
||||
bindFrame.button = nil
|
||||
bindFrame:ClearAllPoints()
|
||||
bindFrame:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[
|
||||
Arguments:
|
||||
string - the keyString to shorten
|
||||
|
||||
Returns:
|
||||
string - the shortened displayString
|
||||
|
||||
Example:
|
||||
local key1 = GetBindingKey(button:GetName())
|
||||
local displayKey = LibKeyBound:ToShortKey(key1)
|
||||
return displayKey
|
||||
|
||||
Notes:
|
||||
* Shortens the key text (returned from GetBindingKey etc.)
|
||||
* Result is suitable for display on a button
|
||||
* Can be used for your button:GetHotkey() return value
|
||||
--]]
|
||||
function LibKeyBound:ToShortKey(key)
|
||||
if key then
|
||||
key = key:upper()
|
||||
key = key:gsub(' ', '')
|
||||
key = key:gsub('ALT%-', L['Alt'])
|
||||
key = key:gsub('CTRL%-', L['Ctrl'])
|
||||
key = key:gsub('SHIFT%-', L['Shift'])
|
||||
key = key:gsub('NUMPAD', L['NumPad'])
|
||||
|
||||
key = key:gsub('PLUS', '%+')
|
||||
key = key:gsub('MINUS', '%-')
|
||||
key = key:gsub('MULTIPLY', '%*')
|
||||
key = key:gsub('DIVIDE', '%/')
|
||||
|
||||
key = key:gsub('BACKSPACE', L['Backspace'])
|
||||
|
||||
for i = 1, NUM_MOUSE_BUTTONS do
|
||||
key = key:gsub('BUTTON' .. i, L['Button' .. i])
|
||||
end
|
||||
|
||||
key = key:gsub('CAPSLOCK', L['Capslock'])
|
||||
key = key:gsub('CLEAR', L['Clear'])
|
||||
key = key:gsub('DELETE', L['Delete'])
|
||||
key = key:gsub('END', L['End'])
|
||||
key = key:gsub('HOME', L['Home'])
|
||||
key = key:gsub('INSERT', L['Insert'])
|
||||
key = key:gsub('MOUSEWHEELDOWN', L['Mouse Wheel Down'])
|
||||
key = key:gsub('MOUSEWHEELUP', L['Mouse Wheel Up'])
|
||||
key = key:gsub('NUMLOCK', L['Num Lock'])
|
||||
key = key:gsub('PAGEDOWN', L['Page Down'])
|
||||
key = key:gsub('PAGEUP', L['Page Up'])
|
||||
key = key:gsub('SCROLLLOCK', L['Scroll Lock'])
|
||||
key = key:gsub('SPACEBAR', L['Spacebar'])
|
||||
key = key:gsub('TAB', L['Tab'])
|
||||
|
||||
key = key:gsub('DOWNARROW', L['Down Arrow'])
|
||||
key = key:gsub('LEFTARROW', L['Left Arrow'])
|
||||
key = key:gsub('RIGHTARROW', L['Right Arrow'])
|
||||
key = key:gsub('UPARROW', L['Up Arrow'])
|
||||
|
||||
return key
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[ Binder Widget ]]--
|
||||
|
||||
function LibKeyBound.Binder:Create()
|
||||
local binder = CreateFrame('Button')
|
||||
binder:RegisterForClicks('anyUp')
|
||||
binder:SetFrameStrata('DIALOG')
|
||||
binder:EnableKeyboard(true)
|
||||
binder:EnableMouseWheel(true)
|
||||
|
||||
for k,v in pairs(self) do
|
||||
binder[k] = v
|
||||
end
|
||||
|
||||
local bg = binder:CreateTexture()
|
||||
bg:SetTexture(0, 0, 0, 0.5)
|
||||
bg:SetAllPoints(binder)
|
||||
|
||||
local text = binder:CreateFontString('OVERLAY')
|
||||
text:SetFontObject('GameFontNormalLarge')
|
||||
text:SetTextColor(0, 1, 0)
|
||||
text:SetAllPoints(binder)
|
||||
binder.text = text
|
||||
|
||||
binder:SetScript('OnClick', self.OnKeyDown)
|
||||
binder:SetScript('OnKeyDown', self.OnKeyDown)
|
||||
binder:SetScript('OnMouseWheel', self.OnMouseWheel)
|
||||
binder:SetScript('OnEnter', self.OnEnter)
|
||||
binder:SetScript('OnLeave', self.OnLeave)
|
||||
binder:SetScript('OnHide', self.OnHide)
|
||||
binder:Hide()
|
||||
|
||||
return binder
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:OnHide()
|
||||
LibKeyBound:Set(nil)
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:OnKeyDown(key)
|
||||
local button = self.button
|
||||
if not button then return end
|
||||
|
||||
if (key == 'UNKNOWN' or key == 'LSHIFT' or key == 'RSHIFT' or
|
||||
key == 'LCTRL' or key == 'RCTRL' or key == 'LALT' or key == 'RALT') then
|
||||
return
|
||||
end
|
||||
|
||||
local screenshotKey = GetBindingKey('SCREENSHOT')
|
||||
if screenshotKey and key == screenshotKey then
|
||||
Screenshot()
|
||||
return
|
||||
end
|
||||
|
||||
local openChatKey = GetBindingKey('OPENCHAT')
|
||||
if openChatKey and key == openChatKey then
|
||||
ChatFrameEditBox:Show()
|
||||
return
|
||||
end
|
||||
|
||||
if key == 'ESCAPE' then
|
||||
self:ClearBindings(button)
|
||||
LibKeyBound:Set(button)
|
||||
return
|
||||
end
|
||||
|
||||
-- dont bind unmodified left or right button
|
||||
if (key == 'LeftButton' or key == 'RightButton') and not IsModifierKeyDown() then
|
||||
return
|
||||
end
|
||||
|
||||
--handle mouse button substitutions
|
||||
if key == 'LeftButton' then
|
||||
key = 'BUTTON1'
|
||||
elseif key == 'RightButton' then
|
||||
key = 'BUTTON2'
|
||||
elseif key == 'MiddleButton' then
|
||||
key = 'BUTTON3'
|
||||
elseif key:match('^Button%d+$') then
|
||||
key = key:upper()
|
||||
end
|
||||
|
||||
--apply modifiers
|
||||
if IsModifierKeyDown() then
|
||||
if IsShiftKeyDown() then
|
||||
key = 'SHIFT-' .. key
|
||||
end
|
||||
if IsControlKeyDown() then
|
||||
key = 'CTRL-' .. key
|
||||
end
|
||||
if IsAltKeyDown() then
|
||||
key = 'ALT-' .. key
|
||||
end
|
||||
end
|
||||
|
||||
if button:IsMouseOver() then
|
||||
self:SetKey(button, key)
|
||||
LibKeyBound:Set(button)
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:OnMouseWheel(arg1)
|
||||
if arg1 > 0 then
|
||||
self:OnKeyDown('MOUSEWHEELUP')
|
||||
else
|
||||
self:OnKeyDown('MOUSEWHEELDOWN')
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:OnEnter()
|
||||
local button = self.button
|
||||
if button and not InCombatLockdown() then
|
||||
if self:GetRight() >= (GetScreenWidth() / 2) then
|
||||
GameTooltip:SetOwner(self, 'ANCHOR_LEFT')
|
||||
else
|
||||
GameTooltip:SetOwner(self, 'ANCHOR_RIGHT')
|
||||
end
|
||||
|
||||
if button.GetActionName then
|
||||
GameTooltip:SetText(button:GetActionName(), 1, 1, 1)
|
||||
else
|
||||
GameTooltip:SetText(button:GetName(), 1, 1, 1)
|
||||
end
|
||||
|
||||
local bindings = self:GetBindings(button)
|
||||
if bindings then
|
||||
GameTooltip:AddLine(bindings, 0, 1, 0)
|
||||
GameTooltip:AddLine(L.ClearTip)
|
||||
else
|
||||
GameTooltip:AddLine(L.NoKeysBoundTip, 0, 1, 0)
|
||||
end
|
||||
GameTooltip:Show()
|
||||
else
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:OnLeave()
|
||||
LibKeyBound:Set(nil)
|
||||
GameTooltip:Hide()
|
||||
end
|
||||
|
||||
|
||||
--[[ Update Functions ]]--
|
||||
|
||||
function LibKeyBound.Binder:ToBinding(button)
|
||||
return format('CLICK %s:LeftButton', button:GetName())
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:FreeKey(button, key)
|
||||
local msg
|
||||
if button.FreeKey then
|
||||
local action = button:FreeKey(key)
|
||||
if button:FreeKey(key) then
|
||||
msg = format(L.UnboundKey, GetBindingText(key, 'KEY_'), action)
|
||||
end
|
||||
else
|
||||
local action = GetBindingAction(key)
|
||||
if action and action ~= '' and action ~= self:ToBinding(button) then
|
||||
msg = format(L.UnboundKey, GetBindingText(key, 'KEY_'), action)
|
||||
end
|
||||
end
|
||||
|
||||
if msg then
|
||||
UIErrorsFrame:AddMessage(msg, 1, 0.82, 0, 1, UIERRORS_HOLD_TIME)
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:SetKey(button, key)
|
||||
if InCombatLockdown() then
|
||||
UIErrorsFrame:AddMessage(L.CannotBindInCombat, 1, 0.3, 0.3, 1, UIERRORS_HOLD_TIME)
|
||||
else
|
||||
self:FreeKey(button, key)
|
||||
|
||||
if button.SetKey then
|
||||
button:SetKey(key)
|
||||
else
|
||||
SetBindingClick(key, button:GetName(), 'LeftButton')
|
||||
end
|
||||
|
||||
local msg
|
||||
if button.GetActionName then
|
||||
msg = format(L.BoundKey, GetBindingText(key, 'KEY_'), button:GetActionName())
|
||||
else
|
||||
msg = format(L.BoundKey, GetBindingText(key, 'KEY_'), button:GetName())
|
||||
end
|
||||
UIErrorsFrame:AddMessage(msg, 1, 1, 1, 1, UIERRORS_HOLD_TIME)
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:ClearBindings(button)
|
||||
if InCombatLockdown() then
|
||||
UIErrorsFrame:AddMessage(L.CannotBindInCombat, 1, 0.3, 0.3, 1, UIERRORS_HOLD_TIME)
|
||||
else
|
||||
if button.ClearBindings then
|
||||
button:ClearBindings()
|
||||
else
|
||||
local binding = self:ToBinding(button)
|
||||
while (GetBindingKey(binding)) do
|
||||
SetBinding(GetBindingKey(binding), nil)
|
||||
end
|
||||
end
|
||||
|
||||
local msg
|
||||
if button.GetActionName then
|
||||
msg = format(L.ClearedBindings, button:GetActionName())
|
||||
else
|
||||
msg = format(L.ClearedBindings, button:GetName())
|
||||
end
|
||||
UIErrorsFrame:AddMessage(msg, 1, 1, 1, 1, UIERRORS_HOLD_TIME)
|
||||
end
|
||||
end
|
||||
|
||||
function LibKeyBound.Binder:GetBindings(button)
|
||||
if button.GetBindings then
|
||||
return button:GetBindings()
|
||||
end
|
||||
|
||||
local keys
|
||||
local binding = self:ToBinding(button)
|
||||
for i = 1, select('#', GetBindingKey(binding)) do
|
||||
local hotKey = select(i, GetBindingKey(binding))
|
||||
if keys then
|
||||
keys = keys .. ', ' .. GetBindingText(hotKey, 'KEY_')
|
||||
else
|
||||
keys = GetBindingText(hotKey, 'KEY_')
|
||||
end
|
||||
end
|
||||
|
||||
return keys
|
||||
end
|
||||
|
||||
LibKeyBound.EventButton = LibKeyBound.EventButton or CreateFrame('Frame')
|
||||
do
|
||||
local EventButton = LibKeyBound.EventButton
|
||||
EventButton:UnregisterAllEvents()
|
||||
EventButton:SetScript('OnEvent', function(self, event, addon)
|
||||
if (event == 'PLAYER_REGEN_DISABLED') then
|
||||
LibKeyBound:PLAYER_REGEN_DISABLED()
|
||||
elseif (event == 'PLAYER_REGEN_ENABLED') then
|
||||
LibKeyBound:PLAYER_REGEN_ENABLED()
|
||||
elseif (event == 'PLAYER_LOGIN' and not LibKeyBound.initialized) then
|
||||
LibKeyBound:Initialize()
|
||||
EventButton:UnregisterEvent('PLAYER_LOGIN')
|
||||
end
|
||||
end)
|
||||
|
||||
if IsLoggedIn() and not LibKeyBound.initialized then
|
||||
LibKeyBound:Initialize()
|
||||
elseif not LibKeyBound.initialized then
|
||||
EventButton:RegisterEvent('PLAYER_LOGIN')
|
||||
end
|
||||
EventButton:RegisterEvent('PLAYER_REGEN_ENABLED')
|
||||
EventButton:RegisterEvent('PLAYER_REGEN_DISABLED')
|
||||
end
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
LibKeyBound-1.0 localization file
|
||||
Deutch by Gamefaq
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "deDE") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = "Tastenzuweisung Modus aktiviert";
|
||||
Disabled = "Tastenzuweisung Modus deaktiviert";
|
||||
ClearTip = format("Drücke %s um alle Tastenzuweisungen zu löschen", GetBindingText("ESCAPE", "KEY_"));
|
||||
NoKeysBoundTip = "Keine Tasten zugewiesen";
|
||||
ClearedBindings = "Entferne alle Zuweisungen von %s";
|
||||
BoundKey = "Setze %s zu %s";
|
||||
UnboundKey = "Entferne %s von %s";
|
||||
CannotBindInCombat = "Kann Tasten nicht im Kampf zuweisen";
|
||||
CombatBindingsEnabled = "Verlasse Kampf, Tastenzuweisung Modus aktiviert";
|
||||
CombatBindingsDisabled = "Beginne Kampf, Tastenzuweisung Modus deaktiviert";
|
||||
BindingsHelp = "Schwebe mit der Maus über einem Schalter. Drück dann eine Taste um sie zuzuweisen. Um die Belegung der Taste wieder zu löschen drück %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "S",
|
||||
["Shift"] = "U",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "WD",
|
||||
["Mouse Wheel Up"] = "WU",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "DA",
|
||||
["Left Arrow"] = "LA",
|
||||
["Right Arrow"] = "RA",
|
||||
["Up Arrow"] = "UA",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,157 @@
|
||||
--[[
|
||||
KeyBound localization file
|
||||
English
|
||||
--]]
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundBaseLocale10 and REVISION <= LibKeyBoundBaseLocale10.BASEREVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundBaseLocale10 = {
|
||||
REVISION = 0;
|
||||
BASEREVISION = REVISION;
|
||||
BindingMode = "Binding Mode";
|
||||
Enabled = 'Bindings mode enabled';
|
||||
Disabled = 'Bindings mode disabled';
|
||||
ClearTip = format('Press %s to clear all bindings', GetBindingText('ESCAPE', 'KEY_'));
|
||||
NoKeysBoundTip = 'No current bindings';
|
||||
ClearedBindings = 'Removed all bindings from %s';
|
||||
BoundKey = 'Set %s to %s';
|
||||
UnboundKey = 'Unbound %s from %s';
|
||||
CannotBindInCombat = 'Cannot bind keys in combat';
|
||||
CombatBindingsEnabled = 'Exiting combat, keybinding mode enabled';
|
||||
CombatBindingsDisabled = 'Entering combat, keybinding mode disabled';
|
||||
BindingsHelp = "Hover over a button, then press a key to set its binding. To clear a button's current keybinding, press %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "WD",
|
||||
["Mouse Wheel Up"] = "WU",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "Dn",
|
||||
["Left Arrow"] = "Lf",
|
||||
["Right Arrow"] = "Rt",
|
||||
["Up Arrow"] = "Up",
|
||||
}
|
||||
if not LibKeyBoundLocale10 then
|
||||
LibKeyBoundLocale10 = LibKeyBoundBaseLocale10
|
||||
else
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
end
|
||||
--[[
|
||||
World of Warcraft/Blizzard Interface Data (enUS)/FrameXML/GlobalStrings.lua:
|
||||
|
||||
KEY_APOSTROPHE = "'";
|
||||
KEY_BACKSLASH = "\\";
|
||||
KEY_BACKSPACE = "Backspace";
|
||||
KEY_BACKSPACE_MAC = "Delete";
|
||||
KEY_BINDING = "Key Binding";
|
||||
KEY_BINDINGS = "Key Bindings"; -- Title for the key bindings frame
|
||||
KEY_BINDINGS_MAC = "Bindings";
|
||||
KEY_BOUND = "Key Bound Successfully";
|
||||
KEY_BUTTON1 = "Left Mouse Button";
|
||||
KEY_BUTTON2 = "Right Mouse Button";
|
||||
KEY_BUTTON3 = "Middle Mouse";
|
||||
KEY_BUTTON4 = "Mouse Button 4";
|
||||
KEY_BUTTON5 = "Mouse Button 5";
|
||||
KEY_COMMA = ",";
|
||||
KEY_DELETE = "Delete";
|
||||
KEY_DELETE_MAC = "Del";
|
||||
KEY_DOWN = "Down Arrow";
|
||||
KEY_END = "End";
|
||||
KEY_HOME = "Home";
|
||||
KEY_INSERT = "Insert";
|
||||
KEY_INSERT_MAC = "Help";
|
||||
KEY_LEFT = "Left Arrow";
|
||||
KEY_LEFTBRACKET = "[";
|
||||
KEY_MINUS = "-";
|
||||
KEY_MOUSEWHEELDOWN = "Mouse Wheel Down";
|
||||
KEY_MOUSEWHEELUP = "Mouse Wheel Up";
|
||||
KEY_NUMLOCK = "Num Lock";
|
||||
KEY_NUMLOCK_MAC = "Clear";
|
||||
KEY_NUMPAD0 = "Num Pad 0";
|
||||
KEY_NUMPAD1 = "Num Pad 1";
|
||||
KEY_NUMPAD2 = "Num Pad 2";
|
||||
KEY_NUMPAD3 = "Num Pad 3";
|
||||
KEY_NUMPAD4 = "Num Pad 4";
|
||||
KEY_NUMPAD5 = "Num Pad 5";
|
||||
KEY_NUMPAD6 = "Num Pad 6";
|
||||
KEY_NUMPAD7 = "Num Pad 7";
|
||||
KEY_NUMPAD8 = "Num Pad 8";
|
||||
KEY_NUMPAD9 = "Num Pad 9";
|
||||
KEY_NUMPADDECIMAL = "Num Pad .";
|
||||
KEY_NUMPADDIVIDE = "Num Pad /";
|
||||
KEY_NUMPADMINUS = "Num Pad -";
|
||||
KEY_NUMPADMULTIPLY = "Num Pad *";
|
||||
KEY_NUMPADPLUS = "Num Pad +";
|
||||
KEY_PAGEDOWN = "Page Down";
|
||||
KEY_PAGEUP = "Page Up";
|
||||
KEY_PAUSE = "Pause";
|
||||
KEY_PAUSE_MAC = "F15";
|
||||
KEY_PERIOD = ".";
|
||||
KEY_PLUS = "+";
|
||||
KEY_PRINTSCREEN = "Print Screen";
|
||||
KEY_PRINTSCREEN_MAC = "F13";
|
||||
KEY_RIGHT = "Right Arrow";
|
||||
KEY_RIGHTBRACKET = "]";
|
||||
KEY_SCROLLLOCK = "Scroll Lock";
|
||||
KEY_SCROLLLOCK_MAC = "F14";
|
||||
KEY_SEMICOLON = ";";
|
||||
KEY_SLASH = "/";
|
||||
KEY_SPACE = "Spacebar"; -- Spacebar
|
||||
KEY_TAB = "Tab";
|
||||
KEY_TILDE = "~";
|
||||
KEY_UNBOUND_ERROR = "|cffff0000%s Function is Now Unbound!|r";
|
||||
KEY_UP = "Up Arrow";
|
||||
|
||||
KEY_ESCAPE = "Escape";
|
||||
--]]
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
LibKeyBound-1.0 localization file
|
||||
Spanish by StiviS
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "esES") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = 'Modo Atajos activado';
|
||||
Disabled = 'Modo Atajos desactivado';
|
||||
ClearTip = format('Pulsa %s para limpiar todos los atajos', GetBindingText('ESCAPE', 'KEY_'));
|
||||
NoKeysBoundTip = 'No existen atajos';
|
||||
ClearedBindings = 'Eliminados todos los atajos de %s';
|
||||
BoundKey = 'Establecer %s a %s';
|
||||
UnboundKey = 'Quitado atajo %s de %s';
|
||||
CannotBindInCombat = 'No se pueden atajar teclas en combate';
|
||||
CombatBindingsEnabled = 'Saliendo de combate, modo de Atajos de Teclado activado';
|
||||
CombatBindingsDisabled = 'Entrando en combate, modo de Atajos de Teclado desactivado';
|
||||
BindingsHelp = "Sitúese en un botón, entonces pulse una tecla para establecer su atajo. Para limpiar el Atajo del botón actual, pulse %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "Fin",
|
||||
["Home"] = "Ini",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "AW",
|
||||
["Mouse Wheel Up"] = "RW",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "AP",
|
||||
["Page Up"] = "RP",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "Ar",
|
||||
["Left Arrow"] = "Ab",
|
||||
["Right Arrow"] = "Iz",
|
||||
["Up Arrow"] = "De",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
LibKeyBound-1.0 localization file
|
||||
Latin America Spanish by ?
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "esMX") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = 'Modo Atajos activado';
|
||||
Disabled = 'Modo Atajos desactivado';
|
||||
ClearTip = format('Pulsa %s para limpiar todos los atajos', GetBindingText('ESCAPE', 'KEY_'));
|
||||
NoKeysBoundTip = 'No existen atajos';
|
||||
ClearedBindings = 'Eliminados todos los atajos de %s';
|
||||
BoundKey = 'Establecer %s a %s';
|
||||
UnboundKey = 'Quitado atajo %s de %s';
|
||||
CannotBindInCombat = 'No se pueden atajar teclas en combate';
|
||||
CombatBindingsEnabled = 'Saliendo de combate, modo de Atajos de Teclado activado';
|
||||
CombatBindingsDisabled = 'Entrando en combate, modo de Atajos de Teclado desactivado';
|
||||
BindingsHelp = "Sitúese en un botón, entonces pulse una tecla para establecer su atajo. Para limpiar el Atajo del botón actual, pulse %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "Fin",
|
||||
["Home"] = "Ini",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "AW",
|
||||
["Mouse Wheel Up"] = "RW",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "AP",
|
||||
["Page Up"] = "RP",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "Ar",
|
||||
["Left Arrow"] = "Ab",
|
||||
["Right Arrow"] = "Iz",
|
||||
["Up Arrow"] = "De",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
LibKeyBound-1.0 localization file
|
||||
French by ?
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "frFR") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = "Mode Raccourcis activé";
|
||||
Disabled = "Mode Raccourcis désactivé";
|
||||
ClearTip = format("Appuyez sur %s pour effacer tous les raccourcis", GetBindingText("ESCAPE", "KEY_"));
|
||||
NoKeysBoundTip = "Aucun raccourci";
|
||||
ClearedBindings = "Suppression de tous les raccourcis de %s";
|
||||
BoundKey = "%s associé à %s";
|
||||
UnboundKey = "%s n'est plus associé à %s";
|
||||
CannotBindInCombat = "Impossible de faire des raccourcis en combat";
|
||||
CombatBindingsEnabled = "Sortie de combat, mode Raccourcis activé";
|
||||
CombatBindingsDisabled = "Entrée en combat, mode Raccourcis désactivé";
|
||||
BindingsHelp = "Survolez un bouton, puis appuyez sur une touche pour définir son raccourci. Pour effacer le raccourci actuel d'un bouton, appuyez sur %s";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "WD",
|
||||
["Mouse Wheel Up"] = "WU",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "BA",
|
||||
["Left Arrow"] = "GA",
|
||||
["Right Arrow"] = "DA",
|
||||
["Up Arrow"] = "HA",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
KeyBound localization file
|
||||
Korean by damjau
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "koKR") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = '단축키 설정 기능 사용 가능';
|
||||
Disabled = '단축키 설정 기능 사용 불가';
|
||||
ClearTip = format('%s키를 누르면 모든 단축키가 초기화됩니다', GetBindingText('ESCAPE', 'KEY_'));
|
||||
NoKeysBoundTip = '현재 단축키 없음';
|
||||
ClearedBindings = '%s의 모든 단축키가 초기화 되었습니다';
|
||||
BoundKey = '%2$s의 단축키로 %1$s|1을;를; 설정합니다.';
|
||||
UnboundKey = '%2$s에서 %1$s의 단축키가 삭제되었습니다';
|
||||
CannotBindInCombat = '전투 중에는 단축키를 지정할 수 없습니다';
|
||||
CombatBindingsEnabled = '전투 종료. 단축키 설정이 가능해집니다';
|
||||
CombatBindingsDisabled = '전투 시작. 단축키 설정이 불가능합니다';
|
||||
BindingsHelp = "버튼 위에 마우스를 올려 놓고 지정할 키를 누르세요. 버튼의 현재 단축키를 삭제하시려면 %s|1을;를; 누르세요.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "WD",
|
||||
["Mouse Wheel Up"] = "WU",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "DA",
|
||||
["Left Arrow"] = "LA",
|
||||
["Right Arrow"] = "RA",
|
||||
["Up Arrow"] = "UA",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
KeyBound localization file
|
||||
Russian by ?
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "ruRU") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = 'Режим назначения клавиш включен';
|
||||
Disabled = 'Режим назначения клавиш отключен';
|
||||
ClearTip = format('Нажмите %s для сброса всех назначений', GetBindingText('ESCAPE', 'KEY_'));
|
||||
NoKeysBoundTip = 'Нет текущих назначений';
|
||||
ClearedBindings = 'Удалить все назначения с %s';
|
||||
BoundKey = 'Установить %s на %s';
|
||||
UnboundKey = 'Снять назначение %s с %s';
|
||||
CannotBindInCombat = 'Невозможно назначить клавишу в бою';
|
||||
CombatBindingsEnabled = 'Выход из боя, режим назначения клавиш включен';
|
||||
CombatBindingsDisabled = 'Начало боя, режим назначения клавиш отключен';
|
||||
BindingsHelp = "Зависните над кнопкой, и тогда нажмите клавишу для установки назначения. Для очистки текущих назначений клавиш, нажмите %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "Ц",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "КМВХ",
|
||||
["Mouse Wheel Up"] = "КМВЗ",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Прбл",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "Dn",
|
||||
["Left Arrow"] = "Lf",
|
||||
["Right Arrow"] = "Rt",
|
||||
["Up Arrow"] = "Up",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,88 @@
|
||||
--[[
|
||||
KeyBound localization file
|
||||
Chinese Simplified by ondh - http://www.ondh.cn
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "zhCN") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
BindingMode = "Binding Mode";
|
||||
Enabled = "按键绑定模式已启用";
|
||||
Disabled = "按键绑定模式已禁用";
|
||||
ClearTip = format("按 %s 清除所有绑定", GetBindingText("ESCAPE", "KEY_"));
|
||||
NoKeysBoundTip = "当前没有绑定按键";
|
||||
ClearedBindings = "从 %s 移除按键绑定";
|
||||
BoundKey = "设置 %s 到 %s";
|
||||
UnboundKey = "取消绑定 %s 从 %s";
|
||||
CannotBindInCombat = "不能在战斗状态绑定按键";
|
||||
CombatBindingsEnabled = "离开战斗状态, 按键绑定模式已启用";
|
||||
CombatBindingsDisabled = "进入战斗状态, 按键绑定模式已禁用";
|
||||
BindingsHelp = "将鼠标停留在按钮上, 然后按下欲指定快捷键之后就能绑定。 要清除目前绑定的按钮请按 %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "B1",
|
||||
["Button2"] = "B2",
|
||||
["Button3"] = "B3",
|
||||
["Button4"] = "B4",
|
||||
["Button5"] = "B5",
|
||||
["Button6"] = "B6",
|
||||
["Button7"] = "B7",
|
||||
["Button8"] = "B8",
|
||||
["Button9"] = "B9",
|
||||
["Button10"] = "B10",
|
||||
["Button11"] = "B11",
|
||||
["Button12"] = "B12",
|
||||
["Button13"] = "B13",
|
||||
["Button14"] = "B14",
|
||||
["Button15"] = "B15",
|
||||
["Button16"] = "B16",
|
||||
["Button17"] = "B17",
|
||||
["Button18"] = "B18",
|
||||
["Button19"] = "B19",
|
||||
["Button20"] = "B20",
|
||||
["Button21"] = "B21",
|
||||
["Button22"] = "B22",
|
||||
["Button23"] = "B23",
|
||||
["Button24"] = "B24",
|
||||
["Button25"] = "B25",
|
||||
["Button26"] = "B26",
|
||||
["Button27"] = "B27",
|
||||
["Button28"] = "B28",
|
||||
["Button29"] = "B29",
|
||||
["Button30"] = "B30",
|
||||
["Button31"] = "B31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "WD",
|
||||
["Mouse Wheel Up"] = "WU",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "DA",
|
||||
["Left Arrow"] = "LA",
|
||||
["Right Arrow"] = "RA",
|
||||
["Up Arrow"] = "UA",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
KeyBound localization file
|
||||
Traditional Chinese by ?
|
||||
--]]
|
||||
|
||||
if (GetLocale() ~= "zhTW") then
|
||||
return
|
||||
end
|
||||
|
||||
local REVISION = 90000 + tonumber(("$Revision: 92 $"):match("%d+"))
|
||||
if (LibKeyBoundLocale10 and REVISION <= LibKeyBoundLocale10.REVISION) then
|
||||
return
|
||||
end
|
||||
|
||||
LibKeyBoundLocale10 = {
|
||||
REVISION = REVISION;
|
||||
Enabled = "按鍵綁定模式已啟用";
|
||||
Disabled = "按鍵綁定模式已停用";
|
||||
ClearTip = format("按 %s 清除所有綁定", GetBindingText("ESCAPE", "KEY_"));
|
||||
NoKeysBoundTip = "目前沒有綁定按鍵";
|
||||
ClearedBindings = "從 %s 移除按鍵綁定";
|
||||
BoundKey = "設定 %s 到 %s";
|
||||
UnboundKey = "取消綁定 %s 從 %s";
|
||||
CannotBindInCombat = "無法在戰鬥狀態綁定按鍵";
|
||||
CombatBindingsEnabled = "離開戰鬥狀態, 按鍵綁定模式已啟用";
|
||||
CombatBindingsDisabled = "進入戰鬥狀態, 按鍵綁定模式已停用";
|
||||
BindingsHelp = "將滑鼠停留在按鈕上, 然後按下欲指定快捷鍵之後就能綁定。 要清除目前綁定的按鈕請按 %s.";
|
||||
|
||||
-- This is the short display version you see on the Button
|
||||
["Alt"] = "A",
|
||||
["Ctrl"] = "C",
|
||||
["Shift"] = "S",
|
||||
["NumPad"] = "N",
|
||||
|
||||
["Backspace"] = "BS",
|
||||
["Button1"] = "鼠1",
|
||||
["Button2"] = "鼠2",
|
||||
["Button3"] = "鼠3",
|
||||
["Button4"] = "鼠4",
|
||||
["Button5"] = "鼠5",
|
||||
["Button6"] = "鼠6",
|
||||
["Button7"] = "鼠7",
|
||||
["Button8"] = "鼠8",
|
||||
["Button9"] = "鼠9",
|
||||
["Button10"] = "鼠10",
|
||||
["Button11"] = "鼠11",
|
||||
["Button12"] = "鼠12",
|
||||
["Button13"] = "鼠13",
|
||||
["Button14"] = "鼠14",
|
||||
["Button15"] = "鼠15",
|
||||
["Button16"] = "鼠16",
|
||||
["Button17"] = "鼠17",
|
||||
["Button18"] = "鼠18",
|
||||
["Button19"] = "鼠19",
|
||||
["Button20"] = "鼠20",
|
||||
["Button21"] = "鼠21",
|
||||
["Button22"] = "鼠22",
|
||||
["Button23"] = "鼠23",
|
||||
["Button24"] = "鼠24",
|
||||
["Button25"] = "鼠25",
|
||||
["Button26"] = "鼠26",
|
||||
["Button27"] = "鼠27",
|
||||
["Button28"] = "鼠28",
|
||||
["Button29"] = "鼠29",
|
||||
["Button30"] = "鼠30",
|
||||
["Button31"] = "鼠31",
|
||||
["Capslock"] = "Cp",
|
||||
["Clear"] = "Cl",
|
||||
["Delete"] = "Del",
|
||||
["End"] = "En",
|
||||
["Home"] = "HM",
|
||||
["Insert"] = "Ins",
|
||||
["Mouse Wheel Down"] = "WD",
|
||||
["Mouse Wheel Up"] = "WU",
|
||||
["Num Lock"] = "NL",
|
||||
["Page Down"] = "PD",
|
||||
["Page Up"] = "PU",
|
||||
["Scroll Lock"] = "SL",
|
||||
["Spacebar"] = "Sp",
|
||||
["Tab"] = "Tb",
|
||||
|
||||
["Down Arrow"] = "下",
|
||||
["Left Arrow"] = "左",
|
||||
["Right Arrow"] = "右",
|
||||
["Up Arrow"] = "上",
|
||||
}
|
||||
setmetatable(LibKeyBoundLocale10, {__index = LibKeyBoundBaseLocale10})
|
||||
@@ -0,0 +1,13 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="Locale-deDE.lua"/>
|
||||
<Script file="Locale-enUS.lua"/>
|
||||
<Script file="Locale-esES.lua"/>
|
||||
<Script file="Locale-esMX.lua"/>
|
||||
<Script file="Locale-frFR.lua"/>
|
||||
<Script file="Locale-koKR.lua"/>
|
||||
<Script file="Locale-zhCN.lua"/>
|
||||
<Script file="Locale-zhTW.lua"/>
|
||||
<Script file="Locale-ruRU.lua"/>
|
||||
<Script file="LibKeyBound-1.0.lua"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,30 @@
|
||||
-- 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
|
||||
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
|
||||
local LibStub = _G[LIBSTUB_MAJOR]
|
||||
|
||||
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(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."):format(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
|
||||
@@ -0,0 +1,13 @@
|
||||
## Interface: 20400
|
||||
## Title: Lib: LibStub
|
||||
## Notes: Universal Library Stub
|
||||
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
|
||||
## X-Website: http://jira.wowace.com/browse/LS
|
||||
## X-Category: Library
|
||||
## X-License: Public Domain
|
||||
## X-Curse-Packaged-Version: 1.0
|
||||
## X-Curse-Project-Name: LibStub
|
||||
## X-Curse-Project-ID: libstub
|
||||
## X-Curse-Repository-ID: wow/libstub/mainline
|
||||
|
||||
LibStub.lua
|
||||
@@ -0,0 +1,317 @@
|
||||
--[[
|
||||
Name: LibWindow-1.1
|
||||
Revision: $Rev: 5 $
|
||||
Author(s): Mikk (dpsgnome@mail.com)
|
||||
Website: http://old.wowace.com/wiki/LibWindow-1.1
|
||||
Documentation: http://old.wowace.com/wiki/LibWindow-1.1
|
||||
SVN: http://svn.wowace.com/root/trunk/WindowLib/Window-1.0
|
||||
Description: A library that handles the basics of "window" style frames: scaling, smart position saving, dragging..
|
||||
Dependencies: none
|
||||
License: Public Domain
|
||||
]]
|
||||
|
||||
local MAJOR = "LibWindow-1.1"
|
||||
local MINOR = tonumber(("$Revision: 5 $"):match("(%d+)"))
|
||||
|
||||
local lib = LibStub:NewLibrary(MAJOR,MINOR)
|
||||
if not lib then return end
|
||||
|
||||
local min,max,abs = min,max,abs
|
||||
local pairs = pairs
|
||||
local tostring = tostring
|
||||
local UIParent,GetScreenWidth,GetScreenHeight,IsAltKeyDown = UIParent,GetScreenWidth,GetScreenHeight,IsAltKeyDown
|
||||
-- GLOBALS: error, ChatFrame1, assert
|
||||
|
||||
local function print(msg) ChatFrame1:AddMessage(MAJOR..": "..tostring(msg)) end
|
||||
|
||||
lib.utilFrame = lib.utilFrame or CreateFrame("Frame")
|
||||
lib.delayedSavePosition = lib.delayedSavePosition or {}
|
||||
lib.windowData = lib.windowData or {}
|
||||
--[frameref]={
|
||||
-- names={optional names data from .RegisterConfig()}
|
||||
-- storage= -- tableref where config data is read/written
|
||||
-- altEnable=true/false
|
||||
--}
|
||||
|
||||
|
||||
lib.embeds = lib.embeds or {}
|
||||
|
||||
local mixins = {} -- "FuncName"=true
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- UTILITIES
|
||||
---------------------------------------------------------
|
||||
|
||||
|
||||
local function getStorageName(frame, name)
|
||||
local names = lib.windowData[frame].names
|
||||
if names then
|
||||
if names[name] then
|
||||
return names[name]
|
||||
end
|
||||
if names.prefix then
|
||||
return names.prefix .. name;
|
||||
end
|
||||
end
|
||||
return name;
|
||||
end
|
||||
|
||||
local function setStorage(frame, name, value)
|
||||
lib.windowData[frame].storage[getStorageName(frame, name)] = value
|
||||
end
|
||||
|
||||
local function getStorage(frame, name)
|
||||
return lib.windowData[frame].storage[getStorageName(frame, name)]
|
||||
end
|
||||
|
||||
|
||||
lib.utilFrame:SetScript("OnUpdate", function(this)
|
||||
this:Hide()
|
||||
for frame,_ in pairs(lib.delayedSavePosition) do
|
||||
lib.delayedSavePosition[frame] = nil
|
||||
lib.SavePosition(frame)
|
||||
end
|
||||
end)
|
||||
|
||||
local function queueSavePosition(frame)
|
||||
lib.delayedSavePosition[frame] = true
|
||||
lib.utilFrame:Show()
|
||||
end
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- IMPORTANT APIS
|
||||
---------------------------------------------------------
|
||||
|
||||
mixins["RegisterConfig"]=true
|
||||
function lib.RegisterConfig(frame, storage, names)
|
||||
if not lib.windowData[frame] then
|
||||
lib.windowData[frame] = {}
|
||||
end
|
||||
lib.windowData[frame].names = names
|
||||
lib.windowData[frame].storage = storage
|
||||
|
||||
--[[ debug
|
||||
frame.tx = frame:CreateTexture()
|
||||
frame.tx:SetTexture(0,0,0, 0.4)
|
||||
frame.tx:SetAllPoints(frame)
|
||||
frame.tx:Show()
|
||||
]]
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- POSITIONING AND SCALING
|
||||
---------------------------------------------------------
|
||||
|
||||
local nilParent = {
|
||||
GetWidth = function()
|
||||
return GetScreenWidth() * UIParent:GetScale()
|
||||
end,
|
||||
GetHeight = function()
|
||||
return GetScreenHeight() * UIParent:GetScale()
|
||||
end,
|
||||
GetScale = function()
|
||||
return 1
|
||||
end,
|
||||
}
|
||||
|
||||
mixins["SavePosition"]=true
|
||||
function lib.SavePosition(frame)
|
||||
local parent = frame:GetParent() or nilParent
|
||||
-- No, this won't work very well with frames that aren't parented to nil or UIParent
|
||||
local s = frame:GetScale()
|
||||
local left,top = frame:GetLeft()*s, frame:GetTop()*s
|
||||
local right,bottom = frame:GetRight()*s, frame:GetBottom()*s
|
||||
local pwidth, pheight = parent:GetWidth(), parent:GetHeight()
|
||||
|
||||
local x,y,point;
|
||||
if left < (pwidth-right) and left < abs((left+right)/2 - pwidth/2) then
|
||||
x = left;
|
||||
point="LEFT";
|
||||
elseif (pwidth-right) < abs((left+right)/2 - pwidth/2) then
|
||||
x = right-pwidth;
|
||||
point="RIGHT";
|
||||
else
|
||||
x = (left+right)/2 - pwidth/2;
|
||||
point="";
|
||||
end
|
||||
|
||||
if bottom < (pheight-top) and bottom < abs((bottom+top)/2 - pheight/2) then
|
||||
y = bottom;
|
||||
point="BOTTOM"..point;
|
||||
elseif (pheight-top) < abs((bottom+top)/2 - pheight/2) then
|
||||
y = top-pheight;
|
||||
point="TOP"..point;
|
||||
else
|
||||
y = (bottom+top)/2 - pheight/2;
|
||||
-- point=""..point;
|
||||
end
|
||||
|
||||
if point=="" then
|
||||
point = "CENTER"
|
||||
end
|
||||
|
||||
setStorage(frame, "x", x)
|
||||
setStorage(frame, "y", y)
|
||||
setStorage(frame, "point", point)
|
||||
setStorage(frame, "scale", s)
|
||||
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint(point, frame:GetParent(), point, x/s, y/s);
|
||||
end
|
||||
|
||||
|
||||
mixins["RestorePosition"]=true
|
||||
function lib.RestorePosition(frame)
|
||||
local x = getStorage(frame, "x")
|
||||
local y = getStorage(frame, "y")
|
||||
local point = getStorage(frame, "point")
|
||||
|
||||
local s = getStorage(frame, "scale")
|
||||
if s then
|
||||
frame:SetScale(s)
|
||||
else
|
||||
s = frame:GetScale()
|
||||
end
|
||||
|
||||
if not x or not y then -- nothing stored in config yet, smack it in the center
|
||||
x=0; y=0; point="CENTER"
|
||||
end
|
||||
|
||||
x = x/s
|
||||
y = y/s
|
||||
|
||||
frame:ClearAllPoints()
|
||||
if not point and y==0 then -- errr why did i do this check again? must have been a reason, but i can't remember it =/
|
||||
point="CENTER"
|
||||
end
|
||||
|
||||
if not point then -- we have position, but no point, which probably means we're going from data stored by the addon itself before LibWindow was added to it. It was PROBABLY topleft->bottomleft anchored. Most do it that way.
|
||||
frame:SetPoint("TOPLEFT", frame:GetParent(), "BOTTOMLEFT", x, y)
|
||||
-- make it compute a better attachpoint (on next update)
|
||||
queueSavePosition(frame)
|
||||
return
|
||||
end
|
||||
|
||||
frame:SetPoint(point, frame:GetParent(), point, x, y)
|
||||
end
|
||||
|
||||
|
||||
mixins["SetScale"]=true
|
||||
function lib.SetScale(frame, scale)
|
||||
setStorage(frame, "scale", scale)
|
||||
frame:SetScale(scale)
|
||||
lib.RestorePosition(frame)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- DRAG SUPPORT
|
||||
---------------------------------------------------------
|
||||
|
||||
|
||||
function lib.OnDragStart(frame)
|
||||
lib.windowData[frame].isDragging = true
|
||||
frame:StartMoving()
|
||||
end
|
||||
|
||||
|
||||
function lib.OnDragStop(frame)
|
||||
frame:StopMovingOrSizing()
|
||||
lib.SavePosition(frame)
|
||||
lib.windowData[frame].isDragging = false
|
||||
if lib.windowData[frame].altEnable and not IsAltKeyDown() then
|
||||
frame:EnableMouse(false)
|
||||
end
|
||||
end
|
||||
|
||||
local function onDragStart(...) return lib.OnDragStart(...) end -- upgradable
|
||||
local function onDragStop(...) return lib.OnDragStop(...) end -- upgradable
|
||||
|
||||
mixins["MakeDraggable"]=true
|
||||
function lib.MakeDraggable(frame)
|
||||
assert(lib.windowData[frame])
|
||||
frame:SetMovable(true)
|
||||
frame:SetScript("OnDragStart", onDragStart)
|
||||
frame:SetScript("OnDragStop", onDragStop)
|
||||
frame:RegisterForDrag("LeftButton")
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- MOUSEWHEEL
|
||||
---------------------------------------------------------
|
||||
|
||||
function lib.OnMouseWheel(frame, dir)
|
||||
local scale = getStorage(frame, "scale")
|
||||
if dir<0 then
|
||||
scale=max(scale*0.9, 0.1)
|
||||
else
|
||||
scale=min(scale/0.9, 3)
|
||||
end
|
||||
lib.SetScale(frame, scale)
|
||||
end
|
||||
|
||||
local function onMouseWheel(...) return lib.OnMouseWheel(...) end -- upgradable
|
||||
|
||||
mixins["EnableMouseWheelScaling"]=true
|
||||
function lib.EnableMouseWheelScaling(frame)
|
||||
frame:SetScript("OnMouseWheel", onMouseWheel)
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- ENABLEMOUSE-ON-ALT
|
||||
---------------------------------------------------------
|
||||
|
||||
lib.utilFrame:SetScript("OnEvent", function(this, event, key, state)
|
||||
if event=="MODIFIER_STATE_CHANGED" then
|
||||
if key == "LALT" or key == "RALT" then
|
||||
for frame,_ in pairs(lib.altEnabledFrames) do
|
||||
if not lib.windowData[frame].isDragging then -- if it's already dragging, it'll disable mouse on DragStop instead
|
||||
frame:EnableMouse(state == 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
mixins["EnableMouseOnAlt"]=true
|
||||
function lib.EnableMouseOnAlt(frame)
|
||||
assert(lib.windowData[frame])
|
||||
lib.windowData[frame].altEnable = true
|
||||
frame:EnableMouse(not not IsAltKeyDown())
|
||||
if not lib.altEnabledFrames then
|
||||
lib.altEnabledFrames = {}
|
||||
lib.utilFrame:RegisterEvent("MODIFIER_STATE_CHANGED")
|
||||
end
|
||||
lib.altEnabledFrames[frame] = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------
|
||||
-- Embed support (into FRAMES, not addons!)
|
||||
---------------------------------------------------------
|
||||
|
||||
function lib:Embed(target)
|
||||
if not target or not target[0] or not target.GetObjectType then
|
||||
error("Usage: LibWindow:Embed(frame)", 1)
|
||||
end
|
||||
for name, _ in pairs(mixins) do
|
||||
target[name] = self[name]
|
||||
end
|
||||
lib.embeds[target] = true
|
||||
return target
|
||||
end
|
||||
|
||||
for target, _ in pairs(lib.embeds) do
|
||||
lib:Embed(target)
|
||||
end
|
||||
@@ -0,0 +1,274 @@
|
||||
--[[---------------------------------------------------------------------------------
|
||||
General Library providing an alternate StartMoving() that allows you to
|
||||
specify a number of frames to snap-to when moving the frame around
|
||||
|
||||
Example Usage:
|
||||
|
||||
<OnLoad>
|
||||
this:RegisterForDrag("LeftButton")
|
||||
</OnLoad>
|
||||
<OnDragStart>
|
||||
StickyFrames:StartMoving(this, {WatchDogFrame_player, WatchDogFrame_target, WatchDogFrame_party1, WatchDogFrame_party2, WatchDogFrame_party3, WatchDogFrame_party4},3,3,3,3)
|
||||
</OnDragStart>
|
||||
<OnDragStop>
|
||||
StickyFrames:StopMoving(this)
|
||||
StickyFrames:AnchorFrame(this)
|
||||
</OnDragStop>
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
This is a modified version by Nevcairiel for Bartender4
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
local MAJOR, MINOR = "LibSimpleSticky-1.0", 2
|
||||
local StickyFrames, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
||||
|
||||
if not StickyFrames then return end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Class declaration, along with a temporary table to hold any existing OnUpdate
|
||||
scripts.
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
StickyFrames.scripts = StickyFrames.scripts or {}
|
||||
StickyFrames.rangeX = 15
|
||||
StickyFrames.rangeY = 15
|
||||
StickyFrames.sticky = StickyFrames.sticky or {}
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
StickyFrames:StartMoving() - Sets a custom OnUpdate for the frame so it follows
|
||||
the mouse and snaps to the frames you specify
|
||||
|
||||
frame: The frame we want to move. Is typically "this"
|
||||
|
||||
frameList: A integer indexed list of frames that the given frame should try to
|
||||
stick to. These don't have to have anything special done to them,
|
||||
and they don't really even need to exist. You can inclue the
|
||||
moving frame in this list, it will be ignored. This helps you
|
||||
if you have a number of frames, just make ONE list to pass.
|
||||
|
||||
{WatchDogFrame_player, WatchDogFrame_party1, .. WatchDogFrame_party4}
|
||||
|
||||
left: If your frame has a tranparent border around the entire frame
|
||||
(think backdrops with borders). This can be used to fine tune the
|
||||
edges when you're stickying groups. Refers to any offset on the
|
||||
LEFT edge of the frame being moved.
|
||||
|
||||
top: same
|
||||
right: same
|
||||
bottom: same
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
function StickyFrames:StartMoving(frame, frameList, left, top, right, bottom)
|
||||
local x,y = GetCursorPosition()
|
||||
local aX,aY = frame:GetCenter()
|
||||
local aS = frame:GetEffectiveScale()
|
||||
|
||||
aX,aY = aX*aS,aY*aS
|
||||
local xoffset,yoffset = (aX - x),(aY - y)
|
||||
self.scripts[frame] = frame:GetScript("OnUpdate")
|
||||
frame:SetScript("OnUpdate", self:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom))
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
This stops the OnUpdate, leaving the frame at its last position. This will
|
||||
leave it anchored to UIParent. You can call StickyFrames:AnchorFrame() to
|
||||
anchor it back "TOPLEFT" , "TOPLEFT" to the parent.
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
function StickyFrames:StopMoving(frame)
|
||||
frame:SetScript("OnUpdate", self.scripts[frame])
|
||||
self.scripts[frame] = nil
|
||||
|
||||
if StickyFrames.sticky[frame] then
|
||||
local sticky = StickyFrames.sticky[frame]
|
||||
StickyFrames.sticky[frame] = nil
|
||||
return true, sticky
|
||||
else
|
||||
return false, nil
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
This can be called in conjunction with StickyFrames:StopMoving() to anchor the
|
||||
frame right back to the parent, so you can manipulate its children as a group
|
||||
(This is useful in WatchDog)
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
function StickyFrames:AnchorFrame(frame)
|
||||
local xA,yA = frame:GetCenter()
|
||||
local parent = frame:GetParent() or UIParent
|
||||
local xP,yP = parent:GetCenter()
|
||||
local sA,sP = frame:GetEffectiveScale(), parent:GetEffectiveScale()
|
||||
|
||||
xP,yP = (xP*sP) / sA, (yP*sP) / sA
|
||||
|
||||
local xo,yo = (xP - xA)*-1, (yP - yA)*-1
|
||||
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint("CENTER", parent, "CENTER", xo, yo)
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Internal Functions -- Do not call these.
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Returns an anonymous OnUpdate function for the frame in question. Need
|
||||
to provide the frame, frameList along with the x and y offset (difference between
|
||||
where the mouse picked up the frame, and the insets (left,top,right,bottom) in the
|
||||
case of borders, etc.w
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
function StickyFrames:GetUpdateFunc(frame, frameList, xoffset, yoffset, left, top, right, bottom)
|
||||
return function()
|
||||
local x,y = GetCursorPosition()
|
||||
local s = frame:GetEffectiveScale()
|
||||
local sticky = nil
|
||||
|
||||
x,y = x/s,y/s
|
||||
|
||||
frame:ClearAllPoints()
|
||||
frame:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x+xoffset, y+yoffset)
|
||||
|
||||
StickyFrames.sticky[frame] = nil
|
||||
for i = 1, #frameList do
|
||||
local v = frameList[i]
|
||||
if frame ~= v and frame ~= v:GetParent() and not IsShiftKeyDown() and v:IsVisible() then
|
||||
if self:SnapFrame(frame, v, left, top, right, bottom) then
|
||||
StickyFrames.sticky[frame] = v
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Internal debug function.
|
||||
------------------------------------------------------------------------------------]]
|
||||
|
||||
function StickyFrames:debug(msg)
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cffffff00StickyFrames: |r"..tostring(msg))
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
This is called when finding an overlap between two sticky frame. If frameA is near
|
||||
a sticky edge of frameB, then it will snap to that edge and return true. If there
|
||||
is no sticky edge collision, will return false so we can test other frames for
|
||||
stickyness.
|
||||
------------------------------------------------------------------------------------]]
|
||||
function StickyFrames:SnapFrame(frameA, frameB, left, top, right, bottom)
|
||||
local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale()
|
||||
local xA, yA = frameA:GetCenter()
|
||||
local xB, yB = frameB:GetCenter()
|
||||
local hA, hB = frameA:GetHeight() / 2, ((frameB:GetHeight() * sB) / sA) / 2
|
||||
local wA, wB = frameA:GetWidth() / 2, ((frameB:GetWidth() * sB) / sA) / 2
|
||||
|
||||
local newX, newY = xA, yA
|
||||
|
||||
if not left then left = 0 end
|
||||
if not top then top = 0 end
|
||||
if not right then right = 0 end
|
||||
if not bottom then bottom = 0 end
|
||||
|
||||
-- Lets translate B's coords into A's scale
|
||||
xB, yB = (xB*sB) / sA, (yB*sB) / sA
|
||||
|
||||
local stickyAx, stickyAy = wA * 0.75, hA * 0.75
|
||||
local stickyBx, stickyBy = wB * 0.75, hB * 0.75
|
||||
|
||||
-- Grab the edges of each frame, for easier comparison
|
||||
|
||||
local lA, tA, rA, bA = frameA:GetLeft(), frameA:GetTop(), frameA:GetRight(), frameA:GetBottom()
|
||||
local lB, tB, rB, bB = frameB:GetLeft(), frameB:GetTop(), frameB:GetRight(), frameB:GetBottom()
|
||||
local snap = nil
|
||||
|
||||
-- Translate into A's scale
|
||||
lB, tB, rB, bB = (lB * sB) / sA, (tB * sB) / sA, (rB * sB) / sA, (bB * sB) / sA
|
||||
|
||||
if (bA <= tB and bB <= tA) then
|
||||
|
||||
-- Horizontal Centers
|
||||
if xA <= (xB + StickyFrames.rangeX) and xA >= (xB - StickyFrames.rangeX) then
|
||||
newX = xB
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Interior Left
|
||||
if lA <= (lB + StickyFrames.rangeX) and lA >= (lB - StickyFrames.rangeX) then
|
||||
newX = lB + wA
|
||||
if frameB == UIParent or frameB == WorldFrame then newX = newX - left/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Interior Right
|
||||
if rA <= (rB + StickyFrames.rangeX) and rA >= (rB - StickyFrames.rangeX) then
|
||||
newX = rB - wA
|
||||
if frameB == UIParent or frameB == WorldFrame then newX = newX + right/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Exterior Left to Right
|
||||
if lA <= (rB + StickyFrames.rangeX) and lA >= (rB - StickyFrames.rangeX) then
|
||||
newX = rB + (wA - left)
|
||||
if frameB == UIParent or frameB == WorldFrame then newX = newX + left/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Exterior Right to Left
|
||||
if rA <= (lB + StickyFrames.rangeX) and rA >= (lB - StickyFrames.rangeX) then
|
||||
newX = lB - (wA - right)
|
||||
if frameB == UIParent or frameB == WorldFrame then newX = newX - right/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (lA <= rB and lB <= rA) then
|
||||
|
||||
-- Vertical Centers
|
||||
if yA <= (yB + StickyFrames.rangeY) and yA >= (yB - StickyFrames.rangeY) then
|
||||
newY = yB
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Interior Top
|
||||
if tA <= (tB + StickyFrames.rangeY) and tA >= (tB - StickyFrames.rangeY) then
|
||||
newY = tB - hA
|
||||
if frameB == UIParent or frameB == WorldFrame then newY = newY + top/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Interior Bottom
|
||||
if bA <= (bB + StickyFrames.rangeY) and bA >= (bB - StickyFrames.rangeY) then
|
||||
newY = bB + hA
|
||||
if frameB == UIParent or frameB == WorldFrame then newY = newY - bottom/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Exterior Top to Bottom
|
||||
if tA <= (bB + StickyFrames.rangeY + bottom) and tA >= (bB - StickyFrames.rangeY + bottom) then
|
||||
newY = bB - (hA - top)
|
||||
if frameB == UIParent or frameB == WorldFrame then newY = newY - top/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
-- Exterior Bottom to Top
|
||||
if bA <= (tB + StickyFrames.rangeY - top) and bA >= (tB - StickyFrames.rangeY - top) then
|
||||
newY = tB + (hA - bottom)
|
||||
if frameB == UIParent or frameB == WorldFrame then newY = newY + bottom/2 end
|
||||
snap = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if snap then
|
||||
frameA:ClearAllPoints()
|
||||
frameA:SetPoint("CENTER", UIParent, "BOTTOMLEFT", newX, newY)
|
||||
return true
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/usr/local/bin/lua
|
||||
|
||||
-- CONFIG --
|
||||
|
||||
--[[
|
||||
Prefix to all files if this script is run from a subdir, for example
|
||||
]]
|
||||
local filePrefix = "../"
|
||||
|
||||
--[[
|
||||
List of all files to parse
|
||||
]]
|
||||
local files = {
|
||||
"ActionBar.lua",
|
||||
"ActionBars.lua",
|
||||
"ActionButton.lua",
|
||||
"BagBar.lua",
|
||||
"Bar.lua",
|
||||
"Bartender4.lua",
|
||||
"ButtonBar.lua",
|
||||
"MicroMenu.lua",
|
||||
"MultiCastBar.lua",
|
||||
"PetBar.lua",
|
||||
"PetButton.lua",
|
||||
"RepXPBar.lua",
|
||||
"StanceBar.lua",
|
||||
"StateBar.lua",
|
||||
"VehicleBar.lua",
|
||||
--
|
||||
"Options/ActionBar.lua",
|
||||
"Options/BagBar.lua",
|
||||
"Options/Bar.lua",
|
||||
"Options/ButtonBar.lua",
|
||||
"Options/MicroMenu.lua",
|
||||
"Options/MultiCastBar.lua",
|
||||
"Options/Options.lua",
|
||||
"Options/PetBar.lua",
|
||||
"Options/RepXPBar.lua",
|
||||
"Options/StanceBar.lua",
|
||||
"Options/StateBar.lua",
|
||||
"Options/VehicleBar.lua",
|
||||
}
|
||||
|
||||
local out = "Strings.lua"
|
||||
-- CODE --
|
||||
|
||||
local strings = {}
|
||||
|
||||
-- extract data from specified lua files
|
||||
for idx,filename in pairs(files) do
|
||||
local file = io.open(string.format("%s%s", filePrefix or "", filename), "r")
|
||||
assert(file, "Could not open " .. filename)
|
||||
local text = file:read("*all")
|
||||
|
||||
for match in string.gmatch(text, "L%[\"(.-)\"%]") do
|
||||
strings[match] = true
|
||||
end
|
||||
end
|
||||
|
||||
local work = {}
|
||||
|
||||
for k,v in pairs(strings) do table.insert(work, k) end
|
||||
table.sort(work)
|
||||
|
||||
-- Write locale files
|
||||
local file = io.open(out, "w")
|
||||
for idx, match in ipairs(work) do
|
||||
file:write(string.format("L[\"%s\"] = true\n", match))
|
||||
end
|
||||
file:close()
|
||||
@@ -0,0 +1,235 @@
|
||||
-- Bartender4 Locale
|
||||
-- Please use the Localization App on WoWAce to Update this
|
||||
-- http://www.wowace.com/projects/bartender4/localization/ ;¶
|
||||
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Bartender4", "deDE")
|
||||
if not L then return end
|
||||
|
||||
L["ActionBar Paging"] = "Aktionsleisten Seitenwechsel"
|
||||
L["Alignment"] = "Ausrichtung"
|
||||
L["Alpha"] = "Transparenz"
|
||||
L["ALT"] = "ALT"
|
||||
L["Always Hide"] = "Immer verbergen"
|
||||
L["Anchor"] = "Anker"
|
||||
L["Auto-Assist"] = "Automatische Hilfe"
|
||||
L["Bag Bar"] = "Taschenleiste"
|
||||
L["Bar Options"] = "Leistenoptionen"
|
||||
L["Bars"] = "Leisten"
|
||||
L["Bar %s"] = "Leiste %s"
|
||||
L["Bar Snapping"] = "An Leisten ausrichten"
|
||||
L["Bar Style & Layout"] = "Leistenform & Anordnung"
|
||||
L["Bars unlocked. Move them now and click Lock when you are done."] = "Leisten freigegeben. Man kann sie jetzt bewegen und dann wieder verschließen."
|
||||
L["Bartender4"] = "Bartender4"
|
||||
L["Button Grid"] = "Schaltflächen Gitternetz"
|
||||
L["Button Lock"] = "Schaltflächen verschließen"
|
||||
L["Button Look"] = "Aussehen der Schaltflächen"
|
||||
L["Buttons"] = "Schaltflächen"
|
||||
L["Button %s"] = "Schaltfläche %s"
|
||||
L["Button Tooltip"] = "Schaltflächen Tooltip"
|
||||
L["Cannot access options during combat."] = "Während des Kampfes kein Zugriff auf die Optionen möglich."
|
||||
L["Center Horizontally"] = "Horizontal zentrieren"
|
||||
L["Centers the bar horizontally on screen."] = "Zentriert die Leiste horizontal auf dem Bildschirm."
|
||||
L["Centers the bar vertically on screen."] = "Zentriert die Leiste vertikal auf dem Bildschirm."
|
||||
L["Center Vertically"] = "Vertikal zentrieren"
|
||||
L["|cffffff00Click|r to toggle bar lock"] = "|cffffff00Klicken|r um das Verschließen der Leisten umzuschalten."
|
||||
L["|cffffff00Right-click|r to open the options menu"] = "|cffffff00Rechtsklicken|r um das Optionsmenü zu öffnen"
|
||||
L["Change the current anchor point of the bar."] = "Den aktuellen Ankerpunkt der Leiste ändern."
|
||||
L["Click-Through"] = "Hindurch klicken"
|
||||
L["Colors"] = "Farben"
|
||||
L["Configure actionbar paging when the %s key is down."] = "Aktionsleistenwechsel, während die %s Taste gedrückt ist, konfigurieren."
|
||||
L["Configure Bar %s"] = "Leiste %s konfigurieren"
|
||||
L["Configure how the Out of Range Indicator should display on the buttons."] = "Konfigurieren, wie die \"Außer Reichweite\"-Anzeige auf den Schaltflächen dargestellt werden soll."
|
||||
L["Configure the alpha of the bar."] = "Die Transparentz der Leiste konfigurieren"
|
||||
L["Configure the Bag Bar"] = "Die Taschenleiste konfigurieren"
|
||||
L["Configure the Button Tooltip."] = "Den Schaltflächen Tooltip konfigurieren."
|
||||
L["Configure the Fade Out Alpha"] = "Transparenz für abgeblendete Leisten konfigurieren"
|
||||
L["Configure the Fade Out Delay"] = "Verzögerung beim Ausblenden konfigurieren"
|
||||
L["Configure the Micro Menu"] = "Das Mikromenü konfigurieren"
|
||||
L["Configure the padding of the buttons."] = "Den Abstand der Schaltflächen konfigurieren"
|
||||
L["Configure the Pet Bar"] = "Die Begleiterleiste konfigurieren"
|
||||
L["Configure the Reputation Bar"] = "Die Rufleiste konfigurieren"
|
||||
L["Configure the scale of the bar."] = "Die Skallierung der Leiste konfigurieren"
|
||||
L["Configure the Stance Bar"] = "Die Haltungsleiste konfigurieren"
|
||||
L["Configure the Totem Bar"] = "Totem-Leiste konfigurieren"
|
||||
L["Configure the VehicleBar"] = "Die Fahrzeugleiste konfigurieren"
|
||||
L["Configure the XP Bar"] = "Die Erfahrungsleiste konfigurieren"
|
||||
L["Copy Conditionals"] = "Bedingungen kopieren"
|
||||
L["Create a copy of the auto-generated conditionals in the custom configuration as a base template."] = "Eine Kopie der automatisch generierten Bedingungen in der eigenen Konfiguration als Basisvorlage erzeugen."
|
||||
L["CTRL"] = "STRG"
|
||||
L["Custom Conditionals"] = "Eigene Bedingungen"
|
||||
L["Default Bar State"] = "Standard Leistenstatus"
|
||||
L["Disable any reaction to mouse events on this bar, making the bar click-through."] = "Jede Mausinteraktion für diese Leiste deaktivieren, durch die Leiste hindurch klicken."
|
||||
L["Disabled"] = "Deaktiviert"
|
||||
L["Disabled in Combat"] = "Im Kampf deaktivieren"
|
||||
L["Don't Page"] = "Kein Seitenwechsel"
|
||||
L["Down"] = "Runter"
|
||||
L[ [=[Enable Auto-Assist for this bar.
|
||||
Auto-Assist will automatically try to cast on your target's target if your target is no valid target for the selected spell.]=] ] = [=[Automatische Hilfe für diese Leiste aktivieren.
|
||||
Falls der gewählte Zauber nicht auf das Ziel anwendbar ist, wird die automatische Hilfe versuchen ihn auf das Ziel des Ziels zu wirken.]=]
|
||||
L[ [=[Enable Bar Switching based on the actionbar controls provided by the game.
|
||||
See Blizzard Key Bindings for assignments - Usually Shift-Mouse Wheel and Shift+1 - Shift+6.]=] ] = [=[Leistenwechsel basierend auf der Tastenbelegung des Spiel aktivieren.
|
||||
Zum Zuweisen die Blizzard Tastaturbelegung benutzen - Normalerweise Umschalt-Mausrad und Umschalt+1 bis 6.]=]
|
||||
L["Enabled"] = "Aktiviert"
|
||||
L["Enable/Disable the bar."] = "Die Leiste aktivieren/deaktivieren."
|
||||
L["Enable State-based Button Swaping"] = "Situationsbedingten Schaltflächenwechsel aktivieren."
|
||||
L["Enable the Bag Bar"] = "Taschenleiste aktivieren"
|
||||
L["Enable the FadeOut mode"] = "Den Ausblendmodus aktivieren"
|
||||
L["Enable the Micro Menu"] = "Mikromenü aktivieren"
|
||||
L["Enable the PetBar"] = "Begleiterleiste aktivieren"
|
||||
L["Enable the Reputation Bar"] = "Rufleiste aktivieren"
|
||||
L["Enable the StanceBar"] = "Haltungsleiste aktivieren"
|
||||
L["Enable the Totem Bar"] = "Totem-Leiste aktivieren"
|
||||
L["Enable the use of a custom condition, disabling all of the above."] = "Die Benutzung von eigenen Bedingungen aktivieren und die obigen deaktivieren."
|
||||
L["Enable the use of the Blizzard Vehicle UI, hiding any Bartender4 bars in the meantime."] = "Die Verwendung des Blizzard-Fahrzeug-UIs aktivieren (versteckt alle Bartender4-Leisten in der Zwischenzeit)."
|
||||
L["Enable the Vehicle Bar"] = "Fahrzeugleiste aktivieren"
|
||||
L["Enable the XP Bar"] = "Erfahrungsleiste aktivieren"
|
||||
L["Fade Out"] = "Ausblenden"
|
||||
L["Fade Out Alpha"] = "Transparenz beim Ausblenden"
|
||||
L["Fade Out Delay"] = "Verzögerung beim Ausblenden"
|
||||
L["FAQ"] = "FAQ"
|
||||
L["FAQ_TEXT"] = [=[
|
||||
|cffffd200
|
||||
Ich habe Bartender4 soeben installiert, aber meine Tastenbelegungen werden auf den Tasten nicht angezeigt/funktionieren nicht vollständig.
|
||||
|r
|
||||
Bartender4 konvertiert nur die Zuweisungen von Leiste 1 direkt, alle anderen Leisten müssen über Bartender4 neu zugewiesen werden. Ein direkter Indikator ob deine Tastenbelegungen korrekt eingerichtet sind ist die Hotkey-Anzeige auf den Tasten. Wenn die Tastenzuweisung auf deiner Taste korrekt angezeigt wird, sollte auch alles andere richtig funktionieren.
|
||||
|
||||
|cffffd200
|
||||
Wie ändere ich dann die Tastenbelegung(en) mit Bartender4?
|
||||
|r
|
||||
Bis wir ein Schnellzugriffsmenü oder ähnliches eingeführt haben (Minimap/FuBar/etc.), musst du den Chatbefehl |cffffff78/kb|r verwenden, um das entsprechende Menü dafür zu öffnen.
|
||||
|
||||
Sobald geöffnet, einfach über die Taste die du zuweisen möchtest fahren, und dann den entsprechenden Hotkey drücken. Der keyBound-Tooltip und eine Meldung am Bildschirm werden dich darüber informieren ob die belegte Taste schon zugewiesen ist, und wenn der Zuweisungsversuch erfolgreich war.
|
||||
|
||||
|cffffd200
|
||||
Ich habe einen Bug gefunden! Wo soll ich diesen melden?
|
||||
|r
|
||||
Hier kannst du Bugs melden und Vorschläge machen: |cffffff78http://forums.wowace.com/showthread.php?t=12513|r
|
||||
|
||||
Oder du besuchst uns auf |cffffff78irc://irc.freenode.org/wowace|r
|
||||
|
||||
Wenn du einen Bug melden solltest, stelle sicher dass du die |cffffff78Schritte zur Reproduzierung des Bugs anführst|r, alle aufgetretenen |cffffff78Fehlermeldung|r auflistest, und uns mitteilst welche |cffffff78Revisionsnummer|r von Bartender4 du verwendest.
|
||||
|
||||
|cffffd200
|
||||
Wer hat dieses coole Addon geschrieben?
|
||||
|r
|
||||
Bartender4 wurde geschrieben von Nevcairiel auf EU-Antonidas!
|
||||
]=]
|
||||
L["Focus-Cast by modifier"] = "Fokus-Zauber nach Modifikator"
|
||||
L["Focus-Cast Modifier"] = "Fokus-Zauber-Modifikator"
|
||||
L["Frequently Asked Questions"] = "Häufig gestellte Fragen"
|
||||
L["Full Button Mode"] = "Komplette Schaltfläche"
|
||||
L["General Settings"] = "Allgemeine Einstellungen"
|
||||
L["Hide Hotkey"] = "Hotkey verstecken"
|
||||
L["Hide in Combat"] = "Im Kampf verstecken"
|
||||
L["Hide in Stance/Form"] = "In einer Haltung/Form verstecken"
|
||||
L["Hide Macro Text"] = "Makrotext verstecken"
|
||||
L["Hide on Vehicle"] = "In einem Fahrzeug verstecken"
|
||||
L["Hide out of Combat"] = "Außerhalb des Kampfes verstecken"
|
||||
L["Hide the Hotkey on the buttons of this bar."] = "Den Hotkey auf den Schaltflächen dieser Leiste verstecken."
|
||||
L["Hide the Macro Text on the buttons of this bar."] = "Makrotext auf den Schaltflächen dieser Leiste verstecken."
|
||||
L["Hide this bar in a specific Stance or Form."] = "Diese Leiste in einer bestimmten Haltung oder Form verstecken."
|
||||
L["Hide this bar when the game wants to show a vehicle UI."] = "Verstecke diese Leiste, wenn das Spiel das Fahrzeug UI zeigen will."
|
||||
L["Hide this bar when you are possessing a NPC."] = "Diese Leiste verstecken wenn man einen NSC übernimmt."
|
||||
L["Hide this bar when you are riding on a vehicle."] = "Diese Leiste verstecken wenn man auf einem Fahrzeug sitzt."
|
||||
L["Hide this bar when you have a pet."] = "Diese Leiste verstecken wenn man einen Begleiter hat."
|
||||
L["Hide this bar when you have no pet."] = "Diese Leiste verstecken wenn man keinen Begleiter hat."
|
||||
L["Hide when Possessing"] = "Beim Übernehmen verstecken"
|
||||
L["Hide without pet"] = "Ohne Begleiter verstecken"
|
||||
L["Hide with pet"] = "Mit Begleiter verstecken"
|
||||
L["Hide with Vehicle UI"] = "Verstecke mit Fahrzeug UI"
|
||||
L["Horizontal Growth"] = "Horizontale Ausweitung"
|
||||
L["Horizontal growth direction for this bar."] = "Horizontale Ausweitungsrichtung für diese Leiste."
|
||||
L["Hotkey Mode"] = "Hotkey Modus"
|
||||
L["Key Bindings"] = "Tastenbelegung"
|
||||
L["Keyring"] = "Schlüsselring"
|
||||
L["Left"] = "Links"
|
||||
L["Lock"] = "Verschließen"
|
||||
L["Lock all bars."] = "Alle Leisten verschließen"
|
||||
L["Lock the buttons."] = "Die Schaltflächen verschließen"
|
||||
L["Micro Menu"] = "Mikromenü"
|
||||
L["Minimap Icon"] = "Icon an der Minikarte"
|
||||
L["Modifier Based Switching"] = "Leistenwechsel über Modifikatortaste."
|
||||
L["No Display"] = "Keine Anzeige"
|
||||
L["None"] = "Keine"
|
||||
L["No Stance/Form"] = "Keine Haltung/Form"
|
||||
L["Note: Enabling Custom Conditionals will disable all of the above settings!"] = "Hinweis: Das Aktivieren von eigenen Bedingungen wird alle obigen Einstellungen deaktivieren."
|
||||
L["Number of buttons."] = "Anzahl der Schaltflächen."
|
||||
L["Number of rows."] = "Anzahl der Reihen."
|
||||
L["Offset in X direction (horizontal) from the given anchor point."] = "Offset in Richtung X (horizontal) vom gegebenen Ankerpunkt aus."
|
||||
L["Offset in Y direction (vertical) from the given anchor point."] = "Offset in Richtung Y (vertikal) vom gegebenen Ankerpunkt aus."
|
||||
L["One Bag"] = "Eine Tasche"
|
||||
L["Only show one Bag Button in the BagBar."] = "Nur eine Tasche in der Taschenleiste zeigen."
|
||||
L["Out of Mana Indicator"] = "\"Kein Mana\" anzeigen"
|
||||
L["Out of Range Indicator"] = "\"Außer Reichweite\" anzeigen"
|
||||
L["Padding"] = "Abstand"
|
||||
L["Page %2d"] = "Seite %2d"
|
||||
L["Pet Bar"] = "Begleiter Leiste"
|
||||
L["Positioning"] = "Positionierung"
|
||||
L["Possess Bar"] = "Steuerungsleiste bei Charakter- / Fahrzeugübernahme"
|
||||
L["Reputation Bar"] = "Rufleiste"
|
||||
L["Reset Position"] = "Position zurücksetzen"
|
||||
L["Reset the position of this bar completly if it ended up off-screen and you cannot reach it anymore."] = "Die Position dieser Leiste komplett zurücksetzen falls sie außerhalb des Bildschirms gelandet ist und du sie nicht mehr erreichen kannst."
|
||||
L["Right"] = "Rechts"
|
||||
L["Right-click Self-Cast"] = "Bei Rechtsklick auf sich selbst wirken"
|
||||
L["Rows"] = "Reihen"
|
||||
L["Scale"] = "Skalierung"
|
||||
L["Select the Focus-Cast Modifier"] = "Den Fokus-Zauber-Modifikator auswählen"
|
||||
L["Select the Self-Cast Modifier"] = "Den Selbstzauber-Modifikator auswählen"
|
||||
L["Self-Cast by modifier"] = "Selbstzauber mittels Modifikatortaste."
|
||||
L["Self-Cast Modifier"] = "Selbstzauber-Modifikator"
|
||||
L["SHIFT"] = "Umschalt"
|
||||
L["Show a Icon to open the config at the Minimap"] = "Icon zum Öffnen der Konfiguration an der Minikarte zeigen."
|
||||
L["Show the keyring button."] = "Schlüsselring Schaltfläche zeigen."
|
||||
L["Specify the Color of the Out of Mana Indicator"] = "Farbe für die \"Kein Mana\" Anzeige festlegen."
|
||||
L["Specify the Color of the Out of Range Indicator"] = "Farbe für die \"Außer Reichweite\" Anzeige festlegen."
|
||||
L["Stance Bar"] = "Haltungsleiste"
|
||||
L["Stance Configuration"] = "Haltungen konfigurieren"
|
||||
L["State Configuration"] = "Status konfigurieren"
|
||||
L["Switch this bar to the Possess Bar when possessing a npc (eg. Mind Control)"] = "Diese Leiste wechseln während man einen NSC übernimmt (z.B. Gedankenkontrolle)"
|
||||
L["Switch to key-binding mode"] = "Zum Tastenbelegungsmodus wechseln"
|
||||
L[ [=[The Alignment menu is still on the TODO.
|
||||
|
||||
As a quick preview of whats planned:
|
||||
|
||||
- Absolute and relative Bar Positioning
|
||||
- Bars "snapping" together and building clusters]=] ] = [=[Das Menü zum Ausrichten ist noch ein unerledigter Punkt auf der Liste.
|
||||
Eine kurze Vorschau des Geplanten:
|
||||
|
||||
- Absolutes und relatives Positionieren der Leisten
|
||||
- Leisten "springen" aneinander und bilden eine Gruppe]=]
|
||||
L["The bar default is to be visible all the time, you can configure conditions here to control when the bar should be hidden."] = "Die Leiste ist standardmäßig immer sichtbar. Man kann Bedingungen konfigurieren um zu kontrollieren wann die Leiste versteckt werden soll."
|
||||
L["The default behaviour of this bar when no state-based paging option affects it."] = "Das Standardverhalten dieser Leiste wenn sie von keinem Wechsel betroffen ist."
|
||||
L["The Positioning options here will allow you to position the bar to your liking and with an absolute precision."] = "Diese Optionen erlauben dir, die Leiste nach deinen Vorstellungen und absolut präzise zu positionieren."
|
||||
L["This bar will be hidden once you enter combat."] = "Diese Leiste wird versteckt sobald man sich im Kampf befindet."
|
||||
L["This bar will be hidden whenever you are not in combat."] = "Diese Leiste wird versteckt solange man sich nicht im Kampf befindet."
|
||||
L[ [=[Toggle Button Zoom
|
||||
For more style options you need to install ButtonFacade]=] ] = [=[Schaltflächen Zoom umschalten
|
||||
Für weitere Stiloptionen muss ButtonFacade installiert werden.]=]
|
||||
L["Toggle the button grid."] = "Das Schaltflächen Gitternetz umschalten."
|
||||
L["Toggle the use of the modifier-based focus-cast functionality."] = "Die modifikatorbasierenden Fokuszauber-Funktionalität ein/ausschalten."
|
||||
L["Toggle the use of the modifier-based self-cast functionality."] = "Schaltet die modifikatorbasierenden Selbstzauber ein oder aus."
|
||||
L["Toggle the use of the right-click self-cast functionality."] = "Die Benutzung der Rechtsklick-Selbstzauber-Funktion ein/ausschalten."
|
||||
L["Totem Bar"] = "Totem-Leiste"
|
||||
L["Up"] = "Hoch"
|
||||
L["Use Blizzard Vehicle UI"] = "Blizzard-Fahrzeug-UI verwenden"
|
||||
L["Use Custom Condition"] = "Eigene Bedingungen benutzen"
|
||||
L["VehicleBar"] = "Fahrzeugsleiste"
|
||||
L["Vehicle Bar"] = "Fahrzeugsleiste"
|
||||
L["Vertical Growth"] = "Vertikale Ausweitung"
|
||||
L["Vertical growth direction for this bar."] = "Vertikale Ausweitungsrichtung für diese Leiste."
|
||||
L["Visibility"] = "Sichtbarkeit"
|
||||
L["X Offset"] = "X Offset"
|
||||
L["XP Bar"] = "Erfahrungsleiste"
|
||||
L["Y Offset"] = "Y Offset"
|
||||
L["You can set the bar to be always hidden, if you only wish to access it using key-bindings."] = "Man kann die Leiste dauerhaft verstecken, um sie nur über die Tastaturbelegung anzusteuern."
|
||||
L[ [=[You can use any macro conditionals in the custom string, using "show" and "hide" as values.
|
||||
|
||||
Example: [combat]hide;show]=] ] = [=[Man kann alle Makrobedingungen in der eigenen Zeichenfolge benutzen, unter Verwendung der Werte "show" und "hide".
|
||||
|
||||
Beispiel: [combat]hide;show]=]
|
||||
L[ [=[You can use any macro conditionals in the custom string, using the number of the bar as target value.
|
||||
Example: [form:1]9;0]=] ] = [=[Man kann alle Makrobedingungen in der eigenen Zeichenfolge benutzen, unter Verwendung der Leistennummer als Zielwert.
|
||||
Beispiel: [form:1]9;0]=]
|
||||
L["You have to exit the vehicle in order to be able to change the Vehicle UI settings."] = "Du musst das Fahrzeug verlassen um Änderungen am Fahrzeug-UI vornehmen zu können."
|
||||
L["Zoom"] = "Zoom"
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
-- Bartender4 Locale
|
||||
-- Please use the Localization App on WoWAce to Update this
|
||||
-- http://www.wowace.com/projects/bartender4/localization/ ;¶
|
||||
|
||||
local debug = false
|
||||
--[===[@debug@
|
||||
debug = true
|
||||
--@end-debug@]===]
|
||||
|
||||
local L = LibStub("AceLocale-3.0"):NewLocale("Bartender4", "enUS", true, debug)
|
||||
|
||||
L["ActionBar Paging"] = true
|
||||
L["Alignment"] = true
|
||||
L["Alpha"] = true
|
||||
L["ALT"] = true
|
||||
L["Always Hide"] = true
|
||||
L["Anchor"] = true
|
||||
L["Auto-Assist"] = true
|
||||
L["Bag Bar"] = true
|
||||
L["Bar Options"] = true
|
||||
L["Bars"] = true
|
||||
L["Bar %s"] = true
|
||||
L["Bar Snapping"] = true
|
||||
L["Bar Style & Layout"] = true
|
||||
L["Bars unlocked. Move them now and click Lock when you are done."] = true
|
||||
L["Bartender4"] = true
|
||||
L["Button Grid"] = true
|
||||
L["Button Lock"] = true
|
||||
L["Button Look"] = true
|
||||
L["Buttons"] = true
|
||||
L["Button %s"] = true
|
||||
L["Button Tooltip"] = true
|
||||
L["Cannot access options during combat."] = true
|
||||
L["Center Horizontally"] = true
|
||||
L["Centers the bar horizontally on screen."] = true
|
||||
L["Centers the bar vertically on screen."] = true
|
||||
L["Center Vertically"] = true
|
||||
L["|cffffff00Click|r to toggle bar lock"] = true
|
||||
L["|cffffff00Right-click|r to open the options menu"] = true
|
||||
L["Change the current anchor point of the bar."] = true
|
||||
L["Click-Through"] = true
|
||||
L["Colors"] = true
|
||||
L["Configure actionbar paging when the %s key is down."] = true
|
||||
L["Configure Bar %s"] = true
|
||||
L["Configure how the Out of Range Indicator should display on the buttons."] = true
|
||||
L["Configure the alpha of the bar."] = true
|
||||
L["Configure the Bag Bar"] = true
|
||||
L["Configure the Button Tooltip."] = true
|
||||
L["Configure the Fade Out Alpha"] = true
|
||||
L["Configure the Fade Out Delay"] = true
|
||||
L["Configure the Micro Menu"] = true
|
||||
L["Configure the padding of the buttons."] = true
|
||||
L["Configure the Pet Bar"] = true
|
||||
L["Configure the Reputation Bar"] = true
|
||||
L["Configure the scale of the bar."] = true
|
||||
L["Configure the Stance Bar"] = true
|
||||
L["Configure the Totem Bar"] = true
|
||||
L["Configure the VehicleBar"] = true
|
||||
L["Configure the XP Bar"] = true
|
||||
L["Copy Conditionals"] = true
|
||||
L["Create a copy of the auto-generated conditionals in the custom configuration as a base template."] = true
|
||||
L["CTRL"] = true
|
||||
L["Custom Conditionals"] = true
|
||||
L["Default Bar State"] = true
|
||||
L["Disable any reaction to mouse events on this bar, making the bar click-through."] = true
|
||||
L["Disabled"] = true
|
||||
L["Disabled in Combat"] = true
|
||||
L["Don't Page"] = true
|
||||
L["Down"] = true
|
||||
L[ [=[Enable Auto-Assist for this bar.
|
||||
Auto-Assist will automatically try to cast on your target's target if your target is no valid target for the selected spell.]=] ] = true
|
||||
L[ [=[Enable Bar Switching based on the actionbar controls provided by the game.
|
||||
See Blizzard Key Bindings for assignments - Usually Shift-Mouse Wheel and Shift+1 - Shift+6.]=] ] = true
|
||||
L["Enabled"] = true
|
||||
L["Enable/Disable the bar."] = true
|
||||
L["Enable State-based Button Swaping"] = true
|
||||
L["Enable the Bag Bar"] = true
|
||||
L["Enable the FadeOut mode"] = true
|
||||
L["Enable the Micro Menu"] = true
|
||||
L["Enable the PetBar"] = true
|
||||
L["Enable the Reputation Bar"] = true
|
||||
L["Enable the StanceBar"] = true
|
||||
L["Enable the Totem Bar"] = true
|
||||
L["Enable the use of a custom condition, disabling all of the above."] = true
|
||||
L["Enable the use of the Blizzard Vehicle UI, hiding any Bartender4 bars in the meantime."] = true
|
||||
L["Enable the Vehicle Bar"] = true
|
||||
L["Enable the XP Bar"] = true
|
||||
L["Fade Out"] = true
|
||||
L["Fade Out Alpha"] = true
|
||||
L["Fade Out Delay"] = true
|
||||
L["FAQ"] = true
|
||||
L["FAQ_TEXT"] = [=[|cffffd200
|
||||
I just installed Bartender4, but my keybindings do not show up on the buttons/do not work entirely.
|
||||
|r
|
||||
Bartender4 only converts the bindings of Bar1 to be directly usable, all other Bars will have to be re-bound to the Bartender4 keys. A direct indicator if your key-bindings are setup correctly is the hotkey display on the buttons. If the key-bindings shows correctly on your button, everything should work fine as well.
|
||||
|
||||
|cffffd200
|
||||
How do I change the Bartender4 Keybindings then?
|
||||
|r
|
||||
You can either click the KeyBound button in the options, or use the |cffffff78/kb|r chat command to open the keyBound control.
|
||||
|
||||
Once open, simply hover the button you want to bind, and press the key you want to be bound to that button. The keyBound tooltip and on-screen status will inform you about already existing bindings to that button, and the success of your binding attempt.
|
||||
|
||||
|cffffd200
|
||||
My BagBar does not have the Keyring on it, how do i get it back?
|
||||
|r
|
||||
Its simple! Just check the Keyring option in the BagBars configuration menu, and it'll appear next to your bags.
|
||||
|
||||
|cffffd200
|
||||
I've found a bug! Where do I report it?
|
||||
|r
|
||||
You can report bugs or give suggestions at the discussion forums at |cffffff78http://forums.wowace.com/showthread.php?t=12513|r or check the project page at |cffffff78http://www.wowace.com/projects/bartender4/|r
|
||||
|
||||
Alternatively, you can also find us on |cffffff78irc://irc.freenode.org/wowace|r
|
||||
|
||||
When reporting a bug, make sure you include the |cffffff78steps on how to reproduce the bug|r, supply any |cffffff78error messages|r with stack traces if possible, give the |cffffff78revision number|r of Bartender4 the problem occured in and state whether you are using an |cffffff78English client or otherwise|r.
|
||||
|
||||
|cffffd200
|
||||
Who wrote this cool addon?
|
||||
|r
|
||||
Bartender4 was written by Nevcairiel of EU-Antonidas, the author of Bartender3!
|
||||
]=]
|
||||
L["Focus-Cast by modifier"] = true
|
||||
L["Focus-Cast Modifier"] = true
|
||||
L["Frequently Asked Questions"] = true
|
||||
L["Full Button Mode"] = true
|
||||
L["General Settings"] = true
|
||||
L["Hide Hotkey"] = true
|
||||
L["Hide in Combat"] = true
|
||||
L["Hide in Stance/Form"] = true
|
||||
L["Hide Macro Text"] = true
|
||||
L["Hide on Vehicle"] = true
|
||||
L["Hide out of Combat"] = true
|
||||
L["Hide the Hotkey on the buttons of this bar."] = true
|
||||
L["Hide the Macro Text on the buttons of this bar."] = true
|
||||
L["Hide this bar in a specific Stance or Form."] = true
|
||||
L["Hide this bar when the game wants to show a vehicle UI."] = true
|
||||
L["Hide this bar when you are possessing a NPC."] = true
|
||||
L["Hide this bar when you are riding on a vehicle."] = true
|
||||
L["Hide this bar when you have a pet."] = true
|
||||
L["Hide this bar when you have no pet."] = true
|
||||
L["Hide when Possessing"] = true
|
||||
L["Hide without pet"] = true
|
||||
L["Hide with pet"] = true
|
||||
L["Hide with Vehicle UI"] = true
|
||||
L["Horizontal Growth"] = true
|
||||
L["Horizontal growth direction for this bar."] = true
|
||||
L["Hotkey Mode"] = true
|
||||
L["Key Bindings"] = true
|
||||
L["Keyring"] = true
|
||||
L["Left"] = true
|
||||
L["Lock"] = true
|
||||
L["Lock all bars."] = true
|
||||
L["Lock the buttons."] = true
|
||||
L["Micro Menu"] = true
|
||||
L["Minimap Icon"] = true
|
||||
L["Modifier Based Switching"] = true
|
||||
L["No Display"] = true
|
||||
L["None"] = true
|
||||
L["No Stance/Form"] = true
|
||||
L["Note: Enabling Custom Conditionals will disable all of the above settings!"] = true
|
||||
L["Number of buttons."] = true
|
||||
L["Number of rows."] = true
|
||||
L["Offset in X direction (horizontal) from the given anchor point."] = true
|
||||
L["Offset in Y direction (vertical) from the given anchor point."] = true
|
||||
L["One Bag"] = true
|
||||
L["Only show one Bag Button in the BagBar."] = true
|
||||
L["Out of Mana Indicator"] = true
|
||||
L["Out of Range Indicator"] = true
|
||||
L["Padding"] = true
|
||||
L["Page %2d"] = true
|
||||
L["Pet Bar"] = true
|
||||
L["Positioning"] = true
|
||||
L["Possess Bar"] = true
|
||||
L["Reputation Bar"] = true
|
||||
L["Reset Position"] = true
|
||||
L["Reset the position of this bar completly if it ended up off-screen and you cannot reach it anymore."] = true
|
||||
L["Right"] = true
|
||||
L["Right-click Self-Cast"] = true
|
||||
L["Rows"] = true
|
||||
L["Scale"] = true
|
||||
L["Select the Focus-Cast Modifier"] = true
|
||||
L["Select the Self-Cast Modifier"] = true
|
||||
L["Self-Cast by modifier"] = true
|
||||
L["Self-Cast Modifier"] = true
|
||||
L["SHIFT"] = true
|
||||
L["Show a Icon to open the config at the Minimap"] = true
|
||||
L["Show the keyring button."] = true
|
||||
L["Specify the Color of the Out of Mana Indicator"] = true
|
||||
L["Specify the Color of the Out of Range Indicator"] = true
|
||||
L["Stance Bar"] = true
|
||||
L["Stance Configuration"] = true
|
||||
L["State Configuration"] = true
|
||||
L["Switch this bar to the Possess Bar when possessing a npc (eg. Mind Control)"] = true
|
||||
L["Switch to key-binding mode"] = true
|
||||
L[ [=[The Alignment menu is still on the TODO.
|
||||
|
||||
As a quick preview of whats planned:
|
||||
|
||||
- Absolute and relative Bar Positioning
|
||||
- Bars "snapping" together and building clusters]=] ] = true
|
||||
L["The bar default is to be visible all the time, you can configure conditions here to control when the bar should be hidden."] = true
|
||||
L["The default behaviour of this bar when no state-based paging option affects it."] = true
|
||||
L["The Positioning options here will allow you to position the bar to your liking and with an absolute precision."] = true
|
||||
L["This bar will be hidden once you enter combat."] = true
|
||||
L["This bar will be hidden whenever you are not in combat."] = true
|
||||
L[ [=[Toggle Button Zoom
|
||||
For more style options you need to install ButtonFacade]=] ] = true
|
||||
L["Toggle the button grid."] = true
|
||||
L["Toggle the use of the modifier-based focus-cast functionality."] = true
|
||||
L["Toggle the use of the modifier-based self-cast functionality."] = true
|
||||
L["Toggle the use of the right-click self-cast functionality."] = true
|
||||
L["Totem Bar"] = true
|
||||
L["Up"] = true
|
||||
L["Use Blizzard Vehicle UI"] = true
|
||||
L["Use Custom Condition"] = true
|
||||
L["VehicleBar"] = true
|
||||
L["Vehicle Bar"] = true
|
||||
L["Vertical Growth"] = true
|
||||
L["Vertical growth direction for this bar."] = true
|
||||
L["Visibility"] = true
|
||||
L["X Offset"] = true
|
||||
L["XP Bar"] = true
|
||||
L["Y Offset"] = true
|
||||
L["You can set the bar to be always hidden, if you only wish to access it using key-bindings."] = true
|
||||
L[ [=[You can use any macro conditionals in the custom string, using "show" and "hide" as values.
|
||||
|
||||
Example: [combat]hide;show]=] ] = true
|
||||
L[ [=[You can use any macro conditionals in the custom string, using the number of the bar as target value.
|
||||
Example: [form:1]9;0]=] ] = true
|
||||
L["You have to exit the vehicle in order to be able to change the Vehicle UI settings."] = true
|
||||
L["Zoom"] = true
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user