WoWInterface SVN RepWatchWotlK

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /trunk
    from Rev 7 to Rev 8
    Reverse comparison

Rev 7 → Rev 8

RepWatch/RepWatch.toc New file
0,0 → 1,13
## Interface: 30000
## Title: |cffFFA500RepWatch |cff6495EDWotlK|r |cff7fff7fBETA|r |cff7fff7f|r
## Notes: Changes the "Watched Reputation Bar" Automatically Depending on What Zone or Instance you Enter.
## Author: Seglberg
## Version: 2.0.0 (Alpha)
## SavedVariables: RepWatchDB
## OptionalDeps: Ace3
## X-Embeds: Ace3
## X-Category: Interface Enhancements
 
embeds.xml
 
Core.lua
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Core.lua New file
0,0 → 1,796
-------------------------------------------------------
-- RepWatch by Seglberg|Dragonspew (Horde) on THRALL
-- Whisper Me or Email Me at Seglberg@live.com
--
-- Thanks to Ephemerality for Helping me with the "Default Watch" Feature
-------------------------------------------------------
-- Future Additions and Improvments:
--
-- o) Ability to Stop the Bar from Changing if you are Already Exalted with that Faction
-- o) Sub-Zone Support
-- o) Classic Instance Support
-- o) Wrath of the Lich King Support
--
-------------------------------------------------------
 
RepWatch = LibStub("AceAddon-3.0"):NewAddon("RepWatch", "AceEvent-3.0", "AceConsole-3.0")
 
--This Build's Version
--Underlay Version: 1.0.9
RepWatch.Version = "2.0.1 (WotlK BETA)"
RepWatch.VersionDesc = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffFF7F24[RepWatch] Version:" .. RepWatch.Version .. "\nAuthor: Seglberg of Thrall|r"
 
 
 
--#######################--
--# Option Tables #--
--#######################--
 
local options = {
name = "RepWatch",
handler = RepWatch,
type = "group",
args = {
changeOptionsDesc = {
order = 1,
type = "description",
name = " |cffFFD700Auto-Changing Options|r",
cmdHidden = true,
},
changeWotlK = {
order = 2,
type = "toggle",
name = "|cff6495EDWotlK Instances|r",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you Zone into a Wrath of the Lich King Instance (Default: On)",
get = "IsChangeWotlK",
set = "ToggleChangeWotlK",
},
changeBC = {
order = 3,
type = "toggle",
name = "|cff00CD00BC Instances|r",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you Zone into a Burning Crusade Instance (Default: On)",
get = "IsChangeBC",
set = "ToggleChangeBC",
},
changeClassic = {
order = 4,
type = "toggle",
name = "|cffD2691EClassic Instances|r",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you Zone into a Classic Instance (Default: On)",
get = "IsChangeClassic",
set = "ToggleChangeClassic",
},
changeCities = {
order = 5,
type = "toggle",
name = "In Cities",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you Zone into Capital Cities (Default: On)",
get = "IsChangeCities",
set = "ToggleChangeCities",
},
changeBGs = {
order = 6,
type = "toggle",
name = "In Battlegrounds",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you Zone into a Battleground (Default: On)",
get = "IsChangeBGs",
set = "ToggleChangeBGs",
},
changeSubZones = {
order = 6,
type = "toggle",
name = "In Sub-Zones",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you Enter a Sub-Zone (Default: On)",
get = "IsChangeSubZones",
set = "ToggleChangeSubZones",
},
otherOptionsDesc = {
order = 10,
type = "description",
name = " |cffFFD700Other Options|r",
cmdHidden = true,
},
showInChat = {
order = 11,
type = "toggle",
name = "Display Notice",
desc = "Toggle this on/off to Enable or Disable the Announcements in the Chatbox (Default: On)",
get = "IsShowInChat",
set = "ToggleShowInChat",
},
changeIfExalted = {
order = 12,
type = "toggle",
name = "Change if Exalted",
desc = "Toggle this on/off to Enable or Disable the Changing of the Reputation Bar when you are Exalted with the Zone's Faction (Default: Off)",
get = "IsChangeIfExalted",
set = "ToggleChangeIfExalted",
},
defaultFaction = {
order = 20,
type = "select",
name = " Default Faction",
desc = "Selects the Faction to Be Used if No Faction Is Available for the Area. Does NOT Apply for Sub-Zone Changes. (Default: None)",
values = "GetAllFactions",
get = "GetDefaultFaction",
set = "SetDefaultFaction",
style = "dropdown",
},
versionDesc = {
order = 100,
type = "description",
name = RepWatch.VersionDesc,
cmdHidden = true,
},
},
}
 
local defaults = {
char = {
changeWotlK = true,
changeBC = true,
changeClassic = true,
changeCities = true,
changeBGs = true,
changeSubZones = true,
showInChat = true,
changeIfExalted = false,
defaultFaction = 1, --"None"
},
}
 
--#####################--
--# Reputation Tables #--
--#####################--
 
---------|WotlK Instances|----------
---------|WotlK Instances|----------
 
----------|BC Instances|------------
if UnitFactionGroup("player") == "Horde" then
RepWatch.HellfireRep = "Thrallmar"
else
RepWatch.HellfireRep = "Honor Hold"
end
 
local BCInstances = {
["Magisters' Terrace"] = "Shattered Sun Offensive",
["Sunwell Plateau"] = "Shattered Sun Offensive",
["Old Hillsbrad Foothills"] = "Keepers of Time",
["The Black Morass"] = "Keepers of Time",
["Hyjal Summit"] = "The Scale of the Sands",
["Mana-Tombs"] = "The Consortium",
["Auchenai Crypts"] = "Lower City",
["Sethekk Halls"] = "Lower City",
["Shadow Labyrinth"] = "Lower City",
["The Slave Pens"] = "Cenarion Expedition",
["The Underbog"] = "Cenarion Expedition",
["The Streamvault"] = "Cenarion Expedition",
["Serpentshrine Cavern"] = "Cenarion Expedition",
["The Mechanar"] = "The Sha'tar",
["The Botanica"] = "The Sha'tar",
["The Arcatraz"] = "The Sha'tar",
["The Blood Furnace"] = RepWatch.HellfireRep,
["Hellfire Ramparts"] = RepWatch.HellfireRep,
["The Shattered Halls"] = RepWatch.HellfireRep,
["Karazhan"] = "The Violet Eye",
["Black Temple"] = "Ashtongue Deathsworn",
}
----------|BC Instances|------------
 
--------|Classic Instances|---------
local ClassicInstances = {
["Blackrock Depths"] = "Thorium Brotherhood",
["Blackwing Lair"] = nil,
["Dire Maul"] = "Shen'Dralar",
["Maraudon"] = "Cenarion Circle",
["Molten Core"] = "Hydraxian Waterlords",
["Naxxramas"] = "Argent Dawn",
["Ruins of Ahn'Qiraj"] = "Cenarion Circle",
["Scholomance"] = "Argent Dawn",
["Ahn'Qiraj"] = "Brood of Nozdormu",
["Zul'Gurub"] = "Zandalar Tribe",
}
--------|Classic Instances|---------
 
---------|Capital Cities|-----------
local CapitalCities = {
["Orgrimmar"] = "Orgrimmar",
["Undercity"] = "Undercity",
["Thunder Bluff"] = "Thunder Bluff",
["Silvermoon City"] = "Silvermoon City",
["Stormwind City"] = "Stormwind",
["Ironforge"] = "Ironforge",
["Darnassus"] = "Darnassus",
["The Exodar"] = "Exodar",
["Shattrath City"] = "The Sha'tar",
}
---------|Capital Cities|-----------
 
----------|Battlegrounds|-----------
local Battlegrounds = {
Horde = {
["Warsong Gulch"] ="Warsong Outriders",
["Arathi Basin"] = "The Defilers",
["Alterac Valley"] = "Frostwolf Clan",
},
Alliance = {
["Warsong Gulch"] ="Silverwing Sentinels",
["Arathi Basin"] = "The League of Arathor",
["Alterac Valley"] = "Stormpike Guard",
},
}
----------|Battlegrounds|-----------
 
------------|Sub-Zones|-------------
local SubZones = {
["Isle of Quel'Danas"] = "Shattered Sun Offensive",
["Scryer's Tier"] = "The Scryers",
["Aldor Rise"] = "The Aldor",
 
--Orgi'la Reps
["Forge Camp: Wrath"] = "Ogri'la",
["Vortex Pinnacle"] = "Ogri'la",
["Ogri'la"] = "Ogri'la",
["Forge Camp: Terror"] = "Ogri'la",
 
--Timbermaw Reps
["Timbermaw Hold"] = "Timbermaw Hold",
["Timbermaw Post"] = "Timbermaw Hold",
 
--Thrallmar
["Thrallmar"] = "Thrallmar",
 
--The Mag'har
["Mag'har Grounds"] = "The Mag'har",
["Garadar"] = "The Mag'har",
 
--Sporeggar
["Funggor Cavern"] = "Sporeggar",
["The Spawning Glen"] = "Sporeggar",
 
--Cenarion Expedition
["Cenarion Watchpost"] = "Cenarion Expedition",
}
------------|Sub-Zones|-------------
 
 
 
 
 
--#############--
--# Functions #--
--#############--
 
-------------------------------------
function RepWatch:OnInitialize()
-------------------------------------
--Called When the Addon is Loaded
 
--Register the Database
RepWatch.db = LibStub("AceDB-3.0"):New("RepWatchDB", defaults, "Char")
 
--Register Options Table and Menu
LibStub("AceConfig-3.0"):RegisterOptionsTable("RepWatch", options)
 
--Adds Menu to Blizzard's Menu
self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("RepWatch", "RepWatch")
 
--Register the /RepWatch Chat Command
self:RegisterChatCommand("RepWatch", "ChatCommand")
 
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:OnEnable()
-------------------------------------
--Called When the Addon is Enabled
 
--Register Event Triggers
RepWatch:RegisterEvent("ZONE_CHANGED_NEW_AREA") --Fires everytime Channels Switch
RepWatch:RegisterEvent("ZONE_CHANGED") --Fires everytime Subzones Switch
 
--Print off Version and Enable Message
self:Print("RepWatch Ver.|cff6495ED", RepWatch.Version, "|rLoaded")
self:Print("Type /RepWatch for Options Menu")
self:Print("No |cff6495EDWotlK|r Reputations are Working Yet,\nThis Version is Meant to Test out Compatability\nwith Client 3.0")
 
--Manually Fires Change to Check when Initially Logging In
RepWatch:ZONE_CHANGED_NEW_AREA()
 
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:OnDisable()
-------------------------------------
--called when the Addon is Disabled
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ChatCommand(input)
-------------------------------------
--Handles chat command input
if not input or input:trim() == "" then
InterfaceOptionsFrame_OpenToFrame(self.optionsFrame)
else
--LibStub("AceConfigDialog-3.0").HandleCommand(RepWatch, "RepWatch", input)
RepWatch:Print("Command Not Available, type /RepWatch for Options Menu")
end
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeWotlK(info)
-------------------------------------
return (self.db.char.changeWotlK)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeWotlK(info, value)
-------------------------------------
self.db.char.changeWotlK = value
if (self.db.char.showInChat) then
if (self.db.char.changeWotlK) then
self:Print("Entering |cff6495EDWotlK|r Instances |cff32cd32Will Now|r Switch the Rep Bar")
else
self:Print("Entering |cff6495EDWotlK|r Instances |cffff0000Will Not|r Switch the Rep Bar")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeBC(info)
-------------------------------------
return (self.db.char.changeBC)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeBC(info, value)
-------------------------------------
self.db.char.changeBC = value
if (self.db.char.showInChat) then
if (self.db.char.changeBC) then
self:Print("Entering |cff00CD00BC|r Instances |cff32cd32Will Now|r Switch the Rep Bar")
else
self:Print("Entering |cff00CD00BC|r Instances |cffff0000Will Not|r Switch the Rep Bar")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeClassic(info)
-------------------------------------
return (self.db.char.changeClassic)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeClassic(info, value)
-------------------------------------
self.db.char.changeClassic = value
if (self.db.char.showInChat) then
if (self.db.char.changeClassic) then
self:Print("Entering |cffD2691EClassic|r Instances |cff32cd32Will Now|r Switch the Rep Bar")
else
self:Print("Entering |cffD2691EClassic|r Instances |cffff0000Will Not|r Switch the Rep Bar")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeCities(info)
-------------------------------------
return (self.db.char.changeCities)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeCities(info, value)
-------------------------------------
self.db.char.changeCities = value
if (self.db.char.showInChat) then
if (self.db.char.changeCities) then
self:Print("Entering Capital Cities |cff32cd32Will Now|r Switch the Rep Bar")
else
self:Print("Entering capital Cities |cffff0000Will Not|r Switch the Rep Bar")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeBGs(info)
-------------------------------------
return (self.db.char.changeBGs)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeBGs(info, value)
-------------------------------------
self.db.char.changeBGs = value
if (self.db.char.showInChat) then
if (self.db.char.changeBGs) then
self:Print("Entering Battlegrounds |cff32cd32Will Now|r Switch the Rep Bar")
else
self:Print("Entering Battlegrounds |cffff0000Will Not|r Switch the Rep Bar")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeSubZones(info)
-------------------------------------
return (self.db.char.changeSubZones)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeSubZones(info, value)
-------------------------------------
self.db.char.changeSubZones = value
if (self.db.char.showInChat) then
if (self.db.char.changeSubZones) then
self:Print("Entering Sub-Zones |cff32cd32Will Now|r Switch the Rep Bar")
else
self:Print("Entering Sub-Zones |cffff0000Will Not|r Switch the Rep Bar")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsShowInChat(info)
-------------------------------------
return (self.db.char.showInChat)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleShowInChat(info, value)
-------------------------------------
self.db.char.showInChat = value
if (self.db.char.showInChat) then
self:Print("Notices |cff32cd32Will Now|r Be Shown in the Chat Window")
else
self:Print("Notices |cffff0000Will Not|r Be Shown in the Chat Window")
end
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:IsChangeIfExalted(info)
-------------------------------------
return (self.db.char.changeIfExalted)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ToggleChangeIfExalted(info, value)
-------------------------------------
self.db.char.changeIfExalted = value
if (self.db.char.showInChat) then
if (value) then
self:Print("The Rep Bar |cff32cd32Will Now|r Change When You Are Exalted with a Faction")
else
self:Print("The Rep Bar |cffff0000Will Not|r Change When You Are Exalted with a Faction")
end
end
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:GetDefaultFaction(info)
-------------------------------------
return (self.db.char.defaultFaction)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:SetDefaultFaction(info, value)
-------------------------------------
self.db.char.defaultFaction = value
if (self.db.char.showInChat) then
if (value) == 1 then --Remember: 1 is the eqiv. to "None"
self:Print("The Rep Bar |cffff0000Will Not|r Change if No Faction is Available for the Area")
elseif (value) == 2 then --Remember: 2 is the quiv. to "Auto-Off"
self:Print("The Rep Bar |cff32cd32Will Disappear|r if No Faction is Available for the Area")
else
self:Print("The Rep Bar Will Change to |cff32cd32", GetFactionInfo(value - 2), "|r if No Faction is Available for the Area")
end
end
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:GetAllFactions()
-------------------------------------
local factionList = {
"None",
"Auto-Off",
}
factionListIndex = 3
for factionIndex = 1, GetNumFactions() do
local isHeader = select(9, GetFactionInfo(factionIndex))
if isHeader ~= 1 then
factionList[factionListIndex] = GetFactionInfo(factionIndex)
end
factionListIndex = (factionListIndex + 1)
end
return (factionList)
end
-------------------------------------
-------------------------------------
 
 
-------------------------------------
function RepWatch:ZONE_CHANGED()
-------------------------------------
--RepWatch.Print("Zone Changed Fired")
RepWatch:ZONE_CHANGED_NEW_AREA()
end
-------------------------------------
function RepWatch:ZONE_CHANGED_NEW_AREA()
-------------------------------------
RepWatch.ZoneFound = 0
RepWatch.SubZoneFound = 0
self.usedDefault = 0
RepWatch.usedMini = 0
 
--self:Print("Zone Changed New Area Fired")
 
 
--if (self.db.char.changeWotlK) then
-- RepWatch.ZoneFound = RepWatch:ChangeRep("WotlKInstances")
-- self.colorCode = "|cff6495ED"
--end
 
if (self.db.char.changeBC) and (RepWatch.ZoneFound ~= 1) then
tableName = BCInstances
RepWatch.ZoneFound = RepWatch:ChangeRep(tableName)
self.colorCode = "|cff00CD00"
end
 
if (self.db.char.changeClassic) and (RepWatch.ZoneFound ~= 1) then
tableName = ClassicInstances
RepWatch.ZoneFound = RepWatch:ChangeRep(tableName)
self.colorCode = "|cffEE7621"
end
 
if (self.db.char.changeCities) and (RepWatch.ZoneFound ~= 1) then
tableName = CapitalCities
RepWatch.ZoneFound = RepWatch:ChangeRep(tableName)
self.colorCode = "|cffFFD700"
end
 
if (self.db.char.changeBGs) and (RepWatch.ZoneFound ~= 1) then
tableName = Battlegrounds
RepWatch.ZoneFound = RepWatch:ChangeBGRep(tableName)
self.colorCode = "|cffFFD700"
end
 
if (self.db.char.changeSubZones) then
tableName = SubZones
RepWatch.SubZoneFound = RepWatch:ChangeSubRep(tableName)
self.colorCode = "|cffFFD700"
end
 
--Checks the showInChat Option for Display
if (self.db.char.showInChat == false) then
RepWatch.noDisplay = 1
end
 
if (RepWatch.ZoneFound == 0) and (RepWatch.SubZoneFound == 0) then
self.usedDefault = 1
if (GetWatchedFactionInfo() == GetFactionInfo(self.db.char.defaultFaction - 2)) then
RepWatch.noDisplay = 1
end
if (self.db.char.defaultFaction == 2) then
SetWatchedFactionIndex(0)
if (RepWatch.noDisplay ~= 1) then
self:Print("Auto-Off")
end
elseif (self.db.char.defaultFaction ~= 1) then
SetWatchedFactionIndex(self.db.char.defaultFaction - 2)
if (RepWatch.noDisplay ~= 1) then
self:Print("Changing To: [|cffFFD700" .. GetFactionInfo(self.db.char.defaultFaction - 2) .. "|r]")
end
end
end
 
if (RepWatch.noDisplay ~= 1) and (RepWatch.usedMini ~= 1) then
if (RepWatch.ZoneFound == 1) or (RepWatch.SubZoneFound == 1) then
self:Print("Changing To: [" .. self.colorCode .. RepWatch.factionName .. "|r]")
end
elseif (RepWatch.noDisplay ~= 1) then
if (RepWatch.ZoneFound == 1) or (RepWatch.SubZoneFound == 1) then
self:Print("Changing To: [" .. self.colorCode .. RepWatch.factionName .. "|r]")
end
end
 
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ChangeRep(tableName)
-------------------------------------
RepWatch.noDisplay = 0
 
--RepWatch:Print("Table Name:", tableName)
if (GetWatchedFactionInfo() == tableName[GetRealZoneText()]) then
RepWatch.noDisplay = 1
end
 
--Sets the Watched Faction using Real Zone Text
for factionIndex = 1, GetNumFactions() do
RepWatch.factionName = GetFactionInfo(factionIndex)
if RepWatch.factionName == tableName[GetRealZoneText()] then
if (select(6, GetFactionInfo(factionIndex)) == 42999) then
 
if (self.db.char.changeIfExalted) then
SetWatchedFactionIndex(factionIndex)
else
return (0)
end
else
SetWatchedFactionIndex(factionIndex)
end
return (1)
end
end
 
if (GetWatchedFactionInfo() == tableName[GetMinimapZoneText()]) then
RepWatch.noDisplay = 1
end
 
--Sets the Watched Faction using Minimap Zone Text
for factionIndex = 1, GetNumFactions() do
RepWatch.factionName = GetFactionInfo(factionIndex)
if RepWatch.factionName == tableName[GetMinimapZoneText()] then
if (select(6, GetFactionInfo(factionIndex)) == 42999) then
 
if (self.db.char.changeIfExalted) then
SetWatchedFactionIndex(factionIndex)
else
return (0)
end
else
SetWatchedFactionIndex(factionIndex)
end
return (1)
end
end
 
return (0)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ChangeBGRep(tableName)
-------------------------------------
RepWatch.noDisplay = 0
--RepWatch:Print("Table Name:", tableName)
if (GetWatchedFactionInfo() == tableName[UnitFactionGroup("player")][GetRealZoneText()]) then
RepWatch.noDisplay = 1
end
--Sets the Watched Faction
for factionIndex = 1, GetNumFactions() do
RepWatch.factionName = GetFactionInfo(factionIndex)
if RepWatch.factionName == tableName[UnitFactionGroup("player")][GetRealZoneText()] then
if (select(6, GetFactionInfo(factionIndex)) == 42999) then
self.isExalted = 1
if (self.db.char.changeIfExalted) then
SetWatchedFactionIndex(factionIndex)
else
return (0)
end
else
SetWatchedFactionIndex(factionIndex)
end
return (1)
end
end
return (0)
end
-------------------------------------
-------------------------------------
 
-------------------------------------
function RepWatch:ChangeSubRep(tableName)
-------------------------------------
 
--RepWatch:Print("Table Name:", tableName)
if (GetWatchedFactionInfo() == tableName[GetRealZoneText()]) then
RepWatch.noDisplay = 1
end
 
--Sets the Watched Faction using Real Zone Text
for factionIndex = 1, GetNumFactions() do
RepWatch.factionName2 = GetFactionInfo(factionIndex)
if RepWatch.factionName2 == tableName[GetRealZoneText()] then
RepWatch.noDisplay = 0
if (GetWatchedFactionInfo() == tableName[GetRealZoneText()]) then
RepWatch.noDisplay = 1
end
RepWatch.factionName = RepWatch.factionName2
if (select(6, GetFactionInfo(factionIndex)) == 42999) then
self.isExalted = 1
if (self.db.char.changeIfExalted) then
SetWatchedFactionIndex(factionIndex)
else
return (0)
end
else
SetWatchedFactionIndex(factionIndex)
end
return (1)
end
end
 
--Sets the Watched Faction using Sub Zone Text
for factionIndex = 1, GetNumFactions() do
RepWatch.factionName2 = GetFactionInfo(factionIndex)
if RepWatch.factionName2 == tableName[GetSubZoneText()] then
RepWatch.noDisplay = 0
if (GetWatchedFactionInfo() == tableName[GetSubZoneText()]) then
RepWatch.noDisplay = 1
end
RepWatch.factionName = RepWatch.factionName2
if (select(6, GetFactionInfo(factionIndex)) == 42999) then
self.isExalted = 1
if (self.db.char.changeIfExalted) then
SetWatchedFactionIndex(factionIndex)
else
return (0)
end
else
SetWatchedFactionIndex(factionIndex)
end
return (1)
end
end
return (0)
end
-------------------------------------
-------------------------------------
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/split.bat New file
0,0 → 1,20
@echo off
for /D %%i in (*-?.*) do call :splitone %%i
move Ace3.toc Ace3.toc.unsplit
echo ##Interface: 20400 > Ace3.toc
echo ##Title: Lib: Ace3 >> Ace3.toc
echo ##OptionalDeps: AceAddon-3.0, AceConsole-3.0, AceConfig-3.0 >> Ace3.toc
echo LibStub\LibStub.lua >> Ace3.toc
echo Ace3.lua >> Ace3.toc
goto :eof
 
:splitone
echo Splitting off %1...
echo %1 >> split.txt
echo ##Interface: 20400 > %1\%1.toc
echo ##Title: Lib: %1 >> %1\%1.toc
if not "%1" == "CallbackHandler-1.0" echo ##OptionalDeps: LibStub, CallbackHandler-1.0, AceGUI-3.0, AceConsole-3.0 >> %1\%1.toc
echo ##LoadWith: Ace3 >> %1\%1.toc
echo %1.xml >> %1\%1.toc
move %1 ..
goto :eof
\ No newline at end of file Property changes : Added: svn:eol-style + CRLF Added: svn:mime-type + text/plain
RepWatch/Libs/LICENSE.txt New file
0,0 → 1,29
Copyright (c) 2007, Ace3 Development Team
 
All rights reserved.
 
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
 
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Redistribution of a stand alone version is strictly prohibited without
prior written authorization from the Lead of the Ace3 Development Team.
* Neither the name of the Ace3 Development Team nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceComm-3.0/ChatThrottleLib.lua New file
0,0 → 1,456
--
-- ChatThrottleLib by Mikk
--
-- Manages AddOn chat output to keep player from getting kicked off.
--
-- ChatThrottleLib.SendChatMessage/.SendAddonMessage functions that accept
-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
--
-- Priorities get an equal share of available bandwidth when fully loaded.
-- Communication channels are separated on extension+chattype+destination and
-- get round-robinned. (Destination only matters for whispers and channels,
-- obviously)
--
-- Will install hooks for SendChatMessage and SendAdd[Oo]nMessage to measure
-- bandwidth bypassing the library and use less bandwidth itself.
--
--
-- Fully embeddable library. Just copy this file into your addon directory,
-- add it to the .toc, and it's done.
--
-- Can run as a standalone addon also, but, really, just embed it! :-)
--
 
local CTL_VERSION = 19
 
if _G.ChatThrottleLib and _G.ChatThrottleLib.version >= CTL_VERSION then
-- There's already a newer (or same) version loaded. Buh-bye.
return
end
 
if not _G.ChatThrottleLib then
_G.ChatThrottleLib = {}
end
 
ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above use and we're copypasted (AceComm, sigh)
local ChatThrottleLib = _G.ChatThrottleLib
 
------------------ TWEAKABLES -----------------
 
ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
 
ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
 
ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
 
 
local setmetatable = setmetatable
local table_remove = table.remove
local tostring = tostring
local GetTime = GetTime
local math_min = math.min
local math_max = math.max
local next = next
local strlen = string.len
 
ChatThrottleLib.version = CTL_VERSION
 
 
-----------------------------------------------------------------------
-- Double-linked ring implementation
 
local Ring = {}
local RingMeta = { __index = Ring }
 
function Ring:New()
local ret = {}
setmetatable(ret, RingMeta)
return ret
end
 
function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
if self.pos then
obj.prev = self.pos.prev
obj.prev.next = obj
obj.next = self.pos
obj.next.prev = obj
else
obj.next = obj
obj.prev = obj
self.pos = obj
end
end
 
function Ring:Remove(obj)
obj.next.prev = obj.prev
obj.prev.next = obj.next
if self.pos == obj then
self.pos = obj.next
if self.pos == obj then
self.pos = nil
end
end
end
 
 
 
-----------------------------------------------------------------------
-- Recycling bin for pipes
-- A pipe is a plain integer-indexed queue, which also happens to be a ring member
 
ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
local PipeBin = setmetatable({}, {__mode="k"})
 
local function DelPipe(pipe)
for i = #pipe, 1, -1 do
pipe[i] = nil
end
pipe.prev = nil
pipe.next = nil
 
PipeBin[pipe] = true
end
 
local function NewPipe()
local pipe = next(PipeBin)
if pipe then
PipeBin[pipe] = nil
return pipe
end
return {}
end
 
 
 
 
-----------------------------------------------------------------------
-- Recycling bin for messages
 
ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
local MsgBin = setmetatable({}, {__mode="k"})
 
local function DelMsg(msg)
msg[1] = nil
-- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
MsgBin[msg] = true
end
 
local function NewMsg()
local msg = next(MsgBin)
if msg then
MsgBin[msg] = nil
return msg
end
return {}
end
 
 
-----------------------------------------------------------------------
-- ChatThrottleLib:Init
-- Initialize queues, set up frame for OnUpdate, etc
 
 
function ChatThrottleLib:Init()
 
-- Set up queues
if not self.Prio then
self.Prio = {}
self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
end
 
-- v4: total send counters per priority
for _, Prio in pairs(self.Prio) do
Prio.nTotalSent = Prio.nTotalSent or 0
end
 
if not self.avail then
self.avail = 0 -- v5
end
if not self.nTotalSent then
self.nTotalSent = 0 -- v5
end
 
 
-- Set up a frame to get OnUpdate events
if not self.Frame then
self.Frame = CreateFrame("Frame")
self.Frame:Hide()
end
self.Frame:SetScript("OnUpdate", self.OnUpdate)
self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
self.OnUpdateDelay = 0
self.LastAvailUpdate = GetTime()
self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
 
-- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
if not self.ORIG_SendChatMessage then
-- use secure hooks instead of insecure hooks (v16)
self.securelyHooked = true
--SendChatMessage
self.ORIG_SendChatMessage = SendChatMessage
hooksecurefunc("SendChatMessage", function(...)
return ChatThrottleLib.Hook_SendChatMessage(...)
end)
self.ORIG_SendAddonMessage = SendAddonMessage
--SendAddonMessage
hooksecurefunc("SendAddonMessage", function(...)
return ChatThrottleLib.Hook_SendAddonMessage(...)
end)
end
self.nBypass = 0
end
 
 
-----------------------------------------------------------------------
-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
local self = ChatThrottleLib
local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
if not self.securelyHooked then
self.ORIG_SendChatMessage(text, chattype, language, destination, ...)
end
end
function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
local self = ChatThrottleLib
local size = tostring(text or ""):len() + tostring(prefix or ""):len();
size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD
self.avail = self.avail - size
self.nBypass = self.nBypass + size -- just a statistic
if not self.securelyHooked then
self.ORIG_SendAddonMessage(prefix, text, chattype, destination, ...)
end
end
 
 
 
-----------------------------------------------------------------------
-- ChatThrottleLib:UpdateAvail
-- Update self.avail with how much bandwidth is currently available
 
function ChatThrottleLib:UpdateAvail()
local now = GetTime()
local MAX_CPS = self.MAX_CPS;
local newavail = MAX_CPS * (now - self.LastAvailUpdate)
local avail = self.avail
 
if now - self.HardThrottlingBeginTime < 5 then
-- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
self.bChoking = true
elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
avail = math_min(MAX_CPS, avail + newavail*0.5)
self.bChoking = true -- just a statistic
else
avail = math_min(self.BURST, avail + newavail)
self.bChoking = false
end
 
avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
 
self.avail = avail
self.LastAvailUpdate = now
 
return avail
end
 
 
-----------------------------------------------------------------------
-- Despooling logic
 
function ChatThrottleLib:Despool(Prio)
local ring = Prio.Ring
while ring.pos and Prio.avail > ring.pos[1].nSize do
local msg = table_remove(Prio.Ring.pos, 1)
if not Prio.Ring.pos[1] then
local pipe = Prio.Ring.pos
Prio.Ring:Remove(pipe)
Prio.ByName[pipe.name] = nil
DelPipe(pipe)
else
Prio.Ring.pos = Prio.Ring.pos.next
end
Prio.avail = Prio.avail - msg.nSize
msg.f(unpack(msg, 1, msg.n))
Prio.nTotalSent = Prio.nTotalSent + msg.nSize
DelMsg(msg)
end
end
 
 
function ChatThrottleLib.OnEvent(this,event)
-- v11: We know that the rate limiter is touchy after login. Assume that it's touch after zoning, too.
local self = ChatThrottleLib
if event == "PLAYER_ENTERING_WORLD" then
self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
self.avail = 0
end
end
 
 
function ChatThrottleLib.OnUpdate(this,delay)
local self = ChatThrottleLib
 
self.OnUpdateDelay = self.OnUpdateDelay + delay
if self.OnUpdateDelay < 0.08 then
return
end
self.OnUpdateDelay = 0
 
self:UpdateAvail()
 
if self.avail < 0 then
return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
end
 
-- See how many of our priorities have queued messages
local n = 0
for prioname,Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
n = n + 1
end
end
 
-- Anything queued still?
if n<1 then
-- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
for prioname, Prio in pairs(self.Prio) do
self.avail = self.avail + Prio.avail
Prio.avail = 0
end
self.bQueueing = false
self.Frame:Hide()
return
end
 
-- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
local avail = self.avail/n
self.avail = 0
 
for prioname, Prio in pairs(self.Prio) do
if Prio.Ring.pos or Prio.avail < 0 then
Prio.avail = Prio.avail + avail
if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
self:Despool(Prio)
end
end
end
 
end
 
 
 
 
-----------------------------------------------------------------------
-- Spooling logic
 
 
function ChatThrottleLib:Enqueue(prioname, pipename, msg)
local Prio = self.Prio[prioname]
local pipe = Prio.ByName[pipename]
if not pipe then
self.Frame:Show()
pipe = NewPipe()
pipe.name = pipename
Prio.ByName[pipename] = pipe
Prio.Ring:Add(pipe)
end
 
pipe[#pipe + 1] = msg
 
self.bQueueing = true
end
 
 
 
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName)
if not self or not prio or not text or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix" or nil, "text"[, "chattype"[, "language"[, "destination"]]]', 2)
end
 
prefix = prefix or tostring(this) -- each frame gets its own queue if prefix is not given
 
local nSize = text:len()
 
assert(nSize<=255, "text length cannot exceed 255 bytes");
 
nSize = nSize + self.MSG_OVERHEAD
 
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
self.ORIG_SendChatMessage(text, chattype, language, destination)
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
return
end
 
-- Message needs to be queued
local msg = NewMsg()
msg.f = self.ORIG_SendChatMessage
msg[1] = text
msg[2] = chattype or "SAY"
msg[3] = language
msg[4] = destination
msg.n = 4
msg.nSize = nSize
 
self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
end
 
 
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName)
if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 0)
end
 
local nSize = prefix:len() + 1 + text:len();
 
assert(nSize<=255, "prefix + text length cannot exceed 254 bytes");
 
nSize = nSize + self.MSG_OVERHEAD;
 
-- Check if there's room in the global available bandwidth gauge to send directly
if not self.bQueueing and nSize < self:UpdateAvail() then
self.avail = self.avail - nSize
self.ORIG_SendAddonMessage(prefix, text, chattype, target)
self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
return
end
 
-- Message needs to be queued
local msg = NewMsg()
msg.f = self.ORIG_SendAddonMessage
msg[1] = prefix
msg[2] = text
msg[3] = chattype
msg[4] = target
msg.n = (target~=nil) and 4 or 3;
msg.nSize = nSize
 
self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
end
 
 
 
 
-----------------------------------------------------------------------
-- Get the ball rolling!
 
ChatThrottleLib:Init()
 
--[[ WoWBench debugging snippet
if(WOWB_VER) then
local function SayTimer()
print("SAY: "..GetTime().." "..arg1)
end
ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
end
]]
 
 
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceComm-3.0/AceComm-3.0.xml New file
0,0 → 1,5
<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="ChatThrottleLib.lua"/>
<Script file="AceComm-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceComm-3.0/AceComm-3.0.lua New file
0,0 → 1,285
--[[ $Id: AceComm-3.0.lua 66660 2008-03-28 10:40:54Z nevcairiel $ ]]
 
--[[ AceComm-3.0
 
TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited.
 
]]
 
local MAJOR, MINOR = "AceComm-3.0", 4
 
local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceComm then return end
 
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
 
local type = type
local strsub = string.sub
local strfind = string.find
local tinsert = table.insert
local tconcat = table.concat
 
AceComm.embeds = AceComm.embeds or {}
 
-- for my sanity and yours, let's give the message type bytes names
local MSG_MULTI_FIRST = "\001"
local MSG_MULTI_NEXT = "\002"
local MSG_MULTI_LAST = "\003"
 
AceComm.multipart_origprefixes = AceComm.multipart_origprefixes or {} -- e.g. "Prefix\001"="Prefix", "Prefix\002"="Prefix"
AceComm.multipart_reassemblers = AceComm.multipart_reassemblers or {} -- e.g. "Prefix\001"="OnReceiveMultipartFirst"
 
-- the multipart message spool: indexed by a combination of sender+distribution+
AceComm.multipart_spool = AceComm.multipart_spool or {}
 
 
-----------------------------------------------------------------------
-- API RegisterComm(prefix, method)
-- - prefix (string) A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- - method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
 
function AceComm:RegisterComm(prefix, method)
if method == nil then
method = "OnCommReceived"
end
 
return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
end
 
 
-----------------------------------------------------------------------
-- API SendCommMessage(prefix, text, distribution, target, prio)
-- - prefix (string) A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
-- - text (string) Data to send, nils (\000) not allowed. Any length.
-- - distribution (string) Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
-- - target (string) Destination for some distributions; see SendAddonMessage API
-- - prio (string) OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
 
function AceComm:SendCommMessage(prefix, text, distribution, target, prio)
prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery!
if not( type(prefix)=="string" and
type(text)=="string" and
type(distribution)=="string" and
(target==nil or type(target)=="string") and
(prio=="BULK" or prio=="NORMAL" or prio=="ALERT")
) then
error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"]])', 2)
end
 
if strfind(prefix, "[\001-\003]") then
error("SendCommMessage: Characters \\001--\\003) in prefix are reserved for AceComm metadata", 2)
end
 
 
local textlen = #text
local maxtextlen = 254 - #prefix -- 254 is the max length of prefix + text that can be sent in one message
local queueName = prefix..distribution..(target or "")
 
if textlen <= maxtextlen then
-- fits all in one message
CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName)
else
maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in suffix
 
-- first part
local chunk = strsub(text, 1, maxtextlen)
CTL:SendAddonMessage(prio, prefix..MSG_MULTI_FIRST, chunk, distribution, target, queueName)
 
-- continuation
local pos = 1+maxtextlen
local prefix2 = prefix..MSG_MULTI_NEXT
 
while pos+maxtextlen <= textlen do
chunk = strsub(text, pos, pos+maxtextlen-1)
CTL:SendAddonMessage(prio, prefix2, chunk, distribution, target, queueName)
pos = pos + maxtextlen
end
 
-- final part
chunk = strsub(text, pos)
CTL:SendAddonMessage(prio, prefix..MSG_MULTI_LAST, chunk, distribution, target, queueName)
end
end
 
 
----------------------------------------
-- Message receiving
----------------------------------------
 
do
local compost = setmetatable({}, {__mode=="k"})
local function new()
local t = next(compost)
if t then
compost[t]=nil
for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
t[i]=nil
end
return t
end
 
return {}
end
 
local function lostdatawarning(prefix,sender,where)
DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
end
 
function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
 
--[[
if spool[key] then
lostdatawarning(prefix,sender,"First")
-- continue and overwrite
end
--]]
 
spool[key] = message -- plain string for now
end
 
function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
 
if not olddata then
--lostdatawarning(prefix,sender,"Next")
return
end
 
if type(olddata)~="table" then
-- ... but what we have is not a table. So make it one. (Pull a composted one if available)
local t = new()
t[1] = olddata -- add old data as first string
t[2] = message -- and new message as second string
spool[key] = t -- and put the table in the spool instead of the old string
else
tinsert(olddata, message)
end
end
 
function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
local spool = AceComm.multipart_spool
local olddata = spool[key]
 
if not olddata then
--lostdatawarning(prefix,sender,"End")
return
end
 
spool[key] = nil
 
if type(olddata)=="table" then
-- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
tinsert(olddata, message)
AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender)
compost[olddata]=true
else
-- if we've only received a "first", the spooled data will still only be a string
AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender)
end
end
end
 
 
 
 
 
 
----------------------------------------
-- Embed CallbackHandler
----------------------------------------
 
if not AceComm.callbacks then
-- ensure that 'prefix to watch' table is consistent with registered
-- callbacks
AceComm.__prefixes = {}
 
AceComm.callbacks = CallbackHandler:New(AceComm,
"_RegisterComm",
"UnregisterComm",
"UnregisterAllComm")
end
 
function AceComm.callbacks:OnUsed(target, prefix)
AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = "OnReceiveMultipartFirst"
 
AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = "OnReceiveMultipartNext"
 
AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = prefix
AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = "OnReceiveMultipartLast"
end
 
function AceComm.callbacks:OnUnused(target, prefix)
AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = nil
 
AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = nil
 
AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = nil
AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = nil
end
 
----------------------------------------
-- Event driver
----------------------------------------
 
local function OnEvent(this, event, ...)
if event == "CHAT_MSG_ADDON" then
local prefix,message,distribution,sender = ...
local reassemblername = AceComm.multipart_reassemblers[prefix]
if reassemblername then
-- multipart: reassemble
local aceCommReassemblerFunc = AceComm[reassemblername]
local origprefix = AceComm.multipart_origprefixes[prefix]
aceCommReassemblerFunc(AceComm, origprefix, message, distribution, sender)
else
-- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
AceComm.callbacks:Fire(prefix, message, distribution, sender)
end
else
assert(false, "Received "..tostring(event).." event?!")
end
end
 
AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
AceComm.frame:SetScript("OnEvent", OnEvent)
AceComm.frame:UnregisterAllEvents()
AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
 
 
----------------------------------------
-- Base library stuff
----------------------------------------
 
local mixins = {
"RegisterComm",
"UnregisterComm",
"UnregisterAllComm",
"SendCommMessage",
}
 
function AceComm:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
 
function AceComm:OnEmbedDisable(target)
target:UnregisterAllComm()
end
 
-- Update embeds
for target, v in pairs(AceComm.embeds) do
AceComm:Embed(target)
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/benchs/Bench-AceTimer-3.0/Bench-AceTimer-3.0.toc New file
0,0 → 1,4
## Interface: 20100
## Title: Bench-AceTimer-3.0
 
bench1.lua
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/benchs/Bench-AceTimer-3.0/bench1.lua New file
0,0 → 1,102
-- What did I do with this bench:
-- 1. Log in WoW with this addon loaded.
-- 2. Find somewhere and stare at the wall to have a more constant FPS, check the FPS value.
-- 3. type "/test start" to start running 2000 OnUpdate frames, check how much the FPS suffers.
-- 4. type "/test stop" to hide frames, make sure the FPS went back the original value.
-- 5. type "/test2 start" to start 2000 AceTimer-3.0 timers, check the FPS.
-- 6. type "/test2 stop" to cancel the timers, make sure the FPS went back to original value.
 
 
-- Make sure AceTimer-3.0's Hz value supports this delay.
local DELAY = 0.05
 
-- OnUpdate Frames.
do
local mainFrame = CreateFrame("Frame")
local frames = {}
 
local count = 0
local function DoSomething()
count = count + 1
end
 
local delay = 0
local function OnUpdate(frame,elapsed)
delay = delay + elapsed
if delay > DELAY then
delay = 0
DoSomething()
end
end
 
local function CreateNewFrame()
local frame = CreateFrame("Frame")
frame:SetScript("OnUpdate", OnUpdate)
table.insert(frames,frame)
frame.id = #frames
return frame
end
 
local function SlashParser(cmd)
if cmd == 'start' then
if #frames == 0 then
ChatFrame1:AddMessage("Creating 2000 frames.")
for i=1,2000 do
local frame = CreateNewFrame()
frame:Show()
end
else
ChatFrame1:AddMessage("Showing all frames.")
for i, frame in ipairs(frames) do
frame:Show()
end
end
elseif cmd == 'stop' then
ChatFrame1:AddMessage("Hiding all frames.")
for i, frame in ipairs(frames) do
frame:Hide()
end
elseif cmd == 'stat' then
ChatFrame1:AddMessage(count)
end
end
 
SlashCmdList["TESTONUPDATE"] = SlashParser
SLASH_TESTONUPDATE1 = "/test"
end
 
 
-- AceTimer-3.0
do
local Timer = LibStub("AceTimer-3.0")
local timers = {}
local addon = {}
 
local count = 0
addon.DoSomething = function()
count = count + 1
end
 
local function CreateNewTimer()
local timer = Timer.ScheduleRepeatingTimer(addon,"DoSomething",DELAY)
table.insert(timers,timer)
return timer
end
 
local function SlashParser(cmd)
if cmd == 'start' then
ChatFrame1:AddMessage("Creating 2000 timers.")
for i=1,2000 do
CreateNewTimer()
end
elseif cmd == 'stop' then
ChatFrame1:AddMessage("Cancelling all timers.")
Timer.CancelAllTimers(addon)
elseif cmd == 'stat' then
ChatFrame1:AddMessage(count)
end
end
 
SlashCmdList["TESTACETIMER"] = SlashParser
SLASH_TESTACETIMER1 = "/test2"
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/runall.bat New file
0,0 → 1,25
@echo off
echo.
echo Running all -?.x test cases:
echo.
 
setlocal
if _%lua%_==__ set lua=lua
 
for %%i in (*-?.*.lua) do call :runtest %%i
 
 
echo.
echo -----------------------
echo DONE!
echo.
echo (To point at a specific lua.exe, use "set lua=c:\path\to\lua.exe" prior to executing %0)
echo.
pause
goto :eof
 
 
:runtest
echo ----- Running %1:
%lua% %1
goto :eof
Property changes : Added: svn:eol-style + CRLF Added: svn:mime-type + text/plain
RepWatch/Libs/tests/AceTimer-3.0-test1.lua New file
0,0 → 1,197
-- Test1: Tests basic functionality and upgrading of AceTimer
 
dofile("wow_api.lua")
dofile("LibStub.lua")
 
local MAJOR = "AceTimer-3.0"
 
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
local AceTimer,minor = LibStub:GetLibrary(MAJOR)
_G.AceTimer=AceTimer
 
-----------------------------------------------------------------------
-- Test embedding
 
local obj={}
AceTimer:Embed(obj)
 
assert(type(obj.ScheduleTimer)=="function")
assert(type(obj.ScheduleRepeatingTimer)=="function")
assert(type(obj.CancelTimer)=="function")
assert(type(obj.CancelAllTimers)=="function")
 
 
 
-----------------------------------------------------------------------
-- Test basic registering, both ways
 
t1s = 0
function obj:Timer1(arg)
assert(self==obj)
assert(arg=="t1")
t1s = t1s + 1
end
 
t2s = 0
function Timer2(arg)
assert(arg=="t2")
t2s = t2s + 1
end
 
function obj:Timer3()
assert(false) -- This should never run!
end
 
t4s=0
t5s=0
local function Timer4_5(arg)
assert(arg=="t4s" or arg=="t5s", dump(arg))
_G[arg] = _G[arg] + 1
end
function obj:Timer4(arg)
assert(self==obj)
Timer4_5(arg)
end
 
-- 3 repeating timers:
timer1 = obj:ScheduleRepeatingTimer("Timer1", 1, "t1")
timer2 = obj:ScheduleRepeatingTimer(Timer2, 2, "t2")
timer3 = obj:ScheduleRepeatingTimer("Timer3", 3, "t3")
 
-- 2 single shot timers:
timer4 = obj:ScheduleTimer("Timer4", 1, "t4s")
timer5 = obj.ScheduleTimer("myObj", Timer4_5, 2, "t5s") -- string as self
 
 
t3s = 0
function obj:Timer3(arg) -- This should be the one to run, not the old Timer3
assert(self==obj)
assert(arg=="t3")
t3s = t3s + 1
end
 
 
-----------------------------------------------------------------------
-- Now do some basic tests of timers running at the right time and
-- the right amount of times
 
 
WoWAPI_FireUpdate(0)
assert(t1s==0 and t2s==0 and t3s==0 and t4s==0 and t5s==0)
 
WoWAPI_FireUpdate(0.99)
assert(t1s==0 and t2s==0 and t3s==0 and t4s==0 and t5s==0)
 
WoWAPI_FireUpdate(1.00)
assert(t1s==1 and t2s==0 and t3s==0 and t4s==1 and t5s==0, dump(t1s,t2s,t3s,t4s,t5s))
 
WoWAPI_FireUpdate(1.99)
assert(t1s==1 and t2s==0 and t3s==0 and t4s==1 and t5s==0)
 
WoWAPI_FireUpdate(2.5)
assert(t1s==2 and t2s==1 and t3s==0 and t4s==1 and t5s==1)
 
WoWAPI_FireUpdate(2.99)
assert(t1s==2 and t2s==1 and t3s==0)
 
WoWAPI_FireUpdate(3.099)
assert(t1s==3 and t2s==1, t2s and t3s==1, t3s)
 
WoWAPI_FireUpdate(6.000)
assert(t3s==2)
 
assert(t4s==1 and t5s==1) -- make sure our single shot timers haven't run more than once
 
 
 
t6s=0
obj:ScheduleTimer(function() t6s=t6s+1 end, 1) -- fire up a single oneshot timer to live past our upgrade below
 
 
-----------------------------------------------------------------------
-- Screw up our mixins, pretend to have an older acetimer loaded, and reload acetimer
 
obj.ScheduleTimer = 12345
 
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
assert(obj.ScheduleTimer == 12345) -- shouldn't have gotten replaced yet
 
LibStub.minors[MAJOR] = LibStub.minors[MAJOR] - 1
 
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
assert(type(obj.ScheduleTimer)=="function") -- should have been replaced now
 
 
-----------------------------------------------------------------------
-- Test that timers still live
 
t1s, t2s, t3s, t4s, t5s = 0,0,0,0,0
 
WoWAPI_FireUpdate(6.5)
assert(t1s==0 and t2s==0 and t3s==0 and t4s==0 and t5s==0 and t6s==0)
 
WoWAPI_FireUpdate(7.7)
assert(t1s==1 and t2s==0 and t3s==0 and t4s==0 and t5s==0 and t6s==1, dump(t1s,t2s,t3s,t4s,t5s,t6s))
 
WoWAPI_FireUpdate(9.8)
assert(t1s==2 and t2s==1 and t3s==1 and t4s==0 and t5s==0 and t6s==1) -- NOTE: t1s will only fire ONCE now, since we had a >1.99s lag!
 
 
 
-----------------------------------------------------------------------
-- Test cancelling
-- - test right and wrong 'self'
-- - test cancelling from within the timer
 
t1s, t2s, t3s, t4s, t5s, t6s = 0,0,0,0,0,0
 
assert(not AceTimer:CancelTimer(timer1, true)) -- wrong self, shouldnt cancel anything
 
assert(obj:CancelTimer(timer1)) -- right self - cancel timer1
 
WoWAPI_FireUpdate(10.01)
assert(t1s==0 and t2s==1) -- timer 2 should still work
 
obj.Timer3 = function()
t3s=t3s+1
t3cancelled=true
assert(obj:CancelTimer(timer3))
end
 
WoWAPI_FireUpdate(13.01)
assert(t1s==0 and t2s==2 and t3s==1)
assert(t3cancelled)
 
WoWAPI_FireUpdate(16.01)
assert(t1s==0 and t2s==3 and t3s==1, t1s..t2s..t3s)
assert(t3cancelled)
 
 
t1s, t2s, t3s, t4s, t5s = 0,0,0,0,0
 
obj:CancelAllTimers()
 
local i = 17
local e = i + AceTimer.debug.BUCKETS / AceTimer.debug.HZ * 5 -- 5 full loops of all buckets
while i < e do
i=i+math.random()
WoWAPI_FireUpdate(i) -- long time in the future
end
assert(t1s==0 and t2s==0 and t3s==0 and t4s==0 and t5s==0 and t6s==0) -- nothing should have fired
 
 
-----------------------------------------------------------------------
--
 
for i=1,AceTimer.debug.BUCKETS do
if AceTimer.hash[i]~=false then
error("AceTimer.hash["..i.."] was '"..tostring(AceTimer.hash[i]).."' - expected false")
end
end
 
-----------------------------------------------------------------------
 
print "OK"
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/runall.sh New file
0,0 → 1,20
echo
echo Running all -?.x test cases:
echo
 
if [ -z $lua ]; then
lua=lua
fi
 
for i in *-?.*.lua; do
echo ----- Running $i:
$lua $i
done
 
 
echo
echo -----------------------
echo DONE!
echo
echo '(To point at a specific lua.exe, use "export lua=/path/to/lua" prior to executing runall.sh)'
echo
Property changes : Added: svn:eol-style + LF Added: svn:executable + Added: svn:mime-type + text/plain
RepWatch/Libs/tests/CallbackHandler-1.0.lua New file
0,0 → 1,362
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
 
local CH = assert(LibStub("CallbackHandler-1.0"))
 
 
-----------------------------------------------------------------------
-- test default names
do
local test = {}
CH:New(test, nil, nil, nil)
 
assert(test.RegisterCallback)
assert(test.UnregisterCallback)
assert(test.UnregisterAllCallbacks)
end
 
 
-----------------------------------------------------------------------
-- test custom names
do
local test = {}
CH:New(test, "Reg", "Unreg", "UnregAll")
 
assert(test.Reg)
assert(test.Unreg)
assert(test.UnregAll)
end
 
 
-----------------------------------------------------------------------
-- test with unregall==false
do
local test = {}
CH:New(test, "Reg", "Unreg", false)
 
assert(test.Reg)
assert(test.Unreg)
assert(test.UnregisterAllCallbacks == nil)
end
 
 
-----------------------------------------------------------------------
-- test OnUsed / OnUnused
do
local test = {}
 
local n=0
 
local reg = CH:New(test, "Reg", "Unreg", "UnregAll")
 
local lastOnUsed
function reg:OnUsed(target, event)
assert(self==reg)
assert(target==test)
lastOnUsed=event
n=n+1
end
 
local lastOnUnused
function reg:OnUnused(target, event)
assert(self==reg)
assert(target==test)
lastOnUnused=event
n=n+1
end
 
 
local function func() end
 
test.Reg("addon1", "Thing1", func) -- should fire an OnUsed Thing1
assert(n==1 and lastOnUsed=="Thing1")
 
test.Reg("addon1", "Thing2", func) -- should fire an OnUsed Thing2
assert(n==2 and lastOnUsed=="Thing2")
 
test.Reg("addon1", "Thing1", func) -- should NOT fire an OnUsed (Thing1 seen already)
assert(n==2)
 
test.Reg("addon2", "Thing1", func) -- should NEITHER fire an OnUsed (Thing1 seen already)
assert(n==2)
 
test.Reg("addon2", "Thing2", func) -- should NEITHER fire an OnUsed (Thing2 seen already)
assert(n==2)
 
-- now start unregging Thing1
 
test.Unreg("addon1", "Thing1") -- Still one left, shouldnt fire OnUnused yet
assert(n==2)
 
test.Unreg("addon2", "Thing1")
assert(n==3 and lastOnUnused=="Thing1", dump(n,lastOnUnused)) -- Now we should get OnUnused Thing1
 
-- aaand unreg Thing2 (via some UnregAlls)
 
test.UnregAll("addon1")
assert(n==3)
test.UnregAll("addon2")
assert(n==4 and lastOnUnused=="Thing2")
 
end
 
 
-----------------------------------------------------------------------
-- ACE-67: Test registering new handlers for an event while in a callback for that event
--
-- Problem: for k,v in pairs(eventlist) eventlist[somethingnew]=foo end
-- This happens when we fire callback X, and the handler registers another handler for X
 
do
local test={}
local reg = CH:New(test, "Reg", "Unreg", "UnregAll")
local REPEATS = 1000 -- we get roughly 50% failure ratio, so 1000 tests WILL trigger it
 
local hasRun = {}
local hasRunNoops = {}
 
local function noop(noopName)
hasRunNoops[noopName]=hasRunNoops[noopName]+1
end
 
local rnd=math.random
 
local regMore=true
local function RegOne(name)
hasRun[name]=hasRun[name]+1
if regMore then
local noopName
repeat
noopName = tostring(rnd(1,99999999))
until not hasRunNoops[noopName] and not hasRun[noopName]
hasRunNoops[noopName]=0
test.Reg(noopName, "EVENT", noop, noopName)
end
end
 
for i=1,REPEATS do
local name
repeat
name=tostring(rnd(1,99999999))
until not hasRun[name]
hasRun[name]=0
test.Reg(name, "EVENT", RegOne, name)
end
 
-- Firing this event should lead to all 1000 callbacks running, and registering another 1000 callbacks
reg:Fire("EVENT")
 
-- Test that they all ran once
local n=0
for k,v in pairs(hasRun) do
assert(v==1, dump(k,v).." should be ==1")
n=n+1
end
assert(n==REPEATS, dump(n))
 
-- And that all the noops didnt run (they should have been delayed til the next fire)
local n=0
for k,v in pairs(hasRunNoops) do
assert(v==0, dump(k,v).." should be ==0")
n=n+1
end
assert(n==REPEATS, dump(n))
 
 
-- Now we run all of them again without registering more, so we should get 1000+1000 callbacks
regMore=false
reg:Fire("EVENT")
 
-- Test that all main events ran another time (total 2)
local n=0
for k,v in pairs(hasRun) do
assert(v==2, dump(k,v).." should be ==2")
n=n+1
end
assert(n==REPEATS, dump(n))
 
-- And that all the noops ran once
local n=0
for k,v in pairs(hasRunNoops) do
assert(v==1, dump(k,v).." should be ==1")
n=n+1
end
assert(n==REPEATS, dump(n))
end
 
 
-----------------------------------------------------------------------
-- ACE-67: Test reentrancy (firing an event from inside a callback) PLUS regging more callbacks from inside them!
 
for REPEATS=1,20 do
local test={}
local reg = CH:New(test, "Reg", "Unreg", "UnregAll")
 
local fires=0
local extraFires=0
 
local function extrahandler()
extraFires = extraFires+1
end
 
local function handler(n, event, arg)
fires=fires+1
assert(reg.recurse==arg, dump(reg.recurse, arg)) -- check up that the internal recursion counter is tracking correctly
 
-- to make things even more interesting, we'll reg even more callbacks recursively (a lot of these should be overwrites)
test.Reg("extra"..n..","..arg, "EVENT", extrahandler)
 
if arg==n then
reg:Fire("EVENT", arg+1) -- we'll end up with up to REPEATS levels of recursion
end
end
 
for n=1,REPEATS do
test.Reg("handler"..n, "EVENT", handler, n)
end
 
-- Fire the event!
assert(reg.recurse==0)
reg:Fire("EVENT", 1)
assert(reg.recurse==0)
 
assert(fires == REPEATS + (REPEATS*REPEATS), dump(fires, REPEATS + (REPEATS*REPEATS), REPEATS))
assert(extraFires==0)
 
-- Fire again! This time we should see extraFires
fires=0
assert(reg.recurse==0)
reg:Fire("EVENT", 1)
assert(reg.recurse==0)
 
assert(fires == REPEATS + (REPEATS*REPEATS), dump(fires, REPEATS + (REPEATS*REPEATS), REPEATS))
assert(extraFires== fires + fires*REPEATS)
 
end
 
 
-----------------------------------------------------------------------
-- ACE-67: Test that a recursively registered callback is properly removed
 
for REPEATS=1,20 do
local test={}
local reg = CH:New(test, "Reg", "Unreg", "UnregAll")
 
local extraFired=0
local function extra()
extraFired=extraFired+1
end
 
local fired=0
local function RegExtra()
fired = fired + 1
 
local name=tostring(math.random(1,999999))
test.Reg(name,"EVENT",extra)
if fired==1 then
test.Unreg(name,"EVENT") -- #1: test single unreg
elseif fired==2 then
test.UnregAll(name) -- #2: test unregall
elseif fired==3 then
-- let it be regged
end
end
 
test.Reg("test","EVENT",RegExtra)
 
reg:Fire("EVENT")
assert(fired==1)
assert(extraFired==0, dump(extraFired))
 
reg:Fire("EVENT")
assert(fired==2)
assert(extraFired==0, dump(extraFired))
 
reg:Fire("EVENT")
assert(fired==3)
assert(extraFired==0, dump(extraFired)) -- there's an extra regged, but it hasn't fired yet
 
reg:Fire("EVENT")
assert(fired==4)
assert(extraFired==1, dump(extraFired)) -- yeah ok now it fired
 
end
 
 
 
-----------------------------------------------------------------------
-- Delayed registration:
-- - Verify that delayed OnUsed are fired
-- - Verify that OnUnused aren't fired if OnUsed hasn't been fired yet
 
do
local obj = {}
local reg = CH:New(obj, "Reg", "Unreg", "UnregAll")
 
local dummys, regs, onused, onunused = 0,0,0,0
 
local addon = {}
addon.Dummy = function() dummys=dummys+1 end
addon.ReggingEvent = function() end
obj.Reg(addon,"ReggingEvent")
 
reg.OnUsed = function(reg,tgt,evt)
assert(evt=="Dummy")
onused = onused + 1
end
reg.OnUnused = function(rev,tgt,evt)
assert(evt=="Dummy")
onunused = onunused + 1
end
 
-- Register "Dummy" from inside "ReggingEvent"
addon.ReggingEvent = function()
regs=regs+1
obj.Reg(addon,"Dummy")
assert(onused==0) -- shouldn't fire yet
end
 
reg:Fire("ReggingEvent")
assert(regs==1) -- should have run once
assert(onused==1) -- should have fired now
assert(dummys==0)
reg:Fire("Dummy")
assert(dummys==1)
assert(onunused==0)
 
-- Now unregister "Dummy" normally
obj.Unreg(addon,"Dummy")
assert(onunused==1)
reg:Fire("Dummy") -- sanity: should do nothing unless something is SERIOUSLY broken
assert(dummys==1)
 
 
-- Register "Dummy" from inside "ReggingEvent" and then unregister it
dummys, regs, onused, onunused = 0,0,0,0
addon.ReggingEvent = function() -- This event tries to register more events inside it
regs=regs+1
obj.Reg(addon,"Dummy")
assert(onused==0) -- shouldn't fire yet
reg:Fire("Dummy") -- this shouldn't fire; it should still be queued
obj.Unreg(addon,"Dummy")
assert(onunused==0) -- shouldn't fire at all now since onused never did
end
 
reg:Fire("ReggingEvent")
assert(regs==1)
assert(dummys==0)
 
reg:Fire("Dummy") -- sanity: should do nothing unless something is SERIOUSLY broken
assert(onused==0)
assert(onunused==0)
assert(dummys==0)
 
end
 
 
 
-- We do not test the actual callback logic here. The AceEvent tests do that plenty.
 
-----------------------------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceTimer-3.0-test2.lua New file
0,0 → 1,136
 
-- AceTimer test suite 2: Errors
 
 
dofile("wow_api.lua")
dofile("LibStub.lua")
 
local MAJOR = "AceTimer-3.0"
 
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
local AceTimer,minor = LibStub:GetLibrary(MAJOR)
 
-- NOTE, the below pcalls should NOT contain error position information.
-- The reason is that if the error level is correctly set, it will point to _inside_ the pcall(), which does not have a position
 
 
-------------------------------------------------------------------
-- Test ScheduleTimer errorchecking of method
 
obj = {}
 
ok,msg = pcall(AceTimer.ScheduleTimer, obj, "method", 4, "arg") -- This should fail - method not defined
assert(not ok)
assert(msg == MAJOR..": ScheduleTimer(\"methodName\", delay, arg): 'methodName' - method not found on target object.", msg)
 
 
obj.method = "hi, i'm NOT a function, i'm something else"
 
ok,msg = pcall(AceTimer.ScheduleTimer, obj, "method", 4, "arg") -- This should fail - obj["method"] is not a function
assert(not ok)
assert(msg == MAJOR..": ScheduleTimer(\"methodName\", delay, arg): 'methodName' - method not found on target object.", msg)
 
 
ok,msg = pcall(AceTimer.ScheduleTimer, obj, nil, 4, "arg") -- This should fail (method is nil)
assert(not ok)
assert(msg == MAJOR..": ScheduleTimer(callback, delay, arg): 'callback' - function or method name expected.", msg)
 
 
ok,msg = pcall(AceTimer.ScheduleTimer, obj, {}, 4, "arg") -- This should fail (method is table)
assert(not ok)
assert(msg == MAJOR..": ScheduleTimer(callback, delay, arg): 'callback' - function or method name expected.", msg)
 
 
-- (Note: ScheduleRepeatingTimer here just to check naming)
ok,msg = pcall(AceTimer.ScheduleRepeatingTimer, obj, 123, 4, "arg") -- This should fail too (method is integer)
assert(not ok)
assert(msg == MAJOR..": ScheduleRepeatingTimer(callback, delay, arg): 'callback' - function or method name expected.", msg)
 
 
 
-------------------------------------------------------------------
-- Check AceTimer:CancelAllTimers() -- not allowed
 
ok,msg = pcall(AceTimer.CancelAllTimers, AceTimer)
assert(not ok)
assert(msg == MAJOR..": CancelAllTimers(): supply a meaningful 'self'", dump(msg))
 
 
-------------------------------------------------------------------
-- Scheduling a timer on a member function that later becomes a nonfunction
 
cnt=0
obj.method = function() cnt=cnt+1 end
 
AceTimer.ScheduleRepeatingTimer(obj, "method", 1, "arg")
 
WoWAPI_FireUpdate(2) -- Border case: at this exact bucket, we should be able to convince the timer to fire twice even though it only gets a single onupdate
assert(cnt==2, cnt) -- This should have worked nicely
 
errors=0
function geterrorhandler()
return function(msg)
errors=errors+1
assert(strmatch(msg, "a string value"))
end
end
 
obj.method = "this should cause errors"
WoWAPI_FireUpdate(4)
 
assert(errors==2) -- timer should have run twice
 
 
-----------------------------------------------------------------------
-- :CancelTimer() on something that's already cancelled / never existed
 
local handle = AceTimer.ScheduleTimer(obj, function() assert("this shouldnt run") end, 1)
 
AceTimer.CancelTimer(obj, handle) -- Should work
 
 
errors=0
function geterrorhandler()
return function(msg)
errors=errors+1
assert(strmatch(msg, "already cancelled"))
end
end
 
AceTimer.CancelTimer(obj, handle) -- Should error -- already cancelled
assert(errors==1)
 
 
WoWAPI_FireUpdate(6) -- Let the timer disappear from the buckets
 
 
errors=0
function geterrorhandler()
return function(msg)
errors=errors+1
assert(strmatch(msg, "no such timer"))
end
end
 
AceTimer.CancelTimer(obj, handle) -- Should error -- doesnt exist at all
assert(errors==1)
 
 
function geterrorhandler()
return function(msg)
error("This shouldn't have errored! -- "..msg)
end
end
AceTimer.CancelTimer(obj, handle, true) -- silent: shouldn't error
 
 
 
 
 
 
 
 
-----------------------------------------------------------------------
 
print "OK"
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/serialize.lua New file
0,0 → 1,46
local recurse = false
function serialize(o, indent, file)
if not file then file = io.stdout end
 
if type(o) == "number" then
file:write(o)
elseif type(o) == "string" then
file:write(string.format("%q", o))
elseif type(o) == "boolean" then
file:write(o and "true" or "false")
elseif type(o) == "function" then
file:write("nil --[["..tostring(o).."]]")
elseif type(o) == "table" then
if not indent then indent = " " else indent = indent .. " " end
local old = recurse
recurse = true
file:write("{\n")
-- Check to see if we have an integer section
if #o > 0 then
for k,v in ipairs(o) do
file:write(indent)
serialize(v, indent, file)
file:write(",\n")
end
end
 
for k,v in pairs(o) do
local mask
if type(k) == "number" and #o > 0 and k > 0 and k <= #o then
mask = true
end
 
if not mask then
file:write(indent .. "[")
serialize(k, indent, file)
file:write("] = ")
serialize(v, indent, file)
file:write(",\n")
end
end
recurse = old
file:write(string.sub(indent,1,-3) .. (recurse and "}" or "}\n"))
else
error("Cannot serialize a " .. type(o))
end
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceTimer-3.0-test3.lua New file
0,0 → 1,69
dofile("wow_api.lua")
dofile("LibStub.lua")
 
local MAJOR = "AceTimer-3.0"
 
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
local AceTimer,minor = LibStub:GetLibrary(MAJOR)
 
 
---- test all methods of registration: anonymous funcs, member func names, etc etc
 
 
local function func(arg)
assert(arg=="t1s" or arg=="t2s" or arg=="t3s" or arg=="t4s")
assert(_G[arg]==nil or type(_G[arg])=="number", dump(arg,type(_G[arg])))
_G[arg]=(_G[arg] or 0)+1
end
 
-- Completely anonymous timer
local t1 = AceTimer:ScheduleRepeatingTimer(func, 1, "t1s")
 
-- Timer associated to a table
local obj2={}
local t2 = AceTimer.ScheduleRepeatingTimer(obj2, func, 1, "t2s")
 
-- Member function on a table
local obj3={}
function obj3:func(arg)
assert(self==obj3 and arg=="oogabooga")
func("t3s")
end
local t3 = AceTimer.ScheduleRepeatingTimer(obj3, "func", 1, "oogabooga")
 
-- Timer associated to a string
local t4 = AceTimer.ScheduleRepeatingTimer("me4", func, 1, "t4s")
 
 
 
WoWAPI_FireUpdate(0)
assert(t1s==nil and t2s==nil and t3s==nil and t4s==nil, dump(t1s,t2s,t3s,t4s))
 
WoWAPI_FireUpdate(1)
assert(t1s==1 and t2s==1 and t3s==1 and t4s==1, dump(t1s,t2s,t3s,t4s))
 
AceTimer.CancelAllTimers(obj2)
 
WoWAPI_FireUpdate(2)
assert(t1s==2 and t2s==1 and t3s==2 and t4s==2, dump(t1s,t2s,t3s,t4s))
 
AceTimer.CancelAllTimers(obj3)
 
WoWAPI_FireUpdate(3)
assert(t1s==3 and t2s==1 and t3s==2 and t4s==3, dump(t1s,t2s,t3s,t4s))
 
AceTimer.CancelAllTimers("me4")
 
WoWAPI_FireUpdate(4)
assert(t1s==4 and t2s==1 and t3s==2 and t4s==3, dump(t1s,t2s,t3s,t4s))
 
AceTimer:CancelTimer(t1)
 
WoWAPI_FireUpdate(5)
assert(t1s==4 and t2s==1 and t3s==2 and t4s==3, dump(t1s,t2s,t3s,t4s))
 
 
 
-----------------------------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceEvent-3.0.lua New file
0,0 → 1,256
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceEvent-3.0/AceEvent-3.0.lua")
 
local AceEvent = LibStub("AceEvent-3.0")
 
local addon = {}
 
AceEvent:Embed(addon)
 
-- Test embedding and then registering and unregistering and seeing that things are caught and NOT caught correctly
do
local eventResult
function addon:EVENT_TEST(event,arg1)
assert(self==addon)
assert(event=="EVENT_TEST")
eventResult = arg1
end
 
eventResult = 1
addon:RegisterEvent("EVENT_TEST") -- simple reg & test
WoWAPI_FireEvent("EVENT_TEST", 2)
assert(eventResult==2)
 
eventResult = 3
addon:UnregisterEvent("SOMETHINGELSE") -- unreg something that doesn't exist
WoWAPI_FireEvent("SOMETHINGELSE", 4) -- fire something with no handler
assert(eventResult==3)
 
eventResult = 5
addon:UnregisterEvent("SOMETHINGELSE") -- again unregister something that doesn't exist (why? ohwell)
WoWAPI_FireEvent("EVENT_TEST", 6) -- this should still fire
assert(eventResult==6)
 
eventResult = 7
addon:UnregisterAllEvents() -- test unregging everything
WoWAPI_FireEvent("EVENT_TEST", 8) -- this should NOT fire
assert(eventResult==7)
 
addon:RegisterEvent("EVENT_TEST") -- re-register
WoWAPI_FireEvent("EVENT_TEST", 9)
assert(eventResult==9) -- should fire again!
 
local switched=0
function addon:EVENT_TEST() -- overwrite handler, should work with self["methodname"] syntax
switched=switched+1
end
WoWAPI_FireEvent("EVENT_TEST", 10)
assert(switched==1)
assert(eventResult==9)
 
local woot=0
addon:RegisterEvent("EVENT_TEST", function(event, arg)
assert(event=="EVENT_TEST")
assert(arg=="woot", dump(event,arg))
woot=woot+1
end) -- CHANGE registration (to a funcref even!)
WoWAPI_FireEvent("EVENT_TEST", "woot")
assert(switched==1)
assert(eventResult==9)
assert(woot==1)
 
addon:UnregisterAllEvents()
WoWAPI_FireEvent("EVENT_TEST")
assert(switched==1)
assert(eventResult==9)
assert(woot==1)
end
 
 
-- Test nonembedded funcref calling style, two events to same handler
do
local eventName
local eventCount=0
local function handler(event, ...)
eventName=event
eventCount=eventCount+1
end
 
AceEvent:RegisterEvent("EVENT1", handler)
AceEvent:RegisterEvent("EVENT2", handler)
 
WoWAPI_FireEvent("EVENT1")
assert(eventName=="EVENT1" and eventCount==1)
 
WoWAPI_FireEvent("EVENT2")
assert(eventName=="EVENT2" and eventCount==2)
 
end
 
-- Test "addonID" instead of self
do
local eventName
local eventCount=0
local function handler(event, ...)
eventName=event
eventCount=eventCount+1
end
 
local event3Count=0
local function handler3(event, ...)
event3Count=event3Count+1
end
 
 
AceEvent.RegisterEvent("myAddon", "EVENT1", handler)
AceEvent.RegisterEvent("myOtherAddon", "EVENT2", handler)
AceEvent.RegisterEvent("myOtherAddon", "EVENT3", handler3)
 
WoWAPI_FireEvent("EVENT1")
assert(eventName=="EVENT1" and eventCount==1)
 
WoWAPI_FireEvent("EVENT2")
assert(eventName=="EVENT2" and eventCount==2)
 
WoWAPI_FireEvent("EVENT3")
assert(event3Count==1)
 
AceEvent.UnregisterAllEvents("myAddon") -- note "." calling style
 
WoWAPI_FireEvent("EVENT1") -- should not fire
assert(eventCount==2)
 
WoWAPI_FireEvent("EVENT2")
assert(eventCount==3)
 
WoWAPI_FireEvent("EVENT3")
assert(event3Count==2)
 
AceEvent:UnregisterAllEvents("myOtherAddon") -- now ":" calling style
 
WoWAPI_FireEvent("EVENT1") -- should not fire
assert(eventCount==3)
 
WoWAPI_FireEvent("EVENT2") -- should not fire
assert(eventCount==3)
 
WoWAPI_FireEvent("EVENT3") -- should not fire
assert(event3Count==2)
 
end
 
 
 
 
 
-- Test multiple args, different types
do
local arg3={}
 
local args
local function handler(event, ...)
args = { ... }
end
 
AceEvent:RegisterEvent("ARGZZ", handler) -- ":" calling style, self=AceEvent
 
WoWAPI_FireEvent("ARGZZ", "arg1", 2, arg3)
 
assert(#args==3)
assert(args[1]=="arg1")
assert(args[2]==2)
assert(args[3]==arg3)
end
 
 
-- Test user-supplied args, all styles
do
local addon={}
local n=0
AceEvent:Embed(addon)
 
-- test self["methodname"]
function addon:HANDLER(userarg, event, a1,a2)
assert(self==addon)
assert(userarg=="userarg")
assert(event=="EVENT")
assert(a1==1 and a2==2, dump(a1,a2))
n=n+1
end
addon:RegisterEvent("EVENT", "HANDLER", "userarg")
WoWAPI_FireEvent("EVENT",1,2)
assert(n==1)
 
-- test functionref
local function handler(userarg, event, a1,a2)
assert(userarg==nil)
assert(event=="EVENT")
assert(a1==1 and a2==2, dump(a1,a2))
n=n+1
end
addon:RegisterEvent("EVENT", handler, nil) -- look, a nil that should still be passed!
WoWAPI_FireEvent("EVENT",1,2)
assert(n==2)
 
-- test functionref with self="addonId"
AceEvent.RegisterEvent("myAddon", "EVENT", handler, nil) -- look, a nil that should still be passed!
WoWAPI_FireEvent("EVENT",1,2)
assert(n==4) -- should have fired twice, once for the addon table, once for "myAddon"
 
addon:UnregisterAllEvents("myAddon") -- unregs BOTH for addon and "myAddon"
WoWAPI_FireEvent("EVENT",1,2)
assert(n==4) -- shouldnt have fired
 
end
 
 
-- Register a methodname on AceEvent itself -- should error
do
local addon={}
local ok,res = pcall(AceEvent.RegisterEvent, AceEvent, "whatever")
assert(not ok and res=="Usage: RegisterEvent(\"eventname\", \"methodname\"): do not use Library:RegisterEvent(), use your own 'self'", dump(ok,res))
end
 
-- Register a nonexistant methodname -- should error
do
local addon={}
local ok,res = pcall(AceEvent.RegisterEvent, addon, "THISDOESNTEXIST")
assert(not ok and res=="Usage: RegisterEvent(\"eventname\", \"methodname\"): 'methodname' - method 'THISDOESNTEXIST' not found on self.", dump(ok,res))
end
 
-- Don't give UnregAll an arg -- should error
do
local ok,res = pcall(AceEvent.UnregisterAllEvents)
assert(not ok and res==[[Usage: UnregisterAllEvents([whatFor]): missing 'self' or "addonId" to unregister events for.]], dump(ok,res))
end
 
-- Attempt to unregister everything on the library itself -- should error
do
local ok,res = pcall(AceEvent.UnregisterAllEvents, AceEvent)
assert(not ok and res==[[Usage: UnregisterAllEvents([whatFor]): supply a meaningful 'self' or "addonId"]], dump(ok,res))
end
 
-- These should be ok though (note '.' rather than ':' )
AceEvent.UnregisterAllEvents(AceEvent, "BLAH")
AceEvent.UnregisterAllEvents("BLAH")
AceEvent.UnregisterAllEvents("BLAH", AceEvent)
AceEvent.UnregisterAllEvents({})
 
 
 
 
 
 
do -- Tests on messages.
local messageResult
function addon:MESSAGE_TEST(message,...)
end
-- TODO
end
 
 
 
------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceTimer-3.0-ACE94.lua New file
0,0 → 1,197
-- Test for ACE-94: memory reclaiming of table indices
 
dofile("wow_api.lua")
dofile("LibStub.lua")
 
local MAJOR = "AceTimer-3.0"
 
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
local AceTimer,minor = LibStub:GetLibrary(MAJOR)
 
local function dummy() end
 
local VERBOSE = strmatch(arg[1] or "", "v")
 
-- Initial memory that we have to include...
 
local objs={}
for n=1,3 do
objs[n] = {}
end
 
WoWAPI_FireUpdate(GetTime()+100)
 
-----------------------------------------------------------------------
-- Get "empty" memory count
 
collectgarbage("collect")
local mem = collectgarbage("count")
 
 
 
-----------------------------------------------------------------------
-- Run the whole test five times to make sure the cleaner keeps working after a loop
 
for LOOP=1,5 do
 
if VERBOSE then print("\n------------- Loop "..LOOP) end
 
-----------------------------------------------------------------------
-- Schedule a boatload of timers
 
for _,obj in pairs(objs) do
for t=1,1000 do
AceTimer.ScheduleTimer(obj, dummy, 1)
end
end
 
collectgarbage("collect")
if VERBOSE then print(collectgarbage("count") - mem.."KB used - everything live") end
-- About 688K in original test
 
 
 
-----------------------------------------------------------------------
-- Cancel them all again
 
for _,obj in pairs(objs) do
AceTimer.CancelAllTimers(obj)
end
 
-- .. and let them get removed from hash buckets over time
WoWAPI_FireUpdate(GetTime()+100)
 
collectgarbage("collect")
local idxwaste = collectgarbage("count") - mem
if VERBOSE then print(idxwaste.."KB used - this is table index waste. Expecting ~110 KB.") end
 
-- We should be wasting about 110K here (warnmsg in original test)
-- 1000 timers * 3 objects * ~40 bytes per index = ~120KB. Sounds about right.
assert(idxwaste>80 and idxwaste<160, dump(idxwaste))
 
 
 
-----------------------------------------------------------------------
-- Now start firing PLAYER_REGEN_ENABLED and watch memory decrease
 
-- Clean up 2 thirds
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
 
-- See if 1 third remains
collectgarbage("collect")
local thirdwaste = collectgarbage("count") - mem
 
assert(thirdwaste > idxwaste/3*0.9 and thirdwaste < idxwaste/3*1.1, dump(thirdwaste, idxwaste))
 
-- Clean up last third
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
 
 
-----------------------------------------------------------------------
-- We should now be back to near 0 mem consumption
 
collectgarbage("collect")
local endresult = collectgarbage("count") - mem
if VERBOSE then print(endresult.."KB used - should be nearly clean") end
-- I'm getting ~2.5K waste from system total, probably something eating a bit more after being run once, not going to go hunting for it
-- Loops 2..n keep using the same total.
assert(endresult>0 and endresult<10)
 
 
end -- for LOOP=1,5
 
 
-----------------------------------------------------------------------
-- Test the excessive timer count warning system
-- Also make sure the cleaner obeys our minimum operation criteria and doesn't run too often
-- (Cleaner and warning runs at the same time)
 
if VERBOSE then print("\n------------- Testing excessive timer count warnings") end
 
local obj = setmetatable({}, {
__tostring = function(self)
return "MyTestObj"
end
})
 
assert(AceTimer.debug.BUCKETS < 1000) -- .BUCKETS is the warning limit
for t=1,1000 do
AceTimer.ScheduleTimer(obj, dummy, 1)
end
 
local warnmsg
local numwarnmsgs=0
function ChatFrame1:AddMessage(msg)
if VERBOSE then print("Warning message emitted: <"..msg..">") end
warnmsg = msg
numwarnmsgs=numwarnmsgs+1
end
 
for _ in pairs(AceTimer.selfs) do
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
end
assert(numwarnmsgs==1, dump(numwarnmsgs))
assert(strmatch(warnmsg, "MyTestObj.*has 100[1-9] live timers"), dump(warnmsg, msg)) -- it won't be 1000 since __ops etc gets counted. it'll be a little more.
 
-- Now it shouldn't clean&warn again since there are no operations on the table
numwarnmsgs=0
for _ in pairs(AceTimer.selfs) do
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
end
assert(numwarnmsgs==0)
 
-- Artificially inflate __ops somewhat, still shouldn't warn
AceTimer.selfs[obj].__ops = 10
numwarnmsgs=0
for _ in pairs(AceTimer.selfs) do
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
end
assert(numwarnmsgs==0)
 
-- Artificially inflate __ops A LOT, now it should warn again. Once.
AceTimer.selfs[obj].__ops = 1000000
numwarnmsgs=0
for LOOP=1,20 do
for _ in pairs(AceTimer.selfs) do
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
end
end
assert(numwarnmsgs==1)
 
 
-----------------------------------------------------------------------
-- Test a fencepost case: only one addon. That one addon should be
-- checked for every PLAYER_REGEN_ENABLED.
 
LibStub.libs[MAJOR] = nil
LibStub.minors[MAJOR] = nil
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
local AceTimer,minor = LibStub:GetLibrary(MAJOR)
 
assert(AceTimer.debug.BUCKETS < 1000) -- .BUCKETS is the warning limit
for t=1,1000 do
AceTimer.ScheduleTimer(obj, dummy, 1)
end
 
for LOOP=1,3 do
numwarnmsgs=0
AceTimer.selfs[obj].__ops = 1000000
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
assert(numwarnmsgs==1)
end
 
for LOOP=1,3 do
numwarnmsgs=0
-- no __ops increase, nothing should be checked
WoWAPI_FireEvent("PLAYER_REGEN_ENABLED")
assert(numwarnmsgs==0)
end
 
 
 
 
-----------------------------------------------------------------------
print "OK"
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceAddon-3.0.lua New file
0,0 → 1,117
-- TODO:
-- Test module support of AceAddon-3.0.
 
 
 
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../AceAddon-3.0/AceAddon-3.0.lua")
 
local AceAddon = LibStub("AceAddon-3.0")
 
do -- Test create addon.
 
local success, reason, addon
 
-- 'name' - string expected
success, reason = pcall( function() AceAddon:NewAddon() end )
assert( success == false and reason:find("'name' - string expected",1,true) )
 
-- Cannot find a library instance of "Testing123".
success, reason = pcall( function() AceAddon:NewAddon("TestAddon-1", "Testing123") end )
assert( success == false and reason:find("Cannot find a library instance",1,true) )
 
-- Success.
addon = AceAddon:NewAddon("TestAddon-2")
assert( addon and addon == AceAddon:GetAddon("TestAddon-2") )
 
-- Addon 'TestAddon-2' already exists.
success, reason = pcall( function() addon = AceAddon:NewAddon("TestAddon-2") end )
assert( success == false and reason:find("Addon 'TestAddon-2' already exists",1,true) )
 
end
 
 
 
do -- Test mixin.
 
-- Define a simple library for testing mixin.
local libA = LibStub:NewLibrary("LibStupid",1)
if libA then
libA.mixins = { "BecomeStupid", "BecomeDumb" }
function libA:BecomeStupid()
end
function libA:BecomeDumb()
end
function libA:Embed(target)
for i,method in ipairs(self.mixins) do
target[method] = self[method]
end
end
end
 
-- Yet another library.
local libB = LibStub:NewLibrary("LibSmart",1)
if libB then
libB.mixins = { "BecomeSmart", "BecomeClever" }
function libB:BecomeSmart()
end
function libB:BecomeClever()
end
function libB:Embed(target)
for i,method in ipairs(self.mixins) do
target[method] = self[method]
end
end
end
 
-- Create an AceAddon object with 2 libraries mixed.
local addon = AceAddon:NewAddon("TestAddon-3","LibStupid","LibSmart")
 
-- Are the methods mixed correctly?
assert( addon.BecomeStupid == libA.BecomeStupid )
assert( addon.BecomeDumb == libA.BecomeDumb )
assert( addon.BecomeSmart == libB.BecomeSmart )
assert( addon.BecomeClever == libB.BecomeClever )
end
 
 
do -- Test the call to OnInitialize, OnEnable and OnDisable.
 
local addon = AceAddon:NewAddon("TestAddon-4","LibStupid","LibSmart")
 
local initialized = false
function addon:OnInitialize()
initialized = true
end
 
local enabled = false
function addon:OnEnable()
enabled = true
end
 
function addon:OnDisable()
enabled = false
end
 
-- Testing the call to addon:OnInitialize().
WoWAPI_FireEvent("ADDON_LOADED",ADDON_NAME)
assert(initialized and not enabled)
 
-- IsLoggedIn() is supposed to return true when addon receives PLAYER_LOGIN.
function IsLoggedIn() return true end
 
-- Testing the call to addon:OnEnable()
WoWAPI_FireEvent("PLAYER_LOGIN")
assert(initialized and enabled)
 
-- Testing the call to addon:OnDisable()
AceAddon:DisableAddon(addon)
assert(initialized and not enabled)
 
end
 
print("Test finished.")
 
 
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceDB-3.0.lua New file
0,0 → 1,216
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceDB-3.0/AceDB-3.0.lua")
dofile("serialize.lua")
 
-- Test the defaults system
do
 
local defaults = {
profile = {
singleEntry = "singleEntry",
tableEntry = {
tableDefault = "tableDefault",
},
starTest = {
["*"] = {
starDefault = "starDefault",
},
sibling = {
siblingDefault = "siblingDefault",
},
},
doubleStarTest = {
["**"] = {
doubleStarDefault = "doubleStarDefault",
},
sibling = {
siblingDefault = "siblingDefault",
},
},
},
}
 
local db = LibStub("AceDB-3.0"):New("MyDB", defaults)
assert(db.profile.singleEntry == "singleEntry")
assert(db.profile.tableEntry.tableDefault == "tableDefault")
assert(db.profile.starTest.randomkey.starDefault == "starDefault")
assert(db.profile.starTest.sibling.siblingDefault == "siblingDefault")
assert(db.profile.starTest.sibling.starDefault == nil)
assert(db.profile.doubleStarTest.randomkey.doubleStarDefault == "doubleStarDefault")
assert(db.profile.doubleStarTest.sibling.siblingDefault == "siblingDefault")
assert(db.profile.doubleStarTest.sibling.doubleStarDefault == "doubleStarDefault")
end
 
-- Test the dynamic creation of sections
do
local defaults = {
char = { alpha = "alpha",},
realm = { beta = "beta",},
class = { gamma = "gamma",},
race = { delta = "delta",},
faction = { epsilon = "epsilon",},
factionrealm = { zeta = "zeta",},
profile = { eta = "eta",},
global = { theta = "theta",},
}
 
local db = LibStub("AceDB-3.0"):New({}, defaults)
 
assert(rawget(db, "char") == nil)
assert(rawget(db, "realm") == nil)
assert(rawget(db, "class") == nil)
assert(rawget(db, "race") == nil)
assert(rawget(db, "faction") == nil)
assert(rawget(db, "factionrealm") == nil)
assert(rawget(db, "profile") == nil)
assert(rawget(db, "global") == nil)
assert(rawget(db, "profiles") == nil)
 
-- Check dynamic default creation
assert(db.char.alpha == "alpha")
assert(db.realm.beta == "beta")
assert(db.class.gamma == "gamma")
assert(db.race.delta == "delta")
assert(db.faction.epsilon == "epsilon")
assert(db.factionrealm.zeta == "zeta")
assert(db.profile.eta == "eta")
assert(db.global.theta == "theta")
end
 
-- Test OnProfileChanged
do
local testdb = LibStub("AceDB-3.0"):New({})
 
local triggers = {}
 
local function OnProfileChanged(message, db, ...)
if message == "OnProfileChanged" and db == testdb then
local profile = ...
assert(profile == "Healers")
triggers[message] = true
end
end
 
testdb:RegisterCallback("OnProfileChanged", OnProfileChanged)
testdb:SetProfile("Healers")
assert(triggers.OnProfileChanged)
end
 
-- Test GetProfiles() fix for ACE-35
do
local db = LibStub("AceDB-3.0"):New({})
 
local profiles = {
"Healers",
"Tanks",
"Hunter",
}
 
for idx,profile in ipairs(profiles) do
db:SetProfile(profile)
end
 
local profileList = db:GetProfiles()
table.sort(profileList)
assert(profileList[1] == "Healers")
assert(profileList[2] == "Hunter")
assert(profileList[3] == "Tanks")
assert(profileList[4] == UnitName("player" .. " - " .. GetRealmName()))
end
 
-- Very simple default test
do
local defaults = {
profile = {
sub = {
["*"] = {
sub2 = {},
sub3 = {},
},
},
},
}
 
local db = LibStub("AceDB-3.0"):New({}, defaults)
 
assert(type(db.profile.sub.monkey.sub2) == "table")
assert(type(db.profile.sub.apple.sub3) == "table")
 
db.profile.sub.random.sub2.alpha = "alpha"
end
 
-- Table insert kills us
do
local defaults = {
profile = {
["*"] = {},
},
}
 
local db = LibStub("AceDB-3.0"):New({}, defaults)
 
table.insert(db.profile.monkey, "alpha")
table.insert(db.profile.random, "beta")
 
-- Here, the tables db.profile.monkey should be REAL, not cached
assert(rawget(db.profile, "monkey"))
end
 
 
-- Test multi-level defaults for hyper
do
local defaults = {
profile = {
autoSendRules = {
['*'] = {
include = {
['*'] = {},
},
exclude = {
['*'] = {},
},
},
},
}
}
 
local db = LibStub("AceDB-3.0"):New({}, defaults)
 
assert(rawget(db.profile.autoSendRules.Cairthas.include, "ptSets") == nil)
assert(rawget(db.profile.autoSendRules.Cairthas.include, "items") == nil)
table.insert(db.profile.autoSendRules.Cairthas.include.ptSets, "TradeSkill.Mat.ByProfession.Leatherworking")
table.insert(db.profile.autoSendRules.Cairthas.include.items, "Light Leather")
 
db.profile.autoSendRules.Cairthas.include.ptSets.boo = true
 
-- Tables should be real now, not cached.
assert(rawget(db.profile.autoSendRules.Cairthas.include, "ptSets"))
assert(rawget(db.profile.autoSendRules.Cairthas.include, "items"))
end
 
do
local testdb = LibStub("AceDB-3.0"):New("testdbtable", {profile = { test = 2, test3 = { a=1}}})
assert(testdb.profile.test == 2) --true
testdb.profile.test = 3
testdb.profile.test2 = 4
testdb.profile.test3.b = 2
assert(testdb.profile.test == 3) --true
assert(testdb.profile.test2 == 4) --true
local firstprofile = testdb:GetCurrentProfile()
testdb:SetProfile("newprofile")
assert(testdb.profile.test == 2) --true
testdb:CopyProfile(firstprofile)
assert(testdb.profile.test == 3) --false, the value is 2
assert(testdb.profile.test2 == 4) --true
assert(testdb.profile.test3.a == 1)
end
 
do
local testdb = LibStub("AceDB-3.0"):New({})
testdb:SetProfile("testprofile")
testdb:SetProfile("testprofile2")
testdb:SetProfile("testprofile")
assert(#testdb:GetProfiles() == 3)
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceConfigRegisty-3.0-errors.lua New file
0,0 → 1,128
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
local MAJOR="AceConfigRegistry-3.0"
dofile("../AceConfig-3.0/"..MAJOR.."/"..MAJOR..".lua")
 
local creg = assert(LibStub(MAJOR))
 
local errpattern = "^"..string.gsub(MAJOR,"-","%%-")..":ValidateOptionsTable"
 
---------------- the option table!!
 
local opts = {
type = "group",
get = function(info) return true end,
set = function(info,v) end,
validate = function() return end,
 
args = {
input = {
type="input",
name="Input",
},
toggle = {
type="toggle",
name="Toggle",
},
grp = {
type="group",
name="Grp",
args = {
toggle = {
type="toggle",
name="Toggle",
}
}
},
select = {
type="select",
name="Select",
desc="Styled!",
style="dropdown",
values={},
}
},
 
plugins = { -- test plugins
plugin1 = {
plugcmd = {
name="PluggedCmd",
type="toggle",
},
plugcmd2 = {
name="PluggedCmd2",
type="toggle",
}
},
}
}
 
creg:RegisterOptionsTable("testapp", opts)
 
assert(creg:GetOptionsTable("testapp","cmd","foo-1") == opts)
 
-- This should not error
creg:ValidateOptionsTable(opts,"mytable")
 
-----------------------------------------------------------------------
-- Smack various things to pieces and make sure we get a validation error
-- Make sure that errors are indicated on the right callstack offset!
 
local function test(pattern)
local ok,msg=pcall(creg.ValidateOptionsTable, creg, opts,"mytable")
assert(not ok, "Wtf, this didnt error?")
assert(string.match(msg, errpattern), "<"..msg.."> did not match <"..errpattern..">") -- error should point at the pcall == no location info
assert(string.match(msg,pattern), "<"..msg.."> did not match <"..pattern..">")
end
 
opts.type=nil
test("mytable.type")
opts.type="group"
 
opts.plugins.plugin1["bad key"]=true
test("mytable.plugins.plugin1.*contained spaces")
opts.plugins.plugin1["bad key"]=nil
 
opts.plugins.mybad = "hi"
test("mytable.plugins.mybad.*expected a table")
opts.plugins.mybad = nil
 
opts.plugins.plugin1.plugcmd.type="barf"
test("unknown type")
opts.plugins.plugin1.plugcmd.type="toggle"
 
opts.args.select.style="hi2u"
test("select.style.*expect string value 'hi2u'")
opts.args.select.style="radio"
assert(pcall(creg.ValidateOptionsTable, creg, opts,"mytable"))
opts.args.select.style=nil
assert(pcall(creg.ValidateOptionsTable, creg, opts,"mytable"))
 
opts.args.select.values=nil
test("select.values.*expected a methodname, funcref or table")
opts.args.select.values={}
 
 
-----------------------------------------------------------------------
-- Make sure we get correct error message levels via other apis also
 
opts.hateme=true
local pattern="testapp.hateme.*unknown param"
 
local ok,msg=pcall(creg.GetOptionsTable,creg,"testapp","dropdown","foo-1")
assert(not ok)
assert(string.match(msg, errpattern), "<"..msg.."> did not match <"..errpattern..">") -- error should point at the pcall == no location info
assert(string.match(msg,pattern), "<"..msg.."> did not match <"..pattern..">")
 
local ok,msg=pcall(creg:GetOptionsTable("testapp"),"dropdown","foo-1")
assert(not ok)
assert(string.match(msg, errpattern), "<"..msg.."> did not match <"..errpattern..">") -- error should point at the pcall == no location info
assert(string.match(msg,pattern), "<"..msg.."> did not match <"..pattern..">")
 
 
 
 
 
-----------------------------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceConfigCmd-3.0.lua New file
0,0 → 1,227
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceConsole-3.0/AceConsole-3.0.lua")
dofile("../AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua")
dofile("../AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua")
 
local ccmd = assert(LibStub("AceConfigCmd-3.0"))
local creg = assert(LibStub("AceConfigRegistry-3.0"))
 
 
local app={}
 
-- helper: counts of what's been execd
local n = setmetatable({}, { __index = function(self,k) return 0 end })
function n:clear()
for k,v in pairs(self) do
if k~="clear" then
self[k]=nil
end
end
end
 
 
----- set / get on application object
 
function app:get_toggle(info, ...)
assert(self==app)
assert(select("#",...)==0)
 
n.get_toggle = n.get_toggle + 1
return true
end
 
function app:set_toggle(info, ...)
assert(self==app, "Expected self=="..tostring(app)..", got "..tostring(self))
assert(select("#",...)==1)
local b = select(1,...)
n.set_toggle = n.set_toggle + 1
assert(b==false)
end
 
 
--- set / get / validate as function refs
 
function makefunc(name)
_G[name] = function(info,...)
assert(type(info)=="table")
assert(#info>=1)
n[name] = n[name] + 1
return _G["_"..name](info,...)
end
end
 
makefunc("set_base")
makefunc("get_base")
makefunc("validate_base")
 
 
 
 
---------------- the option table!!
 
local opts = {
type = "group",
get = get_base, -- tests inheritance by declaring it at the bottom
set = set_base,
validate = validate_base,
 
args = {
input = {
type="input",
name="Input",
desc="Input Desc",
validate = false, -- tests removing inherited validate
},
toggle = {
type="toggle",
name="Toggle",
desc="Toggle Desc",
handler=app, -- tests "handler" arg
get = "get_toggle", -- tests overriding, and membernames
set = "set_toggle",
},
plugcmd = { -- this should never be used, we should use the plugin!
name="PlugCmdOrig",
desc="YOU SHOULD NOT SEE THIS",
type="toggle",
set = function() assert(false) end,
get = function() assert(false) end,
}
},
 
plugins = { -- test plugins
plugin1 = {
plugcmd = {
name="PluggedCmd",
desc="Woohoo",
type="toggle",
},
plugcmd2 = {
name="PluggedCmd2",
desc="WooTwo",
type="toggle",
}
},
plugin2 = {
-- empty, shouldnt cause errors
},
plugin3 = {
p3cmd = {
name="Plugin3Cmd",
desc="WooThree",
type="toggle",
},
}
 
}
}
 
creg:RegisterOptionsTable("testapp", opts)
 
assert(creg:GetOptionsTable("testapp")("cmd","foo-1") == opts)
assert(creg:GetOptionsTable("testapp","cmd","foo-1") == opts)
 
 
-- User error handler
local expect = {} -- list of strings to expect
function ChatFrame1.AddMessage(self, txt)
local expstr = tremove(expect)
assert(expstr, "Unexpected output: <"..txt..">")
assert(string.match(txt,expstr), "Got output <"..txt..">, expected <"..expstr..">")
end
 
 
 
--------------- test "/test toggle" (via handler:methodname)
 
function _validate_base() end -- noop
 
tinsert(expect, "/test toggle : 'thisshoulderror' %- expected 'on' or 'off', or no argument to toggle.")
ccmd:HandleCommand("test","testapp","toggle thisshoulderror") -- shouldn't work
assert(n.get_toggle==0)
assert(n.set_toggle==0)
assert(n.validate_base==0)
assert(table.getn(expect)==0)
 
n:clear()
ccmd:HandleCommand("test","testapp","toggle off")
assert(n.get_toggle==0)
assert(n.set_toggle==1)
assert(n.validate_base==1)
 
n:clear()
ccmd:HandleCommand("test","testapp","toggle")
assert(n.get_toggle==1)
assert(n.set_toggle==1)
assert(n.validate_base==1)
 
function _validate_base(info, ...)
return "THIS FAILS"
end
n:clear()
tinsert(expect, "/test toggle : 'on' %- THIS FAILS")
ccmd:HandleCommand("test","testapp","toggle on") -- "on" since it'll error if it reachest the set handler (it only accepts false)
assert(n.get_base==0)
assert(n.set_base==0)
assert(n.validate_base==1)
 
 
 
-------------- test "/test input" (via funcrefs)
 
function _set_base(info,...)
assert(select("#",...)==1)
assert(#info==1)
assert(info[0]=="test")
assert(info[1]=="input")
local a1 = ...
assert(a1=="")
end
 
n:clear()
ccmd:HandleCommand("test","testapp","input")
assert(n.get_base==0)
assert(n.validate_base==0)
assert(n.set_base==1)
 
 
function _set_base(info, ...)
assert(...=="hi2u woo ",dump(...))
end
ccmd:HandleCommand("test","testapp","input hi2u woo ")
 
 
 
 
-----------------------------------------------------------------------
 
local seen = {
[".*Arguments to.*"]=0,
["input.*Input Desc"]=0,
["toggle.*Toggle Desc"]=0,
["plugcmd.*Woohoo"]=0,
["plugcmd2.*WooTwo"]=0,
["p3cmd.*WooThree"]=0,
}
function ChatFrame1.AddMessage(self, txt)
local ok
for k,v in pairs(seen) do
if strmatch(txt, k) then
seen[k]=seen[k]+1
ok=true
break
end
end
assert(ok, "Did not expect to see "..format("%q",txt))
end
 
ccmd:HandleCommand("test","testapp","")
 
for k,v in pairs(seen) do
assert(v==1, "Expected to see <"..k.."> once. Saw it "..v.." times.")
end
 
-----------------------------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceDB-3.0-defaults.lua New file
0,0 → 1,186
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceDB-3.0/AceDB-3.0.lua")
dofile("serialize.lua")
 
-- Test the defaults system
do
 
local defaults = {
profile = {
singleEntry = "singleEntry",
tableEntry = {
tableDefault = "tableDefault",
},
starTest = {
["*"] = {
starDefault = "starDefault",
},
sibling = {
siblingDefault = "siblingDefault",
},
siblingDeriv = {
starDefault = "not-so-starDefault",
},
},
doubleStarTest = {
["**"] = {
doubleStarDefault = "doubleStarDefault",
},
sibling = {
siblingDefault = "siblingDefault",
},
siblingDeriv = {
doubleStarDefault = "overruledDefault",
}
},
starTest2 = {
["*"] = "fun",
sibling = "notfun",
}
},
}
 
local db = LibStub("AceDB-3.0"):New("MyDB", defaults)
assert(db.profile.singleEntry == "singleEntry")
assert(db.profile.tableEntry.tableDefault == "tableDefault")
assert(db.profile.starTest.randomkey.starDefault == "starDefault")
assert(db.profile.starTest.sibling.siblingDefault == "siblingDefault")
assert(db.profile.starTest.sibling.starDefault == nil)
assert(db.profile.doubleStarTest.randomkey.doubleStarDefault == "doubleStarDefault")
assert(db.profile.doubleStarTest.sibling.siblingDefault == "siblingDefault")
assert(db.profile.doubleStarTest.sibling.doubleStarDefault == "doubleStarDefault")
assert(db.profile.doubleStarTest.siblingDeriv.doubleStarDefault == "overruledDefault")
assert(db.profile.starTest2.randomkey == "fun")
assert(db.profile.starTest2.sibling == "notfun")
 
db.profile.doubleStarTest.siblingDeriv.doubleStarDefault = "doubleStarDefault"
db.profile.starTest2.randomkey = "notfun"
db.profile.starTest2.randomkey2 = "fun"
db.profile.starTest2.sibling = "fun"
 
WoWAPI_FireEvent("PLAYER_LOGOUT")
 
assert(db.profile.singleEntry == nil)
assert(db.profile.tableEntry == nil)
assert(db.profile.starTest == nil)
assert(db.profile.doubleStarTest.randomkey == nil)
assert(db.profile.doubleStarTest.siblingDeriv.doubleStarDefault == "doubleStarDefault")
assert(db.profile.starTest2.randomkey == "notfun")
assert(db.profile.starTest2.randomkey2 == nil)
assert(db.profile.starTest2.sibling == "fun")
end
 
do
local defaultTest = {
profile = {
units = {
["**"] = {
test = 2
},
["player"] = {
},
["pet"] = {
test = 3
},
["bug"] = {
test = 3,
},
}
}
}
 
local bugdb = {
["profileKeys"] = {
["player - Realm Name"] = "player - Realm Name",
},
["profiles"] = {
["player - Realm Name"] = {
["units"] = {
["player"] = {
},
["pet"] = {
},
["focus"] = {
},
bug = "bug",
},
},
},
}
 
local data = LibStub("AceDB-3.0"):New(bugdb, defaultTest)
 
assert(data.profile.units["player"].test == 2)
assert(data.profile.units["pet"].test == 3)
assert(data.profile.units["focus"].test == 2)
assert(type(data.profile.units.bug) == "string")
WoWAPI_FireEvent("PLAYER_LOGOUT")
end
 
do
local defaultTest = {
profile = {
units = {
["*"] = {
test = 2
},
["player"] = {
}
}
}
}
 
local bugdb = {
["profileKeys"] = {
["player - Realm Name"] = "player - Realm Name",
},
["profiles"] = {
["player - Realm Name"] = {
["units"] = {
["player"] = {
},
["pet"] = {
},
},
},
},
}
 
local data = LibStub("AceDB-3.0"):New(bugdb, defaultTest)
 
assert(data.profile.units["player"].test == nil)
assert(data.profile.units["pet"].test == 2)
assert(data.profile.units["focus"].test == 2)
end
 
do
local defaultTest = {
profile = {
foo = {
["*"] = {
plyf = true,
},
}
}
}
 
 
local bugdb = {
["profileKeys"] = {
["player - Realm Name"] = "player - Realm Name",
},
["profiles"] = {
["player - Realm Name"] = {
["foo"] = {
hopla = 42,
},
},
},
}
 
local data = LibStub("AceDB-3.0"):New(bugdb, defaultTest)
 
assert(data.profile.foo.hopla == 42)
end
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
RepWatch/Libs/tests/AceComm-3.0.lua New file
0,0 → 1,133
dofile("wow_api.lua")
dofile("../LibStub/LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceComm-3.0/ChatThrottleLib.lua")
dofile("../AceComm-3.0/AceComm-3.0.lua")
 
switches = arg[1] or ""
 
local VERBOSE,n = strfind(switches, "vv*") -- "v" anywhere in the first arg
if VERBOSE then VERBOSE = n-VERBOSE+1 end -- "v"=1, "vv"=2, ...
 
local NOCTL = strfind(switches, "t")
 
if NOCTL then -- "t" anywhere in the first arg
print("NOTE: Testing mode without ChatThrottleLib!")
-- Replace ChatThrottleLib with a dummy passthrough for testing purposes
function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName)
self.ORIG_SendAddonMessage(prefix, text, chattype, target)
end
function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName)
self.ORIG_SendChatMessage(text, chattype, language, destination)
end
end
 
 
local AceComm = LibStub("AceComm-3.0")
 
local function printf(format, ...)
print(format:format(...))
end
 
local addon1 = {}
local prefix1 = "Test"
 
local addon2 = {}
local prefix2 = "TestTest"
 
 
local data = ""
local received = {}
local chartot = 0
 
AceComm:Embed(addon1)
 
local received1 = {}
function addon1:OnCommReceived(prefix, message, distribution, sender)
assert(self==addon1)
assert(prefix == prefix1)
assert(distribution == "RAID", dump(distribution))
tinsert(received, message)
tinsert(received1, message)
assert(#message == #received1)
assert(message == strsub(data,1,#message))
chartot=chartot+#message
end
 
AceComm:Embed(addon2)
 
local received2 = {}
function addon2:OnCommReceived(prefix, message, distribution, sender)
assert(self==addon2)
assert(prefix == prefix2)
assert(distribution == "GROUP", dump(distribution))
tinsert(received, message)
tinsert(received2, message)
assert(#message == #received2+9)
assert(message == "OogaBooga"..strsub(data,1,#message-9))
chartot=chartot+#message
end
 
addon1:RegisterComm(prefix1)
addon2:RegisterComm(prefix2)
 
 
local MSGS=255*4 -- length 1..1000, covers all of: Single, First+Last, First+Next+Last, First+Next+Next+Last
for i = 1,MSGS do
data = data .. string.char(math.random(32, 255))
end
 
-- First send a boatload of data without pumping OnUpdates to CTL
 
for i = 1,MSGS do
if VERBOSE and VERBOSE>=2 then print("Sending len "..i) end
addon1:SendCommMessage(prefix1, strsub(data,1,i), "RAID", nil)
addon2:SendCommMessage(prefix2, "OogaBooga"..strsub(data,1,i), "GROUP", nil)
end
 
-- Now start pumping OnUpdates; there should be plenty of stuff queued in CTL, and it should all be sent in the right order!
if not NOCTL then
local sampledmid
local esttime = ( (MSGS+20)*MSGS*2/1.62 ) / ChatThrottleLib.MAX_CPS
local midpos = esttime * 0.5
local latepos = esttime * 0.9
 
local lastchartot=0
local dispinterval=20
 
local t=0
if VERBOSE then
print("time","rcvtot","rcv1","rcv2","cps","CTL choke")
end
while #received < MSGS*2 do
WoWAPI_FireUpdate(t)
if t%dispinterval==0 then
local cps = floor((chartot-lastchartot)/dispinterval)
if VERBOSE then print(t..": ",#received, #received1, #received2, cps, ChatThrottleLib.bChoking) end
lastchartot=chartot
if t>midpos then -- when our bandwidth isn't mostly eaten by headers and stuff
assert(cps>=ChatThrottleLib.MAX_CPS*0.6 and cps<ChatThrottleLib.MAX_CPS*1.1, cps)
end
end
if t>midpos and not sampledmid then
sampledmid=true
assert(#received > MSGS*1.33 and #received < MSGS*1.5, dump(#received, MSGS*1.33, MSGS*1.5)) -- would be around 1 if we sent the same amount of data in each message, but we send less around the start
end
if t>midpos and t<latepos then
-- prefix2 should have slightly less data transferred since the prefix name itself is longer and uses more bandwidth compared to useful data
assert(#received2 >= #received1*0.975 and #received2 < #received1*0.99, #received1.." : "..#received2)
end
t=t+1
end
 
assert(t>=esttime*0.9 and t<=esttime*1.1, dump(t, esttime))
 
assert(sampledmid)
 
end
 
assert(#received==MSGS*2)
assert(#received1==MSGS and #received2==MSGS)
 
-----------------------------------------------------------------------
print "OK"
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceConsole-3.0-GetArgs.lua New file
0,0 → 1,109
 
local MAJOR="AceConsole-3.0"
 
dofile("wow_api.lua")
 
dofile("LibStub.lua")
dofile("../"..MAJOR.."/"..MAJOR..".lua")
 
 
local AC = assert(LibStub(MAJOR))
 
 
 
 
----------------------------------------------------------
-- Simple tests
-- (no need to explicitly test startpos; if multi-arg tests work, it works)
 
local a1,a2 = AC:GetArgs("") -- no arg
assert(a1==nil and a2==1e9)
 
local a1,a2 = AC:GetArgs(" ") -- still no arg
assert(a1==nil and a2==1e9)
 
local a1,a2 = AC:GetArgs("a1") -- simple
assert(a1=="a1" and a2==1e9)
 
local a1 = AC:GetArgs("a1", 0) -- fetch 0 args
assert(a1==1)
 
local a1 = AC:GetArgs(" a1", 0) -- fetch 0 args, leading space
assert(a1==3)
 
local a1,a2 = AC:GetArgs("a1 a2") -- args remaining, check nextpos
assert(a1=="a1" and a2==4)
 
local a1,a2 = AC:GetArgs("a1 a2") -- args remaining, check nextpos
assert(a1=="a1" and a2==6, dump(a1,a2))
 
local a1,a2,a3 = AC:GetArgs("a1 a2", 2) -- 2 args
assert(a1=="a1" and a2=="a2" and a3==1e9)
 
local a1,a2,a3 = AC:GetArgs(" a1 a2 ", 2) -- surplous space
assert(a1=="a1" and a2=="a2" and a3==1e9, dump(a1,a2,a3))
 
local a1,a2,a3 = AC:GetArgs(" a1 a2 ", 2) -- one more space at end
assert(a1=="a1" and a2=="a2" and a3==1e9, dump(a1,a2,a3))
 
 
local a1,a2,a3 = AC:GetArgs(" a1 ", 2) -- missing arg2
assert(a1=="a1" and a2==nil and a3==1e9, dump(a1,a2,a3))
 
 
 
----------------------------------------------------------
-- Test quoting
 
local a1,a2 = AC:GetArgs([["a1"]]) -- simple quote
assert(a1=="a1" and a2==1e9, dump(a1,a2))
 
local a1,a2 = AC:GetArgs([["a 1"]]) -- quote with space in it
assert(a1=="a 1" and a2==1e9, dump(a1,a2))
 
local a1,a2 = AC:GetArgs([[" a 1 "]]) -- quote with space at beginning and end
assert(a1==" a 1 " and a2==1e9, dump(a1,a2))
 
local a1,a2 = AC:GetArgs([['a 1']]) -- single quote
assert(a1=="a 1" and a2==1e9, dump(a1,a2))
 
local a1,a2,a3 = AC:GetArgs([["a 1" "a 2"]], 2) -- 2 args
assert(a1=="a 1" and a2=="a 2" and a3==1e9, dump(a1,a2,a3))
 
local a1,a2,a3 = AC:GetArgs([["a 1" 'a 2']], 2) -- mixed quoting
assert(a1=="a 1" and a2=="a 2" and a3==1e9, dump(a1,a2,a3))
 
local a1,a2,a3 = AC:GetArgs([[ "a 1" 'a 2' ]], 2) -- surplous spacing between quotes
assert(a1=="a 1" and a2=="a 2" and a3==1e9, dump(a1,a2,a3))
 
local a1,a2,a3 = AC:GetArgs([["foo'bar" 'foo"bar']], 2) -- don't break on nonmatching quote
assert(a1=="foo'bar" and a2=='foo"bar' and a3==1e9, dump(a1,a2,a3))
 
local a1,a2 = AC:GetArgs([[ "unfinished quote]], 1) -- missing " at end
assert(a1=="unfinished quote" and a2==1e9, dump(a1,a2))
 
 
------------------------------------------------------------
-- Hyperlinks and combos
 
local a1,a2,a3,a4 = AC:GetArgs("simple |Cff112233|Hitem:0:0:0:0|hand here's a text with \"s and stuff|h|r", 3)
assert(a1=="simple" and a2=="|Cff112233|Hitem:0:0:0:0|hand here's a text with \"s and stuff|h|r" and a3==nil and a4==1e9, dump(a1,a2,a3,a4))
 
local a1,a2,a3,a4 = AC:GetArgs("simple '|Cff112233|Hitem:0:0:0:0|hand here's a text with \"s and stuff|h|r'", 3)
assert(a1=="simple" and a2=="|Cff112233|Hitem:0:0:0:0|hand here's a text with \"s and stuff|h|r" and a3==nil and a4==1e9, dump(a1,a2,a3,a4))
 
local a1,a2,a3,a4 = AC:GetArgs("simple \"|Cff112233|Hitem:0:0:0:0|hand here's a text with \"s and stuff|h|r\" 'bar'", 3)
assert(a1=="simple" and a2=="|Cff112233|Hitem:0:0:0:0|hand here's a text with \"s and stuff|h|r" and a3=="bar" and a4==1e9, dump(a1,a2,a3,a4))
 
local a1,a2,a3,a4 = AC:GetArgs("simple |H|ha 1|h|H|ha 1|h", 3)
assert(a1=="simple" and a2=="|H|ha 1|h|H|ha 1|h" and a3==nil and a4==1e9, dump(a1,a2,a3,a4))
 
local a1,a2,a3,a4 = AC:GetArgs("simple ||H|ha 1|h|H|ha 1|h", 3) -- note double ||
assert(a1=="simple" and a2=="||H|ha" and a3=="1|h|H|ha 1|h" and a4==1e9, dump(a1,a2,a3,a4))
 
local a1,a2,a3,a4 = AC:GetArgs("simple |||H|ha 1|h|H|ha 1|h", 3) -- note double || followed by |H
assert(a1=="simple" and a2=="|||H|ha 1|h|H|ha 1|h" and a3==nil and a4==1e9, dump(a1,a2,a3,a4))
 
 
------------------------------------------------------------
print "OK"
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/LibStub.lua New file
0,0 → 1,51
-- $Id: LibStub.lua 48018 2007-09-03 01:50:17Z mikk $
-- 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]
 
-- Check to see is this version of the stub is obsolete
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
LibStub = LibStub or {libs = {}, minors = {} }
_G[LIBSTUB_MAJOR] = LibStub
LibStub.minor = LIBSTUB_MINOR
 
-- LibStub:NewLibrary(major, minor)
-- major (string) - the major version of the library
-- minor (string or number ) - the minor version of the library
--
-- returns nil if a newer or same version of the lib is already present
-- returns empty library object or old library object if upgrade is needed
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
 
-- LibStub:GetLibrary(major, [silent])
-- major (string) - the major version of the library
-- silent (boolean) - if true, library is optional, silently return nil if its not found
--
-- throws an error if the library can not be found (except silent is set)
-- returns the library object if found
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
 
-- LibStub:IterateLibraries()
--
-- Returns an iterator for the currently registered libraries
function LibStub:IterateLibraries()
return pairs(self.libs)
end
 
setmetatable(LibStub, { __call = LibStub.GetLibrary })
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceLocale-3.0-test2.lua New file
0,0 → 1,145
 
dofile("wow_api.lua")
 
 
dofile("LibStub.lua")
dofile("../AceLocale-3.0/AceLocale-3.0.lua")
 
local AL = assert(LibStub("AceLocale-3.0"))
 
------------------------------------------
-- Create enUS locale
 
local L = assert(AL:NewLocale("Loc1", "enUS", true))
L["foo1"] = true
 
local L = assert(AL:NewLocale("Loc1", "enUS", true)) -- should be ok to add more!
L["foo1"] = "this should not overwrite foo1 since this a default locale"
L["foo2"] = "manual foo2"
L["foo2"] = "this should not overwrite foo2 since this a default locale"
 
 
local x="untouched"
ok, msg = pcall(function() x = L["i can't read from write proxies"] end)
assert(not ok, "got: "..tostring(ok))
assert(x=="untouched", "got: "..tostring(x))
assert(strfind(msg, "assertion failed"), "got: "..tostring(msg))
 
 
 
 
-------------------------------------------
-- Test enUS locale
 
local L = assert(AL:GetLocale("Loc1"))
assert(L["foo1"] == "foo1")
assert(L["foo2"] == "manual foo2")
 
-- test warning system for nonexistant strings
local errormsg
function geterrorhandler() return function(msg) errormsg=msg end end
 
assert(L["this doesn't exist"]=="this doesn't exist")
assert(errormsg=="AceLocale-3.0: Loc1: Missing entry for 'this doesn't exist'", "got: "..errormsg)
 
-- we shouldnt get warnings for the same string twice
errormsg="no error"
 
assert(L["this doesn't exist"]=="this doesn't exist")
assert(errormsg=="no error")
 
 
-- (don't) create deDE locale
local L = AL:NewLocale("Loc1", "deDE")
assert(not L)
 
 
 
 
-------------------------------------------
-- Get locale for nonexisting app
 
-- silent
local L = AL:GetLocale("Loc2", true)
assert(not L)
 
-- nonsilent - should error
local ok, msg = pcall(function() return AL:GetLocale("Loc2") end)
assert(not ok, "got: "..tostring(ok))
assert(msg=="Usage: GetLocale(application[, silent]): 'application' - No locales registered for 'Loc2'", "got: "..tostring(msg))
 
 
 
 
 
 
---------------------------------------------------------------
---------------------------------------------------------------
---------------------------------------------------------------
--
-- Hi2u, we're a german client now!
--
 
 
function GetLocale() return "deDE" end
 
LibStub = nil
dofile("LibStub.lua")
dofile("../AceLocale-3.0/AceLocale-3.0.lua")
 
local AL = assert(LibStub("AceLocale-3.0"))
 
 
 
assert( not AL:NewLocale("Loc1", "frFR") ) -- no, we're still not french
 
 
---------------------------------------------------------------
-- Register deDE
 
local L = assert(AL:NewLocale("Loc1", "deDE"))
L["yes"]="jawohl"
L["no"]="nein"
 
 
---------------------------------------------------------------
-- Register enUS (default)
 
local L = assert(AL:NewLocale("Loc1", "enUS", true))
L["yes"]=true
L["no"]="no"
L["untranslated"]="untranslated"
 
---------------------------------------------------------------
-- Test deDE
 
local L = assert(AL:GetLocale("Loc1"))
assert(L["yes"]=="jawohl")
assert(L["no"]=="nein")
assert(L["untranslated"]=="untranslated")
 
 
 
 
---------------------------------------------------------------
---------------------------------------------------------------
---------------------------------------------------------------
--
-- Test overriding with GAME_LOCALE
--
 
GAME_LOCALE = "frFR"
 
assert(not AL:NewLocale("Loc1", "deDE")) -- shouldn't be krauts anymore now
 
local L = assert(AL:NewLocale("Loc1", "frFR")) -- we're frog eaters!
L["yes"] = "oui"
 
local L = assert(AL:GetLocale("Loc1"))
assert(L["yes"] == "oui") -- should have been overwritten
assert(L["no"] == "nein") -- should be left from kraut days
 
 
---------------------------------------------------------------
 
print "OK"
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/wow_api.lua New file
0,0 → 1,258
local _G = getfenv(0)
 
local donothing = function() end
 
local frames = {} -- Stores globally created frames, and their internal properties.
 
local FrameClass = {} -- A class for creating frames.
FrameClass.methods = { "SetScript", "RegisterEvent", "UnregisterEvent", "UnregisterAllEvents", "Show", "Hide", "IsShown", "ClearAllPoints", "SetParent" }
function FrameClass:New()
local frame = {}
for i,method in ipairs(self.methods) do
frame[method] = self[method]
end
local frameProps = {
events = {},
scripts = {},
timer = GetTime(),
isShow = true,
parent = nil,
}
return frame, frameProps
end
function FrameClass:SetScript(script,handler)
frames[self].scripts[script] = handler
end
function FrameClass:RegisterEvent(event)
frames[self].events[event] = true
end
function FrameClass:UnregisterEvent(event)
frames[self].events[event] = nil
end
function FrameClass:UnregisterAllEvents(frame)
for event in pairs(frames[self].events) do
frames[self].events[event] = nil
end
end
function FrameClass:Show()
frames[self].isShow = true
end
function FrameClass:Hide()
frames[self].isShow = false
end
function FrameClass:IsShown()
return frames[self].isShow
end
function FrameClass:ClearAllPoints()
end
function FrameClass:SetParent(parent)
frames[self].parent = parent
end
 
 
function CreateFrame(kind, name, parent)
local frame,internal = FrameClass:New()
internal.parent = parent
frames[frame] = internal
if name then
_G[name] = frame
end
return frame
end
 
function UnitName(unit)
return unit
end
 
function GetRealmName()
return "Realm Name"
end
 
function UnitClass(unit)
return "Warrior", "WARRIOR"
end
 
function UnitHealthMax()
return 100
end
 
function UnitHealth()
return 50
end
 
function GetNumRaidMembers()
return 1
end
 
function GetNumPartyMembers()
return 1
end
 
FACTION_HORDE = "Horde"
FACTION_ALLIANCE = "Alliance"
 
function UnitFactionGroup(unit)
return "Horde", "Horde"
end
 
function UnitRace(unit)
return "Undead", "Scourge"
end
 
 
_time = 0
function GetTime()
return _time
end
 
function IsAddOnLoaded() return nil end
 
SlashCmdList = {}
 
function __WOW_Input(text)
local a,b = string.find(text, "^/%w+")
local arg, text = string.sub(text, a,b), string.sub(text, b + 2)
for k,handler in pairs(SlashCmdList) do
local i = 0
while true do
i = i + 1
if not _G["SLASH_" .. k .. i] then
break
elseif _G["SLASH_" .. k .. i] == arg then
handler(text)
return
end
end
end;
print("No command found:", text)
end
 
local ChatFrameTemplate = {
AddMessage = function(self, text)
print((string.gsub(text, "|c%x%x%x%x%x%x%x%x(.-)|r", "%1")))
end
}
 
for i=1,7 do
local f = {}
for k,v in pairs(ChatFrameTemplate) do
f[k] = v
end
_G["ChatFrame"..i] = f
end
DEFAULT_CHAT_FRAME = ChatFrame1
 
debugstack = debug.traceback
date = os.date
 
function GetLocale()
return "enUS"
end
 
function GetAddOnInfo()
return
end
 
function GetNumAddOns()
return 0
end
 
function getglobal(k)
return _G[k]
end
 
function setglobal(k, v)
_G[k] = v
end
 
local function _errorhandler(msg)
print("--------- geterrorhandler error -------\n"..msg.."\n-----end error-----\n")
end
 
function geterrorhandler()
return _errorhandler
end
 
function InCombatLockdown()
return false
end
 
function IsLoggedIn()
return false
end
 
function GetFramerate()
return 60
end
 
time = os.clock
 
strmatch = string.match
 
function SendAddonMessage(prefix, message, distribution, target)
assert(#prefix + #message < 255,
string.format("SendAddonMessage: message too long (%d bytes)",
#prefix + #message))
-- CHAT_MSG_ADDON(prefix, message, distribution, sender)
WoWAPI_FireEvent("CHAT_MSG_ADDON", prefix, message, distribution, "Sender")
end
 
function hooksecurefunc(func_name, post_hook_func)
local orig_func = _G[func_name]
 
_G[func_name] = function (...)
local ret = { orig_func(...) } -- yeahyeah wasteful, see if i care, it's a test framework
post_hook_func(...)
return unpack(ret)
end
end
 
RED_FONT_COLOR_CODE = ""
GREEN_FONT_COLOR_CODE = ""
 
StaticPopupDialogs = {}
 
function WoWAPI_FireEvent(event,...)
for frame, props in pairs(frames) do
if props.events[event] then
if props.scripts["OnEvent"] then
for i=1,select('#',...) do
_G["arg"..i] = select(i,...)
end
_G.event=event
props.scripts["OnEvent"](frame,event,...)
end
end
end
end
 
function WoWAPI_FireUpdate(forceNow)
if forceNow then
_time = forceNow
end
local now = GetTime()
for frame,props in pairs(frames) do
if props.isShow and props.scripts.OnUpdate then
_G.arg1=now-props.timer
props.scripts.OnUpdate(frame,now-props.timer)
props.timer = now
end
end
end
 
 
 
 
-- utility function for "dumping" a number of arguments (return a string representation of them)
function dump(...)
local t = {}
for i=1,select("#", ...) do
local v = select(i, ...)
if type(v)=="string" then
tinsert(t, string.format("%q", v))
else
tinsert(t, tostring(v))
end
end
return "<"..table.concat(t, "> <")..">"
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceLocale-3.0.lua New file
0,0 → 1,30
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../AceLocale-3.0/AceLocale-3.0.lua")
 
local AceLocale = LibStub("AceLocale-3.0")
 
local locale_1 = AceLocale:NewLocale("test", "enUS")
locale_1["a"] = "A"
locale_1["c"] = "C"
 
local locale_2 = AceLocale:NewLocale("test", "deDE", true)
locale_2["a"] = "aa"
locale_2["b"] = "bb"
locale_2["c"] = "cc"
 
local locale_3 = AceLocale:NewLocale("test", "frFR")
 
local locale_4 = AceLocale:GetLocale("test")
 
--[[ no longer true with proxy metatables /mikk assert(locale_2 == locale_1) ]]
assert(locale_3 == nil)
--[[ no longer true with proxy metatables /mikk assert(locale_4 == locale_1) ]]
 
print(locale_4["a"], locale_4["b"], locale_4["c"])
assert(locale_4["a"] == "A")
assert(locale_4["b"] == "bb")
assert(locale_4["c"] == "C")
 
------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceConfigCmd-3.0-ordering.lua New file
0,0 → 1,175
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceConsole-3.0/AceConsole-3.0.lua")
dofile("../AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua")
dofile("../AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua")
 
local ccmd = assert(LibStub("AceConfigCmd-3.0"))
local creg = assert(LibStub("AceConfigRegistry-3.0"))
 
 
local app={}
 
 
---------------- the option table!!
 
local opts = {
type = "group",
get = function() end,
set = function() end,
 
args = {
first = {
type="toggle",
name="1",
order=1
},
second = {
type="toggle",
name="2",
order=2
},
plugcmd = { -- this should never be used, we should use the plugin!
name="PlugCmdOrig",
desc="YOU SHOULD NOT SEE THIS",
type="toggle",
},
inlinegroup = {
order=70,
name="inlinegroup",
desc="An inline group",
type="group",
inline=false,
cmdInline=true, -- test that cmdInline overrides inline
args = {
inline1 = {
type="toggle",
name="inline1",
order=11,
},
inline2 = {
type="toggle",
name="inline2",
order=12,
},
ininlinegroup = {
order=1,
name="ininlinegroup",
desc="An inline inline group",
type="group",
inline=true,
args = {
ininline1 = {
type="toggle",
name="ininline1",
}
}
}
},
},
unset1 = {
type="toggle",
name="unset1",
},
unset2 = {
type="toggle",
name="unset2",
},
unset3 = {
type="toggle",
name="unset3",
},
afterunset = {
type="toggle",
name="101",
order=101
},
last1 = {
type="toggle",
name="-1",
order=-1,
},
last2 = {
type="toggle",
name="-2",
order=-2,
},
last3 = {
type="toggle",
name="-3",
order=-3,
},
last4 = {
type="toggle",
name="-4",
order=-4,
},
},
 
plugins = { -- test plugins
plugin1 = {
plugcmd = {
name="50",
type="toggle",
order=50
},
plugcmd2 = {
name="52",
type="toggle",
order=52
}
},
plugin2 = {
-- empty, shouldnt cause errors
},
plugin3 = {
p3cmd = {
name="51",
type="toggle",
order=51,
},
}
 
}
}
 
creg:RegisterOptionsTable("testapp", opts)
 
 
 
local output = {
"Arguments to", -- header
"first",
"second",
"plugcmd.*50",
"p3cmd",
"plugcmd2",
"An inline group",
"An inline inline group",
"ininline1",
"inline1",
"inline2",
"unset1",
"unset2",
"unset3",
"afterunset",
"last4",
"last3",
"last2",
"last1"
}
 
function ChatFrame1.AddMessage(self, txt)
-- print("> "..txt)
local str = assert(tremove(output, 1))
assert(string.match(txt, str), "Expected <"..str.."> got <"..txt..">")
end
 
ccmd:HandleCommand("test","testapp","")
 
assert(not next(output), "we didnt get all the output we expected!")
 
 
-----------------------------------------------------------------------
print "OK"
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceDB-3.0-namespaces.lua New file
0,0 → 1,38
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceDB-3.0/AceDB-3.0.lua")
dofile("serialize.lua")
 
do
local defaults = { profile = { key3 = "stillfun" } }
local db = LibStub("AceDB-3.0"):New({})
local namespace = db:RegisterNamespace("test", defaults)
 
namespace.profile.key1 = "fun"
namespace.profile.key2 = "nofun"
 
local oldprofile = db:GetCurrentProfile()
db:SetProfile("newprofile")
assert(namespace.profile.key1 == nil)
assert(namespace.profile.key2 == nil)
assert(namespace.profile.key3 == "stillfun")
db:SetProfile(oldprofile)
assert(namespace.profile.key1 == "fun")
assert(namespace.profile.key2 == "nofun")
assert(namespace.profile.key3 == "stillfun")
db:SetProfile("newprofile2")
db:CopyProfile(oldprofile)
assert(namespace.profile.key1 == "fun")
assert(namespace.profile.key2 == "nofun")
assert(namespace.profile.key3 == "stillfun")
db:ResetProfile()
assert(namespace.profile.key1 == nil)
assert(namespace.profile.key2 == nil)
assert(namespace.profile.key3 == "stillfun")
db:DeleteProfile(oldprofile)
db:SetProfile(oldprofile)
assert(namespace.profile.key1 == nil)
assert(namespace.profile.key2 == nil)
assert(namespace.profile.key3 == "stillfun")
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/AceDB-3.0-callbacks.lua New file
0,0 → 1,46
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../CallbackHandler-1.0/CallbackHandler-1.0.lua")
dofile("../AceDB-3.0/AceDB-3.0.lua")
dofile("serialize.lua")
 
-- Test OnProfileChanged
do
local testdb = LibStub("AceDB-3.0"):New({})
 
local triggers = {}
 
local function OnCallback(message, db, ...)
if db == testdb then
if message == "OnProfileChanged" then
local profile = ...
assert(profile == "Healers" or profile == "Tanks")
elseif message == "OnProfileDeleted" then
local profile = ...
assert(profile == "Healers")
elseif message == "OnProfileCopied" then
local profile = ...
assert(profile == "Healers")
elseif message == "OnNewProfile" then
local profile = ...
assert(profile == "Healers" or profile == "Tanks")
end
triggers[message] = triggers[message] and triggers[message] + 1 or 1
end
end
 
testdb:RegisterCallback("OnProfileChanged", OnCallback)
testdb:RegisterCallback("OnProfileDeleted", OnCallback)
testdb:RegisterCallback("OnProfileCopied", OnCallback)
testdb:RegisterCallback("OnDatabaseReset", OnCallback)
testdb:RegisterCallback("OnNewProfile", OnCallback)
testdb:ResetDB("Healers")
testdb:SetProfile("Tanks")
testdb:CopyProfile("Healers")
testdb:DeleteProfile("Healers")
assert(triggers.OnProfileChanged == 2)
assert(triggers.OnDatabaseReset == 1)
assert(triggers.OnProfileDeleted == 1)
assert(triggers.OnProfileCopied == 1)
assert(triggers.OnNewProfile == 2)
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/tests/check_globals.sh New file
0,0 → 1,22
#!/bin/bash
 
echo "Checking all Ace3 files"
 
foundGlobals=0
for listing in `find .. -name "*.lua" -print`; do
dir=`echo $listing | awk -F '/' '{print $2}'`
file=`echo $listing | sed 's/^[^/]*\/[^/]*\/\(.*\)$/\1/'`
if [[ $dir != "tests" && $dir != "benchs" ]]; then
res=`luac -p -l "$listing" | grep SETGLOBAL`
if [[ $? == 0 ]]; then
if [[ $foundGlobals == 0 ]]; then
tput bold
echo "Globals found:"
tput sgr0
fi
foundGlobals=1
echo "$listing:"
echo $res | awk 'BEGIN { format = "%--50s \033[32m%s\033[0m\n" } { printf format, $7, $2 }'
fi;
fi;
done
Property changes : Added: svn:executable + Added: svn:mime-type + text/plain Added: svn:eol-style + LF
RepWatch/Libs/tests/AceGUITest/test.lua New file
0,0 → 1,783
local AceGUI = LibStub("AceGUI-3.0")
 
local function print(a)
DEFAULT_CHAT_FRAME:AddMessage(a)
end
 
 
local function ZOMGConfig(widget, event)
AceGUI:Release(widget.userdata.parent)
 
local f = AceGUI:Create("Frame")
 
f:SetCallback("OnClose",function(widget, event) print("Closing") AceGUI:Release(widget) end )
f:SetTitle("ZOMG Config!")
f:SetStatusText("Status Bar")
f:SetLayout("Fill")
 
local maingroup = AceGUI:Create("DropdownGroup")
maingroup:SetLayout("Fill")
maingroup:SetGroupList({Addons = "Addons !!", Zomg = "Zomg Addons"})
maingroup:SetGroup("Addons")
maingroup:SetTitle("")
 
f:AddChild(maingroup)
 
local tree = { "A", "B", "C", "D", B = { "B1", "B2", B1 = { "B11", "B12" } }, C = { "C1", "C2", C1 = { "C11", "C12" } } }
local text = { A = "Option 1", B = "Option 2", C = "Option 3", D = "Option 4", J = "Option 10", K = "Option 11", L = "Option 12",
B1 = "Option 2-1", B2 = "Option 2-2", B11 = "Option 2-1-1", B12 = "Option 2-1-2",
C1 = "Option 3-1", C2 = "Option 3-2", C11 = "Option 3-1-1", C12 = "Option 3-1-2" }
local t = AceGUI:Create("TreeGroup")
t:SetLayout("Fill")
t:SetTree(tree, text)
maingroup:AddChild(t)
 
local tab = AceGUI:Create("TabGroup")
tab:SetTabs({"A","B","C","D"},{A="Yay",B="We",C="Have",D="Tabs"})
tab:SetLayout("Fill")
tab:SelectTab(1)
t:AddChild(tab)
 
local component = AceGUI:Create("DropdownGroup")
component:SetLayout("Fill")
component:SetGroupList({Blah = "Blah", Splat = "Splat"})
component:SetGroup("Blah")
component:SetTitle("Choose Componet")
 
tab:AddChild(component)
 
local more = AceGUI:Create("DropdownGroup")
more:SetLayout("Fill")
more:SetGroupList({ButWait = "But Wait!", More = "Theres More"})
more:SetGroup("More")
more:SetTitle("And More!")
 
component:AddChild(more)
 
local sf = AceGUI:Create("ScrollFrame")
sf:SetLayout("Flow")
more:AddChild(sf)
local stuff = AceGUI:Create("Heading")
stuff:SetText("Omg Stuff Here")
stuff.width = "fill"
sf:AddChild(stuff)
 
for i = 1, 10 do
local edit = AceGUI:Create("EditBox")
edit:SetText("")
edit:SetWidth(200)
edit:SetLabel("Stuff!")
edit:SetCallback("OnEnterPressed",function(widget,event,text) widget:SetLabel(text) end )
edit:SetCallback("OnTextChanged",function(widget,event,text) print(text) end )
sf:AddChild(edit)
end
 
f:Show()
end
 
local function GroupA(content)
content:ReleaseChildren()
 
local sf = AceGUI:Create("ScrollFrame")
sf:SetLayout("Flow")
 
local edit = AceGUI:Create("EditBox")
edit:SetText("Testing")
edit:SetWidth(200)
edit:SetLabel("Group A Option")
edit:SetCallback("OnEnterPressed",function(widget,event,text) widget:SetLabel(text) end )
edit:SetCallback("OnTextChanged",function(widget,event,text) print(text) end )
sf:AddChild(edit)
 
local slider = AceGUI:Create("Slider")
slider:SetLabel("Group A Slider")
slider:SetSliderValues(0,1000,5)
slider:SetDisabled(false)
sf:AddChild(slider)
 
local zomg = AceGUI:Create("Button")
zomg.userdata.parent = content.userdata.parent
zomg:SetText("Zomg!")
zomg:SetCallback("OnClick", ZOMGConfig)
sf:AddChild(zomg)
 
local heading1 = AceGUI:Create("Heading")
heading1:SetText("Heading 1")
heading1.width = "fill"
sf:AddChild(heading1)
 
for i = 1, 5 do
local radio = AceGUI:Create("CheckBox")
radio:SetLabel("Test Check "..i)
radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
sf:AddChild(radio)
end
 
local heading2 = AceGUI:Create("Heading")
heading2:SetText("Heading 2")
heading2.width = "fill"
sf:AddChild(heading2)
 
for i = 1, 5 do
local radio = AceGUI:Create("CheckBox")
radio:SetLabel("Test Check "..i+5)
radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
sf:AddChild(radio)
end
 
local heading1 = AceGUI:Create("Heading")
heading1:SetText("Heading 1")
heading1.width = "fill"
sf:AddChild(heading1)
 
for i = 1, 5 do
local radio = AceGUI:Create("CheckBox")
radio:SetLabel("Test Check "..i)
radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
sf:AddChild(radio)
end
 
local heading2 = AceGUI:Create("Heading")
heading2:SetText("Heading 2")
heading2.width = "fill"
sf:AddChild(heading2)
 
for i = 1, 5 do
local radio = AceGUI:Create("CheckBox")
radio:SetLabel("Test Check "..i+5)
radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Check "..i.." Checked" or "Check "..i.." Unchecked") end )
sf:AddChild(radio)
end
 
content:AddChild(sf)
end
 
local function GroupB(content)
content:ReleaseChildren()
local sf = AceGUI:Create("ScrollFrame")
sf:SetLayout("Flow")
 
local check = AceGUI:Create("CheckBox")
check:SetLabel("Group B Checkbox")
check:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Checked" or "Unchecked") end )
 
local dropdown = AceGUI:Create("Dropdown")
dropdown:SetText("Test")
dropdown:SetLabel("Group B Dropdown")
dropdown.list = {"Test","Test2"}
dropdown:SetCallback("OnValueChanged",function(widget,event,value) print(value) end )
 
sf:AddChild(check)
sf:AddChild(dropdown)
content:AddChild(sf)
end
 
local function OtherGroup(content)
content:ReleaseChildren()
 
local sf = AceGUI:Create("ScrollFrame")
sf:SetLayout("Flow")
 
local check = AceGUI:Create("CheckBox")
check:SetLabel("Test Check")
check:SetCallback("OnValueChanged",function(widget,event,value) print(value and "CheckButton Checked" or "CheckButton Unchecked") end )
 
sf:AddChild(check)
 
local inline = AceGUI:Create("InlineGroup")
inline:SetLayout("Flow")
inline:SetTitle("Inline Group")
inline.width = "fill"
 
local heading1 = AceGUI:Create("Heading")
heading1:SetText("Heading 1")
heading1.width = "fill"
inline:AddChild(heading1)
 
for i = 1, 10 do
local radio = AceGUI:Create("CheckBox")
radio:SetLabel("Test Radio "..i)
radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Radio "..i.." Checked" or "Radio "..i.." Unchecked") end )
radio:SetType("radio")
inline:AddChild(radio)
end
 
local heading2 = AceGUI:Create("Heading")
heading2:SetText("Heading 2")
heading2.width = "fill"
inline:AddChild(heading2)
 
for i = 1, 10 do
local radio = AceGUI:Create("CheckBox")
radio:SetLabel("Test Radio "..i)
radio:SetCallback("OnValueChanged",function(widget,event,value) print(value and "Radio "..i.." Checked" or "Radio "..i.." Unchecked") end )
radio:SetType("radio")
inline:AddChild(radio)
end
 
 
sf:AddChild(inline)
content:AddChild(sf)
end
 
local function SelectGroup(widget, event, value)
if value == "A" then
GroupA(widget)
elseif value == "B" then
GroupB(widget)
else
OtherGroup(widget)
end
end
 
 
local function TreeWindow(content)
content:ReleaseChildren()
 
local 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 t = AceGUI:Create("TreeGroup")
t:SetLayout("Fill")
t:SetTree(tree)
t:SetCallback("OnGroupSelected", SelectGroup )
content:AddChild(t)
SelectGroup(t,"OnGroupSelected","A")
 
end
 
local function TabWindow(content)
content:ReleaseChildren()
local tab = AceGUI:Create("TabGroup")
tab.userdata.parent = content.userdata.parent
tab:SetTabs({"A","B","C","D"},{A="Alpha",B="Bravo",C="Charlie",D="Deltaaaaaaaaaaaaaa"})
tab:SetTitle("Tab Group")
tab:SetLayout("Fill")
tab:SetCallback("OnGroupSelected",SelectGroup)
tab:SelectTab(1)
content:AddChild(tab)
 
end
 
 
function TestFrame()
local f = AceGUI:Create("Frame")
f:SetCallback("OnClose",function(widget, event) print("Closing") AceGUI:Release(widget) end )
f:SetTitle("AceGUI Prototype")
f:SetStatusText("Root Frame Status Bar")
f:SetLayout("Fill")
 
local maingroup = AceGUI:Create("DropdownGroup")
maingroup.userdata.parent = f
maingroup:SetLayout("Fill")
maingroup:SetGroupList({Tab = "Tab Frame", Tree = "Tree Frame"})
maingroup:SetGroup("Tab")
maingroup:SetTitle("Select Group Type")
maingroup:SetCallback("OnGroupSelected", function(widget, event, value)
widget:ReleaseChildren()
if value == "Tab" then
TabWindow(widget)
else
TreeWindow(widget)
end
end )
 
TabWindow(maingroup)
f:AddChild(maingroup)
 
 
f:Show()
end
 
-----------------------
-- DragTarget Widget --
-----------------------
-- Designed to replace type='input' in AceConfigDialog-3.0
do
local Type = "DragTarget"
local Version = 1
local function Acquire(self)
 
end
 
local function Release(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
 
local function SetLabel(self, text)
self.label:SetText(text)
end
 
local function PickupItem(link)
local name = GetItemInfo(link)
for bag = 0, 4 do
for slot = 1, GetContainerNumSlots(bag) do
local slotlink = GetContainerItemLink(bag, slot)
if slotlink then
local slotname = GetItemInfo(slotlink)
if slotname == name then
PickupContainerItem(bag, slot)
return
end
end
end
end
end
 
local function DragLinkOnDragStart(this)
local self = this.obj
if (self.objType == "item") then
PickupItem(self.value)
elseif (self.objType == "spell") then
PickupSpell(self.value)
elseif (self.objType == "macro") then
PickupMacro(strsub(self.value,7))
end
self:SetText("")
self:Fire("OnEnterPressed", self.value)
end
 
 
local function DragLinkGetTexture(self)
if (self.objType == "item") then
local texture = select(10,GetItemInfo(self.value))
if (texture) then
return texture
end
elseif (self.objType == "spell") then
local texture = GetSpellTexture(self.value)
if (texture) then
return texture
end
elseif (self.objType == "macro") then
local name, texture = GetMacroInfo(strsub(self.value,7))
return texture
end
return "Interface\\Icons\\INV_Misc_QuestionMark"
end
 
local function GetValueFromParams(objType, Info1, Info2)
if objType == "item" then
--for items use the link
return Info2
elseif objType == "spell" then
local name, rank = GetSpellName(Info1, Info2)
if rank ~= "" then name = name.."("..rank..")" end
return name
elseif objType == "macro" then
return "macro:"..GetMacroInfo(Info1)
end
end
 
local function DragLinkOnReceiveDrag(this)
local self = this.obj
 
local objType, Info1, Info2 = GetCursorInfo()
 
if (objType == "item" or objType == "spell" or objType == "macro") then
self.objType = objType
self.value = GetValueFromParams(objType, Info1, Info2)
self:Fire("OnEnterPressed", self.value)
self.linkIcon:SetTexture(DragLinkGetTexture(self))
 
ClearCursor()
end
end
 
local function SetText(self, text)
if not text then text = "" end
if text:find("item:%d+") then
self.objType = "item"
self.value = text
elseif strsub(text,1,6) == "macro:" then
self.objType = "macro"
self.value = text
elseif text ~= "" then
self.objType = "spell"
self.value = text
else
self.objType = nil
self.value = ""
end
self.linkIcon:SetTexture(DragLinkGetTexture(self))
self.text:SetText(self.value or "")
end
 
local function SetDisabled(self, disabled)
 
end
 
local function Constructor()
local frame = CreateFrame("Button",nil,UIParent)
local self = {}
self.type = Type
 
 
self.Release = Release
self.Acquire = Acquire
self.SetLabel = SetLabel
self.SetText = SetText
self.SetDisabled = SetDisabled
self.UpdateValue = UpdateValue
 
self.frame = frame
frame.obj = self
 
frame:SetScript("OnDragStart", DragLinkOnDragStart)
frame:SetScript("OnReceiveDrag", DragLinkOnReceiveDrag)
frame:SetScript("OnClick", DragLinkOnReceiveDrag)
frame:SetScript("OnEnter", DragLinkOnEnter)
frame:SetScript("OnLeave", DragLinkOnLeave)
 
frame:EnableMouse()
frame:RegisterForDrag("LeftButton")
frame:RegisterForClicks("LeftButtonUp", "RightButtonUp")
 
local linkIcon = frame:CreateTexture(nil, "OVERLAY")
linkIcon:SetWidth(self.iconWidth or 36)
linkIcon:SetHeight(self.iconHeight or 36)
linkIcon:SetPoint("LEFT",frame,"LEFT",0,0)
linkIcon:SetTexture(DragLinkGetTexture(self))
linkIcon:SetTexCoord(0,1,0,1)
linkIcon:Show()
self.linkIcon = linkIcon
 
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
label:SetPoint("TOPLEFT",linkIcon,"TOPRIGHT",3,-3)
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,0)
label:SetHeight(10)
label:SetJustifyH("LEFT")
self.label = label
 
local text = frame:CreateFontString(nil,"OVERLAY","GameFontNormal")
text:SetPoint("BOTTOMLEFT",linkIcon,"BOTTOMRIGHT",3,3)
text:SetPoint("RIGHT",frame,"RIGHT",0,0)
text:SetHeight(10)
text:SetTextColor(1,1,1,1)
text:SetJustifyH("LEFT")
self.text = text
 
text:SetJustifyH("LEFT")
text:SetTextColor(1,1,1)
 
frame:SetHeight(36)
frame:SetWidth(200)
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor,Version)
 
end
 
local name = "ConfigTest"
local groups = {}
local testgroups = {
type = "group",
name = "Test Group Delete/Hide/Diabled",
childGroups = "select",
args = {
 
}
}
 
local function Delete(info)
testgroups.args[info.arg] = nil
end
 
local function Disable(info)
testgroups.args[info.arg].disabled = true
end
 
local function Hide(info)
testgroups.args[info.arg].hidden = true
end
 
local function Replace(info)
testgroups.args[info.arg] = {
type = "execute",
name = "Replaced"..info.arg
}
end
 
groups.description = {
type = 'description',
name = 'This is a test Description Icon + Width and height from a function, no coords',
image = function() return "Interface\\Icons\\Temp.blp", 100, 100 end,
--imageCoords = { 0, 0.5, 0, 0.5 },
order = 1,
}
--[[
groups.description2 = {
type = 'description',
name = 'This is a test Description Image + width and height directly set',
image = "Interface\\Icons\\Temp.blp",
imageCoords = { 0, 0.5, 0, 0.5 },
imageWidth = 100,
imageHeight = 100,
order = 2,
}
 
groups.description3 = {
type = 'description',
name = '',
image = function() return "Interface\\Icons\\Temp.blp", 100, 100 end,
--imageCoords = { 0, 0.5, 0, 0.5 },
order = 3,
}
--]]
groups.confirm = {
type = 'execute',
name = 'Test Confirm',
order = 15,
func = function() print("Confirmed") end,
confirm = true,
confirmText = "Confirm Prompt",
}
 
local dragvalue = nil
 
groups.customDrag = {
type = 'input',
name = 'Test Custom Control',
get = function() return dragvalue end,
set = function(info, value) dragvalue = value end,
dialogControl = "DragTarget",
order = 16,
}
 
 
for i = 1, 5 do
testgroups.args["group"..i] = {
order = i,
type = "group",
name = "Group"..i,
args = {
delete = {
name = "Delete",
desc = "Delete this group",
type = "execute",
arg = "group"..i,
func = Delete,
},
disable = {
name = "Disable",
desc = "Disable this group",
type = "execute",
arg = "group"..i,
func = Disable,
},
hide = {
name = "Hide",
desc = "Hide this group",
type = "execute",
arg = "group"..i,
func = Hide,
},
replace = {
name = "Replace",
desc = "Replace this group",
type = "execute",
arg = "group"..i,
func = Replace,
},
}
}
end
 
local m = { }
 
groups.multi = {
type = 'multiselect',
name = 'multi',
desc = 'Test Multiselect',
tristate = true,
width = "half",
set = function(info, key, value) m[key] = value print(key, value) end,
get = function(info, key) return m[key] end,
order = 100,
values = {
a = "Alpha",
b = "Bravo",
c = "Charlie",
d = "Delta",
e = "Echo",
f = "Foxtrot",
}
}
 
local sel = 'a'
 
groups.select = {
type = 'select',
name = 'select',
desc = 'Test Select',
set = function(info, key, value) sel = key print(sel) end,
get = function(info, key) return sel end,
order = 101,
values = {
a = "Alpha",
b = "Bravo",
c = "Charlie",
d = "Delta",
e = "Echo",
f = "Foxtrot",
}
}
 
local toggleval
 
groups.toggle = {
type = 'toggle',
name = 'toggle',
desc = 'Test Toggle',
set = function(info, value) toggleval = value print(toggleval) end,
get = function(info) return toggleval end,
tristate = true,
order = 102
}
 
local R,G,B,A = 1.0,1.0,1.0,1.0
 
groups.color = {
type = 'color',
name = 'color',
desc = 'Test Color',
set = function(info, r,g,b,a) R,G,B,A = r,g,b,a print(R,G,B,A) end,
get = function(info) return R,G,B,A end,
hasAlpha = false,
order = 103
}
 
groups.colora = {
type = 'color',
name = 'colora',
desc = 'Test Color with Alpha',
set = function(info, r,g,b,a) R,G,B,A = r,g,b,a print(R,G,B,A) end,
get = function(info) return R,G,B,A end,
hasAlpha = true,
order = 104
}
 
local keyval
groups.key = {
type = 'keybinding',
name = 'key',
desc = 'Test Keybind',
set = function(info, value) keyval = value print(keyval) end,
get = function(info) return keyval end,
order = 105,
}
 
local mval
groups.multiline = {
type = 'input',
name = "Multiline",
desc = "Test Multiline",
set = function(info, value) mval = value print(mval) end,
get = function(info) return mval end,
multiline = true,
}
 
local options = {
type = "group",
name = name,
childGroups = "tab",
args = {
test = {
type = "group",
name = "Test Controls",
args = groups,
disabled = false
}
}
}
 
local types = {'input', 'toggle', 'select', 'multiselect', 'range', 'keybinding', 'execute', 'color'}
local function GetTestOpts(disabled)
local values = { input = "Test", select = 'a', multiselect = true, range = 1}
local group = {
type = "group",
--inline = true,
name = "Options",
set = function(info, value) values[info[#info]] = value end,
get = function(info, value) return values[info[#info]] end,
args = {}
}
 
if disabled then
group.name = "Disabled Options"
end
 
for i, type in ipairs(types) do
local opt = {}
opt.name = type
opt.type = type
opt.desc = "Test "..type
opt.order = i
opt.disabled = disabled
if type == "select" or type =="multiselect" then
opt.values = {
a = "Alpha",
b = "Bravo",
c = "Charlie",
d = "Delta",
e = "Echo",
f = "Foxtrot",
}
end
 
if type == "range" then
opt.min = 0
opt.max = 1000
opt.step = 1
opt.bigStep = 10
end
 
if type == "execute" then
opt.func = function(info) print("Execute") end
end
 
group.args[type] = opt
end
return group
end
 
options.plugins = {}
options.plugins.normal = { normal = GetTestOpts() }
options.plugins.disabled = { disabled = GetTestOpts(true) }
options.plugins.test = { testgroups = testgroups }
 
LibStub("AceConfig-3.0"):RegisterOptionsTable(name, options, "ct")
--LibStub("AceConfigDialog-3.0"):Open("ConfigTest" )
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceGUITest/AceGUITest.toc New file
0,0 → 1,10
## Interface: 20200
 
## Title: AceGUITest
 
## Author: Nargiddley
## Version: Alpha
## OptionalDeps: LibStub, Ace3
 
LibStub.lua
test.lua
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceGUI-3.0-recycle.lua New file
0,0 → 1,50
 
dofile("wow_api.lua")
dofile("LibStub.lua")
dofile("../AceGUI-3.0/AceGUI-3.0.lua")
 
local AceGUI = LibStub("AceGUI-3.0")
 
-- create dummy widget
do
local Type = "Example"
 
local function Acquire(self)
 
end
 
local function Release(self)
 
end
 
 
local function Constructor()
local frame = CreateFrame("Frame",nil,UIParent)
local self = {}
self.type = Type
 
self.Release = Release
self.Acquire = Acquire
 
self.frame = frame
frame.obj = self
 
AceGUI:RegisterAsWidget(self)
return self
end
 
AceGUI:RegisterWidgetType(Type,Constructor, 1)
end
 
local widget1 = AceGUI:Create("Example")
AceGUI:Release(widget1)
 
LibStub.minors["AceGUI-3.0"] = -1
 
dofile("../AceGUI-3.0/AceGUI-3.0.lua")
 
local widget2 = AceGUI:Create("Example")
 
assert(widget1 == widget2)
 
print("OK")
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/tests/AceSerializer-3.0.lua New file
0,0 → 1,308
dofile("wow_api.lua")
dofile("../LibStub/LibStub.lua")
dofile("../AceSerializer-3.0/AceSerializer-3.0.lua")
 
-- Usage: lua AceSerializer-3.0.lua [<burnin count, default 1>]
local BURNIN = tonumber(arg[1]) or 1 -- roughly 1 sec execution time per loop, 10000 loops should be a good burn-in
 
local AceSer = LibStub("AceSerializer-3.0")
 
local function printf(fmt, ...)
print(fmt:format(...))
end
 
 
local function comp(input,res,expect,errlvl)
if res~=expect then
error(format("Input %q resulted in %q. Expected %q.", tostring(input), tostring(res), tostring(expect)), 1+(errlvl or 1))
end
end
 
local function test(func, input, expect, errlvl)
local res = func(input)
comp(input,res,expect, 1+(errlvl or 1))
end
 
 
-----------------------------------------------------------------------
-- Test SerializeStringHelper
 
local SerializeStringHelper = assert(AceSer.internals.SerializeStringHelper)
 
 
test(SerializeStringHelper,"\000", "~@")
test(SerializeStringHelper,"\001", "~A")
test(SerializeStringHelper,"\031", "~_")
test(SerializeStringHelper," ", "~`")
test(SerializeStringHelper,"\094", "~\125")
test(SerializeStringHelper,"\126", "~\124")
test(SerializeStringHelper,"\127", "~\123")
 
for i=33,255 do
if i~=94 and i~=126 and i~=127 then
assert(not pcall(SerializeStringHelper, strbyte(i))) -- should error
end
end
 
 
-----------------------------------------------------------------------
-- Test SerializeValue
 
local SerializeValue = assert(AceSer.internals.SerializeValue)
 
 
local function testsv(input, expect, errlvl)
local res = {}
local nres = SerializeValue(input, res, 0)
 
comp(input,table.concat(res), expect, 1+(errlvl or 1))
end
 
-- Strings:
testsv("", "^S")
testsv("hi", "^Shi")
testsv("a\000b\032c", "^Sa~@b~`c")
testsv("^S", "^S~\125S")
 
-- Other simply types
testsv(nil, "^Z")
testsv(true, "^B")
testsv(false, "^b")
testsv(0, "^N0")
testsv(-5, "^N-5")
testsv(12345, "^N12345")
 
-- Tables:
testsv({}, "^T^t")
 
testsv({ -- number indices, string values
"foo","bar"
}, "^T^N1^Sfoo^N2^Sbar^t") -- 50% chance to get ordering right :S luckily all 5.1s behave the same way
 
testsv({
a="hi",b="bye" -- string indices, string values
}, "^T^Sa^Shi^Sb^Sbye^t") -- 50% chance again
 
testsv({ -- table as index, table as value
[{theindex="isatable"}]={thevalue=2}
}, "^T^T^Stheindex^Sisatable^t^T^Sthevalue^N2^t^t")
 
 
-----------------------------------------------------------------------
-- Test Deserialize
 
-- Error testing:
local ok, r1,r2,r3 = AceSer:Deserialize("errormoar") -- plain error
assert(not ok)
assert(strmatch(r1, "not AceSerializer data"))
 
local ok, r1,r2,r3 = AceSer:Deserialize("^2^^") -- unknown version -> error
assert(not ok)
assert(strmatch(r1, "not AceSerializer data"))
 
local ok, r1,r2,r3 = AceSer:Deserialize("^1") -- unterminated -> error
assert(not ok)
assert(strmatch(r1, "misses AceSerializer terminator"), r1)
 
-- Empty data
local function x(ok,...)
assert(ok)
assert(select("#",...)==0)
end
x(AceSer:Deserialize("^1^^")) -- empty data -> ok
 
-- Simple datatypes:
local ok, r1,r2,r3 = assert(AceSer:Deserialize("^1^Sone^Stwo^^")) -- two strings -> ok
assert(r1=="one" and r2=="two" and r3==nil, dump(ok,r1,r2,r3))
 
local ok, r1,r2,r3 = assert(AceSer:Deserialize("^1^B^b^^")) -- true, false -> ok
assert(r1==true and r2==false and r3==nil)
 
local ok, r1,r2,r3 = assert(AceSer:Deserialize("^1^Z^N5^^")) -- nil, 5 -> ok
assert(r1==nil and r2==5 and r3==nil, dump(ok,r1,r2,r3))
 
local ok, r1,r2,r3 = AceSer:Deserialize("^1^Nblurgh^^") -- invalid number -> error
assert(not ok and strmatch(r1,"Invalid serialized number"), r1)
 
-- Tables (ergh):
 
local ok, r1,r2,r3 = assert(AceSer:Deserialize("^1^T^t^^")) -- empty table
assert(type(r1)=="table")
assert(next(r1)==nil)
assert(r2==nil)
 
local ok, r1,r2,r3 = assert(AceSer:Deserialize("^1^T^N1^Shi^t^^")) -- number = string
assert(r1[1]=="hi")
assert(r2==nil)
 
local ok, r1,r2,r3 = assert(AceSer:Deserialize("^1^T^T^Stheindex^Sisatable^t^T^Sthevalue^N2^t^t^Send^^")) -- table = table, with tacked on string to test iterator
local k,v = next(r1)
assert(type(k)=="table")
assert(type(v)=="table")
assert(k.theindex=="isatable")
assert(v.thevalue==2)
assert(r2=="end")
 
-- Table error testing:
local ok,res = AceSer:Deserialize("^1^T")
assert(not ok and strmatch(res, "misses AceSerializer terminator"))
 
local ok,res = AceSer:Deserialize("^1^T^^")
assert(not ok and strmatch(res, "no table end marker"))
 
local ok,res = AceSer:Deserialize("^1^T^Sa")
assert(not ok and strmatch(res, "misses AceSerializer terminator"))
 
local ok,res = AceSer:Deserialize("^1^T^Sa^^")
assert(not ok and strmatch(res, "no table end marker"))
 
local ok,res = AceSer:Deserialize("^1^T^Sa^Sb")
assert(not ok and strmatch(res, "misses AceSerializer terminator"))
 
local ok,res = AceSer:Deserialize("^1^T^Sa^Sb^^")
assert(not ok and strmatch(res, "no table end marker"))
 
assert(AceSer:Deserialize("^1^T^Sa^Sb^t^^"))
 
 
 
-----------------------------------------------------------------------
-- Wild combos
 
local ser = AceSer:Serialize(
"firstval",
123e-17,
true,
false,
nil,
{
{
foo="bar"
},
{
baz={}
},
name="val",
},
"\001\032\127^~fin!^^"
)
 
local ok,r1,r2,r3,r4,r5,r6,r7,r8 = assert(AceSer:Deserialize(ser))
assert(r1=="firstval")
assert(r2==1.23e-15)
assert(r3==true)
assert(r4==false)
assert(r5==nil)
assert(type(r6)=="table")
assert(r6[1].foo=="bar")
assert(type(r6[2].baz)=="table")
assert(r6.name=="val")
comp("?", r7, "\001\032\127^~fin!^^")
assert(r8==nil)
 
 
-----------------------------------------------------------------------
-- Wild combos, now as a table
 
local ser = AceSer:Serialize({
"firstval",
123e-17,
true,
false, -- ACE-130
nil,
{
{
foo="bar"
},
{
baz={}
},
name="val",
},
"\001\032\127^~fin!^^",
[true]="yes",
[false]="no" -- ACE-130
})
 
local ok,r = assert(AceSer:Deserialize(ser))
assert(r[1]=="firstval")
assert(r[2]==1.23e-15)
assert(r[3]==true)
assert(r[4]==false)
assert(r[5]==nil)
assert(type(r[6])=="table")
assert(r[6][1].foo=="bar")
assert(type(r[6][2].baz)=="table")
assert(r[6].name=="val")
comp("?", r7, "\001\032\127^~fin!^^")
assert(r[8]==nil)
 
assert(r[true]=="yes")
assert(r[false]=="no")
 
 
-----------------------------------------------------------------------
-- NaN, inf, etc
 
local ok,res = AceSer:Deserialize(AceSer:Serialize(0/0))
assert(ok and tostring(res)==tostring(0/0))
 
local ok,res = AceSer:Deserialize(AceSer:Serialize(1/0))
assert(ok and tostring(res)==tostring(1/0))
 
local ok,res = AceSer:Deserialize(AceSer:Serialize(-1/0))
assert(ok and tostring(res)==tostring(-1/0))
 
 
-----------------------------------------------------------------------
-- Floating-point accuracy (ACE-123)
 
local function testone(v)
local ser = AceSer:Serialize(v)
local ok,deser = AceSer:Deserialize(ser)
assert(ok and deser==v, dump(ok, v, ser, deser))
end
 
local __myrand_n = 0
local function myrand()
__myrand_n = (__myrand_n + 1.23456789) % 123 -- this prng does not repeat for at least 10G iterations - tested up to 13.048G
local n = frexp(__myrand_n)*2
local ret = math.random() + n
ret = ret - floor(ret)
return ret
end
 
 
testone(1/3)
testone(2/3)
testone(math.pi)
testone(math.exp(1)) -- 2.718281828459...
testone(math.sqrt(math.exp(1))) -- 1.6487212707001...
testone(math.sqrt(0.5)) -- 0.70710678118655...
 
if BURNIN>1 then
print "Floating point precision burn-in test:"
end
local startt = os.clock()
for l=0,BURNIN-1 do -- default 1 = 1 loop, but no printing
if l>=1 then
local tick = (os.clock()-startt) / l
printf("%.2f%% (%.1fs)", (l/BURNIN*100), (BURNIN-l)*tick)
end
for i=1,10000 do
local v = myrand() + myrand()*(2^-20) + myrand()*(2^-40) + myrand()*(2^-60)
if math.random(1,2)==1 then
v = v * -1
end
-- str=format("%+0.20f\t",v)
local e = math.random(-1000, 1000)
v = v * 2^(e)
-- print(str,e,v)
 
testone(v)
end
end
 
 
-----------------------------------------------------------------------
print "OK"
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/unsplit.bat New file
0,0 → 1,6
@echo off
for /F %%i in (split.txt) do move ..\%%i .
del split.txt
del Ace3.toc
move Ace3.toc.unsplit Ace3.toc
 
Property changes : Added: svn:mime-type + text/plain Added: svn:eol-style + CRLF
RepWatch/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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/changelog.txt New file
0,0 → 1,142
Ace3 Beta - Revision 76325 (June 9th, 2008)
--------------------------------------------
- AceGUI-3.0: Finish Multiselect support for the Dropdown widget (nargiddley)
- AceGUI-3.0: Re-write TabGroup layouting (nargiddley)
- AceGUI-3.0: TreeGroup: Add :EnableButtonTooltips(enable) to make the default tooltips on the tree optional, enabled by default. (nargiddley)
- AceGUI-3.0: TabGroup: Add OnTabEnter and OnTabLeave Callbacks (nargiddley)
- AceConfigDialog-3.0: Add :SelectGroup(appName, ...) - Selects the group given by the path specified then refreshes open windows. (nargiddley)
- AceConfigDialog-3.0: :Open now accepts an optional path, when given will open the window with only the given group and its children visible (nargiddley)
- AceConfigDialog-3.0: :AddToBlizOptions now accepts an optional path, this will add the config page to display the specified group and its children only. (nargiddley)
- AceConfigDialog-3.0: ACE-189: allow multiselect to be shown as a dropdown by setting dialogControl = "Dropdown" (nargiddley)
- AceConfigDialog-3.0: Add Custom tooltips to the TreeGroup and TabGroup, shows both name and desc for the group. (nargiddley)
- AceConfigCmd-3.0: ACE-195: Remove unneeded references to .confirm, will no longer error when .confirm is a boolean (nargiddley)
- AceAddon-3.0: Allow for an optional first argument to NewAddon to be a table to be used as the base for the addon. (ammo)
 
Ace3 Beta - Revision 74633 (May 19th, 2008)
--------------------------------------------
- AceTimer-3.0: ACE-173: don't error on nil handle for CancelTimer(), just bail out early. (ammo)
- AceGUI-3.0: ACE-161, ACE-180, ACE-181: New and improved DropDown widget (originally coded by Borlox) (nargiddley,nevcairiel)
- AceGUI-3.0: AceGUI will call OnWidthSet and OnHeightSet as frames resize (nargiddley)
- AceGUI-3.0: TabGroup: Use OptionsFrameTabButtonTemplate for tabs (nargiddley)
- AceGUI-3.0: TabGroup: Tabs now span multiple lines when there are too many to fit in the width of the frame (nargiddley)
- AceGUI-3.0: TreeGroup: Tree is now sizable by dragging, orig patch by yssaril (nargiddley)
- AceGUI-3.0: Flow layout will now reduce widgets width to fit rather than leaving them sticking out the side of container widgets (nargiddley)
- AceGUI-3.0: Dropdowns will no longer be left open in the background when the frame is clicked or other widgets are activated (nargiddley)
- AceGUI-3.0: ACE-159: Rename Release to OnRelease and Acquire to OnAcquire for widgets. (nargiddley)
- AceGUI-3.0: ACE-171: add IsVisible and IsShown methods to the widget metatable (nargiddley)
- AceGUI-3.0: ACE-164: add tooltips to tree to show full text of childs that got clipped (ammo)
- AceGUI-3.0: ACE-174: make buttons in AceGUI-3.0 locale independant (ammo)
- AceGUI-3.0: ACE-166: fix treegroup visual bug (ammo)
- AceGUI-3.0: ACE-184: make numeric entry for slider more intuitive (ammo)
- AceConfigCmd-3.0: ACE-172 - ignore description in cmd (ammo)
- AceConsole-3.0: nolonger check for existance of slashcommands, overwrite where needed. Last one wins, this enables AddonLoader to X-LoadOn-Slash and override the slashcommand from AddonLoader slashcommand with an Ace3 one. (Ammo)
 
Ace3 Beta - Revision 69509 (April 13th, 2008)
---------------------------------------------
- AceComm-3.0: turn off error messages when receiving invalid multi-part messages (its happening on login etc) (nevcairiel)
- AceDBOptions-3.0: shorten info text at top to prevent scrollbars. (nevcairiel)
- AceHook-3.0: ACE-162: fix unhooking of objects that were not actually hooked (nevcairiel)
- AceDB-3.0: fire the DB callbacks after the namespaces changed their profile as well (nevcairiel)
- AceDB-3.0: namespaces can now be individually reset using :ResetProfile() on the namespace directly (nevcairiel)
- AceDB-3.0: added a optional argument to :ResetProfile to not populate the reset to all namespaces (so the main profile can reset individually without reseting all namespaces too) (nevcairiel)
 
Ace3 Beta - Revision 66329 (March 27th, 2008)
---------------------------------------------
- Overall 2.4 clean ups - removing 2.4 checks and work arounds (nevcairiel)
- AceBucket-3.0: clear the timer reference when unregistering a bucket to prevent a error when unregistering a bucket that was never fired (nevcairiel)
- AceAddon-3.0: Bugfix when enabling/disabling modules from the parents OnEnable after disabling / enabling the parent addon. (ammo)
- AceGUI-3.0: Don't parent the BlizOptionsGroup widget to UIParent and Hide it by default. Fixes stray controls on the screen. (nargiddley)
- AceConfigDialog-3.0: Config windows without a default size won't incorrectly get a default size from a previously open window. (nargiddley)
- AceDBOptions-3.0: added zhCN and zhTW locale (nevcairiel)
 
Ace3 Beta - Revision 65665 (March 25th, 2008)
---------------------------------------------
- AceGUI-3.0: ACE-139: Changed all Widgets to resemble the Blizzard 2.4 Options Style (nevcairiel)
- AceGUI-3.0: Fixed "List"-Layout not reporting new width to "fill"-mode widgets (mikk)
- AceGUI-3.0: added :SetColor to the Label widget (nevcairiel)
- AceGUI-3.0: ACE-132: ColorPicker: added checkers texture for better alpha channel display, and fixed "white"-texture bug (nevcairiel,nargiddley,ammo)
- AceConfig-3.0: ACE-113: Added uiName, uiType, handler, option, type to the info table (nevcairiel,nargiddley)
- AceConfigDialog-3.0: ACE-139: Adjusted for 2.4 options panels (nevcairiel)
- AceConfigDialog-3.0: Use "width" parameter for the description widget (if present) (nevcairiel)
- AceConfigDialog-3.0: ACE-135: Add support for specifying a rowcount for multiline editboxes (nargiddley)
- AceConfigDialog-3.0: :AddToBlizOptions will return the frame registered so you can use it in InterfaceOptionsFrame_OpenToFrame (nevcairiel)
- AceConfigCmd-3.0: handle "hidden" in help-output (nevcairiel)
- AceHook-3.0: fix unhooking of secure hooks (nevcairiel)
- AceDBOptions-3.0: add optional argument to GetOptionsTable(db[, noDefaultProfiles]) - if set to true will not show the default profiles in the profile selection (nevcairiel)
- AceDBOptions-3.0: added koKR locale (nevcairiel)
- Ace3 Standalone: Removed the "Ace3" Category from the 2.4 options panel (nevcairiel)
 
Ace3 Beta - Revision 64176 (March 10th, 2008)
---------------------------------------------
- AceGUI-3.0: Improve Alpha handling for the ColorPicker widget, ColorPicker widget closes the ColorPickerFrame before opening to prevent values getting carried over (nargiddley)
- AceGUI-3.0: The Slider widget will only react to the mousewheel after it has been clicked (anywhere including the label) to prevent accidental changes to the value when trying to scroll the container it is in (nargiddley)
- AceGUI-3.0: The TreeGroup widget is scrollable with the mousewheel (nargiddley)
- AceGUI-3.0: ACE-154: Fix frame levels in more cases to prevent widgets ending up behind their containers (nargiddley)
- AceConfigDialog: Color picker obeys hasAlpha on the color type (nargiddley)
- AceConfigDialog-3.0: ACE-155: Make sure that the selected group is type='group' when checking if it exists (nargiddley)
- AceDBOptions-3.0: added frFR locale (nevcairiel)
 
Ace3 Beta - Revision 63886 (March 8th, 2008)
---------------------------------------------
- AceDBOptions-3.0: new library to provide a Ace3Options table to control the AceDB-3.0 profiles (nevcairiel)
- AceDB-3.0: add "silent" option to DeleteProfile and CopyProfile when we deal with namespaces (nevcairiel)
- AceDB-3.0: implement library upgrade path (nevcairiel)
- AceDB-3.0: ACE-146: fix problem with non-table values overruling ['*']-type defaults (nevcairiel)
- AceConsole-3.0: treat |T|t texture links similar to |H|h|h links. (ammo)
- AceGUI-3.0: Use Blizzard Templates for the EditBox and DropDown widget (nevcairiel)
- AceBucket-3.0: ACE-150: callback is now optional, if not supplied will use the eventname as method name (only possible if one event is supplied, and not a event table) (nevcairiel)
- tests: adjust tests for AceGUI and AceConsole changes (nevcairiel)
 
Ace3 Beta - Revision 63220 (Feb 29th, 2008)
---------------------------------------------
- AceTimer-3.0: CancelAllTimers() now cancels silent (elkano)
- AceConfigDialog: Add :SetDefaultSize(appName, width, height), sets the size the dialog will open to. Does not effect already open windows. (nargiddley)
- AceConfigDialog: Fix typo in type check for range values (nargiddley)
- AceGUI: ColorPicker widget will correctly fire OnValueChanged for the cancel event of the colorpicker popup. Reset ColorPicker's color on Acquire. (nargiddley)
- AceGUI: Fix Spelling of Aquire -> Acquire for widgets, all custom widgets will need to be updated. A warning will be printed for widgets not upgraded yet. (nargiddley)
- AceConfigCmd-3.0: add simple coloring to slashcommand output. (ammo)
- AceConsole-3.0: add some color to :Print (ammo)
- AceAddon-3.0: set error level on library embedding to point to the :NewAddon call (nevcairiel)
 
Ace3 Beta - Revision 62182 (Feb 20th, 2008)
---------------------------------------------
- Ace3 StandAlone: Add a page to the Blizzard 2.4 Interface Options with icons to open dialogs for configs registered when installed standalone (nargiddley)
- AceConfigDialog: type = 'description' now uses the fields image and imageCoords instead of icon and iconCoords, add imageWidth and imageHeight (nargiddley)
- AceConfigDialog: Add :AddToBlizzardOptions(appName, name), this will add the specified config to the Blizzard Options pane new in 2.4. This will only be available if running on the 2.4 PTR (nargiddley)
- AceDB: fix GetProfiles() when setting the same profile twice (nevcairiel)
- AceDB: bail out of :SetProfile early when trying to set to the same profile (nevcairiel)
- AceDB: add nil checks to metatable handling (nevcairiel)
- AceDB: clear tables that are empty after defaults removal (nevcairiel)
- AceGUI: Fix a couple of layout bugs causing the width of groups to be wrong (nargiddley)
- AceGUI: Add Icon widget (nargiddley)
- AceGUI: Allow room for the border in the BlizOptionsGroup widget (nargiddley)
- AceGUI: Button and Keybinding use UIPanelButtonTemplate2 (nargiddley)
- AceConsole-3.0: Fix bug where no table for [self] was created when registering weak commands (ammo)
- AceTimer-3.0: add missing :OnEmbedDisable (ammo)
- AceAddon-3.0: added :GetName() that will always return the "real" name of a addon or module object without any prefixes (nevcairiel)
 
Ace3 Beta - Revision 60697 (Feb 9th, 2008)
---------------------------------------------
- CallbackHandler-1.0: remove unnecessary table creation if a event is fired thats not registered (nevcairiel)
- AceAddon-3.0: fixed a bug with recursive addon loading (nevcairiel)
- AceGUI: Update TabGroup's tablist format, tabs are selected by value not index (nargiddley)
- AceGUI: Add MultiLineEditBox widget (nargiddley, originally by bam)
- AceGUI: Small fix to the flow layout preventing controls overlapping in some cases (nargiddley)
- AceConfigDialog: Implement control and dialogControl for types 'input' and 'select' (nargiddley)
- AceConfigDialog: Add support for multiline = true on type = 'input' (nargiddley)
- AceConfigDialog: Fix an error when all groups are hidden in a group with childGroups = 'select' (nargiddley)
- AceConfigDialog: type = 'description' will now show .icon as an image with its text (nargiddley)
- AceConfigDialog: multiline inputs are no longer forced to width = "full" (nargiddley)
- AceConfigDialog: bug fix when loading without AceConsole present (nevcairiel)
 
Ace3 Beta - Revision 60545 (Feb 7th, 2008)
---------------------------------------------
- AceGUI: SetToplevel(true) for the Frame widget, multiple open windows should play nice together now (nargiddley)
- AceGUI: Move Frames to the FULLSCREEN_DIALOG strata (nargiddley)
- AceGUI: Dropdown, Editbox and Keybinding labels grey out when disabled (nargiddley)
- AceGUI: Add OnClick callback to the TreeGroup widget (nargiddley)
- AceConfigDialog: Confirm popups will be above the config window (nargiddley)
 
Ace3 Beta - Revision 60163 (Feb 3rd, 2008)
---------------------------------------------
- Initial Beta release
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/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 Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceLocale-3.0/AceLocale-3.0.lua New file
0,0 → 1,103
--[[ $Id: AceLocale-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]]
local MAJOR,MINOR = "AceLocale-3.0", 1
 
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
geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
rawset(self, key, key) -- only need to see the warning once, really
return key
end
}
 
-- Remember the locale table being registered right now (it gets set by :NewLocale())
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
})
 
-- AceLocale:NewLocale(application, locale, isDefault)
--
-- application (string) - unique name of addon / module
-- locale (string) - name of locale to register, e.g. "enUS", "deDE", etc...
-- isDefault (string) - if this is the default locale being registered
--
-- Returns a table where localizations can be filled out, or nil if the locale is not needed
function AceLocale:NewLocale(application, locale, isDefault)
 
-- 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({}, 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
 
-- AceLocale:GetLocale(application [, silent])
--
-- application (string) - unique name of addon
-- silent (boolean) - if true, the locale is optional, silently return nil if it's not found
--
-- 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)
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceHook-3.0/AceHook-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="AceHook-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceHook-3.0/AceHook-3.0.lua New file
0,0 → 1,372
--[[ $Id: AceHook-3.0.lua 69511 2008-04-13 10:10:53Z nevcairiel $ ]]
local ACEHOOK_MAJOR, ACEHOOK_MINOR = "AceHook-3.0", 4
local AceHook, oldminor = LibStub:NewLibrary(ACEHOOK_MAJOR, ACEHOOK_MINOR)
 
if not AceHook then return end -- No upgrade needed
 
AceHook.embeded = AceHook.embeded or {}
AceHook.registry = AceHook.registry or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end })
AceHook.handlers = AceHook.handlers or {}
AceHook.actives = AceHook.actives or {}
AceHook.scripts = AceHook.scripts or {}
AceHook.onceSecure = AceHook.onceSecure or {}
AceHook.hooks = AceHook.hooks or {}
 
-- local upvalues
local registry = AceHook.registry
local handlers = AceHook.handlers
local actives = AceHook.actives
local scripts = AceHook.scripts
local onceSecure = AceHook.onceSecure
 
local _G = _G
local format = string.format
local next = next
local pairs = pairs
local type = type
 
-- functions for later definition
local donothing, createHook, hook
 
local protectedScripts = {
OnClick = true,
}
 
-- upgrading of embeded is done at the bottom of the file
 
local mixins = {
"Hook", "SecureHook",
"HookScript", "SecureHookScript",
"Unhook", "UnhookAll",
"IsHooked",
"RawHook", "RawHookScript"
}
 
-- AceHook:Embed( target )
-- target (object) - target object to embed AceHook in
--
-- Embeds AceEevent into the target object making the functions from the mixins list available on target:..
function AceHook:Embed( target )
for k, v in pairs( mixins ) do
target[v] = self[v]
end
self.embeded[target] = true
-- inject the hooks table safely
target.hooks = target.hooks or {}
return target
end
 
-- AceHook:OnEmbedDisable( target )
-- target (object) - target object that is being disabled
--
-- Unhooks all hooks when the target disables.
-- this method should be called by the target manually or by an addon framework
function AceHook:OnEmbedDisable( target )
target:UnhookAll()
end
 
function createHook(self, handler, orig, secure, failsafe)
local uid
local method = type(handler) == "string"
if failsafe and not secure then
-- failsafe hook creation
uid = function(...)
if actives[uid] then
if method then
self[handler](self, ...)
else
handler(...)
end
end
return orig(...)
end
-- /failsafe hook
else
-- all other hooks
uid = function(...)
if actives[uid] then
if method then
return self[handler](self, ...)
else
return handler(...)
end
elseif not secure then -- backup on non secure
return orig(...)
end
end
-- /hook
end
return uid
end
 
function donothing() end
 
function hook(self, obj, method, handler, script, secure, raw, forceSecure, usage)
if not handler then handler = method end
 
-- These asserts make sure AceHooks's devs play by the rules.
assert(not script or type(script) == "boolean")
assert(not secure or type(secure) == "boolean")
assert(not raw or type(raw) == "boolean")
assert(not forceSecure or type(forceSecure) == "boolean")
assert(usage)
 
-- Error checking Battery!
if obj and type(obj) ~= "table" then
error(format("%s: 'object' - nil or table expected got %s", usage, type(obj)), 3)
end
if type(method) ~= "string" then
error(format("%s: 'method' - string expected got %s", usage, type(method)), 3)
end
if type(handler) ~= "string" and type(handler) ~= "function" then
error(format("%s: 'handler' - nil, string, or function expected got %s", usage, type(handler)), 3)
end
if type(handler) == "string" and type(self[handler]) ~= "function" then
error(format("%s: 'handler' - Handler specified does not exist at self[handler]", usage), 3)
end
if script then
if not secure and obj:IsProtected() and protectedScripts[method] then
error(format("Cannot hook secure script %q; Use SecureHookScript(obj, method, [handler]) instead.", method), 3)
end
if not obj or not obj.GetScript or not obj:HasScript(method) then
error(format("%s: You can only hook a script on a frame object", usage), 3)
end
else
local issecure
if obj then
issecure = onceSecure[obj] and onceSecure[obj][method] or issecurevariable(obj, method)
else
issecure = onceSecure[method] or issecurevariable(method)
end
if issecure then
if forceSecure then
if obj then
onceSecure[obj] = onceSecure[obj] or {}
onceSecure[obj][method] = true
else
onceSecure[method] = true
end
elseif not secure then
error(format("%s: Attempt to hook secure function %s. Use `SecureHook' or add `true' to the argument list to override.", usage, method), 3)
end
end
end
 
local uid
if obj then
uid = registry[self][obj] and registry[self][obj][method]
else
uid = registry[self][method]
end
 
if uid then
if actives[uid] then
-- Only two sane choices exist here. We either a) error 100% of the time or b) always unhook and then hook
-- choice b would likely lead to odd debuging conditions or other mysteries so we're going with a.
error(format("Attempting to rehook already active hook %s.", method))
end
 
if handlers[uid] == handler then -- turn on a decative hook, note enclosures break this ability, small memory leak
actives[uid] = true
return
elseif obj then -- is there any reason not to call unhook instead of doing the following several lines?
if self.hooks and self.hooks[obj] then
self.hooks[obj][method] = nil
end
registry[self][obj][method] = nil
else
if self.hooks then
self.hooks[method] = nil
end
registry[self][method] = nil
end
handlers[uid], actives[uid], scripts[uid] = nil, nil, nil
uid = nil
end
 
local orig
if script then
orig = obj:GetScript(method) or donothing
elseif obj then
orig = obj[method]
else
orig = _G[method]
end
 
if not orig then
error(format("%s: Attempting to hook a non existing target", usage), 3)
end
 
uid = createHook(self, handler, orig, secure, not (raw or secure))
 
if obj then
self.hooks[obj] = self.hooks[obj] or {}
registry[self][obj] = registry[self][obj] or {}
registry[self][obj][method] = uid
 
if not secure then
if script then
obj:SetScript(method, uid)
else
obj[method] = uid
end
self.hooks[obj][method] = orig
else
if script then
obj:HookScript(method, uid)
else
hooksecurefunc(obj, method, uid)
end
end
else
registry[self][method] = uid
 
if not secure then
_G[method] = uid
self.hooks[method] = orig
else
hooksecurefunc(method, uid)
end
end
 
actives[uid], handlers[uid], scripts[uid] = true, handler, script and true or nil
end
 
-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure])
function AceHook:Hook(object, method, handler, hookSecure)
if type(object) == "string" then
method, handler, hookSecure, object = object, method, handler, nil
end
 
if handler == true then
handler, hookSecure = nil, true
end
 
hook(self, object, method, handler, false, false, false, hookSecure or false, "Usage: Hook([object], method, [handler], [hookSecure])")
end
 
-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure])
function AceHook:RawHook(object, method, handler, hookSecure)
if type(object) == "string" then
method, handler, hookSecure, object = object, method, handler, nil
end
 
if handler == true then
handler, hookSecure = nil, true
end
 
hook(self, object, method, handler, false, false, true, hookSecure or false, "Usage: RawHook([object], method, [handler], [hookSecure])")
end
 
-- ("function", handler) or (object, "method", handler)
function AceHook:SecureHook(object, method, handler)
if type(object) == "string" then
method, handler, object = object, method, nil
end
 
hook(self, object, method, handler, false, true, false, false, "Usage: SecureHook([object], method, [handler])")
end
 
function AceHook:HookScript(frame, script, handler)
hook(self, frame, script, handler, true, false, false, false, "Usage: HookScript(object, method, [handler])")
end
 
function AceHook:RawHookScript(frame, script, handler)
hook(self, frame, script, handler, true, false, true, false, "Usage: RawHookScript(object, method, [handler])")
end
 
function AceHook:SecureHookScript(frame, script, handler)
hook(self, frame, script, handler, true, true, false, false, "Usage: SecureHookScript(object, method, [handler])")
end
 
-- ("function") or (object, "method")
function AceHook:Unhook(obj, method)
local usage = "Usage: Unhook([obj], method)"
if type(obj) == "string" then
method, obj = obj, nil
end
 
if obj and type(obj) ~= "table" then
error(format("%s: 'obj' - expecting nil or table got %s", usage, type(obj)), 2)
end
if type(method) ~= "string" then
error(format("%s: 'method' - expeting string got %s", usage, type(method)), 2)
end
 
local uid
if obj then
uid = registry[self][obj] and registry[self][obj][method]
else
uid = registry[self][method]
end
 
if not uid or not actives[uid] then
-- Declining to error on an unneeded unhook since the end effect is the same and this would just be annoying.
return false
end
 
actives[uid], handlers[uid] = nil, nil
 
if obj then
registry[self][obj][method] = nil
registry[self][obj] = next(registry[self][obj]) and registry[self][obj] or nil
 
-- if the hook reference doesnt exist, then its a secure hook, just bail out and dont do any unhooking
if not self.hooks[obj] or not self.hooks[obj][method] then return true end
 
if scripts[uid] and obj:GetScript(method) == uid then -- unhooks scripts
obj:SetScript(method, self.hooks[obj][method] ~= donothing and self.hooks[obj][method] or nil)
scripts[uid] = nil
elseif obj and self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then -- unhooks methods
obj[method] = self.hooks[obj][method]
end
 
self.hooks[obj][method] = nil
self.hooks[obj] = next(self.hooks[obj]) and self.hooks[obj] or nil
else
registry[self][method] = nil
 
-- if self.hooks[method] doesn't exist, then this is a SecureHook, just bail out
if not self.hooks[method] then return true end
 
if self.hooks[method] and _G[method] == uid then -- unhooks functions
_G[method] = self.hooks[method]
end
 
self.hooks[method] = nil
end
return true
end
 
function AceHook:UnhookAll()
for key, value in pairs(registry[self]) do
if type(key) == "table" then
for method in pairs(value) do
self:Unhook(key, method)
end
else
self:Unhook(key)
end
end
end
 
-- ("function") or (object, "method")
function AceHook:IsHooked(obj, method)
-- we don't check if registry[self] exists, this is done by evil magicks in the metatable
if type(obj) == "string" then
if registry[self][obj] and actives[registry[self][obj]] then
return true, handlers[registry[self][obj]]
end
else
if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
return true, handlers[registry[self][obj][method]]
end
end
 
return false, nil
end
 
--- Upgrade our old embeded
for target, v in pairs( AceHook.embeded ) do
AceHook:Embed( target )
end
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
RepWatch/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 Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceDBOptions-3.0/AceDBOptions-3.0.lua New file
0,0 → 1,353
--[[ $Id: AceDBOptions-3.0.lua 69511 2008-04-13 10:10:53Z nevcairiel $ ]]
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 6
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
 
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
 
end
 
local defaultProfiles
local tmpprofiles = {}
 
--[[
getProfileList(db, common, nocurrent)
 
db - the db object to retrieve the profiles from
common (boolean) - if common is true, getProfileList will add the default profiles to the return list, even if they have not been created yet
nocurrent (boolean) - if true then getProfileList will not display the current profile in the list
]]--
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
 
--[[ 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",
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",
arg = "nocurrent",
confirm = true,
confirmText = L["delete_confirm"],
},
}
 
--[[
GetOptionsTable(db)
db - the database object to create the options table for
 
creates and returns a option table to be used in your addon
]]
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/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 Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceConsole-3.0/AceConsole-3.0.lua New file
0,0 → 1,221
--[[ $Id: AceConsole-3.0.lua 79706 2008-08-03 04:03:05Z gnarfoz $ ]]
local MAJOR,MINOR = "AceConsole-3.0", 6
 
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
 
-- local upvalues
local _G = _G
local pairs = pairs
local select = select
local type = type
local tostring = tostring
local strfind = string.find
local strsub = string.sub
local max = math.max
 
-- AceConsole:Print( [chatframe,] ... )
--
-- Print to DEFAULT_CHAT_FRAME or given chatframe (anything with an .AddMessage member)
function AceConsole:Print(...)
local text = ""
if self ~= AceConsole then
text = "|cff33ff99"..tostring( self ).."|r: "
end
 
local frame = select(1, ...)
if not ( type(frame) == "table" and frame.AddMessage ) then -- Is first argument something with an .AddMessage member?
frame=nil
end
 
for i=(frame and 2 or 1), select("#", ...) do
text = text .. tostring( select( i, ...) ) .." "
end
(frame or DEFAULT_CHAT_FRAME):AddMessage( text )
end
 
 
-- AceConsole:RegisterChatCommand(. command, func, persist )
--
-- command (string) - chat command to be registered WITHOUT leading "/"
-- func (function|membername) - function to call, or self[membername](self, ...) call
-- persist (boolean) - false: the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
--
-- Register a simple chat command
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)
self[func](self, input)
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
 
 
-- AceConsole:UnregisterChatCommand( command )
--
-- Unregister a chatcommand
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
 
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
 
 
-- AceConsole:GetArgs(string, numargs, startpos)
--
-- Retreive one or more space-separated arguments from a string.
-- Treats quoted strings and itemlinks as non-spaced.
--
-- string - The raw argument string
-- numargs - How many arguments to get (default 1)
-- startpos - Where in the string to start scanning (default 1)
--
-- 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",
"RegisterChatCommand",
"UnregisterChatCommand",
"GetArgs",
}
 
-- AceConsole:Embed( target )
-- target (object) - target object to embed AceBucket in
--
-- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-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="AceConfigRegistry-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua New file
0,0 → 1,352
--[[
AceConfigRegistry-3.0:
 
Handle central registration of options tables in use by addons and modules. Do nothing else.
 
Options tables can be registered as raw tables, or as function refs that return a table.
These functions receive two arguments: "uiType" and "uiName".
- Valid "uiTypes": "cmd", "dropdown", "dialog". This is verified by the library at call time.
- The "uiName" field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.
 
:IterateOptionsTables() and :GetOptionsTable() always return a function reference that the requesting config handling addon must call with the above arguments.
]]
 
local MAJOR, MINOR = "AceConfigRegistry-3.0", 6
local lib = LibStub:NewLibrary(MAJOR, MINOR)
 
if not lib then return end
 
lib.tables = lib.tables or {}
 
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
 
if not lib.callbacks then
lib.callbacks = CallbackHandler:New(lib)
end
 
-----------------------------------------------------------------------
-- Validating options table consistency:
 
 
lib.validated = {
-- list of options table names ran through :ValidateOptionsTable automatically.
-- CLEARED ON PURPOSE, since newer versions may have newer validators
cmd = {},
dropdown = {},
dialog = {},
}
 
 
 
local function err(msg, errlvl, ...)
local t = {}
for i=select("#",...),1,-1 do
tinsert(t, (select(i, ...)))
end
error(MAJOR..":ValidateOptionsTable(): "..table.concat(t,".")..msg, errlvl+2)
end
 
 
local isstring={["string"]=true, _="string"}
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
local istable={["table"]=true, _="table"}
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
local optstring={["nil"]=true,["string"]=true, _="string"}
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
local optnumber={["nil"]=true,["number"]=true, _="number"}
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
local opttable={["nil"]=true,["table"]=true, _="table"}
local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
 
local basekeys={
type=isstring,
name=isstringfunc,
desc=optstringfunc,
order=optmethodnumber,
validate=optmethodfalse,
confirm=optmethodbool,
confirmText=optstring,
disabled=optmethodbool,
hidden=optmethodbool,
guiHidden=optmethodbool,
dialogHidden=optmethodbool,
dropdownHidden=optmethodbool,
cmdHidden=optmethodbool,
icon=optstringfunc,
iconCoords=optmethodtable,
handler=opttable,
get=optmethodfalse,
set=optmethodfalse,
func=optmethodfalse,
arg={["*"]=true},
width=optstring,
}
 
local typedkeys={
header={},
description={
image=optstringfunc,
imageCoords=optmethodtable,
imageHeight=optnumber,
imageWidth=optnumber,
},
group={
args=istable,
plugins=opttable,
inline=optbool,
cmdInline=optbool,
guiInline=optbool,
dropdownInline=optbool,
dialogInline=optbool,
childGroups=optstring,
},
execute={
-- func={
-- ["function"]=true,
-- ["string"]=true,
-- _="methodname or funcref"
-- },
},
input={
pattern=optstring,
usage=optstring,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
multiline=optboolnumber,
},
toggle={
tristate=optbool,
},
tristate={
},
range={
min=optnumber,
max=optnumber,
step=optnumber,
bigStep=optnumber,
isPercent=optbool,
},
select={
values=ismethodtable,
style={
["nil"]=true,
["string"]={dropdown=true,radio=true},
_="string: 'dropdown' or 'radio'"
},
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
multiselect={
values=ismethodtable,
style=optstring,
tristate=optbool,
control=optstring,
dialogControl=optstring,
dropdownControl=optstring,
},
color={
hasAlpha=optbool,
},
keybinding={
-- TODO
},
}
 
local function validateKey(k,errlvl,...)
errlvl=(errlvl or 0)+1
if type(k)~="string" then
err("["..tostring(k).."] - key is not a string", errlvl,...)
end
if strfind(k, "[%c \127]") then
err("["..tostring(k).."] - key name contained spaces (or control characters)", errlvl,...)
end
end
 
local function validateVal(v, oktypes, errlvl,...)
errlvl=(errlvl or 0)+1
local isok=oktypes[type(v)] or oktypes["*"]
 
if not isok then
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
end
if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
if not isok[v] then
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
end
end
end
 
local function validate(options,errlvl,...)
errlvl=(errlvl or 0)+1
-- basic consistency
if type(options)~="table" then
err(": expected a table, got a "..type(options), errlvl,...)
end
if type(options.type)~="string" then
err(".type: expected a string, got a "..type(options.type), errlvl,...)
end
 
-- get type and 'typedkeys' member
local tk = typedkeys[options.type]
if not tk then
err(".type: unknown type '"..options.type.."'", errlvl,...)
end
 
-- make sure that all options[] are known parameters
for k,v in pairs(options) do
if not (tk[k] or basekeys[k]) then
err(": unknown parameter", errlvl,tostring(k),...)
end
end
 
-- verify that required params are there, and that everything is the right type
for k,oktypes in pairs(basekeys) do
validateVal(options[k], oktypes, errlvl,k,...)
end
for k,oktypes in pairs(tk) do
validateVal(options[k], oktypes, errlvl,k,...)
end
 
-- extra logic for groups
if options.type=="group" then
for k,v in pairs(options.args) do
validateKey(k,errlvl,"args",...)
validate(v, errlvl,k,"args",...)
end
if options.plugins then
for plugname,plugin in pairs(options.plugins) do
if type(plugin)~="table" then
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
end
for k,v in pairs(plugin) do
validateKey(k,errlvl,tostring(plugname),"plugins",...)
validate(v, errlvl,k,tostring(plugname),"plugins",...)
end
end
end
end
end
 
---------------------------------------------------------------------
-- :ValidateOptionsTable(options,name,errlvl)
-- - options - the table
-- - name - (string) name of table, used in error reports
-- - errlvl - (optional number) error level offset, default 0
--
-- Validates basic structure and integrity of an options table
-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
 
function lib:ValidateOptionsTable(options,name,errlvl)
errlvl=(errlvl or 0)+1
name = name or "Optionstable"
if not options.name then
options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
end
validate(options,errlvl,name)
end
 
------------------------------
-- :NotifyChange(appName)
-- - appName - string identifying the addon
--
-- Fires a ConfigTableChange callback for those listening in on it, allowing config GUIs to refresh
------------------------------
 
function lib:NotifyChange(appName)
if not lib.tables[appName] then return end
lib.callbacks:Fire("ConfigTableChange", appName)
end
 
---------------------------------------------------------------------
-- Registering and retreiving options tables:
 
 
-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
 
local function validateGetterArgs(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+2
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
end
if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
end
end
 
 
---------------------------------------------------------------------
-- :RegisterOptionsTable(appName, options)
-- - appName - string identifying the addon
-- - options - table or function reference
 
function lib:RegisterOptionsTable(appName, options)
if type(options)=="table" then
if options.type~="group" then -- quick sanity checker
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
end
lib.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
if not lib.validated[uiType][appName] then
lib:ValidateOptionsTable(options, appName, errlvl) -- upgradable
lib.validated[uiType][appName] = true
end
return options
end
elseif type(options)=="function" then
lib.tables[appName] = function(uiType, uiName, errlvl)
errlvl=(errlvl or 0)+1
validateGetterArgs(uiType, uiName, errlvl)
local tab = assert(options(uiType, uiName))
if not lib.validated[uiType][appName] then
lib:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
lib.validated[uiType][appName] = true
end
return tab
end
else
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
end
end
 
 
---------------------------------------------------------------------
-- :IterateOptionsTables()
--
-- Returns an iterator of ["appName"]=funcref pairs
 
function lib:IterateOptionsTables()
return pairs(lib.tables)
end
 
 
---------------------------------------------------------------------
-- :GetOptionsTable(appName)
-- - appName - which addon to retreive the options table of
-- Optional:
-- - uiType - "cmd", "dropdown", "dialog"
-- - uiName - e.g. "MyLib-1.0"
--
-- If only appName is given, a function is returned which you
-- can call with (uiType,uiName) to get the table.
-- If uiType&uiName are given, the table is returned.
 
function lib:GetOptionsTable(appName, uiType, uiName)
local f = lib.tables[appName]
if not f then
return nil
end
 
if uiType then
return f(uiType,uiName,1) -- get the table for us
else
return f -- return the function
end
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceConfig-3.0/AceConfig-3.0.xml New file
0,0 → 1,8
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
..\FrameXML\UI.xsd">
<Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/>
<Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/>
<Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/>
<!--<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/>-->
<Script file="AceConfig-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceConfig-3.0/AceConfig-3.0.lua New file
0,0 → 1,43
--[[ $Id: AceConfig-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]]
--[[
AceConfig-3.0
 
Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole.
 
Also automatically adds "config", "enable" and "disable" commands to options table as appropriate.
 
]]
 
local MAJOR, MINOR = "AceConfig-3.0", 2
local lib = LibStub:NewLibrary(MAJOR, MINOR)
 
if not lib then return end
 
 
local cfgreg = LibStub("AceConfigRegistry-3.0")
local cfgcmd = LibStub("AceConfigCmd-3.0")
local cfgdlg = LibStub("AceConfigDialog-3.0")
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0")
 
 
---------------------------------------------------------------------
-- :RegisterOptionsTable(appName, options, slashcmd, persist)
--
-- - appName - (string) application name
-- - options - table or function ref, see AceConfigRegistry
-- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command
 
function lib:RegisterOptionsTable(appName, options, slashcmd)
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options)
if not ok then error(msg, 2) end
 
if slashcmd then
if type(slashcmd) == "table" then
for _,cmd in pairs(slashcmd) do
cfgcmd:CreateChatCommand(cmd, appName)
end
else
cfgcmd:CreateChatCommand(slashcmd, appName)
end
end
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-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="AceConfigDialog-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua New file
0,0 → 1,1735
--[[
AceConfigDialog-3.0
 
]]
local LibStub = LibStub
local MAJOR, MINOR = "AceConfigDialog-3.0", 22
local lib = LibStub:NewLibrary(MAJOR, MINOR)
 
if not lib then return end
 
lib.OpenFrames = lib.OpenFrames or {}
lib.Status = lib.Status or {}
lib.frame = lib.frame or CreateFrame("Frame")
 
local gui = LibStub("AceGUI-3.0")
local reg = LibStub("AceConfigRegistry-3.0")
 
local select = select
local pairs = pairs
local type = type
local assert = assert
local tinsert = tinsert
local tremove = tremove
local error = error
local table = table
local unpack = unpack
local string = string
local next = next
local math = math
local _
 
--[[
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
 
local width_multiplier = 170
 
--[[
Group Types
Tree - All Descendant Groups will all become nodes on the tree, direct child options will appear above the tree
- Descendant Groups with inline=true and thier children will not become nodes
 
Tab - Direct Child Groups will become tabs, direct child options will appear above the tab control
- Grandchild groups will default to inline unless specified otherwise
 
Select- Same as Tab but with entries in a dropdown rather than tabs
 
 
Inline Groups
- Will not become nodes of a select group, they will be effectivly part of thier parent group seperated by a border
- If declared on a direct child of a root node of a select group, they will appear above the group container control
- When a group is displayed inline, all descendants will also be inline members of the group
 
]]
 
-- Recycling functions
local new, del, copy
--newcount, delcount,createdcount,cached = 0,0,0
do
local pool = setmetatable({},{__mode='k'})
function new()
--newcount = newcount + 1
local t = next(pool)
if t then
pool[t] = nil
return t
else
--createdcount = createdcount + 1
return {}
end
end
function copy(t)
local c = new()
for k, v in pairs(t) do
c[k] = v
end
return c
end
function del(t)
--delcount = delcount + 1
for k in pairs(t) do
t[k] = nil
end
pool[t] = true
end
-- function cached()
-- local n = 0
-- for k in pairs(pool) do
-- n = n + 1
-- end
-- return n
-- end
end
 
-- picks the first non-nil value and returns it
local function pickfirstset(...)
for i=1,select("#",...) do
if select(i,...)~=nil then
return select(i,...)
end
end
end
 
--gets an option from a given group, checking plugins
local function GetSubOption(group, key)
if group.plugins then
for plugin, t in pairs(group.plugins) do
if t[key] then
return t[key]
end
end
end
 
return group.args[key]
end
 
--Option member type definitions, used to decide how to access it
 
--Is the member Inherited from parent options
local isInherited = {
set = true,
get = true,
func = true,
confirm = true,
validate = true,
disabled = true,
hidden = true
}
 
--Does a string type mean a literal value, instead of the default of a method of the handler
local stringIsLiteral = {
name = true,
desc = true,
icon = true,
usage = true,
width = true,
image = true,
}
 
--Is Never a function or method
local allIsLiteral = {
type = true,
imageWidth = true,
imageHeight = true,
}
 
--gets the value for a member that could be a function
--function refs are called with an info arg
--every other type is returned
local function GetOptionsMemberValue(membername, option, options, path, appName, ...)
--get definition for the member
local inherits = isInherited[membername]
 
 
--get the member of the option, traversing the tree if it can be inherited
local member
 
if inherits then
local group = options
if group[membername] ~= nil then
member = group[membername]
end
for i = 1, #path do
group = GetSubOption(group, path[i])
if group[membername] ~= nil then
member = group[membername]
end
end
else
member = option[membername]
end
 
--check if we need to call a functon, or if we have a literal value
if ( not allIsLiteral[membername] ) and ( type(member) == "function" or ((not stringIsLiteral[membername]) and type(member) == "string") ) then
--We have a function to call
local info = new()
--traverse the options table, picking up the handler and filling the info with the path
local handler
local group = options
handler = group.handler or handler
 
for i = 1, #path do
group = GetSubOption(group, path[i])
info[i] = path[i]
handler = group.handler or handler
end
 
info.options = options
info.appName = appName
info[0] = appName
info.arg = option.arg
info.handler = handler
info.option = option
info.type = option.type
info.uiType = 'dialog'
info.uiName = MAJOR
 
local a, b, c ,d
--using 4 returns for the get of a color type, increase if a type needs more
if type(member) == "function" then
--Call the function
a,b,c,d = member(info, ...)
else
--Call the method
if handler and handler[member] then
a,b,c,d = handler[member](handler, info, ...)
else
error(string.format("Method %s doesn't exist in handler for type %s", member, membername))
end
end
del(info)
return a,b,c,d
else
--The value isnt a function to call, return it
return member
end
end
 
--[[calls an options function that could be inherited, method name or function ref
local function CallOptionsFunction(funcname ,option, options, path, appName, ...)
local info = new()
 
local func
local group = options
local handler
 
--build the info table containing the path
-- pick up functions while traversing the tree
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
 
for i, v in ipairs(path) do
group = GetSubOption(group, v)
info[i] = v
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
end
 
info.options = options
info[0] = appName
info.arg = option.arg
 
local a, b, c ,d
if type(func) == "string" then
if handler and handler[func] then
a,b,c,d = handler[func](handler, info, ...)
else
error(string.format("Method %s doesn't exist in handler for type func", func))
end
elseif type(func) == "function" then
a,b,c,d = func(info, ...)
end
del(info)
return a,b,c,d
end
--]]
 
--tables to hold orders and names for options being sorted, will be created with new()
--prevents needing to call functions repeatedly while sorting
local tempOrders
local tempNames
 
local function compareOptions(a,b)
if not a then
return true
end
if not b then
return false
end
local OrderA, OrderB = tempOrders[a] or 100, tempOrders[b] or 100
if OrderA == OrderB then
local NameA = (type(tempNames[a] == "string") and tempNames[a]) or ""
local NameB = (type(tempNames[b] == "string") and tempNames[b]) or ""
return NameA:upper() < NameB:upper()
end
if OrderA < 0 then
if OrderB > 0 then
return false
end
else
if OrderB < 0 then
return true
end
end
return OrderA < OrderB
end
 
 
 
--builds 2 tables out of an options group
-- keySort, sorted keys
-- opts, combined options from .plugins and args
local function BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
tempOrders = new()
tempNames = new()
 
if group.plugins then
for plugin, t in pairs(group.plugins) do
for k, v in pairs(t) do
if not opts[k] then
tinsert(keySort, k)
opts[k] = v
 
path[#path+1] = k
tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
path[#path] = nil
end
end
end
end
 
for k, v in pairs(group.args) do
if not opts[k] then
tinsert(keySort, k)
opts[k] = v
 
path[#path+1] = k
tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
path[#path] = nil
end
end
 
table.sort(keySort, compareOptions)
 
del(tempOrders)
del(tempNames)
end
 
local function DelTree(tree)
if tree.children then
local childs = tree.children
for i = 1, #childs do
DelTree(childs[i])
del(childs[i])
end
del(childs)
end
end
 
local function CleanUserData(widget, event)
local user = widget.userdata
 
if user.path then
del(user.path)
end
 
if widget.type == "TreeGroup" then
local tree = widget.tree
if tree then
for i = 1, #tree do
DelTree(tree[i])
del(tree[i])
end
del(tree)
widget.tree = nil
end
end
 
if widget.type == "TabGroup" then
del(widget.tablist)
widget.tablist = nil
end
 
if widget.type == "DropdownGroup" then
if widget.dropdown.list then
del(widget.dropdown.list)
widget.dropdown.list = nil
end
end
end
 
--[[
Gets a status table for the given appname and options path
]]
function lib:GetStatusTable(appName, path)
local status = self.Status
 
if not status[appName] then
status[appName] = {}
status[appName].status = {}
status[appName].children = {}
end
 
status = status[appName]
 
if path then
for i = 1, #path do
local v = path[i]
if not status.children[v] then
status.children[v] = {}
status.children[v].status = {}
status.children[v].children = {}
end
status = status.children[v]
end
end
 
return status.status
end
 
--[[
Sets the given path to be selected
]]
function lib:SelectGroup(appName, ...)
local path = new()
 
 
local app = reg:GetOptionsTable(appName)
if not app then
error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2)
end
local options = app("dialog", MAJOR)
local group = options
local status = self:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
status = status.groups
local treevalue
local treestatus
 
for n = 1, select('#',...) do
local key = select(n, ...)
 
if group.childGroups == "tab" or group.childGroups == "select" then
--if this is a tab or select group, select the group
status.selected = key
--children of this group are no longer extra levels of a tree
treevalue = nil
else
--tree group by default
if treevalue then
--this is an extra level of a tree group, build a uniquevalue for it
treevalue = treevalue.."\001"..key
else
--this is the top level of a tree group, the uniquevalue is the same as the key
treevalue = key
if not status.groups then
status.groups = {}
end
--save this trees status table for any extra levels or groups
treestatus = status
end
--make sure that the tree entry is open, and select it.
--the selected group will be overwritten if a child is the final target but still needs to be open
treestatus.selected = treevalue
treestatus.groups[treevalue] = true
 
end
 
--move to the next group in the path
group = GetSubOption(group, key)
if not group then
break
end
tinsert(path, key)
status = self:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
status = status.groups
end
 
del(path)
reg:NotifyChange(appName)
end
 
local function OptionOnMouseOver(widget, event)
--show a tooltip/set the status bar to the desc text
local user = widget.userdata
local opt = user.option
local options = user.options
local path = user.path
local appName = user.appName
 
GameTooltip:SetOwner(widget.frame, "ANCHOR_TOPRIGHT")
local name = GetOptionsMemberValue("name", opt, options, path, appName)
local desc = GetOptionsMemberValue("desc", opt, options, path, appName)
local usage = GetOptionsMemberValue("usage", opt, options, path, appName)
 
GameTooltip:SetText(name, 1, .82, 0, 1)
 
if opt.type == 'multiselect' then
GameTooltip:AddLine(user.text,0.5, 0.5, 0.8, 1)
end
if type(desc) == "string" then
GameTooltip:AddLine(desc, 1, 1, 1, 1)
end
if type(usage) == "string" then
GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, 1)
end
 
GameTooltip:Show()
end
 
local function OptionOnMouseLeave(widget, event)
GameTooltip:Hide()
end
 
local function GetFuncName(option)
local type = option.type
if type == 'execute' then
return 'func'
else
return 'set'
end
end
local function confirmPopup(appName, rootframe, basepath, info, message, func, ...)
if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then
StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {}
end
local t = StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"]
for k in pairs(t) do
t[k] = nil
end
t.text = message
t.button1 = ACCEPT
t.button2 = CANCEL
local dialog, oldstrata
t.OnAccept = function()
safecall(func, unpack(t))
if dialog and oldstrata then
dialog:SetFrameStrata(oldstrata)
end
lib:Open(appName, rootframe, basepath and unpack(basepath))
del(info)
end
t.OnCancel = function()
if dialog and oldstrata then
dialog:SetFrameStrata(oldstrata)
end
del(info)
end
for i = 1, select('#', ...) do
t[i] = select(i, ...) or false
end
t.timeout = 0
t.whileDead = 1
t.hideOnEscape = 1
 
dialog = StaticPopup_Show("ACECONFIGDIALOG30_CONFIRM_DIALOG")
if dialog then
oldstrata = dialog:GetFrameStrata()
dialog:SetFrameStrata("TOOLTIP")
end
end
 
local function ActivateControl(widget, event, ...)
--This function will call the set / execute handler for the widget
--widget.userdata contains the needed info
local user = widget.userdata
local option = user.option
local options = user.options
local path = user.path
local info = new()
 
local func
local group = options
local funcname = GetFuncName(option)
local handler
local confirm
local validate
--build the info table containing the path
-- pick up functions while traversing the tree
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
confirm = group.confirm
validate = group.validate
for i = 1, #path do
local v = path[i]
group = GetSubOption(group, v)
info[i] = v
if group[funcname] ~= nil then
func = group[funcname]
end
handler = group.handler or handler
if group.confirm ~= nil then
confirm = group.confirm
end
if group.validate ~= nil then
validate = group.validate
end
end
 
info.options = options
info.appName = user.appName
info.arg = option.arg
info.handler = handler
info.option = option
info.type = option.type
info.uiType = 'dialog'
info.uiName = MAJOR
 
local name
if type(option.name) == "function" then
name = option.name(info)
elseif type(option.name) == "string" then
name = option.name
else
name = ""
end
local usage = option.usage
local pattern = option.pattern
 
local validated = true
 
if option.type == "input" then
if type(pattern)=="string" then
if not strmatch(..., pattern) then
validated = false
end
end
end
 
local success
if validated and option.type ~= "execute" then
if type(validate) == "string" then
if handler and handler[validate] then
success, validated = safecall(handler[validate], handler, info, ...)
if not success then validated = false end
else
error(string.format("Method %s doesn't exist in handler for type execute", validate))
end
elseif type(validate) == "function" then
success, validated = safecall(validate, info, ...)
if not success then validated = false end
end
end
 
local rootframe = user.rootframe
if type(validated) == "string" then
--validate function returned a message to display
if rootframe.SetStatusText then
rootframe:SetStatusText(validated)
end
PlaySound("igPlayerInviteDecline")
del(info)
return true
elseif not validated then
--validate returned false
if rootframe.SetStatusText then
if usage then
rootframe:SetStatusText(name..": "..usage)
else
if pattern then
rootframe:SetStatusText(name..": Expected "..pattern)
else
rootframe:SetStatusText(name..": Invalid Value")
end
end
end
PlaySound("igPlayerInviteDecline")
del(info)
return true
else
 
local confirmText = option.confirmText
--call confirm func/method
if type(confirm) == "string" then
if handler and handler[confirm] then
success, confirm = safecall(handler[confirm],handler, info)
if success and type(confirm) == "string" then
confirmText = confirm
confirm = true
elseif not success then
confirm = false
end
else
error(string.format("Method %s doesn't exist in handler for type confirm", confirm))
end
elseif type(confirm) == "function" then
success, confirm = safecall(confirm,info)
if success and type(confirm) == "string" then
confirmText = confirm
confirm = true
elseif not success then
confirm = false
end
end
 
--confirm if needed
if type(confirm) == "boolean" then
if confirm then
if not confirmText then
local name, desc = option.name, option.desc
if type(name) == "function" then
name = name(info)
end
if type(desc) == "function" then
desc = desc(info)
end
confirmText = name
if desc then
confirmText = confirmText.." - "..desc
end
end
 
local iscustom = user.rootframe.userdata.iscustom
local rootframe
 
if iscustom then
rootframe = user.rootframe
end
local basepath = user.rootframe.userdata.basepath
if type(func) == "string" then
if handler and handler[func] then
confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], handler, info, ...)
else
error(string.format("Method %s doesn't exist in handler for type func", func))
end
elseif type(func) == "function" then
confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, info, ...)
end
--func will be called and info deleted when the confirm dialog is responded to
return
end
end
 
--call the function
if type(func) == "string" then
if handler and handler[func] then
safecall(handler[func],handler, info, ...)
else
error(string.format("Method %s doesn't exist in handler for type func", func))
end
elseif type(func) == "function" then
safecall(func,info, ...)
end
 
 
 
local iscustom = user.rootframe.userdata.iscustom
local basepath = user.rootframe.userdata.basepath
--full refresh of the frame, some controls dont cause this on all events
if option.type == "color" then
if event == "OnValueConfirmed" then
 
if iscustom then
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath))
else
lib:Open(user.appName, basepath and unpack(basepath))
end
end
elseif option.type == "range" then
if event == "OnMouseUp" then
if iscustom then
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath))
else
lib:Open(user.appName, basepath and unpack(basepath))
end
end
--multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed'
elseif option.type == "multiselect" then
user.valuechanged = true
else
if iscustom then
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath))
else
lib:Open(user.appName, basepath and unpack(basepath))
end
end
 
end
del(info)
end
 
local function ActivateSlider(widget, event, value)
local option = widget.userdata.option
local min, max, step = option.min or 0, option.max or 100, option.step
if step then
value = math.floor((value - min) / step + 0.5) * step + min
else
value = math.max(math.min(value,max),min)
end
ActivateControl(widget,event,value)
end
 
--called from a checkbox that is part of an internally created multiselect group
--this type is safe to refresh on activation of one control
local function ActivateMultiControl(widget, event, ...)
ActivateControl(widget, event, widget.userdata.value, ...)
local user = widget.userdata
local iscustom = user.rootframe.userdata.iscustom
local basepath = user.rootframe.userdata.basepath
if iscustom then
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath))
else
lib:Open(user.appName, basepath and unpack(basepath))
end
end
 
local function MultiControlOnClosed(widget, event, ...)
local user = widget.userdata
if user.valuechanged then
local iscustom = user.rootframe.userdata.iscustom
local basepath = user.rootframe.userdata.basepath
if iscustom then
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath))
else
lib:Open(user.appName, basepath and unpack(basepath))
end
end
end
 
local function FrameOnClose(widget, event)
local appName = widget.userdata.appName
lib.OpenFrames[appName] = nil
gui:Release(widget)
end
 
local function CheckOptionHidden(option, options, path, appName)
--check for a specific boolean option
local hidden = pickfirstset(option.dialogHidden,option.guiHidden)
if hidden ~= nil then
return hidden
end
 
return GetOptionsMemberValue("hidden", option, options, path, appName)
end
 
local function CheckOptionDisabled(option, options, path, appName)
--check for a specific boolean option
local disabled = pickfirstset(option.dialogDisabled,option.guiDisabled)
if disabled ~= nil then
return disabled
end
 
return GetOptionsMemberValue("disabled", option, options, path, appName)
end
--[[
local function BuildTabs(group, options, path, appName)
local tabs = new()
local text = new()
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
tinsert(tabs, k)
text[k] = GetOptionsMemberValue("name", v, options, path, appName)
end
path[#path] = nil
end
end
 
del(keySort)
del(opts)
 
return tabs, text
end
]]
local function BuildSelect(group, options, path, appName)
local groups = new()
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
groups[k] = GetOptionsMemberValue("name", v, options, path, appName)
end
path[#path] = nil
end
end
 
del(keySort)
del(opts)
 
return groups
end
 
local function BuildSubGroups(group, tree, options, path, appName)
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
local entry = new()
entry.value = k
entry.text = GetOptionsMemberValue("name", v, options, path, appName)
entry.disabled = CheckOptionDisabled(v, options, path, appName)
if not tree.children then tree.children = new() end
tinsert(tree.children,entry)
if (v.childGroups or "tree") == "tree" then
BuildSubGroups(v,entry, options, path, appName)
end
end
path[#path] = nil
end
end
 
del(keySort)
del(opts)
end
 
local function BuildGroups(group, options, path, appName, recurse)
local tree = new()
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
if v.type == "group" then
path[#path+1] = k
local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
local hidden = CheckOptionHidden(v, options, path, appName)
if not inline and not hidden then
local entry = new()
entry.value = k
entry.text = GetOptionsMemberValue("name", v, options, path, appName)
entry.disabled = CheckOptionDisabled(v, options, path, appName)
tinsert(tree,entry)
if recurse and (v.childGroups or "tree") == "tree" then
BuildSubGroups(v,entry, options, path, appName)
end
end
path[#path] = nil
end
end
del(keySort)
del(opts)
return tree
end
 
local function InjectInfo(control, options, option, path, rootframe, appName)
local user = control.userdata
for i = 1, #path do
user[i] = path[i]
end
user.rootframe = rootframe
user.option = option
user.options = options
user.path = copy(path)
user.appName = appName
control:SetCallback("OnRelease", CleanUserData)
control:SetCallback("OnLeave", OptionOnMouseLeave)
control:SetCallback("OnEnter", OptionOnMouseOver)
end
 
 
--[[
options - root of the options table being fed
container - widget that controls will be placed in
rootframe - Frame object the options are in
path - table with the keys to get to the group being fed
--]]
 
local function FeedOptions(appName, options,container,rootframe,path,group,inline)
local keySort = new()
local opts = new()
 
BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
 
for i = 1, #keySort do
local k = keySort[i]
local v = opts[k]
tinsert(path, k)
local hidden = CheckOptionHidden(v, options, path, appName)
local name = GetOptionsMemberValue("name", v, options, path, appName)
if not hidden then
if v.type == "group" then
if inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then
--Inline group
local GroupContainer
if name and name ~= "" then
GroupContainer = gui:Create("InlineGroup")
GroupContainer:SetTitle(name or "")
else
GroupContainer = gui:Create("SimpleGroup")
end
 
GroupContainer.width = "fill"
GroupContainer:SetLayout("flow")
container:AddChild(GroupContainer)
FeedOptions(appName,options,GroupContainer,rootframe,path,v,true)
end
else
--Control to feed
local control
 
local name = GetOptionsMemberValue("name", v, options, path, appName)
 
if v.type == "execute" then
control = gui:Create("Button")
control:SetText(name)
control:SetCallback("OnClick",ActivateControl)
 
elseif v.type == "input" then
local controlType = v.dialogControl or v.control or (v.multiline and "MultiLineEditBox") or "EditBox"
control = gui:Create(controlType)
if not control then
error(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
end
 
if v.multiline then
local lines = 4
if type(v.multiline) == "number" then
lines = v.multiline
end
control:SetHeight(60 + (14*lines))
end
control:SetLabel(name)
control:SetCallback("OnEnterPressed",ActivateControl)
local text = GetOptionsMemberValue("get",v, options, path, appName)
if type(text) ~= "string" then
text = ""
end
control:SetText(text)
 
elseif v.type == "toggle" then
control = gui:Create("CheckBox")
control:SetLabel(name)
control:SetTriState(v.tristate)
local value = GetOptionsMemberValue("get",v, options, path, appName)
control:SetValue(value)
control:SetCallback("OnValueChanged",ActivateControl)
 
elseif v.type == "range" then
control = gui:Create("Slider")
control:SetLabel(name)
control:SetSliderValues(v.min or 0,v.max or 100, v.bigStep or v.step or 0)
control:SetIsPercent(v.isPercent)
local value = GetOptionsMemberValue("get",v, options, path, appName)
if type(value) ~= "number" then
value = 0
end
control:SetValue(value)
control:SetCallback("OnValueChanged",ActivateSlider)
control:SetCallback("OnMouseUp",ActivateSlider)
 
elseif v.type == "select" then
local values = GetOptionsMemberValue("values", v, options, path, appName)
local controlType = v.dialogControl or v.control or "Dropdown"
control = gui:Create(controlType)
if not control then
error(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
end
control:SetLabel(name)
control:SetList(values)
local value = GetOptionsMemberValue("get",v, options, path, appName)
if not values[value] then
value = nil
end
control:SetValue(value)
control:SetCallback("OnValueChanged",ActivateControl)
 
elseif v.type == "multiselect" then
local values = GetOptionsMemberValue("values", v, options, path, appName)
local disabled = CheckOptionDisabled(v, options, path, appName)
 
local controlType = v.dialogControl or v.control
 
local valuesort = new()
if values then
for value, text in pairs(values) do
tinsert(valuesort, value)
end
end
table.sort(valuesort)
 
if controlType then
control = gui:Create(controlType)
if not control then
error(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
end
control:SetMultiselect(true)
control:SetLabel(name)
control:SetList(values)
control:SetDisabled(disabled)
control:SetCallback("OnValueChanged",ActivateControl)
control:SetCallback("OnClosed", MultiControlOnClosed)
local width = GetOptionsMemberValue("width",v,options,path,appName)
if width == "double" then
control:SetWidth(width_multiplier * 2)
elseif width == "half" then
control:SetWidth(width_multiplier / 2)
elseif width == "full" then
control.width = "fill"
else
control:SetWidth(width_multiplier)
end
--check:SetTriState(v.tristate)
for i = 1, #valuesort do
local key = valuesort[i]
local value = GetOptionsMemberValue("get",v, options, path, appName, key)
control:SetItemValue(key,value)
end
else
control = gui:Create("InlineGroup")
control:SetLayout("Flow")
control:SetTitle(name)
control.width = "fill"
 
control:PauseLayout()
local width = GetOptionsMemberValue("width",v,options,path,appName)
for i = 1, #valuesort do
local value = valuesort[i]
local text = values[value]
local check = gui:Create("CheckBox")
check:SetLabel(text)
check.userdata.value = value
check.userdata.text = text
check:SetDisabled(disabled)
check:SetTriState(v.tristate)
check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, value))
check:SetCallback("OnValueChanged",ActivateMultiControl)
InjectInfo(check, options, v, path, rootframe, appName)
control:AddChild(check)
if width == "double" then
check:SetWidth(width_multiplier * 2)
elseif width == "half" then
check:SetWidth(width_multiplier / 2)
elseif width == "full" then
check.width = "fill"
else
check:SetWidth(width_multiplier)
end
end
control:ResumeLayout()
control:DoLayout()
 
 
end
 
del(valuesort)
 
elseif v.type == "color" then
control = gui:Create("ColorPicker")
control:SetLabel(name)
control:SetHasAlpha(v.hasAlpha)
control:SetColor(GetOptionsMemberValue("get",v, options, path, appName))
control:SetCallback("OnValueChanged",ActivateControl)
control:SetCallback("OnValueConfirmed",ActivateControl)
 
elseif v.type == "keybinding" then
control = gui:Create("Keybinding")
control:SetLabel(name)
control:SetKey(GetOptionsMemberValue("get",v, options, path, appName))
control:SetCallback("OnKeyChanged",ActivateControl)
 
elseif v.type == "header" then
control = gui:Create("Heading")
control:SetText(name)
control.width = "fill"
 
elseif v.type == "description" then
control = gui:Create("Label")
control:SetText(name)
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
 
if type(image) == 'string' then
if not width then
width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
end
if not height then
height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
end
if type(imageCoords) == 'table' then
control:SetImage(image, unpack(imageCoords))
else
control:SetImage(image)
end
if type(width) ~= "number" then
width = 32
end
if type(height) ~= "number" then
height = 32
end
control:SetImageSize(width, height)
end
local width = GetOptionsMemberValue("width",v,options,path,appName)
control.width = not width and "fill"
end
 
--Common Init
if control then
if control.width ~= "fill" then
local width = GetOptionsMemberValue("width",v,options,path,appName)
if width == "double" then
control:SetWidth(width_multiplier * 2)
elseif width == "half" then
control:SetWidth(width_multiplier / 2)
elseif width == "full" then
control.width = "fill"
else
control:SetWidth(width_multiplier)
end
end
if control.SetDisabled then
local disabled = CheckOptionDisabled(v, options, path, appName)
control:SetDisabled(disabled)
end
 
InjectInfo(control, options, v, path, rootframe, appName)
container:AddChild(control)
end
 
end
end
tremove(path)
end
container:ResumeLayout()
container:DoLayout()
del(keySort)
del(opts)
end
 
local function BuildPath(path, ...)
for i = 1, select('#',...) do
tinsert(path, (select(i,...)))
end
end
 
 
local function TreeOnButtonEnter(widget, event, uniquevalue, button)
local user = widget.userdata
if not user then return end
local options = user.options
local option = user.option
local path = user.path
local appName = user.appName
 
local feedpath = new()
for i = 1, #path do
feedpath[i] = path[i]
end
 
BuildPath(feedpath, string.split("\001", uniquevalue))
local group = options
for i = 1, #feedpath do
if not group then return end
group = GetSubOption(group, feedpath[i])
end
 
local name = GetOptionsMemberValue("name", group, options, feedpath, appName)
local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName)
 
GameTooltip:SetOwner(button, "ANCHOR_NONE")
if widget.type == "TabGroup" then
GameTooltip:SetPoint("BOTTOM",button,"TOP")
else
GameTooltip:SetPoint("LEFT",button,"RIGHT")
end
 
GameTooltip:SetText(name, 1, .82, 0, 1)
 
if type(desc) == "string" then
GameTooltip:AddLine(desc, 1, 1, 1, 1)
end
 
GameTooltip:Show()
end
 
local function TreeOnButtonLeave(widget, event, value, button)
GameTooltip:Hide()
end
 
 
local function GroupExists(appName, options, path, uniquevalue)
if not uniquevalue then return false end
 
local feedpath = new()
local temppath = new()
for i = 1, #path do
feedpath[i] = path[i]
end
 
BuildPath(feedpath, string.split("\001", uniquevalue))
 
local group = options
for i = 1, #feedpath do
local v = feedpath[i]
temppath[i] = v
group = GetSubOption(group, v)
 
if not group or group.type ~= "group" or CheckOptionHidden(group, options, temppath, appName) then
del(feedpath)
del(temppath)
return false
end
end
del(feedpath)
del(temppath)
return true
end
 
local function GroupSelected(widget, event, uniquevalue)
 
local user = widget.userdata
 
local options = user.options
local option = user.option
local path = user.path
local rootframe = user.rootframe
 
local feedpath = new()
for i = 1, #path do
feedpath[i] = path[i]
end
 
BuildPath(feedpath, string.split("\001", uniquevalue))
local group = options
for i = 1, #feedpath do
group = GetSubOption(group, feedpath[i])
end
 
widget:ReleaseChildren()
lib:FeedGroup(user.appName,options,widget,rootframe,feedpath)
 
del(feedpath)
end
 
 
 
--[[
This function will feed one group, and any inline child groups into the given container
Select Groups will only have the selection control (tree, tabs, dropdown) fed in
and have a group selected, this event will trigger the feeding of child groups
 
Rules:
If the group is Inline, FeedOptions
If the group has no child groups, FeedOptions
 
If the group is a tab or select group, FeedOptions then add the Group Control
If the group is a tree group FeedOptions then
its parent isnt a tree group: then add the tree control containing this and all child tree groups
if its parent is a tree group, its already a node on a tree
--]]
 
function lib:FeedGroup(appName,options,container,rootframe,path, isRoot)
local group = options
--follow the path to get to the curent group
local inline
local grouptype, parenttype = options.childGroups, "none"
 
 
--temp path table to pass to callbacks as we traverse the tree
local temppath = new()
for i = 1, #path do
local v = path[i]
temppath[i] = v
group = GetSubOption(group, v)
inline = inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
parenttype = grouptype
grouptype = group.childGroups
end
del(temppath)
 
if not parenttype then
parenttype = "tree"
end
 
--check if the group has child groups
local hasChildGroups
for k, v in pairs(group.args) do
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then
hasChildGroups = true
end
end
if group.plugins then
for plugin, t in pairs(group.plugins) do
for k, v in pairs(t) do
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then
hasChildGroups = true
end
end
end
end
 
container:SetLayout("flow")
local scroll
 
--Add a scrollframe if we are not going to add a group control, this is the inverse of the conditions for that later on
if (not (hasChildGroups and not inline)) or (grouptype ~= "tab" and grouptype ~= "select" and (parenttype == "tree" and not isRoot)) then
if container.type ~= "InlineGroup" then
scroll = gui:Create("ScrollFrame")
scroll:SetLayout("flow")
scroll.width = "fill"
scroll.height = "fill"
container:SetLayout("fill")
container:AddChild(scroll)
container = scroll
end
end
 
FeedOptions(appName,options,container,rootframe,path,group,nil)
 
if scroll then
container:PerformLayout()
local status = self:GetStatusTable(appName, path)
if not status.scroll then
status.scroll = {}
end
scroll:SetStatusTable(status.scroll)
end
 
if hasChildGroups and not inline then
 
if grouptype == "tab" then
 
local tab = gui:Create("TabGroup")
InjectInfo(tab, options, group, path, rootframe, appName)
tab:SetCallback("OnGroupSelected", GroupSelected)
tab:SetCallback("OnTabEnter", TreeOnButtonEnter)
tab:SetCallback("OnTabLeave", TreeOnButtonLeave)
 
local status = lib:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
tab:SetStatusTable(status.groups)
tab.width = "fill"
tab.height = "fill"
 
local tabs = BuildGroups(group, options, path, appName)
tab:SetTabs(tabs)
 
for i = 1, #tabs do
local entry = tabs[i]
if not entry.disabled then
tab:SelectTab((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
break
end
end
 
container:AddChild(tab)
 
elseif grouptype == "select" then
 
local select = gui:Create("DropdownGroup")
InjectInfo(select, options, group, path, rootframe, appName)
select:SetCallback("OnGroupSelected", GroupSelected)
local status = lib:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
select:SetStatusTable(status.groups)
local grouplist = BuildSelect(group, options, path, appName)
select:SetGroupList(grouplist)
local firstgroup
for k, v in pairs(grouplist) do
if not firstgroup or k < firstgroup then
firstgroup = k
end
end
 
if firstgroup then
select:SetGroup( (GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup)
end
 
select.width = "fill"
select.height = "fill"
 
container:AddChild(select)
 
--assume tree group by default
--if parenttype is tree then this group is already a node on that tree
elseif (parenttype ~= "tree") or isRoot then
local tree = gui:Create("TreeGroup")
InjectInfo(tree, options, group, path, rootframe, appName)
tree:EnableButtonTooltips(false)
 
tree.width = "fill"
tree.height = "fill"
 
tree:SetCallback("OnGroupSelected", GroupSelected)
tree:SetCallback("OnButtonEnter", TreeOnButtonEnter)
tree:SetCallback("OnButtonLeave", TreeOnButtonLeave)
 
local status = lib:GetStatusTable(appName, path)
if not status.groups then
status.groups = {}
end
local treedefinition = BuildGroups(group, options, path, appName, true)
tree:SetStatusTable(status.groups)
 
tree:SetTree(treedefinition)
 
for i = 1, #treedefinition do
local entry = treedefinition[i]
if not entry.disabled then
tree:SelectByValue((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
break
end
end
 
container:AddChild(tree)
end
end
end
 
local old_CloseSpecialWindows
 
function lib:CloseAll()
local closed
for k, v in pairs(self.OpenFrames) do
v:Hide()
closed = true
end
return closed
end
 
function lib:Close(appName)
if self.OpenFrames[appName] then
self.OpenFrames[appName]:Hide()
return true
end
end
 
local function RefreshOnUpdate(this)
for appName in pairs(this.apps) do
if lib.OpenFrames[appName] then
local user = lib.OpenFrames[appName].userdata
lib:Open(appName, user.basepath and unpack(user.basepath))
end
if lib.BlizOptions and lib.BlizOptions[appName] then
local widget = lib.BlizOptions[appName]
local user = widget.userdata
if widget.frame:IsVisible() then
lib:Open(widget.userdata.appName, widget, user.basepath and unpack(user.basepath))
end
end
this.apps[appName] = nil
end
this:SetScript("OnUpdate", nil)
end
 
function lib:ConfigTableChanged(event, appName)
if not lib.frame.apps then
lib.frame.apps = {}
end
lib.frame.apps[appName] = true
lib.frame:SetScript("OnUpdate", RefreshOnUpdate)
end
 
reg.RegisterCallback(lib, "ConfigTableChange", "ConfigTableChanged")
 
function lib:SetDefaultSize(appName, width, height)
local status = lib:GetStatusTable(appName)
if type(width) == "number" and type(height) == "number" then
status.width = width
status.height = height
end
end
 
-- :Open(appName, [container], [path ...])
function lib:Open(appName, container, ...)
if not old_CloseSpecialWindows then
old_CloseSpecialWindows = CloseSpecialWindows
CloseSpecialWindows = function()
local found = old_CloseSpecialWindows()
return self:CloseAll() or found
end
end
local app = reg:GetOptionsTable(appName)
if not app then
error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2)
end
local options = app("dialog", MAJOR)
 
local f
 
local path = new()
local name = GetOptionsMemberValue("name", options, options, path, appName)
 
--If an optional path is specified add it to the path table before feeding the options
--as container is optional as well it may contain the first element of the path
if type(container) == "string" then
tinsert(path, container)
container = nil
end
for n = 1, select('#',...) do
tinsert(path, (select(n, ...)))
end
 
--if a container is given feed into that
if container then
f = container
f:ReleaseChildren()
f.userdata.appName = appName
f.userdata.iscustom = true
if #path > 0 then
f.userdata.basepath = copy(path)
end
local status = lib:GetStatusTable(appName)
if not status.width then
status.width = 700
end
if not status.height then
status.height = 500
end
if f.SetStatusTable then
f:SetStatusTable(status)
end
else
if not self.OpenFrames[appName] then
f = gui:Create("Frame")
self.OpenFrames[appName] = f
else
f = self.OpenFrames[appName]
end
f:ReleaseChildren()
f:SetCallback("OnClose", FrameOnClose)
f.userdata.appName = appName
if #path > 0 then
f.userdata.basepath = copy(path)
end
f:SetTitle(name or "")
local status = lib:GetStatusTable(appName)
f:SetStatusTable(status)
end
 
self:FeedGroup(appName,options,f,f,path,true)
if f.Show then
f:Show()
end
del(path)
end
 
lib.BlizOptions = lib.BlizOptions or {}
 
local function FeedToBlizPanel(widget, event)
local path = widget.userdata.path
lib:Open(widget.userdata.appName, widget, path and unpack(path))
end
 
local function ClearBlizPanel(widget, event)
widget:ReleaseChildren()
end
 
function lib:AddToBlizOptions(appName, name, parent, ...)
local BlizOptions = lib.BlizOptions
 
local key = appName
for n = 1, select('#', ...) do
key = key..'\001'..select(n, ...)
end
 
if not BlizOptions[key] then
local group = gui:Create("BlizOptionsGroup")
BlizOptions[key] = group
group:SetName(name or appName, parent)
 
group:SetTitle(name or appName)
group.userdata.appName = appName
if select('#', ...) > 0 then
local path = {}
for n = 1, select('#',...) do
tinsert(path, (select(n, ...)))
end
group.userdata.path = path
end
group:SetCallback("OnShow", FeedToBlizPanel)
group:SetCallback("OnHide", ClearBlizPanel)
InterfaceOptions_AddCategory(group.frame)
return group.frame
else
error(("%s has already been added to the Blizzard Options Window with the given path"):format(appName), 2)
end
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-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="AceConfigCmd-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua New file
0,0 → 1,729
 
--[[
AceConfigCmd-3.0
 
Handles commandline optionstable access
 
REQUIRES: AceConsole-3.0 for command registration (loaded on demand)
 
]]
 
-- TODO: handle disabled / hidden
-- TODO: implement handlers for all types
-- TODO: plugin args
 
 
local MAJOR, MINOR = "AceConfigCmd-3.0", 6
local lib = LibStub:NewLibrary(MAJOR, MINOR)
 
if not lib then return end
 
lib.commands = lib.commands or {}
local commands = lib.commands
 
local cfgreg = LibStub("AceConfigRegistry-3.0")
local AceConsole -- LoD
local AceConsoleName = "AceConsole-3.0"
 
 
local L = setmetatable({}, { -- TODO: replace with proper locale
__index = function(self,k) return k end
})
 
 
 
local function print(msg)
(SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg)
end
 
 
-- pickfirstset() - picks the first non-nil value and returns it
 
local function pickfirstset(...)
for i=1,select("#",...) do
if select(i,...)~=nil then
return select(i,...)
end
end
end
 
 
-- err() - produce real error() regarding malformed options tables etc
 
local function err(info,inputpos,msg )
local cmdstr=" "..strsub(info.input, 1, inputpos-1)
error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2)
end
 
 
-- usererr() - produce chatframe message regarding bad slash syntax etc
 
local function usererr(info,inputpos,msg )
local cmdstr=strsub(info.input, 1, inputpos-1);
print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table"))
end
 
 
-- callmethod() - call a given named method (e.g. "get", "set") with given arguments
 
local function callmethod(info, inputpos, tab, methodtype, ...)
local method = info[methodtype]
if not method then
err(info, inputpos, "'"..methodtype.."': not set")
end
 
info.arg = tab.arg
info.option = tab
info.type = tab.type
 
if type(method)=="function" then
return method(info, ...)
elseif type(method)=="string" then
if type(info.handler[method])~="function" then
err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler))
end
return info.handler[method](info.handler, info, ...)
else
assert(false) -- type should have already been checked on read
end
end
 
-- callfunction() - call a given named function (e.g. "name", "desc") with given arguments
 
local function callfunction(info, tab, methodtype, ...)
local method = tab[methodtype]
 
info.arg = tab.arg
info.option = tab
info.type = tab.type
 
if type(method)=="function" then
return method(info, ...)
else
assert(false) -- type should have already been checked on read
end
end
 
-- do_final() - do the final step (set/execute) along with validation and confirmation
 
local function do_final(info, inputpos, tab, methodtype, ...)
if info.validate then
local res = callmethod(info,inputpos,tab,"validate",...)
if type(res)=="string" then
usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res)
return
end
end
-- console ignores .confirm
 
callmethod(info,inputpos,tab,methodtype, ...)
end
 
 
-- getparam() - used by handle() to retreive and store "handler", "get", "set", etc
 
local function getparam(info, inputpos, tab, depth, paramname, types, errormsg)
local old,oldat = info[paramname], info[paramname.."_at"]
local val=tab[paramname]
if val~=nil then
if val==false then
val=nil
elseif not types[type(val)] then
err(info, inputpos, "'" .. paramname.. "' - "..errormsg)
end
info[paramname] = val
info[paramname.."_at"] = depth
end
return old,oldat
end
 
 
-- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.*
local dummytable={}
 
local function iterateargs(tab)
if not tab.plugins then
return pairs(tab.args)
end
 
local argtabkey,argtab=next(tab.plugins)
local v
 
return function(_, k)
while argtab do
k,v = next(argtab, k)
if k then return k,v end
if argtab==tab.args then
argtab=nil
else
argtabkey,argtab = next(tab.plugins, argtabkey)
if not argtabkey then
argtab=tab.args
end
end
end
end
end
 
local function showhelp(info, inputpos, tab, noHead)
if not noHead then
print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":")
end
 
local sortTbl = {} -- [1..n]=name
local refTbl = {} -- [name]=tableref
 
for k,v in iterateargs(tab) do
if not refTbl[k] then -- a plugin overriding something in .args
table.insert(sortTbl, k)
refTbl[k] = v
end
end
 
table.sort(sortTbl, function(one, two)
local o1 = refTbl[one].order or 100
local o2 = refTbl[two].order or 100
if type(o1) == "function" or type(o1) == "string" then
info.order = o1
info[#info+1] = one
o1 = callmethod(info, inputpos, refTbl[one], "order")
info[#info] = nil
info.order = nil
end
if type(o2) == "function" or type(o1) == "string" then
info.order = o2
info[#info+1] = two
o2 = callmethod(info, inputpos, refTbl[two], "order")
info[#info] = nil
info.order = nil
end
if o1<0 and o2<0 then return o1<o2 end
if o2<0 then return true end
if o1<0 then return false end
if o1==o2 then return tostring(one)<tostring(two) end -- compare names
return o1<o2
end)
 
for _,k in ipairs(sortTbl) do
local v = refTbl[k]
if not pickfirstset(v.cmdHidden, v.hidden, false) then
-- recursively show all inline groups
local name, desc = v.name, v.desc
if type(name) == "function" then
name = callfunction(info, v, 'name')
end
if type(desc) == "function" then
desc = callfunction(info, v, 'desc')
end
if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then
print(" "..(desc or name)..":")
showhelp(info, inputpos, v, true)
else
print(" |cffffff78"..k.."|r - "..(desc or name or ""))
end
end
end
end
 
 
local function keybindingValidateFunc(text)
if text == nil or text == "NONE" then
return nil
end
text = text:upper()
local shift, ctrl, alt
local modifier
while true do
if text == "-" then
break
end
modifier, text = strsplit('-', text, 2)
if text then
if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then
return false
end
if modifier == "SHIFT" then
if shift then
return false
end
shift = true
end
if modifier == "CTRL" then
if ctrl then
return false
end
ctrl = true
end
if modifier == "ALT" then
if alt then
return false
end
alt = true
end
else
text = modifier
break
end
end
if text == "" then
return false
end
if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then
return false
end
local s = text
if shift then
s = "SHIFT-" .. s
end
if ctrl then
s = "CTRL-" .. s
end
if alt then
s = "ALT-" .. s
end
return s
end
 
-- constants used by getparam() calls below
 
local handlertypes = {["table"]=true}
local handlermsg = "expected a table"
 
local functypes = {["function"]=true, ["string"]=true}
local funcmsg = "expected function or member name"
 
-- handle() - selfrecursing function that processes input->optiontable
-- - depth - starts at 0
-- - retfalse - return false rather than produce error if a match is not found (used by inlined groups)
 
local function handle(info, inputpos, tab, depth, retfalse)
 
if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end
 
-------------------------------------------------------------------
-- Grab hold of handler,set,get,func,etc if set (and remember old ones)
-- Note that we do NOT validate if method names are correct at this stage,
-- the handler may change before they're actually used!
 
local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg)
local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg)
local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg)
local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg)
local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg)
--local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg)
 
-------------------------------------------------------------------
-- Act according to .type of this table
 
if tab.type=="group" then
------------ group --------------------------------------------
 
if type(tab.args)~="table" then err(info, inputpos) end
if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end
 
-- grab next arg from input
local _,nextpos,arg = string.find(info.input, " *([^ ]+) *", inputpos)
if not arg then
showhelp(info, inputpos, tab)
return
end
nextpos=nextpos+1
 
-- loop .args and try to find a key with a matching name
for k,v in iterateargs(tab) do
if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end
 
-- is this child an inline group? if so, traverse into it
if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then
info[depth+1] = k
if handle(info, inputpos, v, depth+1, true)==false then
info[depth+1] = nil
-- wasn't found in there, but that's ok, we just keep looking down here
else
return -- done, name was found in inline group
end
-- matching name and not a inline group
elseif strlower(arg)==strlower(k) then
info[depth+1] = k
return handle(info,nextpos,v,depth+1)
end
end
 
-- no match
if retfalse then
-- restore old infotable members and return false to indicate failure
info.handler,info.handler_at = oldhandler,oldhandler_at
info.set,info.set_at = oldset,oldset_at
info.get,info.get_at = oldget,oldget_at
info.func,info.func_at = oldfunc,oldfunc_at
info.validate,info.validate_at = oldvalidate,oldvalidate_at
--info.confirm,info.confirm_at = oldconfirm,oldconfirm_at
return false
end
 
-- couldn't find the command, display error
usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"])
return
end
 
local str = strsub(info.input,inputpos);
 
if tab.type=="execute" then
------------ execute --------------------------------------------
do_final(info, inputpos, tab, "func")
 
 
 
elseif tab.type=="input" then
------------ input --------------------------------------------
 
local res = true
if tab.pattern then
if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end
if not strmatch(str, tab.pattern) then
usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"])
return
end
end
 
do_final(info, inputpos, tab, "set", str)
 
 
 
elseif tab.type=="toggle" then
------------ toggle --------------------------------------------
local b
local str = strtrim(strlower(str))
if str=="" then
b = callmethod(info, inputpos, tab, "get")
 
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
 
elseif str==L["on"] then
b = true
elseif str==L["off"] then
b = false
elseif tab.tristate and str==L["default"] then
b = nil
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str))
else
usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str))
end
return
end
 
do_final(info, inputpos, tab, "set", b)
 
 
elseif tab.type=="range" then
------------ range --------------------------------------------
local val = tonumber(str)
if not val then
usererr(info, inputpos, "'"..str.."' - "..L["expected number"])
return
end
if type(info.step)=="number" then
val = val- (val % info.step)
end
if type(info.min)=="number" and val<info.min then
usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) )
return
end
if type(info.max)=="number" and val>info.max then
usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) )
return
end
 
do_final(info, inputpos, tab, "set", val)
 
 
elseif tab.type=="select" then
------------ select ------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current selection and possible values
return
end
 
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
 
local ok
for k,v in pairs(values) do
if strlower(k)==str then
str = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
if not ok then
usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"])
return
end
 
do_final(info, inputpos, tab, "set", str)
 
elseif tab.type=="multiselect" then
------------ multiselect -------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current values
return
end
 
local values = tab.values
if type(values) == "function" or type(values) == "string" then
info.values = values
values = callmethod(info, inputpos, tab, "values")
info.values = nil
end
 
--build a table of the selections, checking that they exist
--parse for =on =off =default in the process
--table will be key = true for options that should toggle, key = [on|off|default] for options to be set
local sels = {}
for v in string.gmatch(str, "[^ ]+") do
--parse option=on etc
local opt, val = string.match(v,'(.+)=(.+)')
--get option if toggling
if not opt then
opt = v
end
 
--check that the opt is valid
local ok
for k,v in pairs(values) do
if strlower(k)==opt then
opt = k -- overwrite with key (in case of case mismatches)
ok = true
break
end
end
 
if not ok then
usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"])
return
end
 
--check that if val was supplied it is valid
if val then
if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then
--val is valid insert it
sels[opt] = val
else
if tab.tristate then
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val))
else
usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val))
end
return
end
else
-- no val supplied, toggle
sels[opt] = true
end
end
 
for opt, val in pairs(sels) do
local newval
 
if (val == true) then
--toggle the option
local b = callmethod(info, inputpos, tab, "get", opt)
 
if tab.tristate then
--cycle in true, nil, false order
if b then
b = nil
elseif b == nil then
b = false
else
b = true
end
else
b = not b
end
newval = b
else
--set the option as specified
if val==L["on"] then
newval = true
elseif val==L["off"] then
newval = false
elseif val==L["default"] then
newval = nil
end
end
 
do_final(info, inputpos, tab, "set", opt, newval)
end
 
 
elseif tab.type=="color" then
------------ color --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
 
local r, g, b, a
 
if tab.hasAlpha then
if str:len() == 8 and str:find("^%x*$") then
--parse a hex string
r,g,b,a = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255, tonumber(str:sub(7, 8), 16) / 255
else
--parse seperate values
r,g,b,a = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a)
end
if not (r and g and b and a) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str))
return
end
 
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
a = a / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str))
end
else
a = 1.0
if str:len() == 6 and str:find("^%x*$") then
--parse a hex string
r,g,b = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255
else
--parse seperate values
r,g,b = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+)$")
r,g,b = tonumber(r), tonumber(g), tonumber(b)
end
if not (r and g and b) then
usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str))
return
end
if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then
--values are valid
elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then
--values are valid 0..255, convert to 0..1
r = r / 255
g = g / 255
b = b / 255
else
--values are invalid
usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str))
end
end
 
do_final(info, inputpos, tab, "set", r,g,b,a)
 
elseif tab.type=="keybinding" then
------------ keybinding --------------------------------------------
local str = strtrim(strlower(str))
if str == "" then
--TODO: Show current value
return
end
local value = keybindingValidateFunc(str:upper())
if value == false then
usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str))
return
end
 
do_final(info, inputpos, tab, "set", value)
 
elseif tab.type=="description" then
------------ description --------------------
-- ignore description, GUI config only
else
err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'")
end
end
 
 
-----------------------------------------------------------------------
-- HandleCommand(slashcmd, appName, input)
--
-- Call this from a chat command handler to parse the command input as operations on an aceoptions table
--
-- slashcmd (string) - the slash command WITHOUT leading slash (only used for error output)
-- appName (string) - the application name as given to AceConfigRegistry:RegisterOptionsTable()
-- input (string) -- the commandline input (as given by the WoW handler, i.e. without the command itself)
 
function lib:HandleCommand(slashcmd, appName, input)
 
local optgetter = cfgreg:GetOptionsTable(appName)
if not optgetter then
error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2)
end
local options = assert( optgetter("cmd", MAJOR) )
 
local info = { -- Don't try to recycle this, it gets handed off to callbacks and whatnot
[0] = slashcmd,
appName = appName,
options = options,
input = input,
self = self,
handler = self,
uiType = "cmd",
uiName = MAJOR,
}
 
handle(info, 1, options, 0) -- (info, inputpos, table, depth)
end
 
 
 
-----------------------------------------------------------------------
-- CreateChatCommand(slashcmd, appName)
--
-- Utility function to create a slash command handler.
-- Also registers tab completion with AceTab
--
-- slashcmd (string) - the slash command WITHOUT leading slash (only used for error output)
-- appName (string) - the application name as given to AceConfigRegistry:RegisterOptionsTable()
 
function lib:CreateChatCommand(slashcmd, appName)
if not AceConsole then
AceConsole = LibStub(AceConsoleName)
end
if AceConsole.RegisterChatCommand(self, slashcmd, function(input)
lib.HandleCommand(self, slashcmd, appName, input) -- upgradable
end,
true) then -- succesfully registered so lets get the command -> app table in
commands[slashcmd] = appName
end
end
 
-- GetChatCommandOptions(slashcmd)
--
-- Utility function that returns the options table that belongs to a slashcommand
-- mainly used by AceTab
 
function lib:GetChatCommandOptions(slashcmd)
return commands[slashcmd]
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceTab-3.0/AceConfigTab-3.0.lua New file
0,0 → 1,105
--[[
-- AceConfigTab-3.0
--
-- Creates an AceTab-3.0 completion set for handling AceConfig-3.0 command trees.
-- ]]
 
local MAJOR, MINOR = "AceConfigTab-3.0", 1
local lib = LibStub:NewLibrary(MAJOR, MINOR)
 
if not lib then return end
 
local ac = LibStub("AceConsole-3.0")
 
local function printf(...)
DEFAULT_CHAT_FRAME:AddMessage(string.format(...))
end
 
-- getChildren(opt, ...)
--
-- Retrieve the next valid group args in an AceConfig table.
--
-- opt - AceConfig options table
-- ... - args following the slash command
--
-- opt will need to be determined by the slash-command
-- The args will be obtained using AceConsole:GetArgs() or something similar on the remainder of the line.
--
-- Returns arg1, arg2, ...
local function getLevel(opt, ...)
-- Walk down the options tree to the last arg in the commandline, or return if it does not follow the tree.
local path = ""
local lastChild
for i = 1, select('#', ...) do
local arg = select(i, ...)
if not arg or type(arg) == 'number' then break end
if opt.plugins then
for k in pairs(opt.plugins) do
if string.lower(k) == string.lower(arg) then
opt = opt.plugins[k]
path = path..arg.." "
lastChild = arg
break
end
end
elseif opt.args then
for k in pairs(opt.args) do
if string.lower(k) == string.lower(arg) then
opt = opt.args[k]
path = path..arg.." "
lastChild = arg
break
end
end
else
break
end
end
return opt, path
end
 
local function getChildren(opt, ...)
local lastChild, path
opt, path, lastChild = getLevel(opt, ...)
local args = {}
for _, field in ipairs({"args", "plugins"}) do
if type(opt[field]) == 'table' then
for k in pairs(opt[field]) do
if opt[field].type ~= 'header' then
table.insert(args, k)
end
end
end
end
return args, path
end
 
--LibStub("AceConfig-3.0"):RegisterOptionsTable("ag_UnitFrames", aUF.Options.table)
local function createWordlist(t, cmdline, pos)
local cmd = string.match(cmdline, "(/[^ \t\n]+)")
local argslist = string.sub(cmdline, pos, this:GetCursorPosition())
local opt -- TODO: figure out options table using cmd
opt = LibStub("AceConfigRegistry-3.0"):GetOptionsTable("ag_UnitFrames", "cmd", "AceTab-3.0") -- hardcoded temporarily for testing
if not opt then return end
local args, path = getChildren(opt, ac:GetArgs(argslist, #argslist/2)) -- largest # of args representable by a string of length #argslist, since they must be separated by spaces
for _, v in ipairs(args) do
table.insert(t, path..v)
end
end
 
local function usage(t, matches, _, cmdline)
local cmd = string.match(cmdline, "(/[^ \t\n]+)")
local argslist = string.sub(cmdline, #cmd, this:GetCursorPosition())
local opt -- TODO: figure out options table using cmd
opt = LibStub("AceConfigRegistry-3.0"):GetOptionsTable("ag_UnitFrames")("cmd", "AceTab-3.0") -- hardcoded temporarily for testing
if not opt then return end
local level = getLevel(opt, ac:GetArgs(argslist, #argslist/2)) -- largest # of args representable by a string of length #argslist, since they must be separated by spaces
local option
for _, m in pairs(matches) do
local tail = string.match(m, "([^ \t\n]+)$")
option = level.plugins and level.plugins[tail] or level.args and level.args[tail]
printf("%s - %s", tail, option.desc)
end
end
 
LibStub("AceTab-3.0"):RegisterTabCompletion("aguftest", "%/%w+ ", createWordlist, usage)
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceTab-3.0/AceTab-3.0.xml New file
0,0 → 1,5
<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="AceTab-3.0.lua"/>
<Script file="AceConfigTab-3.0.lua"/>
</Ui>
Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceTab-3.0/AceTab-3.0.lua New file
0,0 → 1,426
--[[ $Id: AceTab-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]]
 
local ACETAB_MAJOR, ACETAB_MINOR = 'AceTab-3.0', 2
local AceTab, oldminor = LibStub:NewLibrary(ACETAB_MAJOR, ACETAB_MINOR)
 
if not AceTab then return end -- No upgrade needed
 
AceTab.registry = AceTab.registry or {}
 
-- local upvalues
local _G = _G
local pairs = pairs
local ipairs = ipairs
local type = type
local registry = AceTab.registry
 
local strfind = string.find
local strsub = string.sub
local strlower = string.lower
local strformat = string.format
local strmatch = string.match
 
local function printf(...)
DEFAULT_CHAT_FRAME:AddMessage(strformat(...))
end
 
local function getTextBeforeCursor(this, start)
return strsub(this:GetText(), start or 1, this:GetCursorPosition())
end
 
-- Hook OnTabPressed and OnTextChanged for the frame, give it an empty matches table, and set its curMatch to 0, if we haven't done so already.
local function hookFrame(f)
if f.hookedByAceTab3 then return end
f.hookedByAceTab3 = true
if f == ChatFrameEditBox then
local origCTP = ChatEdit_CustomTabPressed
function ChatEdit_CustomTabPressed()
if AceTab:OnTabPressed(f) then
return origCTP()
else
return true
end
end
else
local origOTP = f:GetScript('OnTabPressed')
if type(origOTP) ~= 'function' then
origOTP = function() end
end
f:SetScript('OnTabPressed', function()
if AceTab:OnTabPressed(f) then
return origOTP()
end
end)
end
f.at3curMatch = 0
f.at3matches = {}
end
 
local firstPMLength
 
local fallbacks, notfallbacks = {}, {} -- classifies completions into those which have preconditions and those which do not. Those without preconditions are only considered if no other completions have matches.
local pmolengths = {} -- holds the number of characters to overwrite according to pmoverwrite and the current prematch
--------------------------------------------------------------------------------
-- RegisterTabCompletion( descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite )
-- See http://www.wowace.com/wiki/AceTab-2.0 for detailed API documentation
--
-- descriptor string Unique identifier for this tab completion set
--
-- prematches string|table|nil String match(es) AFTER which this tab completion will apply.
-- AceTab will ignore tabs NOT preceded by the string(s).
-- If no value is passed, will check all tabs pressed in the specified editframe(s) UNLESS a more-specific tab complete applies.
--
-- wordlist function|table Function that will be passed a table into which it will insert strings corresponding to all possible completions, or an equivalent table.
-- The text in the editbox, the position of the start of the word to be completed, and the uncompleted partial word
-- are passed as second, third, and fourth arguments, to facilitate pre-filtering or conditional formatting, if desired.
--
-- usagefunc function|boolean|nil Usage statement function. Defaults to the wordlist, one per line. A boolean true squelches usage output.
--
-- listenframes string|table|nil EditFrames to monitor. Defaults to ChatFrameEditBox.
--
-- postfunc function|nil Post-processing function. If supplied, matches will be passed through this function after they've been identified as a match.
--
-- pmoverwrite boolean|number|nil Offset the beginning of the completion string in the editbox when making a completion. Passing a boolean true indicates that we want to overwrite
-- the entire prematch string, and passing a number will overwrite that many characters prior to the cursor.
-- This is useful when you want to use the prematch as an indicator character, but ultimately do not want it as part of the text, itself.
--
-- no return
--------------------------------------------------------------------------------
function AceTab:RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite)
-- Arg checks
if type(descriptor) ~= 'string' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'descriptor' - string expected.", 3) end
if prematches and type(prematches) ~= 'string' and type(prematches) ~= 'table' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'prematches' - string, table, or nil expected.", 3) end
if type(wordlist) ~= 'function' and type(wordlist) ~= 'table' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'wordlist' - function or table expected.", 3) end
if usagefunc and type(usagefunc) ~= 'function' and type(usagefunc) ~= 'boolean' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'usagefunc' - function or boolean expected.", 3) end
if listenframes and type(listenframes) ~= 'string' and type(listenframes) ~= 'table' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'listenframes' - string or table expected.", 3) end
if postfunc and type(postfunc) ~= 'function' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'postfunc' - function expected.", 3) end
if pmoverwrite and type(pmoverwrite) ~= 'boolean' and type(pmoverwrite) ~= 'number' then error("Usage: RegisterTabCompletion(descriptor, prematches, wordlist, usagefunc, listenframes, postfunc, pmoverwrite): 'pmoverwrite' - boolean or number expected.", 3) end
 
local pmtable = type(prematches) == 'table' and prematches or {}
-- Mark this group as a fallback group if no value was passed.
if not prematches then
pmtable[1] = ""
fallbacks[descriptor] = true
-- Make prematches into a one-element table if it was passed as a string.
elseif type(prematches) == 'string' then
pmtable[1] = prematches
notfallbacks[descriptor] = true
end
 
-- Make listenframes into a one-element table if it was not passed a table of frames.
if not listenframes then -- default
listenframes = { ChatFrameEditBox }
elseif type(listenframes) ~= 'table' or type(listenframes[0]) == 'userdata' and type(listenframes.IsFrameType) == 'function' then -- single frame or framename
listenframes = { listenframes }
end
 
-- Hook each registered listenframe and give it a matches table.
for _, f in pairs(listenframes) do
if type(f) == 'string' then
f = _G[f]
end
if type(f) ~= 'table' or type(f[0]) ~= 'userdata' or type(f.IsFrameType) ~= 'function' then
self:error("Cannot register frame %q; it does not exist", f:GetName())
end
if f then
if f:GetFrameType() ~= 'EditBox' then
self:error("Cannot register frame %q; it is not an EditBox", f:GetName())
else
hookFrame(f)
end
end
end
 
-- Everything checks out; register this completion.
if not registry[descriptor] then
registry[descriptor] = { prematches = pmtable, wordlist = wordlist, usagefunc = usagefunc, listenframes = listenframes, postfunc = postfunc, pmoverwrite = pmoverwrite }
end
end
 
function AceTab:IsTabCompletionRegistered(descriptor)
return registry and registry[descriptor]
end
 
function AceTab:UnregisterTabCompletion(descriptor)
registry[descriptor] = nil
pmolengths[descriptor] = nil
fallbacks[descriptor] = nil
notfallbacks[descriptor] = nil
end
 
--------------------------------------------------------------------------------
-- gcbs( s1, s2 )
--
-- s1 string First string to be compared
--
-- s2 string Second string to be compared
--
-- returns the greatest common substring beginning s1 and s2
--------------------------------------------------------------------------------
local function gcbs(s1, s2)
if not s1 and not s2 then return end
if not s1 then s1 = s2 end
if not s2 then s2 = s1 end
if #s2 < #s1 then
s1, s2 = s2, s1
end
if strfind(strlower(s2), "^"..strlower(s1)) then
return s1
else
return gcbs(strsub(s1, 1, -2), s2)
end
end
 
local cursor -- Holds cursor position. Set in :OnTabPressed().
--------------------------------------------------------------------------------
-- cycleTab()
-- For when a tab press has multiple possible completions, we need to allow the user to press tab repeatedly to cycle through them.
-- If we have multiple possible completions, all tab presses after the first will call this function to cycle through and insert the different possible matches.
-- This function will stop being called after OnTextChanged() is triggered by something other than AceTab (i.e. the user inputs a character).
--------------------------------------------------------------------------------
local previousLength, cMatch, matched, postmatch
local function cycleTab(this)
cMatch = 0 -- Counter across all sets. The pseudo-index relevant to this value and corresponding to the current match is held in this.at3curMatch
matched = false
 
-- Check each completion group registered to this frame.
for desc, compgrp in pairs(this.at3matches) do
 
-- Loop through the valid completions for this set.
for m, pm in pairs(compgrp) do
cMatch = cMatch + 1
if cMatch == this.at3curMatch then -- we're back to where we left off last time through the combined list
this.at3lastMatch = m
this.at3lastWord = pm
this.at3curMatch = cMatch + 1 -- save the new cMatch index
matched = true
break
end
end
if matched then break end
end
 
-- If our index is beyond the end of the list, reset the original uncompleted substring and let the cycle start over next time tab is pressed.
if not matched then
this.at3lastMatch = this.at3origMatch
this.at3lastWord = this.at3origWord
this.at3curMatch = 1
end
 
-- Insert the completion.
this:HighlightText(this.at3matchStart-1, cursor)
this:Insert(this.at3lastWord or '')
this.at3_last_precursor = getTextBeforeCursor(this) or ''
end
 
local IsSecureCmd = IsSecureCmd
 
local cands, candUsage = {}, {}
local numMatches = 0
local firstMatch, hasNonFallback, allGCBS, setGCBS, usage
local text_precursor, text_all, text_pmendToCursor
local matches, usagefunc -- convenience locals
 
-- Fill the this.at3matches[descriptor] tables with matching completion pairs for each entry, based on
-- the partial string preceding the cursor position and using the corresponding registered wordlist.
--
-- The entries of the matches tables are of the format raw_match = formatted_match, where raw_match is the plaintext completion and
-- formatted_match is the match after being formatted/altered/processed by the registered postfunc.
-- If no postfunc exists, then the formatted and raw matches are the same.
local pms, pme, pmt, prematchStart, prematchEnd, text_prematch, entry
local function fillMatches(this, desc, fallback)
entry = registry[desc]
-- See what frames are registered for this completion group. If the frame in which we pressed tab is one of them, then we start building matches.
for _, f in ipairs(entry.listenframes) do
if f == this then
 
-- Try each precondition string registered for this completion group.
for _, prematch in ipairs(entry.prematches) do
 
-- Test if our prematch string is satisfied.
-- If it is, then we find its last occurence prior to the cursor, calculate and store its pmoverwrite value (if applicable), and start considering completions.
if fallback then prematch = "%s" end
 
-- Find the last occurence of the prematch before the cursor.
pms, pme, pmt = nil, 1, ''
text_prematch, prematchEnd, prematchStart = nil, nil, nil
while true do
pms, pme, pmt = strfind(text_precursor, "("..prematch..")", pme)
if pms then
prematchStart, prematchEnd, text_prematch = pms, pme, pmt
pme = pme + 1
else
break
end
end
 
if not prematchStart and fallback then
prematchStart, prematchEnd, text_prematch = 0, 0, ''
end
if prematchStart then
-- text_pmendToCursor should be the sub-word/phrase to be completed.
text_pmendToCursor = strsub(text_precursor, prematchEnd + 1)
 
-- How many characters should we eliminate before the completion before writing it in.
pmolengths[desc] = entry.pmoverwrite == true and #text_prematch or entry.pmoverwrite or 0
 
-- This is where we will insert completions, taking the prematch overwrite into account.
this.at3matchStart = prematchEnd + 1 - (pmolengths[desc] or 0)
 
-- We're either a non-fallback set or all completions thus far have been fallback sets, and the precondition matches.
-- Create cands from the registered wordlist, filling it with all potential (unfiltered) completion strings.
local wordlist = entry.wordlist
local cands = type(wordlist) == 'table' and wordlist or {}
if type(wordlist) == 'function' then
wordlist(cands, text_all, prematchEnd + 1, text_pmendToCursor)
end
if cands ~= false then
matches = this.at3matches[desc] or {}
for i in pairs(matches) do matches[i] = nil end
 
-- Check each of the entries in cands to see if it completes the word before the cursor.
-- Finally, increment our match count and set firstMatch, if appropriate.
for _, m in ipairs(cands) do
if strfind(strlower(m), strlower(text_pmendToCursor), 1, 1) == 1 then -- we have a matching completion!
hasNonFallback = not fallback
matches[m] = entry.postfunc and entry.postfunc(m, prematchEnd + 1, text_all) or m
numMatches = numMatches + 1
if numMatches == 1 then
firstMatch = matches[m]
firstPMLength = pmolengths[desc] or 0
end
end
end
this.at3matches[desc] = numMatches > 0 and matches or nil
end
end
end
end
end
end
 
function AceTab:OnTabPressed(this)
if this:GetText() == '' then return true end
 
-- allow Blizzard to handle slash commands, themselves
if this == ChatFrameEditBox then
local command = this:GetText()
if strfind(command, "^/[%a%d_]+$") then
return true
end
local cmd = strmatch(command, "^/[%a%d_]+")
if cmd and IsSecureCmd(cmd) then
return true
end
end
 
cursor = this:GetCursorPosition()
 
text_all = this:GetText()
text_precursor = getTextBeforeCursor(this) or ''
 
-- If we've already found some matches and haven't done anything since the last tab press, then (continue) cycling matches.
-- Otherwise, reset this frame's matches and proceed to creating our list of possible completions.
this.at3lastMatch = this.at3curMatch > 0 and (this.at3lastMatch or this.at3origWord)
-- Detects if we've made any edits since the last tab press. If not, continue cycling completions.
if text_precursor == this.at3_last_precursor then
return cycleTab(this)
else
for i in pairs(this.at3matches) do this.at3matches[i] = nil end
this.at3curMatch = 0
this.at3origWord = nil
this.at3origMatch = nil
this.at3lastWord = nil
this.at3lastMatch = nil
this.at3_last_precursor = text_precursor
end
 
numMatches = 0
firstMatch = nil
firstPMLength = 0
hasNonFallback = false
for i in pairs(pmolengths) do pmolengths[i] = nil end
 
for desc in pairs(notfallbacks) do
fillMatches(this, desc)
end
if not hasNonFallback then
for desc in pairs(fallbacks) do
fillMatches(this, desc, true)
end
end
 
if not firstMatch then
this.at3_last_precursor = "\0"
return true
end
 
-- We want to replace the entire word with our completion, so highlight it up to the cursor.
-- If only one match exists, then stick it in there and append a space.
if numMatches == 1 then
-- HighlightText takes the value AFTER which the highlighting starts, so we have to subtract 1 to have it start before the first character.
this:HighlightText(this.at3matchStart-1, cursor)
 
this:Insert(firstMatch)
this:Insert(" ")
else
-- Otherwise, we want to begin cycling through the valid completions.
-- Beginning a cycle also causes the usage statement to be printed, if one exists.
 
-- Print usage statements for each possible completion (and gather up the GCBS of all matches while we're walking the tables).
allGCBS = nil
for desc, matches in pairs(this.at3matches) do
-- Don't print usage statements for fallback completion groups if we have 'real' completion groups with matches.
if hasNonFallback and fallbacks[desc] then break end
 
-- Use the group's description as a heading for its usage statements.
DEFAULT_CHAT_FRAME:AddMessage(desc..":")
 
usagefunc = registry[desc].usagefunc
if not usagefunc then
-- No special usage processing; just print a list of the (formatted) matches.
for m, fm in pairs(matches) do
DEFAULT_CHAT_FRAME:AddMessage(fm)
allGCBS = gcbs(allGCBS, m)
end
else
-- Print a usage statement based on the corresponding registered usagefunc.
-- candUsage is the table passed to usagefunc to be filled with candidate = usage_statement pairs.
if type(usagefunc) == 'function' then
for i in pairs(candUsage) do candUsage[i] = nil end
 
-- usagefunc takes the greatest common substring of valid matches as one of its args, so let's find that now.
-- TODO: Make the GCBS function accept a vararg or table, after which we can just pass in the list of matches.
setGCBS = nil
for m in pairs(matches) do
setGCBS = gcbs(setGCBS, m)
end
allGCBS = gcbs(allGCBS, setGCBS)
usage = usagefunc(candUsage, matches, setGCBS, strsub(text_precursor, 1, prematchEnd))
 
-- If the usagefunc returns a string, then the entire usage statement has been taken care of by usagefunc, and we need only to print it...
if type(usage) == 'string' then
DEFAULT_CHAT_FRAME:AddMessage(usage)
 
-- ...otherwise, it should have filled candUsage with candidate-usage statement pairs, and we need to print the matching ones.
elseif next(candUsage) and numMatches > 0 then
for m, fm in pairs(matches) do
if candUsage[m] then DEFAULT_CHAT_FRAME:AddMessage(strformat("%s - %s", fm, candUsage[m])) end
end
end
end
end
 
-- Replace the original string with the greatest common substring of all valid completions.
this.at3curMatch = 1
this.at3origWord = strsub(text_precursor, this.at3matchStart, this.at3matchStart + pmolengths[desc] - 1) .. allGCBS or ""
this.at3origMatch = allGCBS or ""
this.at3lastWord = this.at3origWord
this.at3lastMatch = this.at3origMatch
 
this:HighlightText(this.at3matchStart-1, cursor)
this:Insert(this.at3origWord)
this.at3_last_precursor = getTextBeforeCursor(this) or ''
end
end
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceSerializer-3.0/AceSerializer-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="AceSerializer-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceSerializer-3.0/AceSerializer-3.0.lua New file
0,0 → 1,279
--[[ $Id: AceSerializer-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]]
local MAJOR,MINOR = "AceSerializer-3.0", 2
local AceSerializer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceSerializer then return end
 
local strbyte = string.byte
local strchar = string.char
local tconcat = table.concat
local gsub = string.gsub
local gmatch = string.gmatch
local pcall = pcall
local format = string.format
local type = type
local tostring, tonumber = tostring, tonumber
local select = select
 
-- quick copies of string representations of wonky numbers
local serNaN = tostring(0/0)
local serInf = tostring(1/0)
local serNegInf = tostring(-1/0)
 
 
-----------------------------------------------------------------------
-- Serialization functions
 
local function SerializeStringHelper(ch) -- Used by SerializeValue for strings
-- We use \126 ("~") as an escape character for all nonprints plus a few more
local n = strbyte(ch)
if n<=32 then -- nonprint + space
return "\126"..strchar(n+64)
elseif n==94 then -- value separator
return "\126\125"
elseif n==126 then -- our own escape character
return "\126\124"
elseif n==127 then -- nonprint (DEL)
return "\126\123"
else
assert(false) -- can't be reached if caller uses a sane regex
end
end
 
local function SerializeValue(v, res, nres)
-- We use "^" as a value separator, followed by one byte for type indicator
local t=type(v)
 
if t=="string" then -- ^S = string (escaped to remove nonprints, "^"s, etc)
res[nres+1] = "^S"
res[nres+2] = gsub(v,"[%c \94\126\127]", SerializeStringHelper)
nres=nres+2
 
elseif t=="number" then -- ^N = number (just tostring()ed) or ^F (float components)
local str = tostring(v)
if tonumber(str)==v or str==serNaN or str==serInf or str==serNegInf then
-- translates just fine, transmit as-is
res[nres+1] = "^N"
res[nres+2] = str
nres=nres+2
else
local m,e = frexp(v)
res[nres+1] = "^F"
res[nres+2] = format("%.0f",m*2^53) -- force mantissa to become integer (it's originally 0.5--0.9999)
res[nres+3] = "^f"
res[nres+4] = tostring(e-53) -- adjust exponent to counteract mantissa manipulation
nres=nres+4
end
 
elseif t=="table" then -- ^T...^t = table (list of key,value pairs)
nres=nres+1
res[nres] = "^T"
for k,v in pairs(v) do
nres = SerializeValue(k, res, nres)
nres = SerializeValue(v, res, nres)
end
nres=nres+1
res[nres] = "^t"
 
elseif t=="boolean" then -- ^B = true, ^b = false
nres=nres+1
if v then
res[nres] = "^B" -- true
else
res[nres] = "^b" -- false
end
 
elseif t=="nil" then -- ^Z = nil (zero, "N" was taken :P)
nres=nres+1
res[nres] = "^Z"
 
else
error(MAJOR..": Cannot serialize a value of type '"..t.."'") -- can't produce error on right level, this is wildly recursive
end
 
return nres
end
 
 
 
-----------------------------------------------------------------------
-- API Serialize(...)
--
-- Takes a list of values (strings, numbers, booleans, nils, tables)
-- and returns it in serialized form (a string).
-- May throw errors on invalid data types.
--
local serializeTbl = { "^1" } -- "^1" = Hi, I'm data serialized by AceSerializer protocol rev 1
function AceSerializer:Serialize(...)
local nres = 1
 
for i=1,select("#", ...) do
local v = select(i, ...)
nres = SerializeValue(v, serializeTbl, nres)
end
 
serializeTbl[nres+1] = "^^" -- "^^" = End of serialized data
 
return tconcat(serializeTbl, "", 1, nres+1)
end
 
 
-----------------------------------------------------------------------
-- Deserialization functions
 
 
local function DeserializeStringHelper(escape)
if escape<"~\123" then
return strchar(strbyte(escape,2,2)-64)
elseif escape=="~\123" then
return "\127"
elseif escape=="~\124" then
return "\126"
elseif escape=="~\125" then
return "\94"
end
error("DeserializeStringHelper got called for '"..escape.."'?!?") -- can't be reached unless regex is screwed up
end
 
local function DeserializeNumberHelper(number)
if number == serNaN then
return 0/0
elseif number == serNegInf then
return -1/0
elseif number == serInf then
return 1/0
else
return tonumber(number)
end
end
 
-- DeserializeValue: worker function for :Deserialize()
-- It works in two modes:
-- Main (top-level) mode: Deserialize a list of values and return them all
-- Recursive (table) mode: Deserialize only a single value (_may_ of course be another table with lots of subvalues in it)
--
-- The function _always_ works recursively due to having to build a list of values to return
--
-- Callers are expected to pcall(DeserializeValue) to trap errors
 
local function DeserializeValue(iter,single,ctl,data)
 
if not single then
ctl,data = iter()
end
 
if not ctl then
error("Supplied data misses AceSerializer terminator ('^^')")
end
 
if ctl=="^^" then
-- ignore extraneous data
return
end
 
local res
 
if ctl=="^S" then
res = gsub(data, "~.", DeserializeStringHelper)
elseif ctl=="^N" then
res = DeserializeNumberHelper(data)
if not res then
error("Invalid serialized number: '"..tostring(data).."'")
end
elseif ctl=="^F" then -- ^F<mantissa>^f<exponent>
local ctl2,e = iter()
if ctl2~="^f" then
error("Invalid serialized floating-point number, expected '^f', not '"..tostring(ctl2).."'")
end
local m=tonumber(data)
e=tonumber(e)
if not (m and e) then
error("Invalid serialized floating-point number, expected mantissa and exponent, got '"..tostring(m).."' and '"..tostring(e).."'")
end
res = m*(2^e)
elseif ctl=="^B" then -- yeah yeah ignore data portion
res = true
elseif ctl=="^b" then -- yeah yeah ignore data portion
res = false
elseif ctl=="^Z" then -- yeah yeah ignore data portion
res = nil
elseif ctl=="^T" then
-- ignore ^T's data, future extensibility?
res = {}
local k,v
while true do
ctl,data = iter()
if ctl=="^t" then break end -- ignore ^t's data
k = DeserializeValue(iter,true,ctl,data)
if k==nil then
error("Invalid AceSerializer table format (no table end marker)")
end
ctl,data = iter()
v = DeserializeValue(iter,true,ctl,data)
if v==nil then
error("Invalid AceSerializer table format (no table end marker)")
end
res[k]=v
end
else
error("Invalid AceSerializer control code '"..ctl.."'")
end
 
if not single then
return res,DeserializeValue(iter)
else
return res
end
end
 
 
-----------------------------------------------------------------------
-- API Deserialize(str)
--
-- Accepts serialized data, ignoring all control characters and whitespace.
--
-- Returns true followed by a list of values, OR false followed by a message
--
 
function AceSerializer:Deserialize(str)
str = gsub(str, "[%c ]", "") -- ignore all control characters; nice for embedding in email and stuff
 
local iter = gmatch(str, "(^.)([^^]*)") -- Any ^x followed by string of non-^
local ctl,data = iter()
if not ctl or ctl~="^1" then
-- we purposefully ignore the data portion of the start code, it can be used as an extension mechanism
return false, "Supplied data is not AceSerializer data (rev 1)"
end
 
return pcall(DeserializeValue, iter)
end
 
 
----------------------------------------
-- Base library stuff
----------------------------------------
 
AceSerializer.internals = { -- for test scripts
SerializeValue = SerializeValue,
SerializeStringHelper = SerializeStringHelper,
}
 
local mixins = {
"Serialize",
"Deserialize",
}
 
AceSerializer.embeds = AceSerializer.embeds or {}
 
function AceSerializer:Embed(target)
for k, v in pairs(mixins) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
 
-- Update embeds
for target, v in pairs(AceSerializer.embeds) do
AceSerializer:Embed(target)
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceBucket-3.0/AceBucket-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="AceBucket-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceBucket-3.0/AceBucket-3.0.lua New file
0,0 → 1,257
--[[ $Id: AceBucket-3.0.lua 66001 2008-03-26 08:52:07Z nevcairiel $ ]]
 
--[[
This Bucket implementation works as follows:
-- Initially, no schedule is running, and its waiting for the first event to happen.
-- The first event will start the bucket, and get the scheduler running, which will collect all
events in the given interval. When that interval is reached, the bucket is pushed to the
callback and a new schedule is started. When a bucket is empty after its interval, the scheduler is
stopped, and the bucket is only listening for the next event to happen, basicly back in initial state.
]]
 
local MAJOR, MINOR = "AceBucket-3.0", 3
local AceBucket, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceBucket then return end -- No Upgrade needed
 
AceBucket.buckets = AceBucket.buckets or {}
AceBucket.embeds = AceBucket.embeds or {}
 
-- the libraries will be lazyly bound later, to avoid errors due to loading order issues
local AceEvent, AceTimer
 
-- local upvalues
local type = type
local next = next
local pairs = pairs
local select = select
local tonumber = tonumber
local tostring = tostring
 
local bucketCache = setmetatable({}, {__mode='k'})
 
--[[
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
 
-- FireBucket ( bucket )
--
-- send the bucket to the callback function and schedule the next FireBucket in interval seconds
local function FireBucket(bucket)
local received = bucket.received
 
-- we dont want to fire empty buckets
if next(received) then
local callback = bucket.callback
if type(callback) == "string" then
safecall(bucket.object[callback], bucket.object, received)
else
safecall(callback, received)
end
 
for k in pairs(received) do
received[k] = nil
end
 
-- if the bucket was not empty, schedule another FireBucket in interval seconds
bucket.timer = AceTimer.ScheduleTimer(bucket, FireBucket, bucket.interval, bucket)
else -- if it was empty, clear the timer and wait for the next event
bucket.timer = nil
end
end
 
-- BucketHandler ( event, arg1 )
--
-- callback func for AceEvent
-- stores arg1 in the received table, and schedules the bucket if necessary
local function BucketHandler(self, event, arg1)
if arg1 == nil then
arg1 = "nil"
end
 
self.received[arg1] = (self.received[arg1] or 0) + 1
 
-- if we are not scheduled yet, start a timer on the interval for our bucket to be cleared
if not self.timer then
self.timer = AceTimer.ScheduleTimer(self, FireBucket, self.interval, self)
end
end
 
-- RegisterBucket( event, interval, callback, isMessage )
--
-- event(string or table) - the event, or a table with the events, that this bucket listens to
-- interval(int) - time between bucket fireings
-- callback(func or string) - function pointer, or method name of the object, that gets called when the bucket is cleared
-- isMessage(boolean) - register AceEvent Messages instead of game events
local function RegisterBucket(self, event, interval, callback, isMessage)
-- try to fetch the librarys
if not AceEvent or not AceTimer then
AceEvent = LibStub:GetLibrary("AceEvent-3.0", true)
AceTimer = LibStub:GetLibrary("AceTimer-3.0", true)
if not AceEvent or not AceTimer then
error(MAJOR .. " requires AceEvent-3.0 and AceTimer-3.0", 3)
end
end
 
if type(event) ~= "string" and type(event) ~= "table" then error("Usage: RegisterBucket(event, interval, callback): 'event' - string or table expected.", 3) end
if not callback then
if type(event) == "string" then
callback = event
else
error("Usage: RegisterBucket(event, interval, callback): cannot omit callback when event is not a string.", 3)
end
end
if not tonumber(interval) then error("Usage: RegisterBucket(event, interval, callback): 'interval' - number expected.", 3) end
if type(callback) ~= "string" and type(callback) ~= "function" then error("Usage: RegisterBucket(event, interval, callback): 'callback' - string or function or nil expected.", 3) end
if type(callback) == "string" and type(self[callback]) ~= "function" then error("Usage: RegisterBucket(event, interval, callback): 'callback' - method not found on target object.", 3) end
 
local bucket = next(bucketCache)
if bucket then
bucketCache[bucket] = nil
else
bucket = { handler = BucketHandler, received = {} }
end
bucket.object, bucket.callback, bucket.interval = self, callback, tonumber(interval)
 
local regFunc = isMessage and AceEvent.RegisterMessage or AceEvent.RegisterEvent
 
if type(event) == "table" then
for _,e in pairs(event) do
regFunc(bucket, e, "handler")
end
else
regFunc(bucket, event, "handler")
end
 
local handle = tostring(bucket)
AceBucket.buckets[handle] = bucket
 
return handle
end
 
-- AceBucket:RegisterBucketEvent(event, interval, callback)
-- AceBucket:RegisterBucketMessage(message, interval, callback)
--
-- event/message(string or table) - the event, or a table with the events, that this bucket listens to
-- interval(int) - time between bucket fireings
-- callback(func or string) - function pointer, or method name of the object, that gets called when the bucket is cleared
function AceBucket:RegisterBucketEvent(event, interval, callback)
return RegisterBucket(self, event, interval, callback, false)
end
 
function AceBucket:RegisterBucketMessage(message, interval, callback)
return RegisterBucket(self, message, interval, callback, true)
end
 
-- AceBucket:UnregisterBucket ( handle )
-- handle - the handle of the bucket as returned by RegisterBucket*
--
-- will unregister any events and messages from the bucket and clear any remaining data
function AceBucket:UnregisterBucket(handle)
local bucket = AceBucket.buckets[handle]
if bucket then
AceEvent.UnregisterAllEvents(bucket)
AceEvent.UnregisterAllMessages(bucket)
 
-- clear any remaining data in the bucket
for k in pairs(bucket.received) do
bucket.received[k] = nil
end
 
if bucket.timer then
AceTimer.CancelTimer(bucket, bucket.timer)
bucket.timer = nil
end
 
AceBucket.buckets[handle] = nil
-- store our bucket in the cache
bucketCache[bucket] = true
end
end
 
-- AceBucket:UnregisterAllBuckets()
--
-- will unregister all bucketed events.
function AceBucket:UnregisterAllBuckets()
-- hmm can we do this more efficient? (it is not done often so shouldn't matter much)
for handle, bucket in pairs(AceBucket.buckets) do
if bucket.object == self then
AceBucket.UnregisterBucket(self, handle)
end
end
end
 
 
 
--- embedding and embed handling
 
local mixins = {
"RegisterBucketEvent",
"RegisterBucketMessage",
"UnregisterBucket",
"UnregisterAllBuckets",
}
 
-- AceBucket:Embed( target )
-- target (object) - target object to embed AceBucket in
--
-- Embeds AceBucket into the target object making the functions from the mixins list available on target:..
function AceBucket:Embed( target )
for _, v in pairs( mixins ) do
target[v] = self[v]
end
self.embeds[target] = true
return target
end
 
--AceBucket:OnEmbedDisable( target )
-- target (object) - target object that AceBucket is embedded in.
--
-- Disables all buckets registered on the object
function AceBucket:OnEmbedDisable( target )
target:UnregisterAllBuckets()
end
 
for addon in pairs(AceBucket.embeds) do
AceBucket:Embed(addon)
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/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 Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua New file
0,0 → 1,239
--[[ $Id: CallbackHandler-1.0.lua 60697 2008-02-09 16:51: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.
 
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/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 Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceTimer-3.0/AceTimer-3.0.lua New file
0,0 → 1,414
--[[ $Id: AceTimer-3.0.lua 74633 2008-05-21 08:20:50Z 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", 4
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
 
 
-----------------------------------------------------------------------
-- AceTimer:ScheduleTimer( callback, delay, arg )
-- AceTimer:ScheduleRepeatingTimer( callback, delay, arg )
--
-- 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
--
-- returns a handle to the timer, which is used for cancelling it
function AceTimer:ScheduleTimer(callback, delay, arg)
return Reg(self, callback, delay, arg)
end
 
function AceTimer:ScheduleRepeatingTimer(callback, delay, arg)
return Reg(self, callback, delay, arg, true)
end
 
 
-----------------------------------------------------------------------
-- AceTimer:CancelTimer(handle)
--
-- handle - Opaque object given by ScheduleTimer
-- silent - true: Do not error if the timer does not exist / is already cancelled. Default: false
--
-- Cancels a timer with the given handle, registered by the same 'self' as given in ScheduleTimer
--
-- Returns true if a timer was 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
 
 
-----------------------------------------------------------------------
-- AceTimer:CancelAllTimers()
--
-- Cancels all timers registered to given '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
 
 
 
-----------------------------------------------------------------------
-- 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"
}
 
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.
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/docs/AceEvent-3.0.txt New file
0,0 → 1,50
AceEvent-3.0 Documentation
 
Getting a hold of AceEvent:
 
local AceEvent = LibStub:GetLibrary("AceEvent-3.0")
local AceEvent = LibStub("AceEvent-3.0")
 
 
or the more common use embed AceEvent into your addon object:
 
local myAddon = LibStub("AceAddon-3.0"):NewAddon("myAddon", "AceEvent-3.0", ... )
 
or in a random other object/table:
 
local AceEvent = LibStub("AceEvent-3.0")
local mytable = {}
AceEvent:Embed(mytable)
 
For the further API documentation we will assume AceEvent embedded into some object.
 
AceEvent API
 
addon:RegisterEvent( event[, method[, arg]] )
event (string) - Blizzard event to register for.
[method] (string|func) - Method to call when the event is fired. A string method is called like addon[method]( event, [arg, ...] ).
[arg] - optional argument, if set will be passed as the first argument when the event fires.
 
addon:UnregisterEvent( event )
event (string) - Blizzard event to unregister.
 
addon:UnregisterAllEvents()
Unregister all events.
 
addon:RegisterMessage( message[, metod[, arg]] )
message (string) - Message to register for.
[method] (string|func) - Method to call when the message is fired. A string method is called like addon[method]( event, [arg, ...] ).
[arg] - optional argument, if set will be passed as the first argument when the message fires.
Messages are used for interaddon communication.
 
addon:SendMessage( message[, ...] )
message (string) - Message to trigger.
[...] - optional arguments to the message.
Will fire a message towards all listeners.
 
addon:UnregisterMessage( message )
message (string) - Message to unregister
 
addon:UnregisterAllMessages()
Unregster all messages.
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/docs/AceConsole-3.0.txt New file
0,0 → 1,49
AceConsole-3.0 Documentation
 
Getting a hold of AceConsole:
 
local AceConsole = LibStub:GetLibrary("AceConsole-3.0")
local AceConsole = LibStub("AceConsole-3.0")
 
 
or the more common use embed AceConsole into your addon object:
 
local myAddon = LibStub("AceAddon-3.0"):NewAddon("myAddon", "AceConsole-3.0", ... )
 
or in a random other object/table:
 
local AceConsole = LibStub("AceConsole-3.0")
local mytable = {}
AceConsole:Embed(mytable)
 
For the further API documentation we will assume AceConsole embedded into some object.
 
AceConsole API
 
addon:Print( [chatframe,] ... )
[chatframe] - Any messageframe that has a .AddMessage member
Will print the given argument list space separated to the given chatframe or DEFAULT_CHAT_FRAME.
 
 
addon:RegisterChatCommand( command[, func[, persist[, silent]]] )
command (string) - chat command to be registered WITHOUT the leading "/"
func (function|string) - function to call or self[func](self, ...) when func is a string
persist (boolean) - false: the command will be soft disable/enabled when AceConsole is used as a mixin and the addon object is disabled/enabled (default: true)
silent (boolean) - don't whine if the command already exists, silently fail
Register a simple chat command
 
 
addon:UnregisterChatCommand( command )
command (string) - chat command to be unregistered WITHOUT the leading "/"
Unregisters the given command. Will silently fail if it does not exist.
 
 
 
addon:GetArgs( string[, numargs[, startpos]] )
string (string) - the raw argument string to parse for arguments
numargs (number) - How many arguments to get (default: 1)
startpos (number) - Where in the string to start scanning (default: 1)
Returns arg1, arg2, ..., nextposition
Retreives space-separated arguments from the string. Quoted sections are recognized as a single argument, as are hyperlinks.
Missing arguments will be returned as nils. If the end of the string is encountered during scanning, 'nextposition' is returned as 1e9 (1 billion).
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/docs/AceAddon-3.0.txt New file
0,0 → 1,151
AceAddon-3.0 Documentation
 
Getting a hold of AceAddon:
 
local AceAddon = LibStub:GetLibrary("AceAddon-3.0")
local AceAddon = LibStub("AceAddon-3.0")
 
or create an addon object immediately:
 
local myAddon = LibStub("AceAddon-3.0"):NewAddon("myAddon", ... )
 
 
AceAddon API
 
 
AceAddon:NewAddon( name, [lib, lib, lib, ...] )
name (string) - unique addon object name
[lib] (string) - optional libs to embed in the addon object
returns the addon object when succesful
 
Example:
local myAddon = LibStub("AceAddon-3.0"):NewAddon("myAddon", "AceEvent-3.0", "AceDB-3.0", "SomeLib-1.0")
myAddon is now an Ace addon object with AceEvent-3.0, AceDB-3.0 and SomeLib-1.0 mixed into the object.
 
 
AceAddon:GetAddon( name, [silent])
name (string) - unique addon object name
silent (boolean) - if true, addon is optional, silently return nil if its not found
returns the addon object if found
 
 
AceAddon:EmbedLibraries( addon, [lib, lib, lib, ...] )
addon (object) - addon to embed the libs in
[lib] (string) - optional libs to embed
Embeds the given libraries into the addon object.
 
AceAddon:EmbedLibrary( addon, libname, silent, offset )
addon (object) - addon to embed the libs in
libname (string) - lib to embed
[silent] (boolean) - optional, marks an embed to fail silently if the library doesn't exist.
[offset] (number) - will push the error messages back to said offset defaults to 2
Embeds one library into the addon object.
 
 
AceAddon:IntializeAddon( addon )
addon (object) - addon to intialize
Mostly an internal function. Typical developers will not use this. IntializeAddon is called on the addon upon ADDON_LOADED automatically.
calls OnInitialize on the addon object if available
calls OnEmbedInitialize on embedded libs in the addon object if available
 
 
AceAddon:EnableAddon( addon )
addon (object) - addon to enable
This function enables the addon object. This is automatically called upon PLAYER_LOGIN or sequentially after ADDON_LOADED when PLAYER_LOGIN has already fired and the addon is LoD.
calls OnEnable on the addon object if available
calls OnEmbedEnable on embedded libs in the addon object if available
 
 
AceAddon:DisableAddon( addon )
addon (object) - addon to disable
Disables the addon object. This can be used for a soft disable of modules/addons.
calls OnDisable on the addon object if available
calls OnEmbedDisable on embedded libs in the addon object if available
 
 
AceAddon:IterateAddons()
Returns an iterator over all registered AceAddons.
 
AceAddon:IterateEmbedsOnAddon( addon )
Returns an iterator over all embedded libraries in the passed addon.
 
AceAddon:IterateAddonStatus()
Returns an iterator over all addons and their status [name] => [status]
 
AceAddon:IterateModulesOfAddon( addon )
Returns an iterator over all modules of an addon. [name] => [moduleobject]
 
 
 
 
Addon Object API
 
addon:GetModule( name, [silent])
name (string) - unique module object name
silent (boolean) - if true, module is optional, silently return nil if its not found
returns the module object if found
 
addon:NewModule( name, [prototype, [lib, lib, lib, ...] )
name (string) - unique module object name for this addon
prototype (object) - object to derive this module from, methods and values from this table will be mixed into the module, if a string is passed a lib is assumed
[lib] (string) - optional libs to embed in the addon object
returns the addon object when succesful
Modules of an AceAddon are AceAddon objects themselves and thus have the same API.
 
addon:Enable()
Enables the addon and returns true or false depending on success
If the addon is already enabled this will return false
 
addon:Disable()
Disables teh addon and returns true or false depending on success
If the addon is already disabled this will return false
 
addon:EnableModule( name )
name (string) - unique module object name to enable
returns true or false depending on success
 
addon:DisableModule( name )
name (string) - unique module object name to disable
returns true or false depending on success
 
addon:IsEnabled()
return true or false depending on wether the addon is enabled or not.
 
addon:IsModule()
returns true or false depending on wether the addon is a module or not.
 
 
addon:SetDefaultModuleLibraries( [lib, lib, lib, ...] )
[lib] (string) - libs to embed in every module
 
 
addon:SetDefaultModuleState( state )
state (boolean) - default state for new modules (enabled=true, disabled=false)
 
addon:SetDefaultModulePrototype( prototype )
prototype (table) - default prototype to use for modules.
 
addon:SetEnabledState ( state )
state ( boolean ) - set the state of an addon or module (enabled=true, disabled=false)
should only be called before any Enabling actually happend, aka in OnInitialize
 
 
addon:IterateModules()
Iterates over the modules of the current addon object
 
addon:IterateEmbeds()
Iterates over the embedded libraries of the addon object
 
-- Special optional functions
 
addon:OnInitalize()
If this function is defined on your addon object it will be called when it is initialized. Typically on ADDON_LOADED.
 
addon:OnEnable()
If this function is defined on your addon object it will be called when it is enabled. Typically on PLAYER_LOGIN
 
addon:OnDisable()
If this function is defined on your addon object it will be called when it is disabled.
 
addon:OnModuleCreated( module )
If this function is defined on your addon object it will be called whenever a new module is added through NewModule. The module object is passed.
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/docs/AceDB-3.0.txt New file
0,0 → 1,100
AceDB-3.0 Documentation Draft
 
Getting a hold of AceDB:
 
local AceDB = LibStub:GetLibrary("AceDB-3.0")
local AceDB = LibStub("AceDB-3.0")
 
Available Datatypes
 
char
- Character-specific data. No other characters can access or change this data, it is specific to one character and one character alone.
realm
- Realm-specific data. All of the players characters on the same realm share this database.
class
- Class-specific data. All of the players characters of a certain class share this database.
race
- Race-specific data. All of the players characters of a certain race share this database.
faction
- Faction-specific data. All of the players characters of a certain faction share this database.
factionrealm
- Faction and realm specific data. All of the players characters on the same realm and in the same faction share this database.
profile
- Profile-specific data. All characters using the same profile share this database. Every character can select its own profile, or they can all share one.
global
- Global Data. All characters on the same account share this database.
 
Usage Documentation
 
[code]
-- creating a database object on top of our SavedVariables Var
local db = AceDB:New("MyAddonDB")
 
-- now save some value to our profile
db.profile.firstValue = 1
db.profile.secondValue = 2
 
-- and some data to our charecter based data
db.char.firstValue = 1
 
[/code]
 
You can access all datatypes in the same way:
DBObject.<datatype>.key = value
 
 
 
AceDB-3.0 API:
 
AceDB:New( tbl[, defaults[, defaultprofile]] )
tbl (string or table) - target table to store our DB in, either string pointing to a global table (your addons SV table), or a direct table reference
[defaults] (table) - reference to the defaults table
[defaultprofile] (string) - default profile to start with on an empty DB (defaults to character)
Returns a new DBObject encapsulating the specified "tbl"
 
 
DBObject API:
 
DBObject:RegisterDefaults( [defaults] )
[defaults] (table) - A table of defaults for this database
Sets the defaults table for the given database object by clearing any that are currently set, and then setting the new defaults, if specified.
Calling db:RegisterDefaults() without specifying a defaults table will remove all defaults from the table.
 
DBObject:SetProfile( name )
name (string) - The name of the profile to set as the current profile
Changes the profile of the database and all of it's namespaces to the supplied named profile
 
DBObject:GetProfiles( [tbl] )
[tbl] (table) - A table to store the profile names in (optional)
Returns a table with the names of the existing profiles in the database.
You can optionally supply a table to re-use for this purpose.
 
DBObject:GetCurrentProfile()
Returns the current profile name used by the database
 
DBObject:DeleteProfile(name)
name (string) - The name of the profile to be deleted
Deletes a named profile. This profile must not be the active profile.
 
DBObject:CopyProfile(name)
name (string) - The name of the profile to be copied into the current profile
Resets the current profile and copies the specified profile into the current profile.
 
DBObject:ResetProfile()
Resets the current profile
 
DBObject:ResetDB(defaultProfile)
defaultProfile (string) - The profile name to use as the default
Resets the entire database, using the string defaultProfile as the new default profile.
 
DBObject:RegisterNamespace(name [, defaults])
name (string) - The name of the new namespace
defaults (table) - A table of values to use as defaults
Creates a new database namespace, directly tied to the database. This
is a full scale database in it's own rights other than the fact that
it cannot control its profile individually.
Returns a new DBObject pointing to the namespace.
 
 
Defaults Table Documentation:
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/docs/AceSerializer-3.0.txt New file
0,0 → 1,39
AceSerializer 3.0 Documentation
 
 
Getting a hold of AceSerializer:
 
local AceSerializer = LibStub:GetLibrary("AceSerializer-3.0")
local AceSerializer = LibStub("AceSerializer-3.0")
 
 
or the more common use embed AceSerializer into your addon object:
 
local myAddon = LibStub("AceAddon-3.0"):NewAddon("myAddon", "AceSerializer-3.0", ... )
 
or in a random other object/table:
 
local AceSerializer = LibStub("AceSerializer-3.0")
local mytable = {}
AceSerializer:Embed(mytable)
 
For the further API documentation we will assume AceSerializer embedded into some object.
 
AceSerializer API
 
 
addon:Serialize( ... )
... - variable argument list
Takes a list of values (strings, numbers, booleans, nils, tables)
and returns it in serialized form (a string).
May throw errors on invalid data types.
 
addon:Deserialize( str )
str (string) - serialized data to be deserialized
Returns true followed by a list of values, OR false followed by a message
 
 
AceSerializer can be used for any number of things including:
* Sharing addon setup, layouts etc via copy paste.
* Sending arbitrary data over the Addon Message channel
* etc...
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/docs/AceBucket-3.0.txt New file
0,0 → 1,46
AceBucket-3.0 Documentation
 
Getting a hold of AceBucket:
 
local AceBucket = LibStub:GetLibrary("AceBucket-3.0")
local AceBucket = LibStub("AceBucket-3.0")
 
 
or the more common use embed AceBucket into your addon object:
 
local myAddon = LibStub("AceAddon-3.0"):NewAddon("myAddon", "AceBucket-3.0", ... )
 
or in a random other object/table:
 
local AceBucket = LibStub("AceBucket-3.0")
local mytable = {}
AceBucket:Embed(mytable)
 
AceBucket uses most of the AceEvent and AceTimer libraries for it's scheduling and firing of messages.
It will require those libraries on the first use of RegisterBucketEvent/Message
 
For the further API documentation we will assume AceBucket embedded into some object.
 
AceBucket API
 
addon:RegisterBucketEvent( event, interval[, method] )
event (string) - Blizzard event to register for.
interval (number) - Throttling interval
[method] (string|func) - Method to call when the event is fired. A string method is called like addon[method]( event, [arg, ...] ).
Will fire the event into the method with a table containing the first arguments of the event fired.
Returns a handle to the bucket.
 
addon:RegisterBucketMessage( message, inteval[, method] )
message (string) - Message to register for.
interval (number) - Throttling interval
[method] (string|func) - Method to call when the message is fired. A string method is called like addon[method]( event, [arg, ...] ).
Will fire the message into the method with a table containing the first arguments of the event fired.
Returns a handle to the bucket
 
addon:UnregisterBucket( handle )
handle (string) - Bucket to unregister
 
addon:UnregisterAllBuckets()
Unregisters all buckets for this object.
 
 
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/docs/AceLocale-3.0.txt New file
0,0 → 1,46
AceLocale-3.0 Documentation
 
Getting a hold of AceLocale:
 
local AceLocale = LibStub:GetLibrary("AceLocale-3.0")
local AceLocale = LibStub("AceLocale-3.0")
 
API
 
AceLocale:NewLocale( name, locale[, default] )
name (string) - unique name of the locale table
locale (string) - locale being registered (enUS, deDE, frFR etc)
[default] (boolean) - indicate that this will be the default locale (usually enUS)
returns a table to register locales in or nil if no locales are needed.
 
AceLocale:GetLocale( name[, silent] )
name (string) - unique name of the locale table you wish to retrieve
[silent] (boolean) - when silent is set GetLocale will not error but silently return nil if a locale is not found.
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)
 
 
 
USAGE EXAMPLE
 
local AceLocale = LibStub("AceLocale-3.0")
 
local L = AceLocale:NewLocale( "Foo", "enUS", true )
 
if L then
L["bar"] = true
L["foo"] = true
end
 
L = AceLocale:NewLocale( "Foo, "deDE" )
 
if L then
L["bar"] = "barre"
L["foo"] = "fuu"
end
 
..............
 
 
L = AceLocale:GetLocale( "Foo" )
print( L["bar"] )
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/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 Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceEvent-3.0/AceEvent-3.0.lua New file
0,0 → 1,76
--[[ $Id: AceEvent-3.0.lua 60131 2008-02-03 13:03:56Z 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",
}
 
-- AceEvent:Embed( target )
-- target (object) - target object to embed AceEvent in
--
-- Embeds AceEvent into the target object making the functions from the mixins list available on target:..
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/Ace3.lua New file
0,0 → 1,101
 
-- This file is only there in standalone Ace3 and provides handy dev tool stuff I guess
-- for now only /rl to reload your UI :)
-- note the complete overkill use of AceAddon and console, ain't it cool?
 
local gui = LibStub("AceGUI-3.0")
local reg = LibStub("AceConfigRegistry-3.0")
local dialog = LibStub("AceConfigDialog-3.0")
 
Ace3 = LibStub("AceAddon-3.0"):NewAddon("Ace3", "AceConsole-3.0")
local Ace3 = Ace3
 
local selectedgroup
local frame
local select
local status = {}
local configs = {}
 
local function frameOnClose()
gui:Release(frame)
frame = nil
end
 
local function RefreshConfigs()
for name in reg:IterateOptionsTables() do
configs[name] = name
end
end
 
local function ConfigSelected(widget, event, value)
selectedgroup = value
dialog:Open(value, widget)
end
 
local old_CloseSpecialWindows
 
function Ace3:Open()
if not old_CloseSpecialWindows then
old_CloseSpecialWindows = CloseSpecialWindows
CloseSpecialWindows = function()
local found = old_CloseSpecialWindows()
if frame then
frame:Hide()
return true
end
return found
end
end
RefreshConfigs()
if next(configs) == nil then
self:Print("No Configs are Registered")
return
end
 
if not frame then
frame = gui:Create("Frame")
frame:ReleaseChildren()
frame:SetTitle("Ace3 Options")
frame:SetLayout("FILL")
frame:SetCallback("OnClose", frameOnClose)
 
select = gui:Create("DropdownGroup")
select:SetGroupList(configs)
select:SetCallback("OnGroupSelected", ConfigSelected)
frame:AddChild(select)
end
if not selectedgroup then
selectedgroup = next(configs)
end
select:SetGroup(selectedgroup)
frame:Show()
end
 
local function RefreshOnUpdate(this)
select:SetGroup(selectedgroup)
this:SetScript("OnUpdate", nil)
end
 
function Ace3:ConfigTableChanged(event, appName)
if selectedgroup == appName and frame then
frame.frame:SetScript("OnUpdate", RefreshOnUpdate)
end
end
 
reg.RegisterCallback(Ace3, "ConfigTableChange", "ConfigTableChanged")
 
function Ace3:PrintCmd(input)
input = input:trim():match("^(.-);*$")
local func, err = loadstring("LibStub(\"AceConsole-3.0\"):Print(" .. input .. ")")
if not func then
LibStub("AceConsole-3.0"):Print("Error: " .. err)
else
func()
end
end
 
function Ace3:OnInitialize()
self:RegisterChatCommand("ace3", function() self:Open() end)
self:RegisterChatCommand("rl", function() ReloadUI() end)
self:RegisterChatCommand("print", "PrintCmd")
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/AceGUI-3.0.xml New file
0,0 → 1,24
<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-Icon.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceGUI-3.0/AceGUI-3.0.lua New file
0,0 → 1,640
--[[ $Id: AceGUI-3.0.lua 74633 2008-05-21 08:20:50Z nevcairiel $ ]]
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 13
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
tinsert(objPools[type],obj)
end
end
 
 
-------------------
-- API Functions --
-------------------
 
-- Gets a widget Object
 
function AceGUI:Create(type)
local reg = WidgetRegistry
if reg[type] then
local widget = new(type,reg[type])
 
if widget.Acquire then
widget.OnAcquire = widget.Acquire
widget.Acquire = nil
elseif widget.Aquire then
widget.OnAcquire = widget.Aquire
widget.Aquire = nil
end
 
if widget.OnAcquire then
widget:OnAcquire()
else
error(("Widget type %s doesn't supply an OnAcquire Function"):format(type))
end
safecall(widget.ResumeLayout, widget)
return widget
end
end
 
-- Releases a widget Object
function AceGUI:Release(widget)
safecall( widget.PauseLayout, widget )
widget:Fire("OnRelease")
safecall( widget.ReleaseChildren, widget )
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
if widget.Release then
widget.OnRelease = widget.Release
widget.Release = nil
end
if widget.OnRelease then
widget:OnRelease()
else
error(("Widget type %s doesn't supply an OnRelease Function"):format(type))
end
 
--widget.frame:SetParent(nil)
widget.frame:ClearAllPoints()
widget.frame:Hide()
widget.frame:SetParent(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
-----
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.SetHeight = function(self, height)
self.frame:SetHeight(height)
self.frame.height = height
if self.OnHeightSet then
self:OnHeightSet(height)
end
end
 
WidgetBase.IsVisible = function(self)
return self.frame:IsVisible()
end
 
WidgetBase.IsShown= function(self)
return self.frame:IsShown()
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)
tinsert(self.children,child)
child:SetParent(self)
child.frame:Show()
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
 
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
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
 
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
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
function AceGUI:RegisterLayout(Name, LayoutFunc)
assert(type(LayoutFunc) == "function")
if type(Name) == "string" then
Name = Name:upper()
end
LayoutRegistry[Name] = LayoutFunc
end
 
function AceGUI:GetLayout(Name)
if type(Name) == "string" then
Name = Name:upper()
end
return LayoutRegistry[Name]
end
 
AceGUI.counts = AceGUI.counts or {}
 
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)
else
frame:SetPoint("TOPLEFT",children[i-1].frame,"BOTTOMLEFT",0,0)
end
 
if child.width == "fill" then
child:SetWidth(width)
frame:SetPoint("RIGHT",content,"RIGHT")
if child.OnWidthSet then
child:OnWidthSet(content.width or content:GetWidth())
end
if child.DoLayout then
child:DoLayout()
end
end
 
height = height + (frame.height or frame:GetHeight() or 0)
end
safecall( content.obj.LayoutFinished, content.obj, nil, height )
end
)
 
-- A single control fills the whole content area
AceGUI:RegisterLayout("Fill",
function(content, children)
if children[1] then
children[1]:SetWidth(content:GetWidth() or 0)
children[1]:SetHeight(content:GetHeight() or 0)
children[1].frame:SetAllPoints(content)
children[1].frame:Show()
safecall( content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight() )
end
end
)
 
AceGUI:RegisterLayout("Flow",
function(content, children)
--used height so far
local height = 0
--width used in the current row
local usedwidth = 0
--height of the current row
local rowheight = 0
local rowoffset = 0
local lastrowoffset
 
local width = content.width or content:GetWidth() or 0
 
--control at the start of the row
local rowstart
local rowstartoffset
local lastrowstart
local isfullheight
 
local frameoffset
local lastframeoffset
local oversize
for i, child in ipairs(children) do
oversize = nil
local frame = child.frame
local frameheight = frame.height or frame:GetHeight() or 0
local framewidth = frame.width or frame:GetWidth() or 0
lastframeoffset = frameoffset
frameoffset = child.alignoffset or (frameheight / 2)
 
frame:Show()
frame:ClearAllPoints()
if i == 1 then
-- anchor the first control to the top left
--frame:SetPoint("TOPLEFT",content,"TOPLEFT",0,0)
rowheight = frameheight
rowoffset = frameoffset
rowstart = frame
rowstartoffset = frameoffset
usedwidth = framewidth
if usedwidth > width then
oversize = true
end
else
-- if there isn't available width for the control start a new row
-- if a control is "fill" it will be on a row of its own full width
if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then
--anchor the previous row, we will now know its height and offset
rowstart:SetPoint("TOPLEFT",content,"TOPLEFT",0,-(height+(rowoffset-rowstartoffset)+3))
height = height + rowheight + 3
--save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it
rowstart = frame
rowstartoffset = frameoffset
rowheight = frameheight
rowoffset = frameoffset
usedwidth = frame.width or frame:GetWidth()
if usedwidth > width then
oversize = true
end
-- put the control on the current row, adding it to the width and checking if the height needs to be increased
else
--handles cases where the new height is higher than either control because of the offsets
--math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset)
 
--offset is always the larger of the two offsets
rowoffset = math.max(rowoffset, frameoffset)
 
rowheight = math.max(rowheight,rowoffset+(frameheight/2))
frame:SetPoint("TOPLEFT",children[i-1].frame,"TOPRIGHT",0,frameoffset-lastframeoffset)
usedwidth = framewidth + usedwidth
end
end
 
if child.width == "fill" then
child:SetWidth(width)
frame:SetPoint("RIGHT",content,"RIGHT",0,0)
 
usedwidth = 0
rowstart = frame
rowstartoffset = frameoffset
 
if child.DoLayout then
child:DoLayout()
end
rowheight = frame.height or frame:GetHeight() or 0
rowoffset = child.alignoffset or (rowheight / 2)
rowstartoffset = rowoffset
elseif oversize then
if width > 1 then
frame:SetPoint("RIGHT",content,"RIGHT",0,0)
end
end
 
if child.height == "fill" then
frame:SetPoint("BOTTOM",content,"BOTTOM")
isfullheight = true
break
end
end
 
--anchor the last row, if its full height needs a special case since its height has just been changed by the anchor
if isfullheight then
rowstart:SetPoint("TOPLEFT",content,"TOPLEFT",0,-height)
elseif rowstart then
rowstart:SetPoint("TOPLEFT",content,"TOPLEFT",0,-(height+(rowoffset-rowstartoffset)+3))
end
 
height = height + rowheight + 3
safecall( content.obj.LayoutFinished, content.obj, nil, height )
end
)
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-Label.lua New file
0,0 → 1,132
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Label --
--------------------------
do
local Type = "Label"
local Version = 8
 
local function OnAcquire(self)
self:SetText("")
self:SetImage(nil)
self:SetColor()
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 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
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
 
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-MultiLineEditBox.lua New file
0,0 → 1,302
 
--[[
--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 = 6
---------------------
-- 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: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.editbox:ClearFocus()
self.editbox:SetTextColor(0.5, 0.5, 0.5)
else
self.editbox:EnableMouse(true)
self.editbox:SetTextColor(1, 1, 1)
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: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
 
local scrollchild = CreateFrame("Frame", nil, scrollframe)
scrollframe:SetScrollChild(scrollchild)
scrollchild:SetHeight(2)
scrollchild:SetWidth(2)
 
local label = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight")
label:SetPoint("TOPLEFT",frame,"TOPLEFT",14,0)
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-14,0)
label:SetJustifyH("LEFT")
label:SetHeight(18)
self.label = label
 
local editbox = CreateFrame("EditBox", nil, scrollchild)
self.editbox = editbox
editbox.obj = self
editbox:SetPoint("TOPLEFT")
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)
 
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: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
 
 
 
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-Slider.lua New file
0,0 → 1,240
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Slider --
--------------------------
do
local Type = "Slider"
local Version = 5
 
local function OnAcquire(self)
self:SetDisabled(false)
self:SetSliderValues(0,100,1)
self:SetIsPercent(nil)
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)
if self.ispercent then
self.editbox:SetText((math.floor(self.value*1000+0.5)/10)..'%')
else
self.editbox:SetText(math.floor(self.value*100+0.5)/100)
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)
self.lowtext:SetText(min or 0)
self.hightext:SetText(max or 100)
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
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-TabGroup.lua New file
0,0 → 1,338
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 = 14
 
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
end
 
local function Tab_SetText(self, text)
self:_SetText(text)
PanelTemplates_TabResize(self, 0)
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 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:SetScript("OnClick",Tab_OnClick)
tab:SetScript("OnEnter",Tab_OnEnter)
tab:SetScript("OnLeave",Tab_OnLeave)
 
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
 
for i, v in ipairs(tabs) do
v:Hide()
end
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() - 10 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing
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
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
 
--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
local padding = (width - rowwidths[row]) / (endtab - starttab+1)
for i = starttab, endtab do
PanelTemplates_TabResize(tabs[i], padding)
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 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.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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-Keybinding.lua New file
0,0 → 1,201
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Keybinding --
--------------------------
do
local Type = "Keybinding"
local Version = 8
 
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
 
if not self.disabled then
self:Fire("OnKeyChanged",keyPressed)
end
 
this:EnableKeyboard(false)
self.msgframe:Hide()
this:UnlockHighlight()
self.waitingForKey = nil
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)
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)
self.button:SetText(key or "")
end
 
local function SetLabel(self, label)
self.label:SetText(label or "")
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-CheckBox.lua New file
0,0 → 1,217
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Check Box --
--------------------------
--[[
Events :
OnValueChanged
 
]]
do
local Type = "CheckBox"
local Version = 4
 
local function OnAcquire(self)
self:SetValue(false)
self.tristate = nil
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-Icon.lua New file
0,0 → 1,99
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Label --
--------------------------
do
local Type = "Icon"
local Version = 4
 
local function OnAcquire(self)
self:SetText("")
self:SetImage(nil)
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
end
 
local function SetText(self, text)
self.label:SetText(text or "")
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 OnClick(this)
this.obj:Fire("OnClick")
AceGUI:ClearFocus()
end
 
local function OnEnter(this)
this.obj.highlight:Show()
end
 
local function OnLeave(this)
this.obj.highlight:Hide()
end
 
local function Constructor()
local frame = CreateFrame("Button",nil,UIParent)
local self = {}
self.type = Type
 
self.OnRelease = OnRelease
self.OnAcquire = OnAcquire
self.SetText = SetText
self.frame = frame
self.SetImage = SetImage
 
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,10)
label:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,10)
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,-10)
 
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
 
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
RepWatch/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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-InlineGroup.lua New file
0,0 → 1,135
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 = 4
 
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)
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown.lua New file
0,0 → 1,674
--[[ $Id: AceGUIWidget-DropDown.lua 76326 2008-06-09 09:29:17Z 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 = 17
 
--[[ 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)
this.obj.pullout:Close()
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
self.pullout:Close()
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())
end
 
-- exported, AceGUI callback
local function OnRelease(self)
self.pullout:Close()
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)
self.pullout:Close()
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
 
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/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 = 8
 
local function OnAcquire(self)
self:SetDisabled(false)
self.showbutton = true
end
 
local function OnRelease(self)
self.frame:ClearAllPoints()
self.frame:Hide()
self:SetDisabled(false)
end
 
local function Control_OnEnter(this)
this.obj:Fire("OnEnter")
end
 
local function Control_OnLeave(this)
this.obj:Fire("OnLeave")
end
 
local function EditBox_OnEscapePressed(this)
this:ClearFocus()
end
 
local function ShowButton(self)
if self.showbutton then
self.button:Show()
self.editbox:SetTextInsets(0,20,3,3)
end
end
 
local function HideButton(self)
self.button:Hide()
self.editbox:SetTextInsets(0,0,3,3)
end
 
local function EditBox_OnEnterPressed(this)
local self = this.obj
local value = 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 SetWidth(self, width)
self.frame:SetWidth(width)
end
 
local function SetLabel(self, text)
if text and text ~= "" then
self.label:SetText(text)
self.label:Show()
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18)
self.frame:SetHeight(44)
else
self.label:SetText("")
self.label:Hide()
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0)
self.frame:SetHeight(26)
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.SetWidth = SetWidth
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-Heading.lua New file
0,0 → 1,71
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Heading --
--------------------------
do
local Type = "Heading"
local Version = 3
 
local function OnAcquire(self)
self:SetText("")
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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-SimpleGroup.lua New file
0,0 → 1,96
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 = 4
 
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)
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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDownGroup.lua New file
0,0 → 1,157
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 = 9
 
local function OnAcquire(self)
self.dropdown:SetText("")
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 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.OnWidthSet = OnWidthSet
self.OnHeightSet = OnHeightSet
 
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",14,0)
titletext:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-14,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",-7,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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/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 = 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
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",-16,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",0,-16)
scrollbar:SetPoint("BOTTOMLEFT",scrollframe,"BOTTOMRIGHT",0,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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-Button.lua New file
0,0 → 1,81
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- Button --
--------------------------
do
local Type = "Button"
local Version = 7
 
local function OnAcquire(self)
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 frame = CreateFrame("Button","AceGUI30Button"..num,UIParent,"UIPanelButtonTemplate2")
local self = {}
self.num = num
self.type = Type
self.frame = frame
 
local text = frame:GetFontString()
self.text = text
text:SetPoint("LEFT",frame,"LEFT",15,0)
text:SetPoint("RIGHT",frame,"RIGHT",-15,0)
 
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
Property changes : Added: svn:keywords + Revision Date Added: svn:eol-style + native Added: svn:mime-type + text/plain
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-DropDown-Items.lua New file
0,0 → 1,453
--[[ $Id: AceGUIWidget-DropDown-Items.lua 76326 2008-06-09 09:29:17Z nevcairiel $ ]]--
 
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 = 1
 
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
function SetMenu(self, menu)
assert(menu.type == "Dropdown-Pullout")
self.submenu = menu
end
 
-- exported
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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-TreeGroup.lua New file
0,0 → 1,673
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 = 13
 
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(), 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, "InterfaceOptionsButtonTemplate")
buttoncount = buttoncount + 1
button.obj = self
 
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 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 normalText = button.text
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", 8, 2)
else
button:SetNormalFontObject("GameFontHighlightSmall")
button:SetHighlightFontObject("GameFontHighlightSmall")
button.text:SetPoint("LEFT", 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 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)
assert(type(tree) == "table")
self.tree = tree
self:RefreshTree()
end
 
local function BuildLevel(self, tree, level, parent)
local lines = self.lines
 
local status = (self.status or self.localstatus)
local groups = status.groups
local hasChildren = self.hasChildren
 
for i, v in ipairs(tree) do
local line = new()
lines[#lines+1] = line
line.value = v.value
line.text = v.text
line.disabled = v.disabled
line.tree = tree
line.level = level
line.parent = parent
line.uniquevalue = GetButtonUniqueValue(line)
 
if v.children then
line.hasChildren = true
else
line.hasChildren = nil
end
if v.children then
if groups[line.uniquevalue] then
self:BuildLevel(v.children, level+1, line)
end
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)
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 lines = self.lines
local buttons = self.buttons
 
local treeframe = self.treeframe
 
 
while lines[1] do
local t = tremove(lines)
for k in pairs(t) do
t[k] = nil
end
del(t)
end
 
self:BuildLevel(tree, 1)
 
for i, v in ipairs(buttons) do
v:Hide()
end
 
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, ...)
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 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 = {}
 
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.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
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceGUI-3.0/widgets/AceGUIWidget-ColorPicker.lua New file
0,0 → 1,170
local AceGUI = LibStub("AceGUI-3.0")
 
--------------------------
-- ColorPicker --
--------------------------
do
local Type = "ColorPicker"
local Version = 9
 
local function OnAcquire(self)
self.HasAlpha = false
self:SetColor(0,0,0,1)
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
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/AceAddon-3.0/AceAddon-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="AceAddon-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:mime-type + text/xml Added: svn:eol-style + native
RepWatch/Libs/AceAddon-3.0/AceAddon-3.0.lua New file
0,0 → 1,448
--[[ $Id: AceAddon-3.0.lua 76326 2008-06-09 09:29:17Z nevcairiel $ ]]
local MAJOR, MINOR = "AceAddon-3.0", 5
local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
 
if not AceAddon then return end -- No Upgrade needed.
 
AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
AceAddon.addons = AceAddon.addons or {} -- addons in general
AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
 
local tinsert, tconcat = table.insert, table.concat
local fmt = string.format
local pairs, next, type = pairs, next, type
 
--[[
xpcall safecall implementation
]]
local xpcall = xpcall
 
local function errorhandler(err)
return geterrorhandler()(err)
end
 
local function CreateDispatcher(argCount)
local code = [[
local xpcall, eh = ...
local method, ARGS
local function call() return method(ARGS) end
 
local function dispatch(func, ...)
method = func
if not method then return end
ARGS = ...
return xpcall(call, eh)
end
 
return dispatch
]]
 
local ARGS = {}
for i = 1, argCount do ARGS[i] = "arg"..i end
code = code:gsub("ARGS", tconcat(ARGS, ", "))
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
end
 
local Dispatchers = setmetatable({}, {__index=function(self, argCount)
local dispatcher = CreateDispatcher(argCount)
rawset(self, argCount, dispatcher)
return dispatcher
end})
Dispatchers[0] = function(func)
return xpcall(func, errorhandler)
end
 
local function safecall(func, ...)
-- we check to see if the func is passed is actually a function here and don't error when it isn't
-- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
-- present execution should continue without hinderance
if type(func) == "function" then
return Dispatchers[select('#', ...)](func, ...)
end
end
 
-- local functions that will be implemented further down
local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
 
-- used in the addon metatable
local function addontostring( self ) return self.name end
 
-- AceAddon:NewAddon( [object, ]name, [lib, lib, lib, ...] )
-- [object] (table) - table to use as the base for the addon
-- name (string) - unique addon object name
-- [lib] (string) - optional libs to embed in the addon object
--
-- returns the addon object when succesful
function AceAddon:NewAddon(objectorname, ...)
local object,name
local i=1
if type(objectorname)=="table" then
object=objectorname
name=...
i=2
else
name=objectorname
end
if type(name)~="string" then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
end
if self.addons[name] then
error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
end
 
object = object or {}
object.name = name
 
local addonmeta = {}
local oldmeta = getmetatable(object)
if oldmeta then
for k, v in pairs(oldmeta) do addonmeta[k] = v end
end
addonmeta.__tostring = addontostring
 
setmetatable( object, addonmeta )
self.addons[name] = object
object.modules = {}
object.defaultModuleLibraries = {}
Embed( object ) -- embed NewModule, GetModule methods
self:EmbedLibraries(object, select(i,...))
 
-- add to queue of addons to be initialized upon ADDON_LOADED
tinsert(self.initializequeue, object)
return object
end
 
 
-- AceAddon:GetAddon( name, [silent])
-- name (string) - unique addon object name
-- silent (boolean) - if true, addon is optional, silently return nil if its not found
--
-- throws an error if the addon object can not be found (except silent is set)
-- returns the addon object if found
function AceAddon:GetAddon(name, silent)
if not silent and not self.addons[name] then
error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
end
return self.addons[name]
end
 
-- AceAddon:EmbedLibraries( addon, [lib, lib, lib, ...] )
-- addon (object) - addon to embed the libs in
-- [lib] (string) - optional libs to embed
function AceAddon:EmbedLibraries(addon, ...)
for i=1,select("#", ... ) do
local libname = select(i, ...)
self:EmbedLibrary(addon, libname, false, 4)
end
end
 
-- AceAddon:EmbedLibrary( addon, libname, silent, offset )
-- addon (object) - addon to embed the libs in
-- libname (string) - lib to embed
-- [silent] (boolean) - optional, marks an embed to fail silently if the library doesn't exist.
-- [offset] (number) - will push the error messages back to said offset defaults to 2
function AceAddon:EmbedLibrary(addon, libname, silent, offset)
local lib = LibStub:GetLibrary(libname, true)
if not lib and not silent then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
elseif lib and type(lib.Embed) == "function" then
lib:Embed(addon)
tinsert(self.embeds[addon], libname)
return true
elseif lib then
error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
end
end
 
-- addon:GetModule( name, [silent])
-- name (string) - unique module object name
-- silent (boolean) - if true, module is optional, silently return nil if its not found
--
-- throws an error if the addon object can not be found (except silent is set)
-- returns the module object if found
function GetModule(self, name, silent)
if not self.modules[name] and not silent then
error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
end
return self.modules[name]
end
 
local function IsModuleTrue(self) return true end
 
-- addon:NewModule( name, [prototype, [lib, lib, lib, ...] )
-- name (string) - unique module object name for this addon
-- prototype (object) - object to derive this module from, methods and values from this table will be mixed into the module, if a string is passed a lib is assumed
-- [lib] (string) - optional libs to embed in the addon object
--
-- returns the addon object when succesful
function NewModule(self, name, prototype, ...)
if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
 
if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
 
-- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
-- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
 
module.IsModule = IsModuleTrue
module:SetEnabledState(self.defaultModuleState)
module.moduleName = name
 
if type(prototype) == "string" then
AceAddon:EmbedLibraries(module, prototype, ...)
else
AceAddon:EmbedLibraries(module, ...)
end
AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
 
if not prototype or type(prototype) == "string" then
prototype = self.defaultModulePrototype or nil
end
 
if type(prototype) == "table" then
local mt = getmetatable(module)
mt.__index = prototype
setmetatable(module, mt) -- More of a Base class type feel.
end
 
safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
self.modules[name] = module
 
return module
end
 
--addon:GetName()
-- Returns the real name of the addon or module, without any prefix
function GetName(self)
return self.moduleName or self.name
end
 
--addon:Enable()
-- Enables the Addon if possible, return true or false depending on success
function Enable(self)
self:SetEnabledState(true)
return AceAddon:EnableAddon(self)
end
 
--addon:Disable()
-- Disables the Addon if possible, return true or false depending on success
function Disable(self)
self:SetEnabledState(false)
return AceAddon:DisableAddon(self)
end
 
-- addon:EnableModule( name )
-- name (string) - unique module object name
--
-- Enables the Module if possible, return true or false depending on success
function EnableModule(self, name)
local module = self:GetModule( name )
return module:Enable()
end
 
-- addon:DisableModule( name )
-- name (string) - unique module object name
--
-- Disables the Module if possible, return true or false depending on success
function DisableModule(self, name)
local module = self:GetModule( name )
return module:Disable()
end
 
-- addon:SetDefaultModuleLibraries( [lib, lib, lib, ...] )
-- [lib] (string) - libs to embed in every module
function SetDefaultModuleLibraries(self, ...)
if next(self.modules) then
error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleLibraries = {...}
end
 
-- addon:SetDefaultModuleState( state )
-- state (boolean) - default state for new modules (enabled=true, disabled=false)
function SetDefaultModuleState(self, state)
if next(self.modules) then
error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
end
self.defaultModuleState = state
end
 
-- addon:SetDefaultModulePrototype( prototype )
-- prototype (string or table) - the default prototype to use if none is specified on module creation
function SetDefaultModulePrototype(self, prototype)
if next(self.modules) then
error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
end
if type(prototype) ~= "table" then
error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
end
self.defaultModulePrototype = prototype
end
 
-- addon:SetEnabledState ( state )
-- state ( boolean ) - set the state of an addon or module (enabled=true, disabled=false)
--
-- should only be called before any Enabling actually happend, aka in OnInitialize
function SetEnabledState(self, state)
self.enabledState = state
end
 
 
local function IterateModules(self) return pairs(self.modules) end
local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
local function IsEnabled(self) return self.enabledState end
local mixins = {
NewModule = NewModule,
GetModule = GetModule,
Enable = Enable,
Disable = Disable,
EnableModule = EnableModule,
DisableModule = DisableModule,
IsEnabled = IsEnabled,
SetDefaultModuleLibraries = SetDefaultModuleLibraries,
SetDefaultModuleState = SetDefaultModuleState,
SetDefaultModulePrototype = SetDefaultModulePrototype,
SetEnabledState = SetEnabledState,
IterateModules = IterateModules,
IterateEmbeds = IterateEmbeds,
GetName = GetName,
}
local function IsModule(self) return false end
local pmixins = {
defaultModuleState = true,
enabledState = true,
IsModule = IsModule,
}
-- Embed( target )
-- target (object) - target object to embed aceaddon in
--
-- this is a local function specifically since it's meant to be only called internally
function Embed(target)
for k, v in pairs(mixins) do
target[k] = v
end
for k, v in pairs(pmixins) do
target[k] = target[k] or v
end
end
 
 
-- AceAddon:IntializeAddon( addon )
-- addon (object) - addon to intialize
--
-- calls OnInitialize on the addon object if available
-- calls OnEmbedInitialize on embedded libs in the addon object if available
function AceAddon:InitializeAddon(addon)
safecall(addon.OnInitialize, addon)
 
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
end
 
-- we don't call InitializeAddon on modules specifically, this is handled
-- from the event handler and only done _once_
end
 
-- AceAddon:EnableAddon( addon )
-- addon (object) - addon to enable
--
-- calls OnEnable on the addon object if available
-- calls OnEmbedEnable on embedded libs in the addon object if available
function AceAddon:EnableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if self.statuses[addon.name] or not addon.enabledState then return false end
 
-- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
self.statuses[addon.name] = true
 
-- TODO: handle 'first'? Or let addons do it on their own?
safecall(addon.OnEnable, addon)
 
-- make sure we're still enabled before continueing
if self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedEnable, lib, addon) end
end
 
-- enable possible modules.
for name, module in pairs(addon.modules) do
self:EnableAddon(module)
end
end
return self.statuses[addon.name] -- return true if we're disabled
end
 
-- AceAddon:DisableAddon( addon )
-- addon (object|string) - addon to disable
--
-- calls OnDisable on the addon object if available
-- calls OnEmbedDisable on embedded libs in the addon object if available
function AceAddon:DisableAddon(addon)
if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
if not self.statuses[addon.name] then return false end
 
-- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
self.statuses[addon.name] = false
 
safecall( addon.OnDisable, addon )
 
-- make sure we're still disabling...
if not self.statuses[addon.name] then
local embeds = self.embeds[addon]
for i = 1, #embeds do
local lib = LibStub:GetLibrary(embeds[i], true)
if lib then safecall(lib.OnEmbedDisable, lib, addon) end
end
-- disable possible modules.
for name, module in pairs(addon.modules) do
self:DisableAddon(module)
end
end
 
return not self.statuses[addon.name] -- return true if we're disabled
end
 
--The next few funcs are just because no one should be reaching into the internal registries
--Thoughts?
function AceAddon:IterateAddons() return pairs(self.addons) end
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
 
-- Event Handling
local function onEvent(this, event, arg1)
if event == "ADDON_LOADED" or event == "PLAYER_LOGIN" then
-- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
while(#AceAddon.initializequeue > 0) do
local addon = tremove(AceAddon.initializequeue, 1)
-- this might be an issue with recursion - TODO: validate
if event == "ADDON_LOADED" then addon.baseName = arg1 end
AceAddon:InitializeAddon(addon)
tinsert(AceAddon.enablequeue, addon)
end
 
if IsLoggedIn() then
while(#AceAddon.enablequeue > 0) do
local addon = tremove(AceAddon.enablequeue, 1)
AceAddon:EnableAddon(addon)
end
end
end
end
 
AceAddon.frame:RegisterEvent("ADDON_LOADED")
AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
AceAddon.frame:SetScript("OnEvent", onEvent)
 
-- upgrade embeded
for name, addon in pairs(AceAddon.addons) do
Embed(addon)
end
Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date
RepWatch/Libs/AceDB-3.0/AceDB-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="AceDB-3.0.lua"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml
RepWatch/Libs/AceDB-3.0/AceDB-3.0.lua New file
0,0 → 1,626
--[[ $Id: AceDB-3.0.lua 69511 2008-04-13 10:10:53Z nevcairiel $ ]]
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 7
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR)
 
if not AceDB then return end -- No upgrade needed
 
local type = type
local pairs, next = pairs, next
local rawget, rawset = rawget, rawset
local setmetatable = setmetatable
 
AceDB.db_registry = AceDB.db_registry or {}
AceDB.frame = AceDB.frame or CreateFrame("Frame")
 
local CallbackHandler
local CallbackDummy = { Fire = function() end }
 
local DBObjectLib = {}
 
--[[-------------------------------------------------------------------------
AceDB Utility Functions
---------------------------------------------------------------------------]]
 
-- Simple shallow copy for copying defaults
local function copyTable(src, dest)
if type(dest) ~= "table" then dest = {} end
if type(src) == "table" then
for k,v in pairs(src) do
if type(v) == "table" then
-- try to index the key first so that the metatable creates the defaults, if set, and use that table
v = copyTable(v, dest[k])
end
dest[k] = v
end
end
return dest
end
 
-- Called to add defaults to a section of the database
--
-- When a ["*"] default section is indexed with a new key, a table is returned
-- and set in the host table. These tables must be cleaned up by removeDefaults
-- in order to ensure we don't write empty default tables.
local function copyDefaults(dest, src)
-- this happens if some value in the SV overwrites our default value with a non-table
--if type(dest) ~= "table" then return end
for k, v in pairs(src) do
if k == "*" or k == "**" then
if type(v) == "table" then
-- This is a metatable used for table defaults
local mt = {
-- This handles the lookup and creation of new subtables
__index = function(t,k)
if k == nil then return nil end
local tbl = {}
copyDefaults(tbl, v)
rawset(t, k, tbl)
return tbl
end,
}
setmetatable(dest, mt)
-- handle already existing tables in the SV
for dk, dv in pairs(dest) do
if not rawget(src, dk) and type(dv) == "table" then
copyDefaults(dv, v)
end
end
else
-- Values are not tables, so this is just a simple return
local mt = {__index = function(t,k) return k~=nil and v or nil end}
setmetatable(dest, mt)
end
elseif type(v) == "table" then
if not rawget(dest, k) then rawset(dest, k, {}) end
if type(dest[k]) == "table" then
copyDefaults(dest[k], v)
if src['**'] then
copyDefaults(dest[k], src['**'])
end
end
else
if rawget(dest, k) == nil then
rawset(dest, k, v)
end
end
end
end
 
-- Called to remove all defaults in the default table from the database
local function removeDefaults(db, defaults, blocker)
for k,v in pairs(defaults) do
if k == "*" or k == "**" then
if type(v) == "table" then
-- Loop through all the actual k,v pairs and remove
for key, value in pairs(db) do
if type(value) == "table" then
-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables
if defaults[key] == nil then
removeDefaults(value, v)
-- if the table is empty afterwards, remove it
if not next(value) then
db[key] = nil
end
-- if it was specified, only strip ** content, but block values which were set in the key table
elseif k == "**" then
removeDefaults(value, v, defaults[key])
end
end
end
elseif k == "*" then
-- check for non-table default
for key, value in pairs(db) do
if defaults[key] == nil and v == value then
db[key] = nil
end
end
end
elseif type(v) == "table" and type(db[k]) == "table" then
-- if a blocker was set, dive into it, to allow multi-level defaults
removeDefaults(db[k], v, blocker and blocker[k])
if not next(db[k]) then
db[k] = nil
end
else
-- check if the current value matches the default, and that its not blocked by another defaults table
if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then
db[k] = nil
end
end
end
-- remove all metatables from the db
setmetatable(db, nil)
end
 
-- This is called when a table section is first accessed, to set up the defaults
local function initSection(db, section, svstore, key, defaults)
local sv = rawget(db, "sv")
 
local tableCreated
if not sv[svstore] then sv[svstore] = {} end
if not sv[svstore][key] then
sv[svstore][key] = {}
tableCreated = true
end
 
local tbl = sv[svstore][key]
 
if defaults then
copyDefaults(tbl, defaults)
end
rawset(db, section, tbl)
 
return tableCreated, tbl
end
 
-- Metatable to handle the dynamic creation of sections and copying of sections.
local dbmt = {
__index = function(t, section)
local keys = rawget(t, "keys")
local key = keys[section]
if key then
local defaultTbl = rawget(t, "defaults")
local defaults = defaultTbl and defaultTbl[section]
 
if section == "profile" then
local new = initSection(t, section, "profiles", key, defaults)
if new then
-- Callback: OnNewProfile, database, newProfileKey
t.callbacks:Fire("OnNewProfile", t, key)
end
elseif section == "profiles" then
local sv = rawget(t, "sv")
if not sv.profiles then sv.profiles = {} end
rawset(t, "profiles", sv.profiles)
elseif section == "global" then
local sv = rawget(t, "sv")
if not sv.global then sv.global = {} end
if defaults then
copyDefaults(sv.global, defaults)
end
rawset(t, section, sv.global)
else
initSection(t, section, section, key, defaults)
end
end
 
return rawget(t, section)
end
}
 
local function validateDefaults(defaults, keyTbl, offset)
if not defaults then return end
offset = offset or 0
for k in pairs(defaults) do
if not keyTbl[k] or k == "profiles" then
error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset)
end
end
end
 
local preserve_keys = {
["callbacks"] = true,
["RegisterCallback"] = true,
["UnregisterCallback"] = true,
["UnregisterAllCallbacks"] = true,
["children"] = true,
}
 
local realmKey = GetRealmName()
local charKey = UnitName("player") .. " - " .. realmKey
local _, classKey = UnitClass("player")
local _, raceKey = UnitRace("player")
local factionKey = UnitFactionGroup("player")
local factionrealmKey = factionKey .. " - " .. realmKey
-- Actual database initialization function
local function initdb(sv, defaults, defaultProfile, olddb, parent)
-- Generate the database keys for each section
 
-- Make a container for profile keys
if not sv.profileKeys then sv.profileKeys = {} end
 
-- Try to get the profile selected from the char db
local profileKey = sv.profileKeys[charKey] or defaultProfile or charKey
sv.profileKeys[charKey] = profileKey
 
-- This table contains keys that enable the dynamic creation
-- of each section of the table. The 'global' and 'profiles'
-- have a key of true, since they are handled in a special case
local keyTbl= {
["char"] = charKey,
["realm"] = realmKey,
["class"] = classKey,
["race"] = raceKey,
["faction"] = factionKey,
["factionrealm"] = factionrealmKey,
["profile"] = profileKey,
["global"] = true,
["profiles"] = true,
}
 
validateDefaults(defaults, keyTbl, 1)
 
-- This allows us to use this function to reset an entire database
-- Clear out the old database
if olddb then
for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end
end
 
-- Give this database the metatable so it initializes dynamically
local db = setmetatable(olddb or {}, dbmt)
 
if not rawget(db, "callbacks") then
-- try to load CallbackHandler-1.0 if it loaded after our library
if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end
db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy
end
 
-- Copy methods locally into the database object, to avoid hitting
-- the metatable when calling methods
 
if not parent then
for name, func in pairs(DBObjectLib) do
db[name] = func
end
else
-- hack this one in
db.RegisterDefaults = DBObjectLib.RegisterDefaults
db.ResetProfile = DBObjectLib.ResetProfile
end
 
-- Set some properties in the database object
db.profiles = sv.profiles
db.keys = keyTbl
db.sv = sv
--db.sv_name = name
db.defaults = defaults
db.parent = parent
 
-- store the DB in the registry
AceDB.db_registry[db] = true
 
return db
end
 
-- handle PLAYER_LOGOUT
-- strip all defaults from all databases
local function logoutHandler(frame, event)
if event == "PLAYER_LOGOUT" then
for db in pairs(AceDB.db_registry) do
db.callbacks:Fire("OnDatabaseShutdown", db)
for section, key in pairs(db.keys) do
if db.defaults and db.defaults[section] and rawget(db, section) then
removeDefaults(db[section], db.defaults[section])
end
end
end
end
end
 
AceDB.frame:RegisterEvent("PLAYER_LOGOUT")
AceDB.frame:SetScript("OnEvent", logoutHandler)
 
 
--[[-------------------------------------------------------------------------
AceDB Object Method Definitions
---------------------------------------------------------------------------]]
 
-- DBObject:RegisterDefaults(defaults)
-- defaults (table) - A table of defaults for this database
--
-- Sets the defaults table for the given database object by clearing any
-- that are currently set, and then setting the new defaults.
function DBObjectLib:RegisterDefaults(defaults)
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2)
end
 
validateDefaults(defaults, self.keys)
 
-- Remove any currently set defaults
if self.defaults then
for section,key in pairs(self.keys) do
if self.defaults[section] and rawget(self, section) then
removeDefaults(self[section], self.defaults[section])
end
end
end
 
-- Set the DBObject.defaults table
self.defaults = defaults
 
-- Copy in any defaults, only touching those sections already created
if defaults then
for section,key in pairs(self.keys) do
if defaults[section] and rawget(self, section) then
copyDefaults(self[section], defaults[section])
end
end
end
end
 
-- DBObject:SetProfile(name)
-- name (string) - The name of the profile to set as the current profile
--
-- Changes the profile of the database and all of it's namespaces to the
-- supplied named profile
function DBObjectLib:SetProfile(name)
if type(name) ~= "string" then
error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2)
end
 
-- changing to the same profile, dont do anything
if name == self.keys.profile then return end
 
local oldProfile = self.profile
local defaults = self.defaults and self.defaults.profile
 
if oldProfile and defaults then
-- Remove the defaults from the old profile
removeDefaults(oldProfile, defaults)
end
 
self.profile = nil
self.keys["profile"] = name
self.sv.profileKeys[charKey] = name
 
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.SetProfile(db, name)
end
end
 
-- Callback: OnProfileChanged, database, newProfileKey
self.callbacks:Fire("OnProfileChanged", self, name)
end
 
-- DBObject:GetProfiles(tbl)
-- tbl (table) - A table to store the profile names in (optional)
--
-- Returns a table with the names of the existing profiles in the database.
-- You can optionally supply a table to re-use for this purpose.
function DBObjectLib:GetProfiles(tbl)
if tbl and type(tbl) ~= "table" then
error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2)
end
 
-- Clear the container table
if tbl then
for k,v in pairs(tbl) do tbl[k] = nil end
else
tbl = {}
end
 
local curProfile = self.keys.profile
 
local i = 0
for profileKey in pairs(self.profiles) do
i = i + 1
tbl[i] = profileKey
if curProfile and profileKey == curProfile then curProfile = nil end
end
 
-- Add the current profile, if it hasn't been created yet
if curProfile then
i = i + 1
tbl[i] = curProfile
end
 
return tbl, i
end
 
-- DBObject:GetCurrentProfile()
--
-- Returns the current profile name used by the database
function DBObjectLib:GetCurrentProfile()
return self.keys.profile
end
 
-- DBObject:DeleteProfile(name)
-- name (string) - The name of the profile to be deleted
--
-- Deletes a named profile. This profile must not be the active profile.
function DBObjectLib:DeleteProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2)
end
 
if self.keys.profile == name then
error("Cannot delete the active profile in an AceDBObject.", 2)
end
 
if not rawget(self.sv.profiles, name) and not silent then
error("Cannot delete profile '" .. name .. "'. It does not exist.", 2)
end
 
self.sv.profiles[name] = nil
 
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.DeleteProfile(db, name, true)
end
end
 
-- Callback: OnProfileDeleted, database, profileKey
self.callbacks:Fire("OnProfileDeleted", self, name)
end
 
-- DBObject:CopyProfile(name)
-- name (string) - The name of the profile to be copied into the current profile
--
-- Copies a named profile into the current profile, overwriting any conflicting
-- settings.
function DBObjectLib:CopyProfile(name, silent)
if type(name) ~= "string" then
error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2)
end
 
if name == self.keys.profile then
error("Cannot have the same source and destination profiles.", 2)
end
 
if not rawget(self.sv.profiles, name) and not silent then
error("Cannot copy profile '" .. name .. "'. It does not exist.", 2)
end
 
-- Reset the profile before copying
DBObjectLib.ResetProfile(self)
 
local profile = self.profile
local source = self.sv.profiles[name]
 
copyTable(source, profile)
 
-- populate to child namespaces
if self.children then
for _, db in pairs(self.children) do
DBObjectLib.CopyProfile(db, name, true)
end
end
 
-- Callback: OnProfileCopied, database, sourceProfileKey
self.callbacks:Fire("OnProfileCopied", self, name)
end
 
-- DBObject:ResetProfile()
-- noChildren (boolean) - if set to true, the reset will not be populated to the child namespaces of this DB object
--
-- Resets the current profile
function DBObjectLib:ResetProfile(noChildren)
local profile = self.profile
 
for k,v in pairs(profile) do
profile[k] = nil
end
 
local defaults = self.defaults and self.defaults.profile
if defaults then
copyDefaults(profile, defaults)
end
 
-- populate to child namespaces
if self.children and not noChildren then
for _, db in pairs(self.children) do
DBObjectLib.ResetProfile(db)
end
end
 
-- Callback: OnProfileReset, database
self.callbacks:Fire("OnProfileReset", self)
end
 
-- DBObject:ResetDB(defaultProfile)
-- defaultProfile (string) - The profile name to use as the default
--
-- Resets the entire database, using the string defaultProfile as the default
-- profile.
function DBObjectLib:ResetDB(defaultProfile)
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2)
end
 
local sv = self.sv
for k,v in pairs(sv) do
sv[k] = nil
end
 
local parent = self.parent
 
initdb(sv, self.defaults, defaultProfile, self)
 
-- fix the child namespaces
if self.children then
if not sv.namespaces then sv.namespaces = {} end
for name, db in pairs(self.children) do
if not sv.namespaces[name] then sv.namespaces[name] = {} end
initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self)
end
end
 
-- Callback: OnDatabaseReset, database
self.callbacks:Fire("OnDatabaseReset", self)
-- Callback: OnProfileChanged, database, profileKey
self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"])
 
return self
end
 
-- DBObject:RegisterNamespace(name [, defaults])
-- name (string) - The name of the new namespace
-- defaults (table) - A table of values to use as defaults
--
-- Creates a new database namespace, directly tied to the database. This
-- is a full scale database in it's own rights other than the fact that
-- it cannot control its profile individually
function DBObjectLib:RegisterNamespace(name, defaults)
if type(name) ~= "string" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2)
end
if defaults and type(defaults) ~= "table" then
error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2)
end
if self.children and self.children[name] then
error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2)
end
 
local sv = self.sv
if not sv.namespaces then sv.namespaces = {} end
if not sv.namespaces[name] then
sv.namespaces[name] = {}
end
 
local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self)
 
if not self.children then self.children = {} end
self.children[name] = newDB
return newDB
end
 
--[[-------------------------------------------------------------------------
AceDB Exposed Methods
---------------------------------------------------------------------------]]
 
-- AceDB:New(name, defaults, defaultProfile)
-- name (table or string) - The name of variable, or table to use for the database
-- defaults (table) - A table of database defaults
-- defaultProfile (string) - The name of the default profile
--
-- Creates a new database object that can be used to handle database settings
-- and profiles.
function AceDB:New(tbl, defaults, defaultProfile)
if type(tbl) == "string" then
local name = tbl
tbl = getglobal(name)
if not tbl then
tbl = {}
setglobal(name, tbl)
end
end
 
if type(tbl) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2)
end
 
if defaults and type(defaults) ~= "table" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2)
end
 
if defaultProfile and type(defaultProfile) ~= "string" then
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string expected.", 2)
end
 
return initdb(tbl, defaults, defaultProfile)
end
 
-- upgrade existing databases
for db in pairs(AceDB.db_registry) do
if not db.parent then
for name,func in pairs(DBObjectLib) do
db[name] = func
end
else
db.RegisterDefaults = DBObjectLib.RegisterDefaults
end
end
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Libs/Ace3.toc New file
0,0 → 1,27
## Interface: 30000
 
## Title: Lib: Ace3
## Notes: AddOn development framework
## Author: Ace3 Development Team
## X-Website: http://www.wowace.com
## X-Category: Library
## X-License: BSD-2.0
 
LibStub\LibStub.lua
CallbackHandler-1.0\CallbackHandler-1.0.xml
AceAddon-3.0\AceAddon-3.0.xml
AceEvent-3.0\AceEvent-3.0.xml
AceTimer-3.0\AceTimer-3.0.xml
AceBucket-3.0\AceBucket-3.0.xml
AceHook-3.0\AceHook-3.0.xml
AceDB-3.0\AceDB-3.0.xml
AceDBOptions-3.0\AceDBOptions-3.0.xml
AceLocale-3.0\AceLocale-3.0.xml
AceConsole-3.0\AceConsole-3.0.xml
AceGUI-3.0\AceGUI-3.0.xml
AceConfig-3.0\AceConfig-3.0.xml
AceComm-3.0\AceComm-3.0.xml
AceTab-3.0\AceTab-3.0.xml
AceSerializer-3.0\AceSerializer-3.0.xml
 
Ace3.lua
Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/Read Me.txt New file
0,0 → 1,38
This Version Includes NO Additional Reputations from the Latest Beta Builds of the Stable Release.
 
This release is just meant for testing of the addon with Client 3.0, I will be adding WotlK Reputations periodicly
because more classic and TBC factions still need to be added
 
The WotlK Beta Versions use the 1.0.8+ Underlay Code and Many Bugs will be Similar
 
 
 
Until I can get more help main Priority will be to Debug the Normal RepWatch and then come back to the WotlK Version
 
 
 
 
If you find a Bug Please Post it at my Author Addon: http://seglberg.wowinterface.com
or Email me at: Seglberg@live.com wih the subject line: RepWatch WotlK Bug
 
Please Include the Exact Build Name in Your Reports
 
 
 
Reports and Greatly Appriciated as they help the development of the addon go quicker!
 
 
 
 
--Seglberg
 
 
 
 
Visit me on Thrall Under:
- Seglberg
- Dragonspew
 
or on WotlK Beta Server - Northrend Under:
- Seglberg
- Blöödoath
\ No newline at end of file Property changes : Added: svn:mime-type + text/plain Added: svn:keywords + Revision Date Added: svn:eol-style + native
RepWatch/embeds.xml New file
0,0 → 1,12
<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="Libs\LibStub\LibStub.lua"/>
<Include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="Libs\AceGUI-3.0\AceGUI-3.0.xml"/>
<Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml"/>
<Include file="Libs\AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="Libs\AceDB-3.0\AceDB-3.0.xml"/>
<Include file="Libs\AceEvent-3.0\AceEvent-3.0.xml"/>
</Ui>
\ No newline at end of file Property changes : Added: svn:eol-style + native Added: svn:mime-type + text/xml