Quantcast
WoWInterface: SVN - NeedyGreedy - Path Comparison - /tags Rev 178 and /tags Rev 179

WoWInterface SVN NeedyGreedy

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /tags
    from Rev 178 to Rev 179
    Reverse comparison

Rev 178 → Rev 179

1.2.5/NeedyGreedy.lua New file
0,0 → 1,2026
NeedyGreedy = LibStub("AceAddon-3.0"):NewAddon("NeedyGreedy", "AceEvent-3.0", "AceTimer-3.0", "AceConsole-3.0")
 
local L = LibStub("AceLocale-3.0"):GetLocale("NeedyGreedy", true)
 
local report = {}
local items = {}
local nameList = {}
 
-- Set up DataBroker object
local NeedyGreedyLDB = LibStub("LibDataBroker-1.1"):NewDataObject("NeedyGreedy", {
type = "launcher",
label = "Needy Greedy",
icon = "Interface\\Buttons\\UI-GroupLoot-Dice-Up",
OnClick = function(frame, button)
if button == "RightButton" then
InterfaceOptionsFrame_OpenToCategory("NeedyGreedy")
elseif IsShiftKeyDown() then
NeedyGreedy.db.profile.detachedTooltip = not NeedyGreedy.db.profile.detachedTooltip
LibStub("AceConfigRegistry-3.0"):NotifyChange("NeedyGreedy")
NeedyGreedy:HideDBTooltip()
NeedyGreedy:ShowDBTooltip(frame)
NeedyGreedy:HideDetachedTooltip()
if NeedyGreedy.db.profile.detachedTooltip then
NeedyGreedy.db.profile.displayStatus = true
NeedyGreedy:RefreshTooltip()
end
elseif IsAltKeyDown() then
NeedyGreedy:ClearItems()
elseif NeedyGreedy.db.profile.detachedTooltip then
NeedyGreedy:ToggleDisplay()
end
end,
OnEnter = function(frame)
NeedyGreedy:ShowDBTooltip(frame)
end,
OnLeave = function()
if NeedyGreedy.db.profile.detachedTooltip then
NeedyGreedy:HideDBTooltip()
end
end,
})
local ngDBIcon = LibStub("LibDBIcon-1.0")
 
-- Set up configuration window
local options = {
name = L["NeedyGreedy"],
desc = L["Displays a table of items and the roll choices players have made on them"],
handler = NeedyGreedy,
type = "group",
args = {
general = {
name = L['General'],
type = 'group',
args = {
nItems = {
name = L["Display Items"],
desc = L["Number of item columns in the display window"],
type = "range",
order = 105,
min = 1,
max = 10,
step = 1,
get = "GetNItems",
set = "SetNItems"
},
expiry = {
name = L["Expiry Time"],
desc = L["Minutes after item is received before it is removed from display (0 = forever)"],
type = "range",
order = 120,
min = 0,
max = 110,
step = 1,
get = "GetExpiry",
set = "SetExpiry"
},
quality = {
name = L["Minimum Quality"],
desc = L["Minimum quality of item to be displayed"],
type = "select",
order = 130,
values = {
[ITEM_QUALITY_UNCOMMON] = ITEM_QUALITY2_DESC,
[ITEM_QUALITY_RARE] = ITEM_QUALITY3_DESC,
[ITEM_QUALITY_EPIC] = ITEM_QUALITY4_DESC
},
style = "dropdown",
get = "GetQuality",
set = "SetQuality"
},
resetInNewParty = {
name = L["Reset on Join Party"],
desc = L["Clear the item list when joining a new group"],
type = "select",
values = {
always = "Always",
ask = "Ask",
never = "Never",
},
style = "dropdown",
order = 100,
get = "GetResetInNewParty",
set = "SetResetInNewParty",
},
resetInNewInstance = {
name = L["Reset in Instance"],
desc = L["Clear the item list when entering an instance"],
type = "select",
values = {
always = "Always",
ask = "Ask",
never = "Never",
},
style = "dropdown",
order = 101,
get = "GetResetInNewInstance",
set = "SetResetInNewInstance",
},
 
displayIcons = {
name = L["Graphical Display"],
desc = L["Display icons for rolls types instead of text"],
type = "toggle",
order = 20,
get = "GetDisplayIcons",
set = "SetDisplayIcons",
},
displayTextLink = {
name = L["Item Names"],
desc = L["Toggle the display of the item name in the header"],
order = 30,
type = "toggle",
get = "GetDisplayTextLink",
set = "SetDisplayTextLink",
},
hideMinimapIcon = {
name = L["Minimap Icon"],
desc = L["Toggle the display of the minimap icon"],
type = "toggle",
order = 99,
get = "GetHideMinimapIcon",
set = "SetHideMinimapIcon",
width = "full"
},
filterLootMsgs = {
name = L["Filter Loot Messages"],
desc = L["Enable filtering of loot roll messages"],
type = "toggle",
order = 35,
get = "GetFilterLootMsgs",
set = "SetFilterLootMsgs",
},
showGroupOnly = {
name = L["Hide Non-Members"],
desc = L["Only display the names of members currently in your party"],
type = "toggle",
order = 40,
get = "GetShowGroupOnly",
set = "SetShowGroupOnly",
},
},
},
 
detachedTooltipOptions = {
name = L["Detached Tooltip"],
type = "group",
args = {
detachedTooltip = {
name = L["Detach Tooltip"],
desc = L["Display the roll information in a standalone window"],
type = "toggle",
order = 10,
get = "GetDetachedTooltip",
set = "SetDetachedTooltip",
},
autoPopUp = {
name = L["Popup when rolling"],
desc = L["Automatically show the detached tooltip when an item is being rolled on"],
type = "toggle",
order = 11,
get = "GetAutoPopUp",
set = "SetAutoPopUp",
},
showOnParty = {
name = L["Show in party"],
desc = L["Display the detached window when joining a party and hide the tooltip when leaving a party"],
type = "toggle",
order = 12,
get = "GetShowOnParty",
set = "SetShowOnParty",
},
hideInCombat = {
name = L["Hide in combat"],
desc = L["Only display the detached window when not in combat"],
type = "toggle",
order = 14,
get = "GetHideInCombat",
set = "SetHideInCombat",
},
tooltipScale = {
name = L["Scale"],
desc = L["Adjust the scale of the detached tooltip"],
type = "range",
order = 16,
min = 0.5,
max= 2.0,
step = 0.01,
get = "GetTooltipScale",
set = "SetTooltipScale",
},
lockTooltip = {
name = L["Lock Tooltip"],
desc = L["Adjust the position of the detached tooltip"],
type = "toggle",
order = 100,
get = "GetLockTooltip",
set = "SetLockTooltip",
width = "full",
},
 
},
},
 
dataBrokerOptions = {
name = L["DataBroker Tooltip"],
type = "group",
args = {
suppressInRaid = {
name = L["Hide In Raid"],
desc = L["Suppress the display of the LibDataBroker tooltip when in a raid"],
type = "toggle",
order = 10,
get = "GetSuppressInRaid",
set = "SetSuppressInRaid",
},
},
},
 
}
}
 
-- Set profile defaults
local defaults = {
profile = {
nItems = 2,
expiry = 5,
quality = ITEM_QUALITY_RARE,
displayIcons = true,
detachedTooltip = false,
displayTextLink = false,
displayStatus = false,
minimap = { hide = false },
filterLootMsgs = false,
showOnParty = false,
hideInCombat = false,
showGroupOnly = true,
autoPopUp = true,
resetInNewParty = "ask",
resetInNewInstance = "ask",
tooltipScale = 1,
lockTooltip = false,
suppressInRaid = false,
}
}
 
-- Console commands
local slashTable = {
handler = NeedyGreedy,
type = "group",
args = {
config = {
name = L["Open the configuration menu"],
type = "execute",
func = function() InterfaceOptionsFrame_OpenToCategory("NeedyGreedy") end,
},
hide = {
name = L["Hide the detached tooltip"],
type = "execute",
func = "SlashHide",
},
report = {
name = L["Generate a text summary"],
type = "execute",
func = "PrintReport",
},
reset = {
name = L["Reset the item list"],
type = "execute",
func = "ClearItems",
},
show = {
name = L["Show the detached tooltip"],
type = "execute",
func = "SlashShow",
},
},
}
 
-- Icon textures
local iconSize = 27
local NEEDYGREEDY_CHOICE = {
["need"] = {
["string"] = "|c00FF0000" .. NEED .. "|r",
["icon"] = "|TInterface\\Buttons\\UI-GroupLoot-Dice-Up:" .. iconSize .. "|t",
},
["greed"] = {
["string"] = "|c0000FF00" .. GREED .. "|r",
["icon"] = "|TInterface\\Buttons\\UI-GroupLoot-Coin-Up:" .. iconSize .. "|t",
},
["pass"] = {
["string"] = "|c00CCCCCC" .. PASS .. "|r",
["icon"] = "|TInterface\\Buttons\\UI-GroupLoot-Pass-Up:" .. iconSize .. "|t",
},
["disenchant"] = {
["string"] = "|c00FF00FF" .. ROLL_DISENCHANT .. "|r",
["icon"] = "|TInterface\\Buttons\\UI-GroupLoot-DE-Up:" .. iconSize .. "|t",
}
}
local BLANK_ICON = "|T:27|t"
local CLOSE_ICON = "|TInterface\\Buttons\\UI-Panel-MinimizeButton-Up:" .. iconSize .. "|t"
local PAGER_ICONS = {
leftUp = "|TInterface\\Buttons\\UI-SpellbookIcon-PrevPage-Up:" .. iconSize .. "|t",
leftDisabled = "|TInterface\\Buttons\\UI-SpellbookIcon-PrevPage-Disabled:" .. iconSize .. "|t",
rightUp = "|TInterface\\Buttons\\UI-SpellbookIcon-NextPage-Up:" .. iconSize .. "|t",
rightDisabled = "|TInterface\\Buttons\\UI-SpellbookIcon-NextPage-Disabled:" .. iconSize .. "|t",
}
 
-- Funky colors for text strings
local yC = "|cffFFCC00" -- Golden
local eC = "|cffEDA55F" -- Orange
local gC = "|cff00FF00" -- Green
 
-- For tracking original state of detailed loot information
local originalSpamFilterSetting = nil
 
-- For tracking combat status
local IS_IN_COMBAT = nil
 
-- We track rolling on items like this to avoid the scenario where you're in
-- combat the window pops up, you leave combat briefly before another add
-- attacks and the window disappears as you're deciding
local WATCH_ITEM_BEING_ROLLED_ON = nil
 
-- For tracking grouped status
local IS_IN_PARTY = nil
local IS_IN_RAID = nil
 
-- For tracking ghost status
local WAS_GHOST = nil
 
-- Utility functions
local function sanitizePattern(pattern)
pattern = string.gsub(pattern, "%(", "%%(")
pattern = string.gsub(pattern, "%)", "%%)")
pattern = string.gsub(pattern, "%%s", "(.+)")
pattern = string.gsub(pattern, "%%d", "(%%d+)")
pattern = string.gsub(pattern, "%-", "%%-")
return pattern
end
 
-- Converts a format string into a pattern and list of capture group indices
-- e.g. %2$s won the %1$s
local function patternFromFormat(format)
local pattern = ""
local captureIndices = {}
 
local start = 1
local captureIndex = 0
repeat
-- find the next group
local s, e, group, position = format:find("(%%([%d$]*)[ds])", start)
if s then
-- add the text between the last group and this group
pattern = pattern..sanitizePattern(format:sub(start, s-1))
-- update the current capture index, using the position bit in the
-- group if it exists, otherwise just increment
if #position > 0 then
-- chop off the $ and convert to a number
captureIndex = tonumber(position:sub(1, #position-1))
else
captureIndex = captureIndex + 1
end
-- add the current capture index to our list
tinsert(captureIndices, captureIndex)
-- remove the position bit from the group, sanitize the remainder
-- and add it to the pattern
pattern = pattern..sanitizePattern(group:gsub("%d%$", "", 1))
-- start searching again from past the end of the group
start = e + 1
else
-- if no more groups can be found, but there's still more text
-- remaining in the format string, sanitize the remainder, add it
-- to the pattern and finish the loop
if start <= #format then
pattern = pattern..sanitizePattern(format:sub(start))
end
break
end
until start > #format
 
return pattern, captureIndices
end
 
-- Like string:find but uses a list of capture indices to re-order the capture
-- groups. For use with converted format strings that use positional args.
-- e.g. %2$s won the %1$s.
local function superFind(text, pattern, captureIndices)
local results = { text:find(pattern) }
if #results == 0 then
return
end
 
local s, e = tremove(results, 1), tremove(results, 1)
 
local captures = {}
for _, index in ipairs(captureIndices) do
tinsert(captures, results[index])
end
 
return s, e, unpack(captures)
end
 
-- Strips the item ID out of the item link
-- Needed for items that change their unique identifier
local function itemIdFromLink(itemLink)
local found, _, itemString = string.find(itemLink, "|H(.+)|h")
if found then
local _, itemId = strsplit(":", itemString)
return tonumber(itemId)
end
return nil
end
 
-- Ye olde pop up box
local function confirmResetDialog()
StaticPopupDialogs["NeedyGreedyResetDialog"] = {
text = L["Do you wish to reset NeedyGreedy?"],
button1 = ACCEPT,
button2 = CANCEL,
timeout = 30,
whileDead = 0,
hideOnEscape = 1,
OnAccept = function() NeedyGreedy:ClearItems() end,
}
StaticPopup_Show("NeedyGreedyResetDialog")
end
 
 
 
-- Event handling functions
function NeedyGreedy:OnInitialize()
 
-- Profile handling
self.db = LibStub("AceDB-3.0"):New("NeedyGreedyDB", defaults, true)
self.db.RegisterCallback(self, "OnProfileChanged", "RefreshProfile")
self.db.RegisterCallback(self, "OnProfileCopied", "RefreshProfile")
self.db.RegisterCallback(self, "OnProfileReset", "RefreshProfile")
options.args.profile = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
 
-- Register config options
LibStub("AceConfig-3.0"):RegisterOptionsTable("NeedyGreedy", options)
 
-- Set up GUI configuration
local ACD = LibStub("AceConfigDialog-3.0")
ACD:AddToBlizOptions("NeedyGreedy", "NeedyGreedy", nil, "general")
ACD:AddToBlizOptions("NeedyGreedy", L["Detached Tooltip"], "NeedyGreedy", "detachedTooltipOptions")
ACD:AddToBlizOptions("NeedyGreedy", L["DataBroker Tooltip"], "NeedyGreedy", "dataBrokerOptions")
ACD:AddToBlizOptions("NeedyGreedy", L["Profile"], "NeedyGreedy", "profile")
 
-- Register slash options table
LibStub("AceConfig-3.0"):RegisterOptionsTable("NeedyGreedyCmds", slashTable, {"ng", "needygreedy"})
 
-- Register the minimap icon
ngDBIcon:Register("NeedyGreedy", NeedyGreedyLDB, self.db.profile.minimap)
end
 
function NeedyGreedy:OnEnable()
self:RegisterEvent("PARTY_MEMBERS_CHANGED")
self:RegisterEvent("START_LOOT_ROLL")
self:RegisterEvent("CHAT_MSG_LOOT")
self:RegisterEvent("PLAYER_REGEN_DISABLED")
self:RegisterEvent("PLAYER_REGEN_ENABLED")
self:RegisterEvent("PLAYER_ALIVE")
self:RegisterEvent("RAID_ROSTER_UPDATE")
 
self:ScheduleRepeatingTimer("ExpireItems", 10)
 
-- Refresh display when class can be determined
self:RegisterEvent("PLAYER_ENTERING_WORLD")
self:RegisterEvent("UNIT_CLASSIFICATION_CHANGED", "PLAYER_ENTERING_WORLD")
 
self:RegisterEvent("PLAYER_LEAVING_WORLD")
 
-- Set up chat filters
if self.db.profile.filterLootMsgs then
self:EnableChatFilter()
end
 
self:SetShowLootSpam()
end
 
function NeedyGreedy:OnDisable()
self:HideDetachedTooltip()
 
-- Turn off chat filters
if self.db.profile.filterLootMsgs then
self:DisableChatFilter()
end
 
self:ResetShowLootSpam()
end
 
function NeedyGreedy:PLAYER_ENTERING_WORLD()
if IS_IN_COMBAT then return end -- The prophet Tharonja's phases do this
 
wipe(nameList)
if self.db.profile.detachedTooltip then
if self:DisplayDetachedTTCheck() then
self:RefreshTooltip()
end
end
 
local inInstance, instanceType = IsInInstance()
if inInstance and (instanceType == "party" or instanceType == "raid") then
-- Don't ask when making a graveyard run
if not WAS_GHOST then
if self.db.profile.resetInNewInstance == "always" and (#items ~= 0) then
self:ClearItems()
elseif self.db.profile.resetInNewInstance == "ask" and (#items ~= 0) then
confirmResetDialog()
end
else
WAS_GHOST = false
end
end
 
self:SetShowLootSpam()
end
 
function NeedyGreedy:PLAYER_LEAVING_WORLD()
self:ResetShowLootSpam()
end
 
function NeedyGreedy:PARTY_MEMBERS_CHANGED()
if (GetNumPartyMembers() > 0 or GetNumRaidMembers() > 0) and not IS_IN_PARTY then
IS_IN_PARTY = true
 
if self.db.profile.resetInNewParty == "always" and (#items ~= 0) then
self:ClearItems()
elseif self.db.profile.resetInNewParty == "ask" and (#items ~= 0) then
confirmResetDialog()
end
 
if self.db.profile.showOnParty and self.db.profile.detachedTooltip and not self.db.profile.displayStatus then
self.db.profile.displayStatus = true
self:ShowDetachedTooltip()
end
 
elseif (GetNumPartyMembers() == 0 and GetNumRaidMembers() == 0) then
IS_IN_PARTY = false
IS_IN_RAID = false
 
if self.db.profile.showOnParty and self.db.profile.detachedTooltip and self.db.profile.displayStatus then
self.db.profile.displayStatus = false
self:HideDetachedTooltip()
end
 
end
 
wipe(nameList)
self:RefreshTooltip()
end
 
function NeedyGreedy:PLAYER_REGEN_DISABLED()
IS_IN_COMBAT = true
self:RefreshTooltip()
end
 
function NeedyGreedy:PLAYER_REGEN_ENABLED()
IS_IN_COMBAT = false
self:RefreshTooltip()
end
 
function NeedyGreedy:PLAYER_ALIVE()
if UnitIsDeadOrGhost("player") then
WAS_GHOST = true
elseif WAS_GHOST then
WAS_GHOST = false
end
end
 
function NeedyGreedy:RAID_ROSTER_UPDATE()
if GetNumRaidMembers() > 0 then
IS_IN_RAID = true
else
IS_IN_RAID = false
end
end
 
 
 
-- Chat scanning and loot recording
function NeedyGreedy:START_LOOT_ROLL(event, rollid, rollTime)
local texture, name, count, quality = GetLootRollItemInfo(rollid)
local link = GetLootRollItemLink(rollid)
if quality >= self.db.profile.quality then
table.insert(items, {
texture = texture,
link = link,
itemID = itemIdFromLink(link),
assigned = "",
received = 0,
choices = {},
rolls = {},
rollTimeOut = GetTime() + rollTime/1000,
})
 
if self.db.profile.detachedTooltip and self.db.profile.autoPopUp then
WATCH_ITEM_BEING_ROLLED_ON = true
self:ShowDetachedTooltip()
end
 
self:UpdateReport()
end
end
 
function NeedyGreedy:CHAT_MSG_LOOT(event, msg)
local me = UnitName("player")
local player, link, number
 
link = self:unformat(LOOT_ROLL_YOU_WON, msg)
if link then
self:RecordAwarded(link, me)
return
end
 
player, link = self:unformat(LOOT_ROLL_WON, msg)
if player then
self:RecordAwarded(link, player)
return
end
 
link = self:unformat(LOOT_ROLL_ALL_PASSED, msg)
if link then
self:RecordAwarded(link, "---")
return
end
 
player, link = self:unformat(LOOT_ROLL_PASSED_AUTO, msg)
if player then
self:RecordChoice(link, player, "pass")
return
end
 
player, link = self:unformat(LOOT_ROLL_PASSED_AUTO_FEMALE, msg)
if player then
self:RecordChoice(link, player, "pass")
return
end
 
link = self:unformat(LOOT_ROLL_NEED_SELF, msg)
if link then
self:RecordChoice(link, me, "need")
return
end
 
link = self:unformat(LOOT_ROLL_GREED_SELF, msg)
if link then
self:RecordChoice(link, me, "greed")
return
end
 
link = self:unformat(LOOT_ROLL_PASSED_SELF, msg)
if link then
self:RecordChoice(link, me, "pass")
return
end
 
link = self:unformat(LOOT_ROLL_PASSED_SELF_AUTO, msg)
if link then
self:RecordChoice(link, me, "pass")
return
end
 
player, link = self:unformat(LOOT_ROLL_NEED, msg)
if player then
self:RecordChoice(link, player, "need")
return
end
 
player, link = self:unformat(LOOT_ROLL_GREED, msg)
if player then
self:RecordChoice(link, player, "greed")
return
end
 
player, link = self:unformat(LOOT_ROLL_PASSED, msg)
if player then
self:RecordChoice(link, player, "pass")
return
end
 
number, link, player = self:unformat(LOOT_ROLL_ROLLED_NEED, msg)
if number then
self:RecordRoll(link, player, number)
return
end
 
number, link, player = self:unformat(LOOT_ROLL_ROLLED_GREED, msg)
if number then
self:RecordRoll(link, player, number)
return
end
 
link = self:unformat(LOOT_ITEM_PUSHED_SELF, msg)
if link then
self:RecordReceived(link, me)
return
end
 
link, number = self:unformat(LOOT_ITEM_PUSHED_SELF_MULTIPLE, msg)
if link then
self:RecordReceived(link, me)
return
end
 
link = self:unformat(LOOT_ITEM_SELF, msg)
if link then
self:RecordReceived(link, me)
return
end
 
link, number = self:unformat(LOOT_ITEM_SELF_MULTIPLE, msg)
if link then
self:RecordReceived(link, me)
return
end
 
player, link = self:unformat(LOOT_ITEM, msg)
if player then
self:RecordReceived(link, player)
return
end
 
player, link, number = self:unformat(LOOT_ITEM_MULTIPLE, msg)
if player then
self:RecordReceived(link, player)
return
end
 
-- To handle new disenchant rules
link = self:unformat(LOOT_ROLL_DISENCHANT_SELF, msg)
if link then
self:RecordChoice(link, me, "disenchant")
return
end
 
player, link = self:unformat(LOOT_ROLL_DISENCHANT, msg)
if link then
self:RecordChoice(link, player, "disenchant")
return
end
 
player, link = self:unformat(LOOT_ROLL_DISENCHANT, msg)
if link then
self:RecordChoice(link, player, "disenchant")
return
end
 
number, link, player = self:unformat(LOOT_ROLL_ROLLED_DE, msg)
if number then
self:RecordRoll(link, player, number)
return
end
end
 
function NeedyGreedy:RecordChoice(link, player, choice)
local _, _, quality = GetItemInfo(link)
if quality < self.db.profile.quality then return end
 
for _, record in ipairs(items) do
if record.assigned == "" and record.link == link then
record.choices[player] = choice
break
end
end
self:UpdateReport()
end
 
function NeedyGreedy:RecordRoll(link, player, number)
local _, _, quality = GetItemInfo(link)
if quality < self.db.profile.quality then return end
 
for _, record in ipairs(items) do
if record.assigned == "" and record.link == link then
record.rolls[player] = number
break
end
end
self:UpdateReport()
end
 
function NeedyGreedy:RecordAwarded(link, player)
local _, _, quality = GetItemInfo(link)
if quality < self.db.profile.quality then return end
 
for _, record in ipairs(items) do
if record.assigned == "" and record.link == link then
record.assigned = player
break
end
end
self:UpdateReport()
end
 
function NeedyGreedy:RecordReceived(link, player)
local _, _, quality = GetItemInfo(link)
-- Because disenchanted items can be white >_<9
if quality < ITEM_QUALITY_COMMON then return end
 
local match = false
for _, record in ipairs(items) do
if record.received == 0 and record.link == link then
record.received = GetTime()
match = true
break
end
end
 
if not match then
-- For items with weird unique identifiers
for _, record in ipairs(items) do
if record.received == 0 and record.itemID == itemIdFromLink(link) then
record.received = GetTime()
match = true
break
end
end
end
 
if not match then
for _, record in ipairs(items) do
-- Since players receive the results of the disenchant, we will never be
-- able to match the link that triggered the received message against
-- our list. However, we should cross disenchanted items that have been
-- assigned off the list as we find them on the assumption that they
-- would have automatically received the item anyway.
if record.choices[player] == "disenchant" and record.assigned == player and record.received == 0 then
record.received = GetTime()
-- It's ok to put in the break since each disenchanted
-- result will trigger a received message
break
end
end
end
 
-- This could be done in one of the other loops, but since I live with
-- pedantic man, we will do this as a separate scan
if WATCH_ITEM_BEING_ROLLED_ON then
local itemsStillBeingRolledOn = 0
for _, record in ipairs(items) do
if record.received == 0 then
itemsStillBeingRolledOn = itemsStillBeingRolledOn + 1
end
end
 
if itemsStillBeingRolledOn == 0 then
WATCH_ITEM_BEING_ROLLED_ON = false
self:RefreshTooltip()
end
end
 
self:UpdateReport()
end
 
function NeedyGreedy:ClearItems()
wipe(items)
wipe(nameList)
self:RefreshTooltip()
self:Print(L["All items have been cleared."])
end
 
 
 
-- Tooltip Information Formatting
function NeedyGreedy:PageLeft()
report.firstItem = report.firstItem - self.db.profile.nItems
if report.firstItem < 1 then
report.firstItem = 1
end
self:UpdateReport()
end
 
function NeedyGreedy:PageRight()
local count = #items
report.firstItem = report.firstItem + self.db.profile.nItems
if count == 0 then
report.firstItem = 1
elseif report.firstItem > count then
report.firstItem = count
end
self:UpdateReport()
end
 
function NeedyGreedy:GetSortedPlayers()
local list = {}
 
if GetNumRaidMembers() > 0 then
for i = 1,MAX_RAID_MEMBERS do
name = GetRaidRosterInfo(i)
if name then
if not (nameList[name]) and (name ~= UNKNKOWN) then nameList[name] = name end
end
end
else
for _, unit in ipairs({"player", "party1", "party2", "party3", "party4"}) do
local name = UnitName(unit)
if name then
if not (nameList[name]) and (name ~= UNKNKOWN) then nameList[name] = name end
end
end
end
 
if not self.db.profile.showGroupOnly then
for _, item in ipairs(items) do
for name, _ in pairs(item.choices) do
if not nameList[name] then nameList[name] = name end
end
end
end
 
for name, _ in pairs(nameList) do
table.insert(list, name)
end
 
table.sort(list)
return list
end
 
function NeedyGreedy:GetNumPlayers()
local nraid = GetNumRaidMembers()
if nraid > 0 then
return nraid
else
return GetNumPartyMembers() + 1
end
end
 
function NeedyGreedy:ColorizeName(name)
local _, class = UnitClass(name)
local color
 
if class then
color = RAID_CLASS_COLORS[class]
color = string.format("\124cff%.2x%.2x%.2x", color.r*255, color.g*255, color.b*255)
end
if not color then
color = GRAY_FONT_COLOR_CODE
end
return color .. name .. "|r"
end
 
function NeedyGreedy:ChoiceText(choice)
local style = "string"
if self.db.profile.displayIcons == true then style = "icon" end
 
if choice then
if NEEDYGREEDY_CHOICE[choice][style] then
return NEEDYGREEDY_CHOICE[choice][style]
end
end
return ""
end
 
function NeedyGreedy:RollText(number)
if number then
return " - " .. number
else
return ""
end
end
 
function NeedyGreedy:AssignedText(item)
if item.received == 0 then
return "|c00FF0000" .. item.assigned .. "|r"
else
return "|c0000FF00" .. item.assigned .. "|r"
end
end
 
function NeedyGreedy:ExpireItems()
local now = GetTime()
local update = false
local displayTimeOut = true
local padding = 60
 
for rollid, record in ipairs(items) do
if record.rollTimeOut and record.rollTimeOut > 0 and now < record.rollTimeOut + padding and WATCH_ITEM_BEING_ROLLED_ON then
displayTimeOut = false
end
 
if self.db.profile.expiry ~= 0 then
if record.received > 0 and now - record.received >= self.db.profile.expiry * 60 then
table.remove(items, rollid)
wipe(nameList)
update = true
end
end
end
 
if displayTimeOut and WATCH_ITEM_BEING_ROLLED_ON then
WATCH_ITEM_BEING_ROLLED_ON = false
self:RefreshTooltip()
end
 
if update then
self:UpdateReport()
end
end
 
local CONVERTED_FORMATS = {}
function NeedyGreedy:unformat(fmt, msg)
local pattern, captureIndices
if CONVERTED_FORMATS[fmt] then
pattern, captureIndices = unpack(CONVERTED_FORMATS[fmt])
else
pattern, captureIndices = patternFromFormat(fmt)
CONVERTED_FORMATS[fmt] = {pattern, captureIndices}
end
 
local _, _, a1, a2, a3, a4 = superFind(msg, pattern, captureIndices)
return a1, a2, a3, a4
end
 
 
 
-- Config option getters and setters
function NeedyGreedy:GetNItems(info)
return self.db.profile.nItems
end
 
function NeedyGreedy:SetNItems(info, nItems)
self.db.profile.nItems = nItems
self:RefreshTooltip()
end
 
function NeedyGreedy:GetExpiry(info)
return self.db.profile.expiry
end
 
function NeedyGreedy:SetExpiry(info, expiry)
self.db.profile.expiry = expiry
self:ExpireItems()
end
 
function NeedyGreedy:GetQuality(info)
return self.db.profile.quality
end
 
function NeedyGreedy:SetQuality(info, quality)
self.db.profile.quality = quality
end
 
function NeedyGreedy:GetDisplayIcons(info)
return self.db.profile.displayIcons
end
 
function NeedyGreedy:SetDisplayIcons(info, displayIcons)
self.db.profile.displayIcons = displayIcons
self:UpdateReport()
end
 
function NeedyGreedy:GetDetachedTooltip(info)
return self.db.profile.detachedTooltip
end
 
function NeedyGreedy:SetDetachedTooltip(info, detachedTooltip)
self.db.profile.detachedTooltip = detachedTooltip
self:HideDBTooltip()
if self.db.profile.detachedTooltip then
self.db.profile.displayStatus = true
if self:CheckDisplayOptions() then
self:ShowDetachedTooltip()
end
else
self.db.profile.displayStatus = false
self:HideDetachedTooltip()
-- Return to page one
report.firstItem = 1
end
end
 
function NeedyGreedy:GetDisplayTextLink(info)
return self.db.profile.displayTextLink
end
 
function NeedyGreedy:SetDisplayTextLink(info, displayTextLink)
self.db.profile.displayTextLink = displayTextLink
self:UpdateReport()
end
 
function NeedyGreedy:GetHideMinimapIcon(info)
return not self.db.profile.minimap.hide
end
 
function NeedyGreedy:SetHideMinimapIcon(info, hideMinimapIcon)
self.db.profile.minimap.hide = not hideMinimapIcon
if self.db.profile.minimap.hide then
ngDBIcon:Hide("NeedyGreedy")
else
ngDBIcon:Show("NeedyGreedy")
end
end
 
function NeedyGreedy:GetFilterLootMsgs(info)
return self.db.profile.filterLootMsgs
end
 
function NeedyGreedy:SetFilterLootMsgs(info, filterLootMsgs)
self.db.profile.filterLootMsgs = filterLootMsgs
if self.db.profile.filterLootMsgs then
self:EnableChatFilter()
else
self:DisableChatFilter()
end
end
 
function NeedyGreedy:GetShowOnParty(info)
return self.db.profile.showOnParty
end
 
function NeedyGreedy:SetShowOnParty(info, showOnParty)
self.db.profile.showOnParty = showOnParty
end
 
function NeedyGreedy:GetHideInCombat(info)
return self.db.profile.hideInCombat
end
 
function NeedyGreedy:SetHideInCombat(info, hideInCombat)
self.db.profile.hideInCombat = hideInCombat
self:RefreshTooltip()
end
 
function NeedyGreedy:GetShowGroupOnly(info)
return self.db.profile.showGroupOnly
end
 
function NeedyGreedy:SetShowGroupOnly(info, showGroupOnly)
self.db.profile.showGroupOnly = showGroupOnly
wipe(nameList)
self:RefreshTooltip()
end
 
function NeedyGreedy:GetAutoPopUp(info)
return self.db.profile.autoPopUp
end
 
function NeedyGreedy:SetAutoPopUp(info, autoPopUp)
self.db.profile.autoPopUp = autoPopUp
self:RefreshTooltip()
end
 
function NeedyGreedy:GetResetInNewParty(info)
return self.db.profile.resetInNewParty
end
 
function NeedyGreedy:SetResetInNewParty(info, resetInNewParty)
self.db.profile.resetInNewParty = resetInNewParty
end
 
function NeedyGreedy:GetResetInNewInstance(info)
return self.db.profile.resetInNewInstance
end
 
function NeedyGreedy:SetResetInNewInstance(info, resetInNewInstance)
self.db.profile.resetInNewInstance = resetInNewInstance
end
 
function NeedyGreedy:GetTooltipScale(info)
return self.db.profile.tooltipScale
end
 
function NeedyGreedy:SetTooltipScale(info, tooltipScale)
self.db.profile.tooltipScale = tooltipScale
self:RefreshTooltip()
end
 
function NeedyGreedy:GetLockTooltip(info)
return self.db.profile.lockTooltip
end
 
function NeedyGreedy:SetLockTooltip(info, lockTooltip)
self.db.profile.lockTooltip = lockTooltip
self:RefreshTooltip()
end
 
function NeedyGreedy:GetSuppressInRaid(info)
return self.db.profile.suppressInRaid
end
 
function NeedyGreedy:SetSuppressInRaid(info, suppressInRaid)
self.db.profile.suppressInRaid = suppressInRaid
self:RefreshTooltip()
end
 
 
 
-- QTip Frames
local LibQTip = LibStub('LibQTip-1.0')
local COL_MIN_WIDTH = 60
 
-- Special cell provider for displaying item icons
local ItemCell, ItemCell_Prototype = LibQTip:CreateCellProvider()
function ItemCell_Prototype:InitializeCell()
local ItemCellHeight = 30
local IconHeight = 25
 
self:SetHeight(ItemCellHeight)
self:SetWidth(COL_MIN_WIDTH)
 
if not self.ItemDetailsBorder then
self.ItemDetailsBorder = self:CreateTexture(nil, 'ARTWORK')
end
 
self.ItemDetailsBorder:SetTexture(nil)
self.ItemDetailsBorder:SetAlpha(1)
self.ItemDetailsBorder:SetHeight(ItemCellHeight)
self.ItemDetailsBorder:SetWidth(ItemCellHeight)
self.ItemDetailsBorder:SetPoint("CENTER", self, "CENTER")
 
if not self.ItemDetails then
self.ItemDetails = self:CreateTexture(nil,"OVERLAY")
end
 
self.ItemDetails:SetTexture(nil)
self.ItemDetails:SetHeight(IconHeight)
self.ItemDetails:SetWidth(IconHeight)
self.ItemDetails:SetPoint("CENTER", self.ItemDetailsBorder, "CENTER")
 
end
 
function ItemCell_Prototype:SetupCell(tooltip, value, justification, font, args)
local icon, quality = unpack(value)
self.ItemDetails:SetTexture(icon)
 
if quality then
local color = {r, g, b, hex}
color.r, color.g, color.b, color.hex = GetItemQualityColor(quality)
self.ItemDetailsBorder:SetTexture(color.r, color.g, color.b)
else
self.ItemDetailsBorder:SetTexture(nil)
end
 
self.ItemDetailsBorder:Show()
 
return self:GetWidth(), self:GetHeight()
end
 
-- Create functions locally to reduce garbage collection
local function Detached_OnMouseDown()
NeedyGreedy.detachedTooltip:StartMoving()
end
 
local function Detached_OnMouseUp()
-- Make it remember
local tooltip = NeedyGreedy.detachedTooltip
local pos = NeedyGreedy.db.profile.reportFramePos
 
tooltip:StopMovingOrSizing()
 
local anchor1, _, anchor2, x, y = tooltip:GetPoint()
 
pos.anchor1 = anchor1
pos.anchor2 = anchor2
pos.x = x
pos.y = y
end
 
-- Detachable tooltip
function NeedyGreedy:ShowDetachedTooltip()
 
-- Acquire a tooltip
if not LibQTip:IsAcquired("NeedyGreedyReport") then
self.detachedTooltip = LibQTip:Acquire("NeedyGreedyReport", 1, "LEFT")
self.detachedTooltip:SetScale(self.db.profile.tooltipScale)
 
-- Add columns here because tooltip:Clear() preserves columns
for i = 1, self.db.profile.nItems do
self.detachedTooltip:AddColumn("LEFT")
end
 
-- Add two columns for left and right buttons if detached
if self.db.profile.detachedTooltip then
self.detachedTooltip:AddColumn("LEFT")
end
 
-- Fill in the info
self:BuildDetachedTooltip(self.detachedTooltip)
 
if self.db.profile.detachedTooltip then
-- To make tooltip detached
self.detachedTooltip:ClearAllPoints()
self.detachedTooltip:SetFrameStrata("FULLSCREEN")
self.detachedTooltip:EnableMouse(true)
self.detachedTooltip:SetResizable(true)
self.detachedTooltip:SetFrameLevel(1)
self.detachedTooltip:SetMovable(true)
self.detachedTooltip:SetClampedToScreen(true)
 
if not self.db.profile.reportFramePos then
self.db.profile.reportFramePos = {
anchor1 = "CENTER",
anchor2 = "CENTER",
x = 0,
y = 0
}
end
self.detachedTooltip:SetPoint(self.db.profile.reportFramePos.anchor1, nil, self.db.profile.reportFramePos.anchor2,
self.db.profile.reportFramePos.x, self.db.profile.reportFramePos.y)
 
-- Make it move !
if not self.db.profile.lockTooltip then
self.detachedTooltip:SetScript("OnMouseDown", Detached_OnMouseDown)
self.detachedTooltip:SetScript("OnMouseUp", Detached_OnMouseUp)
end
end
end
 
-- Show it, et voilà !
self.detachedTooltip:Show()
end
 
function NeedyGreedy:HideDetachedTooltip()
if self.detachedTooltip then
self.detachedTooltip:Hide()
self.detachedTooltip:SetScript("OnMouseDown", nil)
self.detachedTooltip:SetScript("OnMouseUp", nil)
self.detachedTooltip:SetScale(1)
LibQTip:Release(self.detachedTooltip)
self.detachedTooltip = nil
end
end
 
function NeedyGreedy:ShowDBTooltip(frame)
-- Acquire a tooltip
if not LibQTip:IsAcquired("NeedyGreedyDBReport") then
self.dbTooltip = LibQTip:Acquire("NeedyGreedyDBReport", 1, "LEFT")
 
if not self.db.profile.detachedTooltip then
self.dbTooltip:SetAutoHideDelay(0.25, frame)
-- Add columns here because tooltip:Clear() preserves columns
for i = 1, self.db.profile.nItems do
self.dbTooltip:AddColumn("LEFT")
end
 
-- Extra column for the pager arrow
self.dbTooltip:AddColumn("LEFT")
 
-- Fill in the info
self:BuildDBReportTooltip(self.dbTooltip)
else
 
self:AddHeaderText(self.dbTooltip)
self:AddInfoText(self.dbTooltip)
end
 
if frame then self.dbTooltip:SmartAnchorTo(frame) end
end
 
-- Show it, et voilà !
self.dbTooltip:Show()
end
 
function NeedyGreedy:HideDBTooltip()
if self.dbTooltip then
self.dbTooltip:Hide()
LibQTip:Release(self.dbTooltip)
self.dbTooltip = nil
end
end
 
function NeedyGreedy:PopulateReportTooltip(tooltip)
local nItems = self.db.profile.nItems
local players = self:GetSortedPlayers()
 
-- For sizing the columns
local fontString = tooltip:CreateFontString()
fontString:SetFontObject(tooltip:GetFont())
local minWidth = 0
for _, name in ipairs(players) do
fontString:SetText(name)
local fontWidth = fontString:GetStringWidth()
minWidth = max(fontWidth, minWidth)
end
 
-- Verify that report.firstItem is set reasonably
local count = #items
 
if not(report.firstItem) then report.firstItem = 1 end
if count == 0 then
report.firstItem = 1
elseif report.firstItem > count then
report.firstItem = count
end
 
-- Create icon headers
local headerline, _ = tooltip:AddLine("")
for i = 1, nItems do
local index = #items - (report.firstItem + i - 2)
local texture = ""
local item = nil
if index >= 1 then
item = items[index]
end
 
-- Placeholder icons
tooltip:SetCell(headerline, i + 1, "", nil, nil, nil, nil , nil, nil, nil, minWidth)
 
if item then
-- Color surrounding cell according to item rarity
local _, _, quality = GetItemInfo(item.itemID)
tooltip:SetCell(headerline, i + 1, {item.texture, quality}, nil, nil, nil, ItemCell , nil, nil, nil, minWidth)
 
tooltip:SetCellScript(headerline, i + 1, "OnEnter", function()
GameTooltip:SetOwner(tooltip, "ANCHOR_RIGHT")
GameTooltip:SetHyperlink(item.link)
end )
tooltip:SetCellScript(headerline, i + 1, "OnMouseUp", function()
if IsShiftKeyDown() then
ChatEdit_InsertLink(item.link)
end
end )
tooltip:SetCellScript(headerline, i + 1, "OnLeave", function()
GameTooltip:Hide()
end )
end
end
 
-- Now add item link names
if self.db.profile.displayTextLink then
headerline, _ = tooltip:AddLine("")
for i = 1, nItems do
local index = #items - (report.firstItem + i - 2)
local text = ""
local item = nil
if index >= 1 then
item = items[index]
text = item.link
end
tooltip:SetCell(headerline, i + 1, text, nil, nil, nil, nil, nil, nil, nil, 60)
if item then
tooltip:SetCellScript(headerline, i + 1, "OnEnter", function()
GameTooltip:SetOwner(tooltip, "ANCHOR_RIGHT")
GameTooltip:SetHyperlink(item.link)
end )
tooltip:SetCellScript(headerline, i + 1, "OnMouseUp", function()
if IsShiftKeyDown() then
ChatEdit_InsertLink(item.link)
end
end )
tooltip:SetCellScript(headerline, i + 1, "OnLeave", function()
GameTooltip:Hide()
end )
end
end
end
 
tooltip:AddLine("")
 
-- Create table with party names and their rolls
for i, name in ipairs(players) do
local partyLine = tooltip:AddLine("")
tooltip:SetCell(partyLine, 1, self:ColorizeName(name) .. " " .. (self.db.profile.displayIcons and BLANK_ICON or ""), nil, "LEFT", nil, nil, nil, nil, nil, minWidth)
 
for i = 1, nItems do
local index = #items - (report.firstItem + i - 2)
if index >= 1 then
local item = items[index]
tooltip:SetCell(partyLine, i + 1, self:ChoiceText(item.choices[name]) .. self:RollText(item.rolls[name]), nil, "LEFT", nil, nil, nil, nil, nil, minWidth)
end
end
end
 
tooltip:AddSeparator()
 
-- Display winner
local winnerTable = {yC .. "Winner|r"}
for i = 1, nItems do
local index = #items - (report.firstItem + i - 2)
if index >= 1 then
local item = items[index]
table.insert(winnerTable, self:AssignedText(item))
end
end
tooltip:AddLine(unpack(winnerTable))
end
 
function NeedyGreedy:AddHeaderText(tooltip)
local headerText = yC .. "NeedyGreedy|r"
local lineNum = tooltip:AddLine("")
tooltip:SetCell(lineNum, 1, headerText, tooltip:GetHeaderFont(), tooltip:GetColumnCount() - 1)
 
if self.detachedTooltip and tooltip == self.detachedTooltip then
tooltip:SetCell(lineNum, tooltip:GetColumnCount(), CLOSE_ICON)
tooltip:SetCellScript(lineNum, tooltip:GetColumnCount(),"OnMouseUp", function() self:ToggleDisplay() end)
end
 
tooltip:AddLine("")
end
 
function NeedyGreedy:AddPagerArrows(tooltip)
local nItems = self.db.profile.nItems
local count = #items
 
local lineNum, _ = tooltip:AddLine("")
local colNum = nItems + 1
 
if report.firstItem > 1 then
tooltip:SetCell(lineNum, colNum, PAGER_ICONS.leftUp, nil, "RIGHT")
tooltip:SetCellScript(lineNum, colNum, "OnMouseUp", function() self:PageLeft() end)
else
tooltip:SetCell(lineNum, colNum, PAGER_ICONS.leftDisabled, nil, "RIGHT")
end
 
if report.firstItem + nItems - 1 < count then
tooltip:SetCell(lineNum, colNum + 1, PAGER_ICONS.rightUp)
tooltip:SetCellScript(lineNum, colNum + 1, "OnMouseUp", function() self:PageRight() end)
else
tooltip:SetCell(lineNum, colNum + 1, PAGER_ICONS.rightDisabled)
end
 
-- Set the page # text
local pageText = ""
if nItems == 1 and count > 0 then
pageText = tostring(report.firstItem)
elseif count == 0 then
pageText = ""
elseif count == 1 or report.firstItem == count then
pageText = string.format(L["%d of %d"], report.firstItem, count)
else
local lastitem = report.firstItem + nItems - 1
if (lastitem > count) then
lastitem = count
end
pageText = string.format(L["%d-%d of %d"], report.firstItem, lastitem, count)
end
 
tooltip:SetCell(lineNum, colNum - 1, yC .. pageText, nil, "RIGHT")
end
 
function NeedyGreedy:AddInfoText(tooltip)
local lineNum
local helpText
 
tooltip:AddLine("")
 
helpText = ""
if self.db.profile.detachedTooltip then
helpText = helpText .. eC .. L["Click"] .. "|r " .. gC .. L["to hide/show detached tooltip"] .. "|r\n"
end
helpText = helpText .. eC .. L["Shift-Click"] .. "|r " .. gC .. L["to attach/detach tooltip"] .. "|r\n"
helpText = helpText .. eC .. L["Alt-Click"] .. "|r " .. gC .. L["to clear item list"] .. "|r"
lineNum = tooltip:AddLine()
tooltip:SetCell(lineNum, 1, helpText, nil, tooltip:GetColumnCount())
end
 
function NeedyGreedy:BuildDetachedTooltip(tooltip)
tooltip:Clear()
self:AddHeaderText(tooltip)
self:PopulateReportTooltip(tooltip)
self:AddPagerArrows(tooltip)
end
 
function NeedyGreedy:BuildDBReportTooltip(tooltip)
tooltip:Clear()
self:AddHeaderText(tooltip)
if self:DisplayLDBTTCheck() then
self:PopulateReportTooltip(tooltip)
self:AddPagerArrows(tooltip)
end
self:AddInfoText(tooltip)
end
 
function NeedyGreedy:UpdateReport()
local tooltip = nil
if self.detachedTooltip and self.detachedTooltip:IsShown() then
self:BuildDetachedTooltip(self.detachedTooltip)
elseif self.dbTooltip and self.dbTooltip:IsShown() and (not self.db.profile.detachedTooltip) then
self:BuildDBReportTooltip(self.dbTooltip)
else
return
end
end
 
function NeedyGreedy:RefreshTooltip()
if self.db.profile.detachedTooltip and self:DisplayDetachedTTCheck() then
self:HideDetachedTooltip()
self:ShowDetachedTooltip()
else
self:HideDetachedTooltip()
end
self:HideDBTooltip()
end
 
function NeedyGreedy:ToggleDisplay()
if not self.db.profile.detachedTooltip then return end
 
-- Don't toggle display status if we can't see anything to toggle
if self.detachedTooltip and self.detachedTooltip:IsShown() then
if WATCH_ITEM_BEING_ROLLED_ON then
WATCH_ITEM_BEING_ROLLED_ON = false
end
self:HideDetachedTooltip()
self.db.profile.displayStatus = false
elseif self:CheckDisplayOptions() then
self:ShowDetachedTooltip()
self.db.profile.displayStatus = true
end
 
end
 
-- Only use this when not forcing display e.g. RefreshTooltip
function NeedyGreedy:DisplayDetachedTTCheck()
if self.db.profile.autoPopUp and WATCH_ITEM_BEING_ROLLED_ON then
return true
end
 
if not self.db.profile.displayStatus then
return false
end
 
return self:CheckDisplayOptions()
end
 
-- Use this when forcing display of detached tooltip
function NeedyGreedy:CheckDisplayOptions()
if self:CheckShowInCombat() then
return true
end
 
return false
end
 
function NeedyGreedy:CheckShowInCombat()
if self.db.profile.hideInCombat and IS_IN_COMBAT then
return false
end
 
return true
end
 
function NeedyGreedy:DisplayLDBTTCheck()
if self:CheckSuppressInRaid() then
return false
end
 
return true
end
 
function NeedyGreedy:CheckSuppressInRaid()
if IS_IN_RAID and self.db.profile.suppressInRaid then
return true
end
 
return false
end
 
 
 
 
 
-- Chat filter functions
local FILTER_CHAT_LOOT_MSGS = {
--LOOT_ROLL_ALL_PASSED,
LOOT_ROLL_DISENCHANT,
LOOT_ROLL_DISENCHANT_SELF,
LOOT_ROLL_GREED,
LOOT_ROLL_GREED_SELF,
LOOT_ROLL_NEED,
LOOT_ROLL_NEED_SELF,
LOOT_ROLL_PASSED,
LOOT_ROLL_PASSED_AUTO,
LOOT_ROLL_PASSED_AUTO_FEMALE,
LOOT_ROLL_PASSED_SELF,
LOOT_ROLL_PASSED_SELF_AUTO,
LOOT_ROLL_ROLLED_DE,
LOOT_ROLL_ROLLED_GREED,
LOOT_ROLL_ROLLED_NEED,
--LOOT_ROLL_WON,
--LOOT_ROLL_YOU_WON,
--LOOT_ITEM,
--LOOT_ITEM_MULTIPLE,
--LOOT_ITEM_PUSHED_SELF,
--LOOT_ITEM_PUSHED_SELF_MULTIPLE,
--LOOT_ITEM_SELF,
--LOOT_ITEM_SELF_MULTIPLE,
}
 
local function FilterLootMsg(ChatFrameSelf, event, ...)
local msg = arg1
for _, string in ipairs(FILTER_CHAT_LOOT_MSGS) do
local match = NeedyGreedy:unformat(string, msg)
if match then
return true
end
end
 
return false, msg, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11
end
 
function NeedyGreedy:EnableChatFilter()
ChatFrame_AddMessageEventFilter("CHAT_MSG_LOOT", FilterLootMsg)
end
 
function NeedyGreedy:DisableChatFilter()
ChatFrame_RemoveMessageEventFilter("CHAT_MSG_LOOT", FilterLootMsg)
end
 
 
 
-- Automatic enabling of detailed loot information
function NeedyGreedy:SetShowLootSpam()
local showLootSpam = GetCVar("showLootSpam") -- 0 for filtered, 1 for details
if showLootSpam == "0" then
originalSpamFilterSetting = showLootSpam
SetCVar("showLootSpam", "1")
end
end
 
function NeedyGreedy:ResetShowLootSpam()
if originalSpamFilterSetting then
SetCVar("showLootSpam", originalSpamFilterSetting)
originalSpamFilterSetting = nil
end
end
 
 
 
-- Slash Commands
function NeedyGreedy:SlashHide()
self.db.profile.detachedTooltip = true
self.db.profile.displayStatus = false
if WATCH_ITEM_BEING_ROLLED_ON then
WATCH_ITEM_BEING_ROLLED_ON = false
end
self:RefreshTooltip()
LibStub("AceConfigRegistry-3.0"):NotifyChange("NeedyGreedy")
end
 
function NeedyGreedy:SlashShow()
self.db.profile.detachedTooltip = true
self.db.profile.displayStatus = true
self:RefreshTooltip()
LibStub("AceConfigRegistry-3.0"):NotifyChange("NeedyGreedy")
end
 
function NeedyGreedy:PrintReport()
if #items == 0 then self:Print(L["Nothing to report"]) return end
local output = {}
 
for _, item in ipairs(items) do
for name, choice in pairs(item.choices) do
if not output[name] then
output[name] = {
["name"] = name,
["need"] = 0,
["greed"] = 0,
["disenchant"] = 0,
["pass"] = 0,
["assigned"] = 0,
}
end
 
for k, v in pairs(output[name]) do
if choice == k then
output[name][k] = v + 1
end
end
 
if item.assigned == name then
output[name]["assigned"] = output[name]["assigned"] + 1
end
end
end
 
local sorted = {}
for _, record in pairs(output) do
table.insert(sorted, record)
end
table.sort(sorted, function(a,b) return b.assigned < a.assigned end)
 
for _, info in ipairs(sorted) do
self:Printf("%s N:%d G:%d DE:%d P:%d Wins:%d", info.name, info.need, info.greed, info.disenchant, info.pass, info.assigned)
end
end
 
 
 
-- Profile Handling
function NeedyGreedy:RefreshProfile()
if self.db.profile.minimap.hide then
ngDBIcon:Hide("NeedyGreedy")
else
ngDBIcon:Show("NeedyGreedy")
end
 
self:RefreshTooltip()
end
 
 
 
-- Unit tests
--[[
function NeedyGreedy:SetItems(itemList)
items = itemList
self:UpdateReport()
end
 
function NeedyGreedy:GetItems()
return items
end
 
function NeedyGreedy:TestItemList()
items = {
{
["received"] = 108626.818,
["assigned"] = "Evilplaque",
["itemID"] = 36040,
["link"] = "|cff1eff00|Hitem:36040:0:0:0:0:0:-36:-2033450911:80|h[Condor Pants of the Sorcerer]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Lubov"] = "greed",
["Evilplaque"] = "greed",
["Blizzy"] = "disenchant",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Aneeka"] = "24",
["Lubov"] = "66",
["Evilplaque"] = "98",
["Blizzy"] = "52",
["Dkmonkey"] = "3",
},
["texture"] = "Interface\\Icons\\INV_Pants_Cloth_10",
}, -- [6]
{
["received"] = 109046.237,
["assigned"] = "Lubov",
["itemID"] = 50228,
["link"] = "|cffa335ee|Hitem:50228:0:0:0:0:0:0:1749772928:80|h[Barbed Ymirheim Choker]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Blizzy"] = "disenchant",
["Evilplaque"] = "disenchant",
["Lubov"] = "need",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Lubov"] = "17",
},
["texture"] = "Interface\\Icons\\INV_Jewelry_Necklace_22",
}, -- [7]
{
["received"] = 109223.287,
["assigned"] = "Lubov",
["itemID"] = 36260,
["link"] = "|cff1eff00|Hitem:36260:0:0:0:0:0:-40:-1617756088:80|h[Cormorant Footwraps of the Bandit]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Blizzy"] = "disenchant",
["Evilplaque"] = "greed",
["Lubov"] = "greed",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Aneeka"] = "61",
["Blizzy"] = "54",
["Evilplaque"] = "50",
["Lubov"] = "87",
["Dkmonkey"] = "1",
},
["texture"] = "Interface\\Icons\\INV_Boots_Chain_07",
}, -- [8]
{
["received"] = 109267.102,
["assigned"] = "Dkmonkey",
["itemID"] = 50319,
["link"] = "|cffa335ee|Hitem:50319:0:0:0:0:0:0:459549600:80|h[Unsharpened Ice Razor]|h|r",
["choices"] = {
["Aneeka"] = "disenchant",
["Lubov"] = "disenchant",
["Evilplaque"] = "disenchant",
["Blizzy"] = "disenchant",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Aneeka"] = "69",
["Lubov"] = "28",
["Evilplaque"] = "30",
["Blizzy"] = "21",
["Dkmonkey"] = "80",
},
["texture"] = "Interface\\Icons\\inv_weapon_shortblade_61",
}, -- [9]
{
["received"] = 109483.031,
["assigned"] = "Dkmonkey",
["itemID"] = 50262,
["link"] = "|cffa335ee|Hitem:50262:0:0:0:0:0:0:305102456:80|h[Felglacier Bolter]|h|r",
["choices"] = {
["Aneeka"] = "disenchant",
["Blizzy"] = "disenchant",
["Evilplaque"] = "disenchant",
["Lubov"] = "disenchant",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Aneeka"] = "9",
["Lubov"] = "40",
["Evilplaque"] = "69",
["Blizzy"] = "45",
["Dkmonkey"] = "77",
},
["texture"] = "Interface\\Icons\\inv_weapon_crossbow_30",
}, -- [10]
{
["received"] = 109746.236,
["assigned"] = "Blizzy",
["itemID"] = 37780,
["link"] = "|cff0070dd|Hitem:37780:0:0:0:0:0:0:1986751616:80|h[Condor-Bone Chestguard]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Blizzy"] = "disenchant",
["Evilplaque"] = "greed",
["Lubov"] = "greed",
["Dkmonkey"] = "greed",
},
["rolls"] = {
["Aneeka"] = "14",
["Lubov"] = "22",
["Evilplaque"] = "72",
["Blizzy"] = "77",
["Dkmonkey"] = "62",
},
["texture"] = "Interface\\Icons\\INV_Chest_Chain_14",
}, -- [11]
{
["received"] = 110173.528,
["assigned"] = "Lubov",
["itemID"] = 50272,
["link"] = "|cffa335ee|Hitem:50272:0:0:0:0:0:0:349262944:80|h[Frost Wyrm Ribcage]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Blizzy"] = "disenchant",
["Evilplaque"] = "disenchant",
["Lubov"] = "need",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Lubov"] = "2",
},
["texture"] = "Interface\\Icons\\inv_chest_plate23",
}, -- [12]
{
["received"] = 110155.978,
["assigned"] = "Lubov",
["itemID"] = 50285,
["link"] = "|cffa335ee|Hitem:50285:0:0:0:0:0:0:617698400:80|h[Icebound Bronze Cuirass]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Blizzy"] = "disenchant",
["Evilplaque"] = "disenchant",
["Lubov"] = "need",
["Dkmonkey"] = "disenchant",
},
["rolls"] = {
["Lubov"] = "25",
},
["texture"] = "Interface\\Icons\\inv_chest_plate23",
}, -- [13]
{
["received"] = 110154.673,
["assigned"] = "Evilplaque",
["itemID"] = 43102,
["link"] = "|cff0070dd|Hitem:43102:0:0:0:0:0:0:1423004768:80|h[Frozen Orb]|h|r",
["choices"] = {
["Aneeka"] = "greed",
["Lubov"] = "greed",
["Evilplaque"] = "greed",
["Blizzy"] = "greed",
["Dkmonkey"] = "greed",
},
["rolls"] = {
["Aneeka"] = "83",
["Blizzy"] = "96",
["Evilplaque"] = "96",
["Lubov"] = "60",
["Dkmonkey"] = "15",
},
["texture"] = "Interface\\Icons\\Spell_Frost_FrozenCore",
}, -- [14]
}
self:RefreshTooltip()
end
--]]
 
-- /dump NeedyGreedy:TestSuperFind()
--[[
function NeedyGreedy:TestSuperFind()
do
local pattern, captureIndices = patternFromFormat("%s automatically passed on: %s because he cannot loot that item.")
DevTools_Dump({pattern, captureIndices})
DevTools_Dump({superFind("bob automatically passed on: [Tuxedo Jacket] because he cannot loot that item.", pattern, captureIndices)})
end
 
do
local pattern, captureIndices = patternFromFormat("%1$s gewinnt: %3$s |cff818181(Gier - %2$d)|r")
DevTools_Dump({pattern, captureIndices})
DevTools_Dump({superFind("bob gewinnt: [Tuxedo Jacket] |cff818181(Gier - 123)|r", pattern, captureIndices)})
end
 
--DevTools_Dump()
 
end
]]
1.2.5/Localization/enUS.lua New file
0,0 → 1,64
local L = LibStub("AceLocale-3.0"):NewLocale("NeedyGreedy", "enUS", true)
 
if L then
 
L["NeedyGreedy"] = true
L["Displays a table of items and the roll choices players have made on them"] = true
L["Display Items"] = true
L["Number of item columns in the display window"] = true
L["Expiry Time"] = true
L["Minutes after item is received before it is removed from display (0 = forever)"] = true
L["Minimum Quality"] = true
L["Minimum quality of item to be displayed"] = true
L["Graphical Display"] = true
L["Display icons for rolls types instead of text"] = true
L["Detach Tooltip"] = true
L["Display the roll information in a standalone window"] = true
L["Item Names"] = true
L["Toggle the display of the item name in the header"] = true
L["%d of %d"] = true
L["%d-%d of %d"] = true
L["Click"] = true
L["to hide/show detached tooltip"] = true
L["Minimap Icon"] = true
L["Toggle the display of the minimap icon"] = true
L["Shift-Click"] = true
L["to attach/detach tooltip"] = true
L["Filter Loot Messages"] = true
L["Enable filtering of loot roll messages"] = true
L["Alt-Click"] = true
L["to clear item list"] = true
L["General"] = true
L["Profile"] = true
L["Show in party"] = true
L["Display the detached window when joining a party and hide the tooltip when leaving a party"] = true
L["You are not in a party"] = true
L["Hide in combat"] = true
L["Only display the detached window when not in combat"] = true
L["Hide Non-Members"] = true
L["Only display the names of members currently in your party"] = true
L["Valid commands are: config, report, reset"] = true
L["Nothing to report"] = true
L["Popup when rolling"] = true
L["Automatically show the detached tooltip when an item is being rolled on"] = true
L["Reset on Join Party"] = true
L["Clear the item list when joining a new group"] = true
L["Do you wish to reset NeedyGreedy?"] = true
L["All items have been cleared."] = true
L["Reset in Instance"] = true
L["Clear the item list when entering an instance"] = true
L["Open the configuration menu"] = true
L["Hide the detached tooltip"] = true
L["Generate a text summary"] = true
L["Reset the item list"] = true
L["Show the detached tooltip"] = true
L["Scale"] = true
L["Adjust the scale of the detached tooltip"] = true
L["Detached Tooltip"] = true
L["Lock Tooltip"] = true
L["Adjust the position of the detached tooltip"] = true
L["DataBroker Tooltip"] = true
L["Hide In Raid"] = true
L["Suppress the display of the LibDataBroker tooltip when in a raid"] = true
 
end
1.2.5/NeedyGreedy.toc New file
0,0 → 1,13
## Interface: 30300
## Title: NeedyGreedy
## Notes: Displays who has rolled need/greed/pass on what loot items
## Version: 1.2.5
## Author: lokyst, Marco
## SavedVariables: NeedyGreedyDB
## OptionalDeps:
 
embeds.xml
 
Localization\enUS.lua
 
NeedyGreedy.lua
1.2.5/libs/LibDataBroker-1.1/README.textile New file
0,0 → 1,13
LibDataBroker is a small WoW addon library designed to provide a "MVC":http://en.wikipedia.org/wiki/Model-view-controller interface for use in various addons.
LDB's primary goal is to "detach" plugins for TitanPanel and FuBar from the display addon.
Plugins can provide data into a simple table, and display addons can receive callbacks to refresh their display of this data.
LDB also provides a place for addons to register "quicklaunch" functions, removing the need for authors to embed many large libraries to create minimap buttons.
Users who do not wish to be "plagued" by these buttons simply do not install an addon to render them.
 
Due to it's simple generic design, LDB can be used for any design where you wish to have an addon notified of changes to a table.
 
h2. Links
 
* "API documentation":http://github.com/tekkub/libdatabroker-1-1/wikis/api
* "Data specifications":http://github.com/tekkub/libdatabroker-1-1/wikis/data-specifications
* "Addons using LDB":http://github.com/tekkub/libdatabroker-1-1/wikis/addons-using-ldb
1.2.5/libs/LibDataBroker-1.1/LibDataBroker-1.1.lua New file
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
1.2.5/libs/LibStub/LibStub.toc New file
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
1.2.5/libs/LibStub/LibStub.lua New file
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
1.2.5/libs/AceLocale-3.0/AceLocale-3.0.xml New file
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>
\ No newline at end of file
1.2.5/libs/AceLocale-3.0/AceLocale-3.0.lua New file
0,0 → 1,128
--- **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 766 2009-04-04 08:26:05Z nevcairiel $
local MAJOR,MINOR = "AceLocale-3.0", 2
 
local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceLocale then return end -- no upgrade needed
 
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
1.2.5/libs/CallbackHandler-1.0/CallbackHandler-1.0.xml New file
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>
\ No newline at end of file
1.2.5/libs/CallbackHandler-1.0/CallbackHandler-1.0.lua New file
0,0 → 1,239
--[[ $Id: CallbackHandler-1.0.lua 3 2008-09-29 16:54:20Z nevcairiel $ ]]
local MAJOR, MINOR = "CallbackHandler-1.0", 3
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}
 
local type = type
local pcall = pcall
local pairs = pairs
local assert = assert
local concat = table.concat
local loadstring = loadstring
local next = next
local select = select
local type = type
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", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(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.
 
1.2.5/libs/AceTimer-3.0/AceTimer-3.0.xml New file
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="AceTimer-3.0.lua"/>
</Ui>
\ No newline at end of file
1.2.5/libs/AceTimer-3.0/AceTimer-3.0.lua New file
0,0 → 1,467
--- **AceTimer-3.0** provides a central facility for registering timers.
-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered, rescheduled
-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
-- AceTimer is currently limited to firing timers at a frequency of 0.1s. This constant may change
-- in the future, but for now it seemed like a good compromise in efficiency and accuracy.
--
-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
-- need to cancel or reschedule the timer you just registered.
--
-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer: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 AceTimer itself.\\
-- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you
-- make into AceTimer.
-- @class file
-- @name AceTimer-3.0
-- @release $Id: AceTimer-3.0.lua 769 2009-04-04 11:05:08Z nevcairiel $
 
--[[
Basic assumptions:
* In a typical system, we do more re-scheduling per second than there are timer pulses per second
* Regardless of timer implementation, we cannot guarantee timely delivery due to FPS restriction (may be as low as 10)
 
This implementation:
CON: The smallest timer interval is constrained by HZ (currently 1/10s).
PRO: It will still correctly fire any timer slower than HZ over a length of time, e.g. 0.11s interval -> 90 times over 10 seconds
PRO: In lag bursts, the system simly skips missed timer intervals to decrease load
CON: Algorithms depending on a timer firing "N times per minute" will fail
PRO: (Re-)scheduling is O(1) with a VERY small constant. It's a simple linked list insertion in a hash bucket.
CAUTION: The BUCKETS constant constrains how many timers can be efficiently handled. With too many hash collisions, performance will decrease.
 
Major assumptions upheld:
- ALLOWS scheduling multiple timers with the same funcref/method
- ALLOWS scheduling more timers during OnUpdate processing
- ALLOWS unscheduling ANY timer (including the current running one) at any time, including during OnUpdate processing
]]
 
local MAJOR, MINOR = "AceTimer-3.0", 5
local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceTimer then return end -- No upgrade needed
 
AceTimer.hash = AceTimer.hash or {} -- Array of [0..BUCKET-1] = linked list of timers (using .next member)
-- Linked list gets around ACE-88 and ACE-90.
AceTimer.selfs = AceTimer.selfs or {} -- Array of [self]={[handle]=timerobj, [handle2]=timerobj2, ...}
AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame")
 
local type = type
local next = next
local pairs = pairs
local select = select
local tostring = tostring
local floor = floor
local max = max
 
-- Simple ONE-SHOT timer cache. Much more efficient than a full compost for our purposes.
local timerCache = nil
 
--[[
Timers will not be fired more often than HZ-1 times per second.
Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999)
If this is ever LOWERED, all existing timers need to be enforced to have a delay >= 1/HZ on lib upgrade.
If this number is ever changed, all entries need to be rehashed on lib upgrade.
]]
local HZ = 11
 
--[[
Prime for good distribution
If this number is ever changed, all entries need to be rehashed on lib upgrade.
]]
local BUCKETS = 131
 
local hash = AceTimer.hash
for i=1,BUCKETS do
hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes
end
 
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ... -- our arguments are received as unnamed values in "..." since we don't have a proper function declaration
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", table.concat(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
 
local lastint = floor(GetTime() * HZ)
 
-- --------------------------------------------------------------------
-- OnUpdate handler
--
-- traverse buckets, always chasing "now", and fire timers that have expired
 
local function OnUpdate()
local now = GetTime()
local nowint = floor(now * HZ)
 
-- Have we passed into a new hash bucket?
if nowint == lastint then return end
 
local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2
 
-- Pass through each bucket at most once
-- Happens on e.g. instance loads, but COULD happen on high local load situations also
for curint = (max(lastint, nowint - BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteration
local curbucket = (curint % BUCKETS)+1
-- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
local nexttimer = hash[curbucket]
hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
 
while nexttimer do
local timer = nexttimer
nexttimer = timer.next
local when = timer.when
 
if when < soon then
-- Call the timer func, either as a method on given object, or a straight function ref
local callback = timer.callback
if type(callback) == "string" then
safecall(timer.object[callback], timer.object, timer.arg)
elseif callback then
safecall(callback, timer.arg)
else
-- probably nilled out by CancelTimer
timer.delay = nil -- don't reschedule it
end
 
local delay = timer.delay -- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback
 
if not delay then
-- single-shot timer (or cancelled)
AceTimer.selfs[timer.object][tostring(timer)] = nil
timerCache = timer
else
-- repeating timer
local newtime = when + delay
if newtime < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
newtime = now + delay
end
timer.when = newtime
 
-- add next timer execution to the correct bucket
local bucket = (floor(newtime * HZ) % BUCKETS) + 1
timer.next = hash[bucket]
hash[bucket] = timer
end
else -- if when>=soon
-- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
timer.next = hash[curbucket]
hash[curbucket] = timer
end -- if when<soon ... else
end -- while nexttimer do
end -- for curint=lastint,nowint
 
lastint = nowint
end
 
-- ---------------------------------------------------------------------
-- Reg( callback, delay, arg, repeating )
--
-- callback( function or string ) - direct function ref or method name in our object for the callback
-- delay(int) - delay for the timer
-- arg(variant) - any argument to be passed to the callback function
-- repeating(boolean) - repeating timer, or oneshot
--
-- returns the handle of the timer for later processing (canceling etc)
local function Reg(self, callback, delay, arg, repeating)
if type(callback) ~= "string" and type(callback) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(callback, delay, arg): 'callback' - function or method name expected.", 3)
end
if type(callback) == "string" then
if type(self)~="table" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'self' - must be a table.", 3)
end
if type(self[callback]) ~= "function" then
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'methodName' - method not found on target object.", 3)
end
end
 
if delay < (1 / (HZ - 1)) then
delay = 1 / (HZ - 1)
end
 
-- Create and stuff timer in the correct hash bucket
local now = GetTime()
 
local timer = timerCache or {} -- Get new timer object (from cache if available)
timerCache = nil
 
timer.object = self
timer.callback = callback
timer.delay = (repeating and delay)
timer.arg = arg
timer.when = now + delay
 
local bucket = (floor((now+delay)*HZ) % BUCKETS) + 1
timer.next = hash[bucket]
hash[bucket] = timer
 
-- Insert timer in our self->handle->timer registry
local handle = tostring(timer)
 
local selftimers = AceTimer.selfs[self]
if not selftimers then
selftimers = {}
AceTimer.selfs[self] = selftimers
end
selftimers[handle] = timer
selftimers.__ops = (selftimers.__ops or 0) + 1
 
return handle
end
 
--- Schedule a new one-shot timer.
-- The timer will fire once in `delay` seconds, unless canceled before.
-- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds.
-- @param arg An optional argument to be passed to the callback function.
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
--
-- function MyAddon:OnEnable()
-- self:ScheduleTimer("TimerFeedback", 5)
-- end
--
-- function MyAddon:TimerFeedback()
-- print("5 seconds passed")
-- end
function AceTimer:ScheduleTimer(callback, delay, arg)
return Reg(self, callback, delay, arg)
end
 
--- Schedule a repeating timer.
-- The timer will fire every `delay` seconds, until canceled.
-- @param callback Callback function for the timer pulse (funcref or method name).
-- @param delay Delay for the timer, in seconds.
-- @param arg An optional argument to be passed to the callback function.
-- @usage
-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
--
-- function MyAddon:OnEnable()
-- self.timerCount = 0
-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
-- end
--
-- function MyAddon:TimerFeedback()
-- self.timerCount = self.timerCount + 1
-- print(("%d seconds passed"):format(5 * self.timerCount))
-- -- run 30 seconds in total
-- if self.timerCount == 6 then
-- self:CancelTimer(self.testTimer)
-- end
-- end
function AceTimer:ScheduleRepeatingTimer(callback, delay, arg)
return Reg(self, callback, delay, arg, true)
end
 
--- Cancels a timer with the given handle, registered by the same addon object as used for `:ScheduleTimer`
-- Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid
-- and the timer has not fired yet or was canceled before.
-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @param silent If true, no error is raised if the timer handle is invalid (expired or already canceled)
-- @return True if the timer was successfully cancelled.
function AceTimer:CancelTimer(handle, silent)
if not handle then return end -- nil handle -> bail out without erroring
if type(handle) ~= "string" then
error(MAJOR..": CancelTimer(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if silent then
if timer then
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
-- The timer object is removed in the OnUpdate loop
end
return not not timer -- might return "true" even if we double-cancel. we'll live.
else
if not timer then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - no such timer registered")
return false
end
if not timer.callback then
geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - timer already cancelled or expired")
return false
end
timer.callback = nil -- don't run it again
timer.delay = nil -- if this is the currently-executing one: don't even reschedule
return true
end
end
 
--- Cancels all timers registered to the current addon object ('self')
function AceTimer:CancelAllTimers()
if not(type(self) == "string" or type(self) == "table") then
error(MAJOR..": CancelAllTimers(): 'self' - must be a string or a table",2)
end
if self == AceTimer then
error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2)
end
 
local selftimers = AceTimer.selfs[self]
if selftimers then
for handle,v in pairs(selftimers) do
if type(v) == "table" then -- avoid __ops, etc
AceTimer.CancelTimer(self, handle, true)
end
end
end
end
 
--- Returns the time left for a timer with the given handle, registered by the current addon object ('self').
-- This function will raise a warning when the handle is invalid, but not stop execution.
-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
-- @return The time left on the timer, or false if the handle is invalid.
function AceTimer:TimeLeft(handle)
if not handle then return end
if type(handle) ~= "string" then
error(MAJOR..": TimeLeft(handle): 'handle' - expected a string", 2) -- for now, anyway
end
local selftimers = AceTimer.selfs[self]
local timer = selftimers and selftimers[handle]
if not timer then
geterrorhandler()(MAJOR..": TimeLeft(handle): '"..tostring(handle).."' - no such timer registered")
return false
end
return timer.when - GetTime()
end
 
 
-- ---------------------------------------------------------------------
-- PLAYER_REGEN_ENABLED: Run through our .selfs[] array step by step
-- and clean it out - otherwise the table indices can grow indefinitely
-- if an addon starts and stops a lot of timers. AceBucket does this!
--
-- See ACE-94 and tests/AceTimer-3.0-ACE-94.lua
 
local lastCleaned = nil
 
local function OnEvent(this, event)
if event~="PLAYER_REGEN_ENABLED" then
return
end
 
-- Get the next 'self' to process
local selfs = AceTimer.selfs
local self = next(selfs, lastCleaned)
if not self then
self = next(selfs)
end
lastCleaned = self
if not self then -- should only happen if .selfs[] is empty
return
end
 
-- Time to clean it out?
local list = selfs[self]
if (list.__ops or 0) < 250 then -- 250 slosh indices = ~10KB wasted (max!). For one 'self'.
return
end
 
-- Create a new table and copy all members over
local newlist = {}
local n=0
for k,v in pairs(list) do
newlist[k] = v
n=n+1
end
newlist.__ops = 0 -- Reset operation count
 
-- And since we now have a count of the number of live timers, check that it's reasonable. Emit a warning if not.
if n>BUCKETS then
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(self).."' has "..n.." live timers. Surely that's not intended?")
end
 
selfs[self] = newlist
end
 
-- ---------------------------------------------------------------------
-- Embed handling
 
AceTimer.embeds = AceTimer.embeds or {}
 
local mixins = {
"ScheduleTimer", "ScheduleRepeatingTimer",
"CancelTimer", "CancelAllTimers",
"TimeLeft"
}
 
function AceTimer:Embed(target)
AceTimer.embeds[target] = true
for _,v in pairs(mixins) do
target[v] = AceTimer[v]
end
return target
end
 
-- AceTimer:OnEmbedDisable( target )
-- target (object) - target object that AceTimer is embedded in.
--
-- cancel all timers registered for the object
function AceTimer:OnEmbedDisable( target )
target:CancelAllTimers()
end
 
 
for addon in pairs(AceTimer.embeds) do
AceTimer:Embed(addon)
end
 
-- ---------------------------------------------------------------------
-- Debug tools (expose copies of internals to test suites)
AceTimer.debug = AceTimer.debug or {}
AceTimer.debug.HZ = HZ
AceTimer.debug.BUCKETS = BUCKETS
 
-- ---------------------------------------------------------------------
-- Finishing touchups
 
AceTimer.frame:SetScript("OnUpdate", OnUpdate)
AceTimer.frame:SetScript("OnEvent", OnEvent)
AceTimer.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
 
-- In theory, we should hide&show the frame based on there being timers or not.
-- However, this job is fairly expensive, and the chance that there will
-- actually be zero timers running is diminuitive to say the lest.
1.2.5/libs/AceDBOptions-3.0/AceDBOptions-3.0.xml New file
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>
\ No newline at end of file
1.2.5/libs/AceDBOptions-3.0/AceDBOptions-3.0.lua New file
0,0 → 1,396
--- 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 765 2009-04-03 19:14:41Z nevcairiel $
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 10
local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR)
 
if not AceDBOptions then return end -- No upgrade needed
 
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 exisiting 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",
}
 
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"
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"
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"] = "프로필 설정"
elseif LOCALE == "esES" 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"
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"] = "管理設定檔"
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"] = "管理配置文件"
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"] = "Управление профилями"
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",
},
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
1.2.5/libs/AceEvent-3.0/AceEvent-3.0.xml New file
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>
\ No newline at end of file
1.2.5/libs/AceEvent-3.0/AceEvent-3.0.lua New file
0,0 → 1,125
--- 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 766 2009-04-04 08:26:05Z nevcairiel $
local MAJOR, MINOR = "AceEvent-3.0", 3
local AceEvent = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceEvent then return end
 
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
1.2.5/libs/AceConsole-3.0/AceConsole-3.0.xml New file
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>
\ No newline at end of file
1.2.5/libs/AceConsole-3.0/AceConsole-3.0.lua New file
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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua New file
0,0 → 1,687
--[[ $Id: AceGUIWidget-DropDown.lua 793 2009-04-07 09:26:44Z nevcairiel $ ]]--
local min, max, floor = math.min, math.max, math.floor
 
local AceGUI = LibStub("AceGUI-3.0")
 
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 = 2
 
--[[ Static data ]]--
 
local backdrop = {
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
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 = 19
 
--[[ 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
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: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 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
table.sort(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.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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-EditBox.lua New file
0,0 → 1,204
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Edit box --
--------------------------
--[[
Events :
OnTextChanged
OnEnterPressed
 
]]
do
local Type = "EditBox"
local Version = 11
 
local function OnAcquire(self)
self:SetHeight(26)
self:SetWidth(200)
self:SetDisabled(false)
self:SetLabel()
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 = this:GetText()
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_OnReceiveDrag(this)
local self = this.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(this)
local self = this.obj
local value = this:GetText()
if value ~= self.lasttext then
self:Fire("OnTextChanged",value)
self.lasttext = 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.lasttext = text or ""
self.editbox:SetText(text or "")
self.editbox:SetCursorPosition(0)
HideButton(self)
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: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
 
 
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local frame = CreateFrame("Frame",nil,UIParent)
local editbox = CreateFrame("EditBox","AceGUI-3.0EditBox"..num,frame,"InputBoxTemplate")
 
local self = {}
self.type = Type
self.num = num
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
 
self.SetDisabled = SetDisabled
self.SetText = SetText
self.SetLabel = SetLabel
 
self.frame = frame
frame.obj = self
self.editbox = editbox
editbox.obj = self
 
self.alignoffset = 30
 
frame:SetHeight(44)
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:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
 
editbox:SetTextInsets(0,0,3,3)
editbox:SetMaxLetters(256)
 
editbox:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",6,0)
editbox:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
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
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua New file
0,0 → 1,73
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Heading --
--------------------------
do
local Type = "Heading"
local Version = 5
 
local function OnAcquire(self)
self:SetText("")
self:SetFullWidth()
self:SetHeight(18)
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
local function SetText(self, text)
self.label:SetText(text or "")
if (text or "") == "" then
self.left:SetPoint("RIGHT",self.frame,"RIGHT",-3,0)
self.right:Hide()
else
self.left:SetPoint("RIGHT",self.label,"LEFT",-5,0)
self.right:Show()
end
end
 
local function Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetText = SetText
self.frame = frame
frame.obj = self
 
frame:SetHeight(18)
 
local label = frame:CreateFontString(nil,"BACKGROUND","GameFontNormal")
label:SetPoint("TOP",frame,"TOP",0,0)
label:SetPoint("BOTTOM",frame,"BOTTOM",0,0)
label:SetJustifyH("CENTER")
label:SetHeight(18)
self.label = label
 
local left = frame:CreateTexture(nil, "BACKGROUND")
self.left = left
left:SetHeight(8)
left:SetPoint("LEFT",frame,"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")
self.right = right
right:SetHeight(8)
right:SetPoint("RIGHT",frame,"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)
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-SimpleGroup.lua New file
0,0 → 1,97
local AceGUI = LibStub("AceGUI-3.0")
 
 
-------------
-- 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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-ScrollFrame.lua New file
0,0 → 1,225
local AceGUI = LibStub("AceGUI-3.0")
 
-------------
-- 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 = 4
 
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
end
 
local function SetScroll(self, value)
 
local status = self.status or self.localstatus
 
local frame, child = self.scrollframe, self.content
local viewheight = frame:GetHeight()
local height = child:GetHeight()
local offset
if viewheight > height then
offset = 0
else
offset = floor((height - viewheight) / 1000.0 * value)
end
child:ClearAllPoints()
child:SetPoint("TOPLEFT",frame,"TOPLEFT",0,offset)
child:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,offset)
status.offset = offset
status.scrollvalue = value
end
 
local function MoveScroll(self, value)
local status = self.status or self.localstatus
local frame, child = self.scrollframe, self.content
local height, viewheight = frame:GetHeight(), child: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(math.min(math.max(status.scrollvalue + delta*(1000/(diff/45)),0), 1000))
end
end
 
 
local function FixScroll(self)
local status = self.status or self.localstatus
local frame, child = self.scrollframe, self.content
local height, viewheight = frame:GetHeight(), child:GetHeight()
local offset = status.offset
if not offset then
offset = 0
end
local curvalue = self.scrollbar:GetValue()
if viewheight < height then
self.scrollbar:Hide()
self.scrollbar:SetValue(0)
--self.scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,0)
else
self.scrollbar:Show()
--self.scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",-16,0)
local value = (offset / (viewheight - height) * 1000)
if value > 1000 then value = 1000 end
self.scrollbar:SetValue(value)
self:SetScroll(value)
if value < 1000 then
child:ClearAllPoints()
child:SetPoint("TOPLEFT",frame,"TOPLEFT",0,offset)
child:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,offset)
status.offset = offset
end
end
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)
this.obj:FixScroll()
end
 
local function LayoutFinished(self,width,height)
self.content:SetHeight(height or 0 + 20)
self:FixScroll()
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 createdcount = 0
 
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)
local content = CreateFrame("Frame",nil,scrollframe)
createdcount = createdcount + 1
local scrollbar = CreateFrame("Slider",("AceConfigDialogScrollFrame%dScrollBar"):format(createdcount),scrollframe,"UIPanelScrollBarTemplate")
local scrollbg = scrollbar:CreateTexture(nil,"BACKGROUND")
scrollbg:SetAllPoints(scrollbar)
scrollbg:SetTexture(0,0,0,0.4)
self.scrollframe = scrollframe
self.content = content
self.scrollbar = scrollbar
 
scrollbar.obj = self
scrollframe.obj = self
content.obj = self
 
scrollframe:SetScrollChild(content)
scrollframe:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",-20,0)
scrollframe:EnableMouseWheel(true)
scrollframe:SetScript("OnMouseWheel", OnMouseWheel)
scrollframe:SetScript("OnSizeChanged", OnSizeChanged)
 
 
content:SetPoint("TOPLEFT",scrollframe,"TOPLEFT",0,0)
content:SetPoint("TOPRIGHT",scrollframe,"TOPRIGHT",0,0)
content:SetHeight(400)
 
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)
 
self.localstatus.scrollvalue = 0
 
 
self:FixScroll()
AceGUI:RegisterAsContainer(self)
--AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-DropDownGroup.lua New file
0,0 → 1,168
local AceGUI = LibStub("AceGUI-3.0")
 
--[[
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 = 11
 
local function OnAcquire(self)
self.dropdown:SetText("")
self:SetDropdownWidth(200)
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)
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,0)
titletext:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-4,0)
titletext:SetJustifyH("LEFT")
titletext:SetHeight(18)
 
 
self.titletext = titletext
 
local dropdown = AceGUI:Create("Dropdown")
self.dropdown = dropdown
dropdown.frame:SetParent(frame)
dropdown.parentgroup = self
dropdown:SetCallback("OnValueChanged",SelectedGroup)
 
dropdown.frame:SetPoint("TOPLEFT",titletext,"BOTTOMLEFT",-3,3)
dropdown.frame:Show()
dropdown:SetLabel("")
 
local border = CreateFrame("Frame",nil,frame)
self.border = border
border:SetPoint("TOPLEFT",frame,"TOPLEFT",3,-40)
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-3,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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua New file
0,0 → 1,100
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Button --
--------------------------
do
local Type = "Button"
local Version = 10
 
local function OnAcquire(self)
-- restore default values
self:SetHeight(24)
self:SetWidth(200)
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
self:SetDisabled(false)
end
 
local function Button_OnClick(this)
this.obj:Fire("OnClick")
AceGUI:ClearFocus()
end
 
local function Button_OnEnter(this)
this.obj:Fire("OnEnter")
end
 
local function Button_OnLeave(this)
this.obj:Fire("OnLeave")
end
 
local function SetText(self, text)
self.text:SetText(text or "")
end
 
local function SetDisabled(self, disabled)
self.disabled = disabled
if disabled then
self.frame:Disable()
else
self.frame:Enable()
end
end
 
local function Constructor()
local num = AceGUI:GetNextWidgetNum(Type)
local name = "AceGUI30Button"..num
local frame = CreateFrame("Button",name,UIParent,"UIPanelButtonTemplate2")
local self = {}
self.num = num
self.type = Type
self.frame = frame
 
local left = _G[name .. "Left"]
local right = _G[name .. "Right"]
local middle = _G[name .. "Middle"]
 
left:SetPoint("TOP", frame, "TOP", 0, -1)
left:SetPoint("BOTTOM", frame, "BOTTOM", 0, 1)
 
right:SetPoint("TOP", frame, "TOP", 0, -1)
right:SetPoint("BOTTOM", frame, "BOTTOM", 0, 1)
 
middle:SetPoint("TOP", frame, "TOP", 0, -1)
middle:SetPoint("BOTTOM", frame, "BOTTOM", 0, 1)
 
local text = frame:GetFontString()
self.text = text
text:ClearAllPoints()
text:SetPoint("TOPLEFT",frame,"TOPLEFT", 15, -1)
text:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT", -15, 1)
text:SetJustifyV("MIDDLE")
 
frame:SetScript("OnClick",Button_OnClick)
frame:SetScript("OnEnter",Button_OnEnter)
frame:SetScript("OnLeave",Button_OnLeave)
 
self.SetText = SetText
self.SetDisabled = SetDisabled
 
frame:EnableMouse(true)
 
frame:SetHeight(24)
frame:SetWidth(200)
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
 
self.frame = frame
frame.obj = self
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua New file
0,0 → 1,453
--[[ $Id: AceGUIWidget-DropDown-Items.lua 808 2009-05-07 14:45:15Z ammo $ ]]--
 
local AceGUI = LibStub("AceGUI-3.0")
 
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 = 2
 
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
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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-TreeGroup.lua New file
0,0 → 1,715
local AceGUI = LibStub("AceGUI-3.0")
 
-- 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 = 20
 
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 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 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.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 = (math.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,string.split("\001", 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
 
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
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)
treeframe.obj:Fire("OnTreeResize",treeframe:GetWidth())
 
local status = self.status or self.localstatus
status.treewidth = treeframe:GetWidth()
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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua New file
0,0 → 1,172
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- ColorPicker --
--------------------------
do
local Type = "ColorPicker"
local Version = 10
 
local function OnAcquire(self)
self.HasAlpha = false
self:SetColor(0,0,0,1)
self:SetHeight(24)
self:SetWidth(200)
end
 
local function SetLabel(self, text)
self.text:SetText(text)
end
 
local function SetColor(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
 
local function Control_OnEnter(this)
this.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(this)
this.obj:Fire("OnLeave")
end
 
local function SetHasAlpha(self, HasAlpha)
self.HasAlpha = HasAlpha
end
 
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
 
local function ColorSwatch_OnClick(this)
HideUIPanel(ColorPickerFrame)
local self = this.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
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
local function SetDisabled(self, disabled)
self.disabled = disabled
if self.disabled then
self.text:SetTextColor(0.5,0.5,0.5)
else
self.text:SetTextColor(1,1,1)
end
end
 
local function Constructor()
local frame = CreateFrame("Button",nil,UIParent)
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
 
self.SetLabel = SetLabel
self.SetColor = SetColor
self.SetDisabled = SetDisabled
self.SetHasAlpha = SetHasAlpha
 
self.frame = frame
frame.obj = self
 
local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
self.text = text
text:SetJustifyH("LEFT")
text:SetTextColor(1,1,1)
frame:SetHeight(24)
frame:SetWidth(200)
text:SetHeight(24)
frame:SetScript("OnClick", ColorSwatch_OnClick)
frame:SetScript("OnEnter",Control_OnEnter)
frame:SetScript("OnLeave",Control_OnLeave)
 
local colorSwatch = frame:CreateTexture(nil, "OVERLAY")
self.colorSwatch = colorSwatch
colorSwatch:SetWidth(19)
colorSwatch:SetHeight(19)
colorSwatch:SetTexture("Interface\\ChatFrame\\ChatFrameColorSwatch")
local texture = frame:CreateTexture(nil, "BACKGROUND")
colorSwatch.texture = texture
texture:SetWidth(16)
texture:SetHeight(16)
texture:SetTexture(1,1,1)
texture:Show()
 
local checkers = frame:CreateTexture(nil, "BACKGROUND")
colorSwatch.checkers = checkers
checkers:SetTexture("Tileset\\Generic\\Checkers")
checkers:SetDesaturated(true)
checkers:SetVertexColor(1,1,1,0.75)
checkers:SetTexCoord(.25,0,0.5,.25)
checkers:SetWidth(14)
checkers:SetHeight(14)
checkers:Show()
 
local highlight = frame:CreateTexture(nil, "BACKGROUND")
self.highlight = highlight
highlight:SetTexture("Interface\\QuestFrame\\UI-QuestTitleHighlight")
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(frame)
highlight:Hide()
 
texture:SetPoint("CENTER", colorSwatch, "CENTER")
checkers:SetPoint("CENTER", colorSwatch, "CENTER")
colorSwatch:SetPoint("LEFT", frame, "LEFT", 0, 0)
text:SetPoint("LEFT",colorSwatch,"RIGHT",2,0)
text:SetPoint("RIGHT",frame,"RIGHT")
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-InteractiveLabel.lua New file
0,0 → 1,188
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Label --
--------------------------
do
local Type = "InteractiveLabel"
local Version = 3
 
local function OnAcquire(self)
self:SetHeight(18)
self:SetWidth(200)
self:SetText("")
self:SetImage(nil)
self:SetColor()
self:SetFontObject()
self:SetHighlight()
self:SetHighlightTexCoord()
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
local function UpdateImageAnchor(self)
local width = self.frame.width or self.frame:GetWidth() or 0
local image = self.image
local label = self.label
local frame = self.frame
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",frame,"TOP",0,0)
label:SetPoint("TOP",image,"BOTTOM",0,0)
label:SetPoint("LEFT",frame,"LEFT",0,0)
label:SetWidth(width)
height = image:GetHeight() + label:GetHeight()
else
--image on the left
image:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetPoint("TOPLEFT",image,"TOPRIGHT",0,0)
label:SetWidth(width - imagewidth)
height = math.max(image:GetHeight(), label:GetHeight())
end
else
--no image shown
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetWidth(width)
height = self.label:GetHeight()
end
 
self.resizing = true
self.frame:SetHeight(height)
self.frame.height = height
self.resizing = nil
end
 
local function SetText(self, text)
self.label:SetText(text or "")
UpdateImageAnchor(self)
end
 
local function SetColor(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
 
local function OnWidthSet(self, width)
if self.resizing then return end
UpdateImageAnchor(self)
end
 
local function SetImage(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(...)
end
else
self.imageshown = nil
end
UpdateImageAnchor(self)
end
 
local function SetFont(self, font, height, flags)
self.label:SetFont(font, height, flags)
end
 
local function SetFontObject(self, font)
self.label:SetFontObject(font or GameFontHighlightSmall)
end
 
local function SetImageSize(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
UpdateImageAnchor(self)
end
 
local function SetHighlight(self, ...)
self.highlight:SetTexture(...)
end
 
local function SetHighlightTexCoord(self, ...)
if select('#', ...) >= 1 then
self.highlight:SetTexCoord(...)
else
self.highlight:SetTexCoord(0, 1, 0, 1)
end
end
 
local function OnEnter(this)
this.obj.highlight:Show()
this.obj:Fire("OnEnter")
end
 
local function OnLeave(this)
this.obj.highlight:Hide()
this.obj:Fire("OnLeave")
end
 
local function OnClick(this, ...)
this.obj:Fire("OnClick", ...)
AceGUI:ClearFocus()
end
 
local function Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = Type
 
frame:EnableMouse(true)
frame:SetScript("OnEnter", OnEnter)
frame:SetScript("OnLeave", OnLeave)
frame:SetScript("OnMouseDown", OnClick)
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetText = SetText
self.SetColor = SetColor
self.frame = frame
self.OnWidthSet = OnWidthSet
self.SetImage = SetImage
self.SetImageSize = SetImageSize
self.SetFont = SetFont
self.SetFontObject = SetFontObject
self.SetHighlight = SetHighlight
self.SetHighlightTexCoord = SetHighlightTexCoord
frame.obj = self
 
frame:SetHeight(18)
frame:SetWidth(200)
local label = frame:CreateFontString(nil,"BACKGROUND","GameFontHighlightSmall")
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetWidth(200)
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
self.label = label
 
local highlight = frame:CreateTexture(nil, "OVERLAY")
highlight:SetTexture(nil)
highlight:SetAllPoints()
highlight:SetBlendMode("ADD")
highlight:Hide()
self.highlight = highlight
 
local image = frame:CreateTexture(nil,"BACKGROUND")
self.image = image
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
 
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua New file
0,0 → 1,145
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Label --
--------------------------
do
local Type = "Label"
local Version = 10
 
local function OnAcquire(self)
self:SetHeight(18)
self:SetWidth(200)
self:SetText("")
self:SetImage(nil)
self:SetColor()
self:SetFontObject()
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
local function UpdateImageAnchor(self)
local width = self.frame.width or self.frame:GetWidth() or 0
local image = self.image
local label = self.label
local frame = self.frame
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",frame,"TOP",0,0)
label:SetPoint("TOP",image,"BOTTOM",0,0)
label:SetPoint("LEFT",frame,"LEFT",0,0)
label:SetWidth(width)
height = image:GetHeight() + label:GetHeight()
else
--image on the left
image:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetPoint("TOPLEFT",image,"TOPRIGHT",0,0)
label:SetWidth(width - imagewidth)
height = math.max(image:GetHeight(), label:GetHeight())
end
else
--no image shown
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetWidth(width)
height = self.label:GetHeight()
end
 
self.resizing = true
self.frame:SetHeight(height)
self.frame.height = height
self.resizing = nil
end
 
local function SetText(self, text)
self.label:SetText(text or "")
UpdateImageAnchor(self)
end
 
local function SetColor(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
 
local function OnWidthSet(self, width)
if self.resizing then return end
UpdateImageAnchor(self)
end
 
local function SetImage(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(...)
end
else
self.imageshown = nil
end
UpdateImageAnchor(self)
end
 
local function SetFont(self, font, height, flags)
self.label:SetFont(font, height, flags)
end
 
local function SetFontObject(self, font)
self.label:SetFontObject(font or GameFontHighlightSmall)
end
 
local function SetImageSize(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
UpdateImageAnchor(self)
end
 
local function Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetText = SetText
self.SetColor = SetColor
self.frame = frame
self.OnWidthSet = OnWidthSet
self.SetImage = SetImage
self.SetImageSize = SetImageSize
self.SetFont = SetFont
self.SetFontObject = SetFontObject
frame.obj = self
 
frame:SetHeight(18)
frame:SetWidth(200)
local label = frame:CreateFontString(nil,"BACKGROUND","GameFontHighlightSmall")
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0)
label:SetWidth(200)
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
self.label = label
 
local image = frame:CreateTexture(nil,"BACKGROUND")
self.image = image
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
 
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua New file
0,0 → 1,318
 
--[[
--Multiline Editbox Widget, Originally by bam
 
--]]
local assert, error, ipairs, next, pairs, select, tonumber, tostring, type, unpack, pcall, xpcall =
assert, error, ipairs, next, pairs, select, tonumber, tostring, type, unpack, pcall, xpcall
local getmetatable, setmetatable, rawequal, rawget, rawset, getfenv, setfenv, loadstring, debugstack =
getmetatable, setmetatable, rawequal, rawget, rawset, getfenv, setfenv, loadstring, debugstack
local math, string, table = math, string, table
local find, format, gmatch, gsub, tolower, match, toupper, join, split, trim =
string.find, string.format, string.gmatch, string.gsub, string.lower, string.match, string.upper, string.join, string.split, string.trim
local concat, insert, maxn, remove, sort = table.concat, table.insert, table.maxn, table.remove, table.sort
local max, min, abs, ceil, floor = math.max, math.min, math.abs, math.ceil, math.floor
 
local LibStub = assert(LibStub)
 
local ChatFontNormal = ChatFontNormal
local ClearCursor = ClearCursor
local CreateFrame = CreateFrame
local GetCursorInfo = GetCursorInfo
local GetSpellName = GetSpellName
local UIParent = UIParent
local UISpecialFrames = UISpecialFrames
 
-- No global variables after this!
 
local _G = getfenv()
 
local AceGUI = LibStub("AceGUI-3.0")
 
local Version = 10
---------------------
-- Common Elements --
---------------------
 
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 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 }
}
 
--------------------------
-- Edit box --
--------------------------
--[[
Events :
OnTextChanged
OnEnterPressed
 
]]
do
local Type = "MultiLineEditBox"
 
local MultiLineEditBox = {}
 
local function EditBox_OnEnterPressed(this)
local self = this.obj
local value = this:GetText()
local cancel = self:Fire("OnEnterPressed",value)
if not cancel then
self.button:Disable()
end
end
 
local function Button_OnClick(this)
local editbox = this.obj.editbox
editbox:ClearFocus()
EditBox_OnEnterPressed(editbox)
end
 
local function EditBox_OnReceiveDrag(this)
local self = this.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
--self.button:Disable()
AceGUI:ClearFocus()
end
 
function MultiLineEditBox:OnAcquire()
self:SetWidth(200)
self:SetHeight(116)
self:SetNumLines(4)
self:SetDisabled(false)
self:ShowButton(true)
end
 
function MultiLineEditBox:OnRelease()
self.frame:ClearAllPoints()
self.frame:Hide()
self:SetDisabled(false)
end
 
function MultiLineEditBox:SetDisabled(disabled)
self.disabled = disabled
if disabled then
self.editbox:EnableMouse(false)
self.scrollframe: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.scrollframe:EnableMouse(true)
self.editbox:SetTextColor(1, 1, 1)
self.label:SetTextColor(1,.82,0)
end
end
 
function MultiLineEditBox:SetText(text)
text = text or ""
local editbox = self.editbox
local oldText = editbox:GetText()
local dummy = format(" %s", text)
self.lasttext = dummy -- prevents OnTextChanged from firing
editbox:SetText(dummy)
editbox:HighlightText(0, 1)
self.lasttext = oldText
editbox:Insert("")
end
 
function MultiLineEditBox:SetLabel(text)
if (text or "") == "" then
self.backdrop:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,0)
self.label:Hide()
self.label:SetText("")
else
self.backdrop:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,-20)
self.label:Show()
self.label:SetText(text)
end
end
 
function MultiLineEditBox:SetNumLines(number)
number = number or 4
self:SetHeight(60 + (14*number))
end
 
function MultiLineEditBox:GetText()
return self.editbox:GetText()
end
 
function MultiLineEditBox:ShowButton(show)
if show then
self.backdrop:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,22)
self.button:Show()
else
self.backdrop:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",0,0)
self.button:Hide()
end
end
 
local function Constructor()
local frame = CreateFrame("Frame", nil, UIParent)
local backdrop = CreateFrame("Frame", nil, frame)
local self = {}
for k, v in pairs(MultiLineEditBox) do self[k] = v end
self.type = Type
self.frame = frame
self.backdrop = backdrop
frame.obj = self
 
backdrop:SetBackdrop(ControlBackdrop)
backdrop:SetBackdropColor(0, 0, 0)
backdrop:SetBackdropBorderColor(0.4, 0.4, 0.4)
 
backdrop:SetPoint("TOPLEFT",frame,"TOPLEFT",0, -20)
backdrop:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,22)
 
local scrollframe = CreateFrame("ScrollFrame", format("%s@%s@%s", Type, "ScrollFrame", tostring(self)), backdrop, "UIPanelScrollFrameTemplate")
scrollframe:SetPoint("TOPLEFT", 5, -6)
scrollframe:SetPoint("BOTTOMRIGHT", -28, 6)
scrollframe.obj = self
self.scrollframe = scrollframe
 
--local scrollchild = CreateFrame("Frame", nil, scrollframe)
--scrollframe:SetScrollChild(scrollchild)
--scrollchild:SetHeight(2)
--scrollchild:SetWidth(2)
 
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 editbox = CreateFrame("EditBox", nil, scrollframe)
self.editbox = editbox
editbox.obj = self
editbox:SetPoint("TOPLEFT")
editbox:SetPoint("BOTTOMLEFT")
editbox:SetHeight(50)
editbox:SetWidth(50)
editbox:SetMultiLine(true)
-- editbox:SetMaxLetters(7500)
editbox:SetTextInsets(5, 5, 3, 3)
editbox:EnableMouse(true)
editbox:SetAutoFocus(false)
editbox:SetFontObject(ChatFontNormal)
scrollframe:SetScrollChild(editbox)
 
local button = CreateFrame("Button",nil,scrollframe,"UIPanelButtonTemplate")
button:SetWidth(80)
button:SetHeight(20)
button:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,2)
button:SetText(ACCEPT)
button:SetScript("OnClick", Button_OnClick)
button:SetFrameLevel(editbox:GetFrameLevel() + 1)
button:Disable()
button:Hide()
self.button = button
button.obj = self
 
scrollframe:EnableMouse(true)
scrollframe:SetScript("OnMouseUp", function() editbox:SetFocus() end)
scrollframe:SetScript("OnEnter", function(this) this.obj:Fire("OnEnter") end)
scrollframe:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end)
 
editbox:SetScript("OnEnter", function(this) this.obj:Fire("OnEnter") end)
editbox:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end)
 
local function FixSize()
--scrollchild:SetHeight(scrollframe:GetHeight())
--scrollchild:SetWidth(scrollframe:GetWidth())
editbox:SetWidth(scrollframe:GetWidth())
end
scrollframe:SetScript("OnShow", FixSize)
scrollframe:SetScript("OnSizeChanged", FixSize)
 
editbox:SetScript("OnEscapePressed", editbox.ClearFocus)
editbox:SetScript("OnTextChanged", function(_, ...)
scrollframe:UpdateScrollChildRect()
local value = editbox:GetText()
if value ~= self.lasttext then
self:Fire("OnTextChanged", value)
self.lasttext = value
self.button:Enable()
end
end)
 
editbox:SetScript("OnReceiveDrag", EditBox_OnReceiveDrag)
editbox:SetScript("OnMouseDown", EditBox_OnReceiveDrag)
 
do
local cursorOffset, cursorHeight
local idleTime
local function FixScroll(_, elapsed)
if cursorOffset and cursorHeight then
idleTime = 0
local height = scrollframe:GetHeight()
local range = scrollframe:GetVerticalScrollRange()
local scroll = scrollframe:GetVerticalScroll()
local size = height + range
cursorOffset = -cursorOffset
while cursorOffset < scroll do
scroll = scroll - (height / 2)
if scroll < 0 then scroll = 0 end
scrollframe:SetVerticalScroll(scroll)
end
while cursorOffset + cursorHeight > scroll + height and scroll < range do
scroll = scroll + (height / 2)
if scroll > range then scroll = range end
scrollframe:SetVerticalScroll(scroll)
end
elseif not idleTime or idleTime > 2 then
frame:SetScript("OnUpdate", nil)
idleTime = nil
else
idleTime = idleTime + elapsed
end
cursorOffset = nil
end
editbox:SetScript("OnCursorChanged", function(_, x, y, w, h)
cursorOffset, cursorHeight = y, h
if not idleTime then
frame:SetScript("OnUpdate", FixScroll)
end
end)
end
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type, Constructor, Version)
end
 
 
 
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua New file
0,0 → 1,255
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Slider --
--------------------------
do
local Type = "Slider"
local Version = 7
 
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(math.floor(value*1000+0.5)/10))
else
self.editbox:SetText(math.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 = math.min(value + (self.step or 1),self.max)
else
value = math.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)
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
self:Fire("OnMouseUp",value)
end
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 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)
self.editbox = editbox
editbox.obj = self
 
local bg = editbox:CreateTexture(nil,"BACKGROUND")
editbox.bg = bg
bg:SetTexture("Interface\\ChatFrame\\ChatFrameBackground")
bg:SetVertexColor(0,0,0,0.25)
bg:SetAllPoints(editbox)
 
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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua New file
0,0 → 1,219
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Keybinding --
--------------------------
 
do
local Type = "Keybinding"
local Version = 12
 
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()
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
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-TabGroup.lua New file
0,0 → 1,365
local AceGUI = LibStub("AceGUI-3.0")
 
-------------
-- 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 = 20
 
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
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
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 "")
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 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, -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 = 10+((numrows)*20)
self.border:SetPoint("TOPLEFT",self.frame,"TOPLEFT",3,-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")
 
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
self.borderoffset = 27
border:SetPoint("TOPLEFT",frame,"TOPLEFT",3,-27)
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-3,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,-10)
content:SetPoint("BOTTOMRIGHT",border,"BOTTOMRIGHT",-10,10)
 
AceGUI:RegisterAsContainer(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua New file
0,0 → 1,219
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Check Box --
--------------------------
--[[
Events :
OnValueChanged
 
]]
do
local Type = "CheckBox"
local Version = 5
 
local function OnAcquire(self)
self:SetValue(false)
self.tristate = nil
self:SetHeight(24)
self:SetWidth(200)
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
self.check:Hide()
self.highlight:Hide()
self.down = nil
self.checked = nil
self:SetType()
self:SetDisabled(false)
end
 
local function CheckBox_OnEnter(this)
local self = this.obj
if not self.disabled then
self.highlight:Show()
end
self:Fire("OnEnter")
end
 
local function CheckBox_OnLeave(this)
local self = this.obj
if not self.down then
self.highlight:Hide()
end
self:Fire("OnLeave")
end
 
local function CheckBox_OnMouseUp(this)
local self = this.obj
if not self.disabled then
self:ToggleChecked()
self:Fire("OnValueChanged",self.checked)
self.text:SetPoint("LEFT",self.check,"RIGHT",0,0)
end
self.down = nil
end
 
local function CheckBox_OnMouseDown(this)
local self = this.obj
if not self.disabled then
self.text:SetPoint("LEFT",self.check,"RIGHT",1,-1)
self.down = true
end
AceGUI:ClearFocus()
end
 
local function SetDisabled(self,disabled)
self.disabled = disabled
if disabled then
self.text:SetTextColor(0.5,0.5,0.5)
SetDesaturation(self.check, true)
else
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
 
local function SetValue(self,value)
local check = self.check
self.checked = value
if value then
SetDesaturation(self.check, false)
check:SetWidth(24)
check:SetHeight(24)
self.check:Show()
else
--Nil is the unknown tristate value
if self.tristate and value == nil then
SetDesaturation(self.check, true)
check:SetWidth(20)
check:SetHeight(20)
self.check:Show()
else
SetDesaturation(self.check, false)
check:SetWidth(24)
check:SetHeight(24)
self.check:Hide()
end
end
end
 
local function SetTriState(self, enabled)
self.tristate = enabled
self:SetValue(self:GetValue())
end
 
local function GetValue(self)
return self.checked
end
 
local function SetType(self, type)
local checkbg = self.checkbg
local check = self.check
local highlight = self.highlight
 
if type == "radio" then
checkbg:SetTexture("Interface\\Buttons\\UI-RadioButton")
checkbg:SetTexCoord(0,0.25,0,1)
check:SetTexture("Interface\\Buttons\\UI-RadioButton")
check:SetTexCoord(0.5,0.75,0,1)
check:SetBlendMode("ADD")
highlight:SetTexture("Interface\\Buttons\\UI-RadioButton")
highlight:SetTexCoord(0.5,0.75,0,1)
else
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
end
 
local function ToggleChecked(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
 
local function SetLabel(self, label)
self.text:SetText(label)
end
 
local function Constructor()
local frame = CreateFrame("Button",nil,UIParent)
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
 
self.SetValue = SetValue
self.GetValue = GetValue
self.SetDisabled = SetDisabled
self.SetType = SetType
self.ToggleChecked = ToggleChecked
self.SetLabel = SetLabel
self.SetTriState = SetTriState
 
self.frame = frame
frame.obj = self
 
local text = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
self.text = text
 
frame:SetScript("OnEnter",CheckBox_OnEnter)
frame:SetScript("OnLeave",CheckBox_OnLeave)
frame:SetScript("OnMouseUp",CheckBox_OnMouseUp)
frame:SetScript("OnMouseDown",CheckBox_OnMouseDown)
frame:EnableMouse()
local checkbg = frame:CreateTexture(nil,"ARTWORK")
self.checkbg = checkbg
checkbg:SetWidth(24)
checkbg:SetHeight(24)
checkbg:SetPoint("LEFT",frame,"LEFT",0,0)
checkbg:SetTexture("Interface\\Buttons\\UI-CheckBox-Up")
local check = frame:CreateTexture(nil,"OVERLAY")
self.check = check
check:SetWidth(24)
check:SetHeight(24)
check:SetPoint("CENTER",checkbg,"CENTER",0,0)
check:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
 
local highlight = frame:CreateTexture(nil, "BACKGROUND")
self.highlight = highlight
highlight:SetTexture("Interface\\Buttons\\UI-CheckBox-Highlight")
highlight:SetBlendMode("ADD")
highlight:SetAllPoints(checkbg)
highlight:Hide()
 
text:SetJustifyH("LEFT")
frame:SetHeight(24)
frame:SetWidth(200)
text:SetHeight(18)
text:SetPoint("LEFT",check,"RIGHT",0,0)
text:SetPoint("RIGHT",frame,"RIGHT",0,0)
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua New file
0,0 → 1,126
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Label --
--------------------------
do
local Type = "Icon"
local Version = 9
 
local function OnAcquire(self)
self:SetHeight(110)
self:SetWidth(110)
self:SetLabel("")
self:SetImage(nil)
self:SetImageSize(64, 64)
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
local function SetLabel(self, text)
if text and text ~= "" then
self.label:Show()
self.label:SetText(text)
self.frame:SetHeight(self.image:GetHeight() + 25)
else
self.label:Hide()
self.frame:SetHeight(self.image:GetHeight() + 10)
end
end
 
local function SetImage(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(...)
end
else
self.imageshown = nil
end
end
 
local function SetImageSize(self, width, height)
self.image:SetWidth(width)
self.image:SetHeight(height)
--self.frame:SetWidth(width + 30)
if self.label:IsShown() then
self.frame:SetHeight(height + 25)
else
self.frame:SetHeight(height + 10)
end
end
 
local function OnClick(this, button)
this.obj:Fire("OnClick", button)
AceGUI:ClearFocus()
end
 
local function OnEnter(this)
this.obj.highlight:Show()
this.obj:Fire("OnEnter")
end
 
local function OnLeave(this)
this.obj.highlight:Hide()
this.obj:Fire("OnLeave")
end
 
local function Constructor()
local frame = CreateFrame("Button",nil,UIParent)
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetLabel = SetLabel
self.frame = frame
self.SetImage = SetImage
self.SetImageSize = SetImageSize
 
-- SetText should be deprecated along the way
self.SetText = SetLabel
 
frame.obj = self
 
frame:SetHeight(110)
frame:SetWidth(110)
frame:EnableMouse(true)
frame:SetScript("OnClick", OnClick)
frame:SetScript("OnLeave", OnLeave)
frame:SetScript("OnEnter", OnEnter)
local label = frame:CreateFontString(nil,"BACKGROUND","GameFontHighlight")
label:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0)
label:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0)
label:SetJustifyH("CENTER")
label:SetJustifyV("TOP")
label:SetHeight(18)
self.label = label
 
local image = frame:CreateTexture(nil,"BACKGROUND")
self.image = image
image:SetWidth(64)
image:SetHeight(64)
image:SetPoint("TOP",frame,"TOP",0,-5)
 
local highlight = frame:CreateTexture(nil,"OVERLAY")
self.highlight = highlight
highlight:SetAllPoints(image)
highlight:SetTexture("Interface\\PaperDollInfoFrame\\UI-Character-Tab-Highlight")
highlight:SetTexCoord(0,1,0.23,0.77)
highlight:SetBlendMode("ADD")
highlight:Hide()
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
 
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-BlizOptionsGroup.lua New file
0,0 → 1,150
local AceGUI = LibStub("AceGUI-3.0")
 
 
-------------
-- 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
 
 
]]
 
----------------------------------
-- Blizzard Options Group --
----------------------------------
--[[
Group Designed to be added to the bliz interface options panel
]]
 
do
local Type = "BlizOptionsGroup"
local Version = 6
 
local function OnAcquire(self)
 
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
self:SetName()
end
 
local function okay(this)
this.obj:Fire("okay")
end
 
local function cancel(this)
this.obj:Fire("cancel")
end
 
local function defaults(this)
this.obj:Fire("defaults")
end
 
local function SetName(self, name, parent)
self.frame.name = name
self.frame.parent = parent
end
 
local function OnShow(this)
this.obj:Fire("OnShow")
end
 
local function OnHide(this)
this.obj:Fire("OnHide")
end
 
local function OnWidthSet(self, width)
local content = self.content
local contentwidth = width - 63
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 - 26
if contentheight < 0 then
contentheight = 0
end
content:SetHeight(contentheight)
content.height = contentheight
end
 
local function SetTitle(self, title)
local content = self.content
content:ClearAllPoints()
if not title or title == "" then
content:SetPoint("TOPLEFT",self.frame,"TOPLEFT",15,-10)
self.label:SetText("")
else
content:SetPoint("TOPLEFT",self.frame,"TOPLEFT",15,-40)
self.label:SetText(title)
end
content:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",-10,10)
end
 
local function Constructor()
local frame = CreateFrame("Frame")
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.frame = frame
self.SetName = SetName
 
self.OnWidthSet = OnWidthSet
self.OnHeightSet = OnHeightSet
self.SetTitle = SetTitle
 
frame.obj = self
frame.okay = okay
frame.cancel = cancel
frame.defaults = defaults
 
frame:Hide()
frame:SetScript("OnHide",OnHide)
frame:SetScript("OnShow",OnShow)
 
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalLarge")
self.label = label
label:SetPoint("TOPLEFT", frame, "TOPLEFT", 15, -15)
label:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 10, -45)
label:SetJustifyH("LEFT")
label:SetJustifyV("TOP")
 
--Container Support
local content = CreateFrame("Frame",nil,frame)
self.content = content
content.obj = self
content:SetPoint("TOPLEFT",frame,"TOPLEFT",15,-10)
content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-10,10)
 
AceGUI:RegisterAsContainer(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-Frame.lua New file
0,0 → 1,299
local AceGUI = LibStub("AceGUI-3.0")
 
----------------
-- Main Frame --
----------------
--[[
Events :
OnClose
 
]]
do
local Type = "Frame"
local Version = 7
 
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 frameOnClose(this)
this.obj:Fire("OnClose")
end
 
local function closeOnClick(this)
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()
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 Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = "Frame"
 
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.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:SetBackdrop(FrameBackdrop)
frame:SetBackdropColor(0,0,0,1)
frame:SetScript("OnHide",frameOnClose)
frame:SetMinResize(400,200)
frame:SetToplevel(true)
 
local closebutton = CreateFrame("Button",nil,frame,"UIPanelButtonTemplate")
closebutton:SetScript("OnClick", closeOnClick)
closebutton:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-27,17)
closebutton:SetHeight(20)
closebutton:SetWidth(100)
closebutton:SetText("Close")
 
self.closebutton = closebutton
closebutton.obj = self
 
local statusbg = CreateFrame("Frame",nil,frame)
statusbg:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",15,15)
statusbg:SetPoint("BOTTOMRIGHT",frame,"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)
self.statusbg = statusbg
 
local statustext = statusbg:CreateFontString(nil,"OVERLAY","GameFontNormal")
self.statustext = statustext
statustext:SetPoint("TOPLEFT",statusbg,"TOPLEFT",7,-2)
statustext:SetPoint("BOTTOMRIGHT",statusbg,"BOTTOMRIGHT",-7,2)
statustext:SetHeight(20)
statustext:SetJustifyH("LEFT")
statustext:SetText("")
 
local title = CreateFrame("Frame",nil,frame)
self.title = title
title:EnableMouse()
title:SetScript("OnMouseDown",titleOnMouseDown)
title:SetScript("OnMouseUp", frameOnMouseUp)
 
 
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",frame,"TOP",0,12)
titlebg:SetWidth(100)
titlebg:SetHeight(40)
 
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",0,0)
titlebg_l:SetWidth(30)
titlebg_l:SetHeight(40)
 
local titlebg_right = frame:CreateTexture(nil,"OVERLAY")
titlebg_right:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
titlebg_right:SetTexCoord(0.67,0.77,0,0.63)
titlebg_right:SetPoint("LEFT",titlebg,"RIGHT",0,0)
titlebg_right:SetWidth(30)
titlebg_right:SetHeight(40)
 
title:SetAllPoints(titlebg)
local titletext = title:CreateFontString(nil,"OVERLAY","GameFontNormal")
titletext:SetPoint("TOP",titlebg,"TOP",0,-14)
 
self.titletext = titletext
 
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",17,-27)
content:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-17,40)
 
AceGUI:RegisterAsContainer(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
end
1.2.5/libs/AceGUI-3.0/widgets/AceGUIWidget-InlineGroup.lua New file
0,0 → 1,136
local AceGUI = LibStub("AceGUI-3.0")
 
 
-------------
-- 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 = 5
 
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",3,-17)
border:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-3,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
1.2.5/libs/AceGUI-3.0/AceGUI-3.0.xml New file
0,0 → 1,25
<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"/>
<Script file="widgets\AceGUIWidget-Button.lua"/>
<Script file="widgets\AceGUIWidget-CheckBox.lua"/>
<Script file="widgets\AceGUIWidget-ColorPicker.lua"/>
<Script file="widgets\AceGUIWidget-DropDownGroup.lua"/>
<Script file="widgets\AceGUIWidget-DropDown.lua"/>
<Script file="widgets\AceGUIWidget-DropDown-Items.lua"/>
<Script file="widgets\AceGUIWidget-EditBox.lua"/>
<Script file="widgets\AceGUIWidget-Frame.lua"/>
<Script file="widgets\AceGUIWidget-Heading.lua"/>
<Script file="widgets\AceGUIWidget-InlineGroup.lua"/>
<Script file="widgets\AceGUIWidget-Keybinding.lua"/>
<Script file="widgets\AceGUIWidget-ScrollFrame.lua"/>
<Script file="widgets\AceGUIWidget-SimpleGroup.lua"/>
<Script file="widgets\AceGUIWidget-Slider.lua"/>
<Script file="widgets\AceGUIWidget-TabGroup.lua"/>
<Script file="widgets\AceGUIWidget-TreeGroup.lua"/>
<Script file="widgets\AceGUIWidget-Label.lua"/>
<Script file="widgets\AceGUIWidget-MultiLineEditBox.lua"/>
<Script file="widgets\AceGUIWidget-BlizOptionsGroup.lua"/>
<Script file="widgets\AceGUIWidget-InteractiveLabel.lua"/>
<Script file="widgets\AceGUIWidget-Icon.lua"/>
</Ui>
\ No newline at end of file
1.2.5/libs/AceGUI-3.0/AceGUI-3.0.lua New file
0,0 → 1,831
--- **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 803 2009-04-14 12:37:54Z nevcairiel $
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 23
local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR)
 
if not AceGUI then return end -- No upgrade needed
 
--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
 
local pcall = pcall
local select = select
local pairs = pairs
local ipairs = ipairs
local type = type
local assert = assert
local tinsert = tinsert
local tremove = tremove
local CreateFrame = CreateFrame
local UIParent = UIParent
 
--[[
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", table.concat(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 new, del
do
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 new(type,constructor,...)
if not type then
type = "table"
end
if not objPools[type] then
objPools[type] = {}
end
local newObj = tremove(objPools[type])
if not newObj then
newObj = constructor and constructor(...) or {}
end
return newObj
end
-- Releases an instance to the Pool
function del(obj,type)
if not type then
type = "table"
end
if not objPools[type] then
objPools[type] = {}
end
for i,v in ipairs(objPools[type]) do
if v == obj then
error("Attempt to Release Widget that is already released")
return
end
end
tinsert(objPools[type],obj)
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)
local reg = WidgetRegistry
if reg[type] then
local widget = new(type,reg[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(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(nil)
widget.frame.width = nil
widget.frame.height = nil
if widget.content then
widget.content.width = nil
widget.content.height = nil
end
del(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
OnRelease() - 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
: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
:OnLayoutFinished(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 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 WidgetBase = AceGUI.WidgetBase
 
WidgetBase.SetParent = function(self, parent)
local frame = self.frame
frame:SetParent(nil)
frame:SetParent(parent.content)
self.parent = parent
--fixlevels(parent.frame,parent.frame:GetChildren())
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 in ipairs(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")
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})
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
 
--[[ Widget Template
 
--------------------------
-- Widget Name --
--------------------------
do
local Type = "Type"
 
local function OnAcquire(self)
 
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
 
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
 
--Container Support
--local content = CreateFrame("Frame",nil,frame)
--self.content = content
 
--AceGUI:RegisterAsContainer(self)
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor)
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, child in ipairs(children) do
 
 
local frame = child.frame
frame:ClearAllPoints()
frame:Show()
if i == 1 then
frame:SetPoint("TOPLEFT",content,"TOPLEFT",0,0)